Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): moving endpoints only used by IAM to the internal module #782

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
16 changes: 12 additions & 4 deletions api/account/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,15 @@
Customization,
Nonce,
)
from internal.api_key import internal_api_key
from scorer_weighted.models import (
BinaryWeightedScorer,
WeightedScorer,
get_default_weights,
)
from trusta_labs.api import CgrantsApiKey

from .deduplication import Rules

secret_key = CgrantsApiKey()

log = logging.getLogger(__name__)

api = NinjaExtraAPI(urls_namespace="account")
Expand Down Expand Up @@ -597,8 +595,13 @@ def update_community_scorers(request, community_id, payload: ScorerId):
return {"ok": True}


# Public version of endpoint. Also available on the internal API
@api.get("/customization/credential/{provider_id}", auth=None)
def get_credential_definition(request, provider_id: str):
return handle_get_credential_definition(provider_id)


def handle_get_credential_definition(provider_id: str):
decoded_provider_id = provider_id.replace("%23", "#")
return {
"ruleset": get_object_or_404(
Expand Down Expand Up @@ -676,11 +679,16 @@ def get_account_customization(request, dashboard_path: str):
raise APIException("Customization not found", status.HTTP_404_NOT_FOUND)


@api.get("/allow-list/{str:list}/{str:address}", auth=secret_key)
# TODO 3280 Remove this endpoint
@api.get("/allow-list/{str:list}/{str:address}", auth=internal_api_key)
def check_on_allow_list(request, list: str, address: str):
"""
Check if an address is on the allow list for a specific round
"""
return handle_check_allow_list(list, address)


def handle_check_allow_list(list: str, address: str):
try:
is_member = AddressListMember.objects.filter(
list__name=list, address=address
Expand Down
19 changes: 9 additions & 10 deletions api/ceramic_cache/api/v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import tos.schema
from account.models import Account, Community, Nonce
from ceramic_cache.utils import get_utc_time
from internal.api_key import internal_api_key
from registry.api.utils import (
is_valid_address,
)
Expand All @@ -43,9 +44,8 @@
NotFoundApiException,
)
from registry.models import Score
from stake.api import handle_get_gtc_stake
from stake.schema import GetSchemaResponse
from trusta_labs.api import CgrantsApiKey
from stake.api import get_gtc_stake_for_address
from stake.schema import StakeResponse

from ..exceptions import (
InternalServerException,
Expand All @@ -71,8 +71,6 @@

router = Router()

secret_key = CgrantsApiKey()


def get_address_from_did(did: str):
return did.split(":")[-1]
Expand Down Expand Up @@ -560,10 +558,11 @@ def calc_score(
return get_detailed_score_response_for_address(address, payload.alternate_scorer_id)


# TODO 3280 Remove this endpoint
@router.get(
"/score/{int:scorer_id}/{str:address}",
response=DetailedScoreResponse,
auth=secret_key,
auth=internal_api_key,
)
def calc_score_community(
request,
Expand Down Expand Up @@ -685,15 +684,15 @@ def get_detailed_score_response_for_address(
@router.get(
"/stake/gtc",
response={
200: GetSchemaResponse,
200: StakeResponse,
400: ErrorMessageResponse,
},
auth=JWTDidAuth(),
)
def get_staked_gtc(request) -> GetSchemaResponse:
def get_staked_gtc(request) -> StakeResponse:
address = get_address_from_did(request.did)
get_stake_response = handle_get_gtc_stake(address)
response = GetSchemaResponse(items=get_stake_response)
get_stake_response = get_gtc_stake_for_address(address)
response = StakeResponse(items=get_stake_response)
return response


Expand Down
149 changes: 7 additions & 142 deletions api/cgrants/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,22 @@

from enum import Enum

from django.conf import settings
from django.db.models import Count, Q, Sum
from django.http import JsonResponse
from ninja.security import APIKeyHeader
from ninja_extra import NinjaExtraAPI
from ninja_schema import Schema
from ninja_schema.orm.utils.converter import Decimal
from pydantic import Field

import api_logging as logging
from internal.api_key import internal_api_key
from registry.api.v1 import is_valid_address
from registry.exceptions import InvalidAddressException

from .models import (
Contribution,
Grant,
GrantContributionIndex,
ProtocolContributions,
RoundMapping,
SquelchedAccounts,
SquelchProfile,
)

logger = logging.getLogger(__name__)
Expand All @@ -35,17 +30,6 @@
api = NinjaExtraAPI(urls_namespace="cgrants")


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):
num_grants_contribute_to: int = Field()
num_rounds_contribute_to: int = Field()
Expand Down Expand Up @@ -127,22 +111,17 @@ def _get_contributor_statistics_for_protocol(address: str) -> dict:
}


# TODO 3280 Remove this endpoint
@api.get(
"/contributor_statistics",
response=ContributorStatistics,
auth=cg_api_key,
auth=internal_api_key,
)
def contributor_statistics(
request, address: str | None = None, github_id: str | None = None
):
if not address:
return JsonResponse(
{
"error": "Bad request, 'address' is missing or invalid. A valid address is required."
},
status=400,
)
def contributor_statistics(request, address: str):
return handle_get_contributor_statistics(address)


def handle_get_contributor_statistics(address: str):
if not is_valid_address(address):
raise InvalidAddressException()

Expand All @@ -165,117 +144,3 @@ def contributor_statistics(
}

return JsonResponse(combined_contributions)


@api.get(
"/allo/contributor_statistics",
response=ContributorStatistics,
auth=cg_api_key,
)
def allo_contributor_statistics(request, address: str | None = None):
if not address:
return JsonResponse(
{"error": "Bad request, 'address' parameter is missing or invalid"},
status=400,
)

if address:
address = address.lower()

response_for_protocol = _get_contributor_statistics_for_protocol(address)

return JsonResponse(response_for_protocol)


def _get_grantee_statistics(identifier, identifier_type):
if identifier_type == IdentifierType.HANDLE:
grant_identifier_query = Q(admin_profile__handle=identifier)

contribution_identifier_query = Q(
subscription__grant__admin_profile__handle=identifier
) & ~Q(subscription__contributor_profile__handle=identifier)
else:
grant_identifier_query = Q(admin_profile__github_id=identifier)

contribution_identifier_query = Q(
subscription__grant__admin_profile__github_id=identifier
) & ~Q(subscription__contributor_profile__github_id=identifier)

# Get number of owned grants
num_owned_grants = Grant.objects.filter(
grant_identifier_query, hidden=False, active=True, is_clr_eligible=True
).count()

# Get the total amount of contrinutors for one users grants that where not squelched and are not the owner himself
all_squelched = SquelchProfile.objects.filter(active=True).values_list(
"profile_id", flat=True
)

num_grant_contributors = (
Contribution.objects.filter(
contribution_identifier_query,
success=True,
subscription__is_mainnet=True,
subscription__grant__hidden=False,
subscription__grant__active=True,
subscription__grant__is_clr_eligible=True,
)
.exclude(subscription__contributor_profile_id__in=all_squelched)
.order_by("subscription__contributor_profile_id")
.values("subscription__contributor_profile_id")
.distinct()
.count()
)

# Get the total amount of contributions received by the owned grants (excluding the contributions made by the owner)
total_contribution_amount = Contribution.objects.filter(
contribution_identifier_query,
success=True,
subscription__is_mainnet=True,
subscription__grant__hidden=False,
subscription__grant__active=True,
subscription__grant__is_clr_eligible=True,
).aggregate(Sum("amount_per_period_usdt"))["amount_per_period_usdt__sum"]
total_contribution_amount = (
total_contribution_amount if total_contribution_amount is not None else 0
)

# [IAM] As an IAM server, I want to issue stamps for grant owners whose project have tagged matching-eligibel in an eco-system and/or cause round
num_grants_in_eco_and_cause_rounds = Grant.objects.filter(
grant_identifier_query,
hidden=False,
active=True,
is_clr_eligible=True,
clr_calculations__grantclr__type__in=["ecosystem", "cause"],
).count()

return JsonResponse(
{
"num_owned_grants": num_owned_grants,
"num_grant_contributors": num_grant_contributors,
"num_grants_in_eco_and_cause_rounds": num_grants_in_eco_and_cause_rounds,
"total_contribution_amount": total_contribution_amount,
}
)


@api.get(
"/grantee_statistics",
response=GranteeStatistics,
auth=cg_api_key,
)
def grantee_statistics(
request, handle: str | None = None, github_id: str | None = None
):
if not handle and not github_id:
return JsonResponse(
{
"error": "Bad request, 'handle' and 'github_id' parameter is missing or invalid. Either one is required."
},
status=400,
)

if handle:
return _get_grantee_statistics(handle, IdentifierType.HANDLE)
else:
return _get_grantee_statistics(github_id, IdentifierType.GITHUB_ID)
Loading