auth service completed and tested

This commit is contained in:
2025-01-14 19:16:24 +03:00
parent 08b1815156
commit 486fadbfb3
33 changed files with 1325 additions and 248 deletions

View File

@@ -11,7 +11,7 @@ from ApiLibrary import system_arrow
class PyObjectId(ObjectId):
"""Custom type for handling MongoDB ObjectId in Pydantic models."""
@classmethod
def __get_pydantic_core_schema__(
cls,
@@ -21,17 +21,21 @@ class PyObjectId(ObjectId):
"""Define the core schema for PyObjectId."""
return core_schema.json_or_python_schema(
json_schema=core_schema.str_schema(),
python_schema=core_schema.union_schema([
core_schema.is_instance_schema(ObjectId),
core_schema.chain_schema([
core_schema.str_schema(),
core_schema.no_info_plain_validator_function(cls.validate),
]),
]),
python_schema=core_schema.union_schema(
[
core_schema.is_instance_schema(ObjectId),
core_schema.chain_schema(
[
core_schema.str_schema(),
core_schema.no_info_plain_validator_function(cls.validate),
]
),
]
),
serialization=core_schema.plain_serializer_function_ser_schema(
lambda x: str(x),
return_schema=core_schema.str_schema(),
when_used='json',
when_used="json",
),
)
@@ -54,14 +58,14 @@ class PyObjectId(ObjectId):
class MongoBaseModel(BaseModel):
"""Base model for all MongoDB documents."""
model_config = ConfigDict(
arbitrary_types_allowed=True,
json_encoders={ObjectId: str},
populate_by_name=True,
from_attributes=True,
validate_assignment=True,
extra='allow'
extra="allow",
)
# Optional _id field that will be ignored in create operations
@@ -69,11 +73,11 @@ class MongoBaseModel(BaseModel):
def get_extra(self, field_name: str, default: Any = None) -> Any:
"""Safely get extra field value.
Args:
field_name: Name of the extra field to retrieve
default: Default value to return if field doesn't exist
Returns:
Value of the extra field if it exists, otherwise the default value
"""
@@ -81,7 +85,7 @@ class MongoBaseModel(BaseModel):
def as_dict(self) -> Dict[str, Any]:
"""Convert model to dictionary including all fields and extra fields.
Returns:
Dict containing all model fields and extra fields with proper type conversion
"""
@@ -94,18 +98,18 @@ class MongoDocument(MongoBaseModel):
created_at: float = Field(default_factory=lambda: system_arrow.now().timestamp())
updated_at: float = Field(default_factory=lambda: system_arrow.now().timestamp())
@model_validator(mode='before')
@model_validator(mode="before")
@classmethod
def prevent_protected_fields(cls, data: Any) -> Any:
"""Prevent user from setting protected fields like _id and timestamps."""
if isinstance(data, dict):
# Remove protected fields from input
data.pop('_id', None)
data.pop('created_at', None)
data.pop('updated_at', None)
data.pop("_id", None)
data.pop("created_at", None)
data.pop("updated_at", None)
# Set timestamps
data['created_at'] = system_arrow.now().timestamp()
data['updated_at'] = system_arrow.now().timestamp()
data["created_at"] = system_arrow.now().timestamp()
data["updated_at"] = system_arrow.now().timestamp()
return data

View File

@@ -7,7 +7,7 @@ including domain history and access details.
from datetime import datetime
from typing import Any, Dict, List, Optional
from pydantic import Field, model_validator
from pydantic import BaseModel, Field, ConfigDict, model_validator
from ApiLibrary import system_arrow
from Services.MongoDb.Models.action_models.base import MongoBaseModel, MongoDocument
@@ -15,40 +15,38 @@ from Services.MongoDb.Models.action_models.base import MongoBaseModel, MongoDocu
class DomainData(MongoBaseModel):
"""Model for domain data.
Attributes:
user_uu_id: Unique identifier of the user
main_domain: Primary domain
other_domains_list: List of additional domains
extra_data: Additional domain-related data
"""
user_uu_id: str = Field(..., description="User's unique identifier")
main_domain: str = Field(..., description="Primary domain")
other_domains_list: List[str] = Field(
default_factory=list,
description="List of additional domains"
default_factory=list, description="List of additional domains"
)
extra_data: Optional[Dict[str, Any]] = Field(
default_factory=dict,
alias="extraData",
description="Additional domain-related data"
description="Additional domain-related data",
)
class Config:
from_attributes = True
populate_by_name = True
validate_assignment = True
model_config = ConfigDict(
from_attributes=True, populate_by_name=True, validate_assignment=True
)
class DomainDocument(MongoDocument):
"""Model for domain-related documents."""
data: DomainData = Field(..., description="Domain data")
def update_main_domain(self, new_domain: str) -> None:
"""Update the main domain and move current to history.
Args:
new_domain: New main domain to set
"""
@@ -60,19 +58,19 @@ class DomainDocument(MongoDocument):
class DomainDocumentCreate(MongoDocument):
"""Model for creating new domain documents."""
data: DomainData = Field(..., description="Initial domain data")
class Config:
from_attributes = True
populate_by_name = True
validate_assignment = True
model_config = ConfigDict(
from_attributes=True, populate_by_name=True, validate_assignment=True
)
class DomainDocumentUpdate(MongoDocument):
"""Model for updating existing domain documents."""
data: DomainData = Field(..., description="Updated domain data")
class Config:
from_attributes = True
populate_by_name = True
validate_assignment = True
model_config = ConfigDict(
from_attributes=True, populate_by_name=True, validate_assignment=True
)

View File

@@ -15,7 +15,7 @@ from Services.MongoDb.Models.action_models.base import MongoBaseModel, MongoDocu
class PasswordHistoryDetail(MongoBaseModel):
"""Model for password history details."""
timestamp: datetime
ip_address: Optional[str] = Field(None, alias="ipAddress")
user_agent: Optional[str] = Field(None, alias="userAgent")
@@ -24,27 +24,26 @@ class PasswordHistoryDetail(MongoBaseModel):
class PasswordHistoryData(MongoBaseModel):
"""Model for password history data."""
password_history: List[str] = Field([], alias="passwordHistory")
access_history_detail: Dict[str, PasswordHistoryDetail] = Field(
default_factory=dict,
alias="accessHistoryDetail"
default_factory=dict, alias="accessHistoryDetail"
)
class PasswordDocument(MongoDocument):
"""Model for password-related documents."""
data: PasswordHistoryData
class PasswordDocumentCreate(MongoBaseModel):
"""Model for creating new password documents."""
data: PasswordHistoryData = Field(..., description="Initial password data")
class PasswordDocumentUpdate(MongoBaseModel):
"""Model for updating existing password documents."""
data: PasswordHistoryData