🔀 chore(api_key): update import and export names in __init__.py for better clarity and consistency

🔀 chore(api_key): add UnmaskedApiKeyRead model to represent an unmasked API key

🔀 chore(api_key): add user relationship to ApiKey model for easier access to associated user

🔀 chore(api_key): add user_id field to ApiKeyBase and ApiKeyCreate models for easier user association

🔀 chore(api_key): add mask_api_key validator to ApiKeyRead model to mask the API key for security reasons
This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-08-25 12:03:51 -03:00
commit 82fbeace06
2 changed files with 26 additions and 6 deletions

View file

@ -1,3 +1,3 @@
from .api_key import ApiKey, ApiKeyCreate, ApiKeyRead from .api_key import ApiKey, ApiKeyCreate, UnmaskedApiKeyRead, ApiKeyRead
__all__ = ["ApiKey", "ApiKeyCreate", "ApiKeyRead"] __all__ = ["ApiKey", "ApiKeyCreate", "UnmaskedApiKeyRead", "ApiKeyRead"]

View file

@ -1,24 +1,44 @@
from sqlmodel import Field from pydantic import validator
from sqlmodel import Field, Relationship
from uuid import UUID, uuid4 from uuid import UUID, uuid4
from typing import Optional from typing import Optional, TYPE_CHECKING
from datetime import datetime from datetime import datetime
from langflow.services.database.models.base import SQLModelSerializable from langflow.services.database.models.base import SQLModelSerializable
if TYPE_CHECKING:
from langflow.services.database.models.user import User
class ApiKeyBase(SQLModelSerializable): class ApiKeyBase(SQLModelSerializable):
api_key: str = Field(index=True, unique=True) api_key: str = Field(index=True, unique=True)
name: Optional[str] = Field(index=True) name: Optional[str] = Field(index=True)
create_at: datetime = Field(default_factory=datetime.utcnow) created_at: datetime = Field(default_factory=datetime.utcnow)
last_used_at: Optional[datetime] = Field(default=None) last_used_at: Optional[datetime] = Field(default=None)
user_id: UUID = Field()
class ApiKey(ApiKeyBase, table=True): class ApiKey(ApiKeyBase, table=True):
id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True) id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True)
# User relationship
user_id: UUID = Field(index=True, foreign_key="user.id")
user: "User" = Relationship(back_populates="api_keys")
class ApiKeyCreate(ApiKeyBase): class ApiKeyCreate(ApiKeyBase):
pass api_key: Optional[str] = None
user_id: Optional[UUID] = None
class UnmaskedApiKeyRead(ApiKeyBase):
id: UUID
class ApiKeyRead(ApiKeyBase): class ApiKeyRead(ApiKeyBase):
id: UUID id: UUID
api_key: Optional[str] = None
user_id: Optional[UUID] = None
@validator("api_key", always=True)
def mask_api_key(cls, v):
# This validator will always run, and will mask the API key
return f"{'*' * 8}{v[-4:]}"