Skip to content

Commit

Permalink
Fix api-keys endpoint by updating api method response and schema model
Browse files Browse the repository at this point in the history
  • Loading branch information
nickviola committed Nov 14, 2024
1 parent a9a0d02 commit d5d5420
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 9 deletions.
20 changes: 14 additions & 6 deletions backend/src/xfd_django/xfd_api/api_methods/api_key.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""/api-keys API logic"""

# Standard Python Libraries
from datetime import datetime, timezone
import hashlib
import secrets
import uuid
Expand All @@ -12,26 +13,33 @@


def post(current_user):
"""POST API LOGIC"""
"""POST API logic for creating a new API key."""
# Generate a random 16-byte API key
key = secrets.token_hex(16)

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

# Create with schema validation
api_key = ApiKeySchema(
# Create ApiKey instance in the database
api_key_instance = ApiKey.objects.create(
id=uuid.uuid4(),
hashedKey=hashed_key,
lastFour=key[-4:],
userId=current_user,
createdAt=datetime.utcnow(),
updatedAt=datetime.utcnow(),
)

# Return Serialized data from Schema
return ApiKeySchema.model_validate(api_key).model_dump(
exclude={"hashedKey", "userId"}, api_key=key
# Convert the Django model instance to the Pydantic model, excluding fields like hashedKey and userId
validated_data = ApiKeySchema.model_validate(api_key_instance).model_dump(
exclude={"hashedKey", "userId"}
)

# Add the actual API key to the response for initial display to the user
validated_data["api_key"] = key

return validated_data


def delete(id, current_user):
"""DELETE API LOGIC"""
Expand Down
40 changes: 37 additions & 3 deletions backend/src/xfd_django/xfd_api/schema_models/api_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,35 @@
# Third-Party Libraries
from pydantic import BaseModel, ConfigDict

# class ApiKey(BaseModel):
# """Pydantic model for the ApiKey model."""

# id: UUID
# createdAt: datetime
# updatedAt: datetime
# lastUsed: Optional[datetime]
# hashedKey: Optional[str]
# lastFour: Optional[str]
# userId: Optional[UUID]

# @classmethod
# def model_validate(cls, obj):
# # Ensure that we convert the UUIDs to strings when validating
# api_key_data = obj.__dict__.copy()

# # Remove the '_state' field or any other unwanted internal Django fields
# api_key_data.pop("_state", None)
# api_key_data["userId"] = api_key_data.pop("userId_id", None)

# for key, val in api_key_data.items():
# # Convert any UUIDs to strings
# if isinstance(val, UUID):
# api_key_data[key] = str(val)
# return cls(**api_key_data)

# class Config:
# from_attributes = True


class ApiKey(BaseModel):
"""Pydantic model for the ApiKey model."""
Expand All @@ -15,16 +44,21 @@ class ApiKey(BaseModel):
createdAt: datetime
updatedAt: datetime
lastUsed: Optional[datetime]
hashedKey: Optional[str]
hashedKey: Optional[
str
] = None # Make optional to avoid validation error in response
lastFour: Optional[str]
userId: Optional[UUID]
userId: Optional[UUID] = None # Make optional to avoid validation error in response
api_key: Optional[
str
] = None # Add the actual key to the schema for response inclusion

@classmethod
def model_validate(cls, obj):
# Ensure that we convert the UUIDs to strings when validating
api_key_data = obj.__dict__.copy()

# Remove the '_state' field or any other unwanted internal Django fields
# Remove the '_state' field or any other unwanted internal fields
api_key_data.pop("_state", None)
api_key_data["userId"] = api_key_data.pop("userId_id", None)

Expand Down

0 comments on commit d5d5420

Please sign in to comment.