Skip to content

Commit

Permalink
Merge pull request #757 from basedosdados/feat/api_keys
Browse files Browse the repository at this point in the history
feat: view for validating API keys
  • Loading branch information
rdahis authored Feb 11, 2025
2 parents 4a84015 + 2796427 commit c6fe570
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 3 deletions.
4 changes: 2 additions & 2 deletions backend/apps/account/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,8 @@ def save_model(self, request, obj, form, change):
obj, key = DataAPIKey.create_key(**form.cleaned_data)
messages.success(
request,
"API Key generated successfully. "
"Please copy this key now as it won't be shown again: {key}",
f"API Key generated successfully. "
f"Please copy this key now as it won't be shown again: {key}",
)
else:
super().save_model(request, obj, form, change)
Expand Down
3 changes: 2 additions & 1 deletion backend/apps/account/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from hashlib import sha256
from typing import Tuple
from uuid import uuid4

Expand Down Expand Up @@ -644,7 +645,7 @@ def create_key(cls, **kwargs):
key = str(uuid4())
obj = cls(**kwargs)
obj.prefix = key[:8]
obj.hash = key
obj.hash = sha256(key.encode()).hexdigest()
obj.save()
return obj, key

Expand Down
6 changes: 6 additions & 0 deletions backend/apps/account/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from backend.apps.account.views import (
AccountActivateConfirmView,
AccountActivateView,
DataAPIKeyValidateView,
PasswordResetConfirmView,
PasswordResetView,
)
Expand All @@ -29,4 +30,9 @@
PasswordResetConfirmView.as_view(),
name="password_reset_confirm",
),
path(
"account/validate_data_api_key",
DataAPIKeyValidateView.as_view(),
name="validate_data_api_key",
),
]
35 changes: 35 additions & 0 deletions backend/apps/account/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from hashlib import sha256
from json import loads
from typing import Any

Expand All @@ -10,6 +11,7 @@
from django.http import JsonResponse
from django.template.loader import render_to_string
from django.urls import reverse_lazy as r
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.encoding import force_bytes, force_str
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
Expand All @@ -21,6 +23,8 @@
from backend.apps.account.token import token_generator
from backend.custom.environment import get_frontend_url

from .models import DataAPIKey


class AccountActivateView(View):
@method_decorator(csrf_exempt, name="dispatch")
Expand Down Expand Up @@ -139,3 +143,34 @@ def dispatch(self, request, uidb64, token):
return JsonResponse({}, status=200)
else:
return JsonResponse({}, status=422)


class DataAPIKeyValidateView(View):
def get(self, request):
api_key = request.GET.get("id")
if not api_key:
return JsonResponse({"error": "API key not provided", "success": False}, status=400)

# Hash the API key
hashed_key = sha256(api_key.encode()).hexdigest()

try:
key = DataAPIKey.objects.get(hash=hashed_key)

# Check if key is expired
is_expired = False
if key.expires_at and key.expires_at < timezone.now():
is_expired = True

return JsonResponse(
{
"success": True,
"resource": {
"isActive": key.is_active and not is_expired,
"createdAt": key.created_at,
"expiresAt": key.expires_at,
},
}
)
except DataAPIKey.DoesNotExist:
return JsonResponse({"error": "API key not found", "success": False}, status=404)

0 comments on commit c6fe570

Please sign in to comment.