Skip to content

Commit

Permalink
cgrants almost ready, need to add network field
Browse files Browse the repository at this point in the history
  • Loading branch information
lucianHymer committed Jul 13, 2023
1 parent 5b06bd4 commit 28e75e2
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 39 deletions.
1 change: 1 addition & 0 deletions api/.env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ CERAMIC_CACHE_SCORER_ID=
PASSPORT_PUBLIC_URL=https://passport.gitcoin.co/

TRUSTED_IAM_ISSUER=
CGRANTS_API_TOKEN=abc
58 changes: 22 additions & 36 deletions api/cgrants/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,30 @@
import logging
from datetime import datetime

from django.conf import settings
from django.db.models import Sum
from django.http import JsonResponse
from ninja_extra import NinjaExtraAPI
from ninja_schema import Schema
from ninja.security import APIKeyHeader

from .models import Contribution, Grant, GrantContributionIndex, SquelchProfile

# from perftools.models import StaticJsonEnv

logger = logging.getLogger(__name__)


api = NinjaExtraAPI(urls_namespace="cgrants")

# def ami_api_token_required(func):
# def decorator(request, *args, **kwargs):
# try:
# apiToken = StaticJsonEnv.objects.get(key="AMI_API_TOKEN")
# expectedToken = apiToken.data["token"]
# receivedToken = request.headers.get("Authorization")

# if receivedToken:
# # Token shall look like "token <bearer token>", and we need only the <bearer token> part
# receivedToken = receivedToken.split(" ")[1]

# if expectedToken == receivedToken:
# return func(request, *args, **kwargs)
# else:
# return JsonResponse(
# {
# "error": "Access denied",
# },
# status=403,
# )
# except Exception as e:
# logger.error("Error in ami_api_token_required %s", e)
# return JsonResponse(
# {
# "error": "An unexpected error occured",
# },
# status=500,
# )

# return decorator

class CgrantsApiKey(APIKeyHeader):
param_name = "AUTHORIZATION"

def authenticate(self, request, key):
if key == settings.CGRANTS_API_TOKEN:
return key


cg_api_key = CgrantsApiKey()


class ContributorStatistics(Schema):
Expand All @@ -66,8 +46,11 @@ class GranteeStatistics(Schema):
total_contribution_amount = int


# TODO add auth
@api.get("/contributor_statistics", response=ContributorStatistics)
@api.get(
"/contributor_statistics",
response=ContributorStatistics,
auth=cg_api_key,
)
def contributor_statistics(request):
handle = request.GET.get("handle")

Expand Down Expand Up @@ -124,8 +107,11 @@ def contributor_statistics(request):
)


# TODO add auth
@api.get("/grantee_statistics", response=GranteeStatistics)
@api.get(
"/grantee_statistics",
response=GranteeStatistics,
auth=cg_api_key,
)
def grantee_statistics(request):
handle = request.GET.get("handle")

Expand Down
136 changes: 136 additions & 0 deletions api/cgrants/test/test_cgrants_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
from django.test import TestCase, Client
from django.conf import settings
from django.urls import reverse
from cgrants.models import (
Profile,
Grant,
GrantContributionIndex,
Contribution,
Subscription,
SquelchProfile,
)


class CgrantsTest(TestCase):
def setUp(self):
self.client = Client()

self.headers = {"HTTP_AUTHORIZATION": settings.CGRANTS_API_TOKEN}

self.profile1 = Profile.objects.create(handle="user1")
self.profile2 = Profile.objects.create(handle="user2")
self.profile3 = Profile.objects.create(handle="user3")

self.grant1 = Grant.objects.create(
admin_profile=self.profile1, hidden=False, active=True, is_clr_eligible=True
)

self.subscription1 = Subscription.objects.create(
grant=self.grant1, contributor_profile=self.profile1
)
Contribution.objects.create(subscription=self.subscription1)

# create test grant contribution indexes
GrantContributionIndex.objects.create(
profile=self.profile1, grant=self.grant1, amount=100
)

SquelchProfile.objects.create(profile=self.profile3, active=True)

def test_contributor_statistics(self):
# Standard case
response = self.client.get(
reverse("cgrants:contributor_statistics"),
{"handle": "user1"},
**self.headers,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json(),
{
"num_grants_contribute_to": 1,
"num_rounds_contribute_to": 0,
"total_contribution_amount": "100.000000000000000000",
"num_gr14_contributions": 0,
},
)

def test_contributor_statistics_no_contributions(self):
# Edge case: User has made no contributions
response = self.client.get(
reverse("cgrants:contributor_statistics"),
{"handle": "user2"},
**self.headers,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json(),
{
"num_grants_contribute_to": 0,
"num_rounds_contribute_to": 0,
"total_contribution_amount": 0,
"num_gr14_contributions": 0,
},
)

def test_grantee_statistics_standard(self):
# Standard case
response = self.client.get(
reverse("cgrants:grantee_statistics"),
{"handle": "user1"},
**self.headers,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json(),
{
"num_owned_grants": 1,
"num_grant_contributors": 1,
"num_grants_in_eco_and_cause_rounds": 0,
"total_contribution_amount": 0,
},
)

def test_grantee_statistics_no_grants(self):
response = self.client.get(
reverse("cgrants:grantee_statistics"),
{"handle": "user2"},
**self.headers,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json(),
{
"num_owned_grants": 0,
"num_grant_contributors": 0,
"num_grants_in_eco_and_cause_rounds": 0,
"total_contribution_amount": 0,
},
)

def test_invalid_handle(self):
response = self.client.get(
reverse("cgrants:contributor_statistics"),
{"handle": ""},
**self.headers,
)
self.assertEqual(response.status_code, 400) # Not found

def test_contributor_statistics_squelched_profile(self):
response = self.client.get(
reverse("cgrants:contributor_statistics"),
{"handle": self.profile3.handle},
**self.headers,
)

self.assertEqual(response.status_code, 200)
self.assertEqual(response.json().get("num_gr14_contributions"), 0)

def test_grantee_statistics_invalid_token(self):
response = self.client.get(
reverse("cgrants:contributor_statistics"),
{"handle": self.profile1.handle},
**{"HTTP_AUTHORIZATION": "invalidtoken"},
)

self.assertEqual(response.status_code, 401)
3 changes: 0 additions & 3 deletions api/cgrants/tests.py

This file was deleted.

7 changes: 7 additions & 0 deletions api/cgrants/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from .api import api

urlpatterns = [
path("", api.urls),
]
2 changes: 2 additions & 0 deletions api/scorer/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@
"TRUSTED_IAM_ISSUER", default="did:key:GlMY_1zkc0i11O-wMBWbSiUfIkZiXzFLlAQ89pdfyBA"
)

CGRANTS_API_TOKEN = env("CGRANTS_API_TOKEN", default="abc")


IPWARE_META_PRECEDENCE_ORDER = (
"X_FORWARDED_FOR",
Expand Down
1 change: 1 addition & 0 deletions api/scorer/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
path("registry/v2/", registry_api_v2.urls),
path("registry/feature/", feature_flag_api.urls),
path("ceramic-cache/", ceramic_cache_api.urls),
path("cgrants/", include("cgrants.urls")),
path("analytics/", analytics_api.urls),
path("health/", health, {}, "health-check"),
path(
Expand Down
4 changes: 4 additions & 0 deletions infra/prod/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@ const secrets = [
name: "FF_API_ANALYTICS",
valueFrom: `${SCORER_SERVER_SSM_ARN}:FF_API_ANALYTICS::`,
},
{
name: "CGRANTS_API_TOKEN",
valueFrom: `${SCORER_SERVER_SSM_ARN}:CGRANTS_API_TOKEN::`,
},
];
const environment = [
{
Expand Down
4 changes: 4 additions & 0 deletions infra/review/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ const secrets = [
name: "FF_API_ANALYTICS",
valueFrom: `${SCORER_SERVER_SSM_ARN}:FF_API_ANALYTICS::`,
},
{
name: "CGRANTS_API_TOKEN",
valueFrom: `${SCORER_SERVER_SSM_ARN}:CGRANTS_API_TOKEN::`,
},
];
const environment = [
{
Expand Down
4 changes: 4 additions & 0 deletions infra/staging/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ const secrets = [
name: "FF_API_ANALYTICS",
valueFrom: `${SCORER_SERVER_SSM_ARN}:FF_API_ANALYTICS::`,
},
{
name: "CGRANTS_API_TOKEN",
valueFrom: `${SCORER_SERVER_SSM_ARN}:CGRANTS_API_TOKEN::`,
},
];
const environment = [
{
Expand Down

0 comments on commit 28e75e2

Please sign in to comment.