Remove token revocation logic and unused dependencies
Eliminated the `RevokedToken` model and associated logic for managing token revocation. Removed unused files, related tests, and outdated dependencies in authentication modules. Simplified token decoding, user validation, and dependency injection by streamlining the flow and enhancing maintainability.
This commit is contained in:
@@ -1,66 +0,0 @@
|
||||
from typing import Optional
|
||||
from uuid import UUID
|
||||
from pydantic import BaseModel, EmailStr, Field, field_validator
|
||||
from datetime import datetime
|
||||
from passlib.hash import bcrypt
|
||||
|
||||
|
||||
# Base schema with shared user attributes
|
||||
class UserBase(BaseModel):
|
||||
"""Base schema with common user attributes."""
|
||||
email: EmailStr
|
||||
first_name: str
|
||||
last_name: str
|
||||
|
||||
|
||||
# Schema for creating a new user
|
||||
class UserCreate(UserBase):
|
||||
"""Schema for user registration."""
|
||||
password: str = Field(
|
||||
...,
|
||||
min_length=8,
|
||||
description="Password must be at least 8 characters"
|
||||
)
|
||||
|
||||
@field_validator('password')
|
||||
def password_strength(cls, v):
|
||||
# Add more complex password validation if needed
|
||||
if len(v) < 8:
|
||||
raise ValueError('Password must be at least 8 characters')
|
||||
return v
|
||||
|
||||
def hash_password(self) -> str:
|
||||
"""Hash the password before saving it to the database."""
|
||||
return bcrypt.hash(self.password)
|
||||
|
||||
|
||||
# Schema for updating user details
|
||||
class UserUpdate(BaseModel):
|
||||
"""Schema for updating user information."""
|
||||
email: Optional[EmailStr] = None
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
phone_number: Optional[str] = None
|
||||
is_active: Optional[bool] = None
|
||||
preferences: Optional[dict] = None # Provide preferences support
|
||||
|
||||
|
||||
# Schema for user responses (read-only fields)
|
||||
class UserResponse(UserBase):
|
||||
"""Schema for user responses in API."""
|
||||
id: UUID
|
||||
is_active: bool
|
||||
is_superuser: bool # Include roles or superuser flags if needed
|
||||
preferences: Optional[dict] = None # Include preferences in response
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
orm_mode = True # Enable mapping SQLAlchemy models to this schema
|
||||
|
||||
|
||||
# Schema for user authentication (e.g., login requests)
|
||||
class UserAuth(BaseModel):
|
||||
"""Schema for user authentication."""
|
||||
email: EmailStr
|
||||
password: str
|
||||
126
backend/app/schemas/users.py
Normal file
126
backend/app/schemas/users.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# app/schemas/users.py
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import Optional, Dict, Any
|
||||
from uuid import UUID
|
||||
|
||||
import pydantic
|
||||
from pydantic import BaseModel, EmailStr, field_validator, ConfigDict
|
||||
|
||||
|
||||
class UserBase(BaseModel):
|
||||
email: EmailStr
|
||||
first_name: str
|
||||
last_name: str
|
||||
phone_number: Optional[str] = None
|
||||
|
||||
@field_validator('phone_number')
|
||||
@classmethod
|
||||
def validate_phone_number(cls, v: Optional[str]) -> Optional[str]:
|
||||
if v is None:
|
||||
return v
|
||||
# Simple regex for phone validation
|
||||
if not re.match(r'^\+?[0-9\s\-\(\)]{8,20}$', v):
|
||||
raise ValueError('Invalid phone number format')
|
||||
return v
|
||||
|
||||
|
||||
class UserCreate(UserBase):
|
||||
password: str
|
||||
|
||||
@field_validator('password')
|
||||
@classmethod
|
||||
def password_strength(cls, v: str) -> str:
|
||||
"""Basic password strength validation"""
|
||||
if len(v) < 8:
|
||||
raise ValueError('Password must be at least 8 characters')
|
||||
if not any(char.isdigit() for char in v):
|
||||
raise ValueError('Password must contain at least one digit')
|
||||
if not any(char.isupper() for char in v):
|
||||
raise ValueError('Password must contain at least one uppercase letter')
|
||||
return v
|
||||
|
||||
|
||||
class UserUpdate(BaseModel):
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
phone_number: Optional[str] = None
|
||||
preferences: Optional[Dict[str, Any]] = None
|
||||
|
||||
@field_validator('phone_number')
|
||||
@classmethod
|
||||
def validate_phone_number(cls, v: Optional[str]) -> Optional[str]:
|
||||
if v is None:
|
||||
return v
|
||||
# Simple regex for phone validation
|
||||
if not re.match(r'^\+?[0-9\s\-\(\)]{8,20}$', v):
|
||||
raise ValueError('Invalid phone number format')
|
||||
return v
|
||||
|
||||
|
||||
class UserInDB(UserBase):
|
||||
id: UUID
|
||||
is_active: bool
|
||||
is_superuser: bool
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class UserResponse(UserBase):
|
||||
id: UUID
|
||||
is_active: bool
|
||||
is_superuser: bool
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class Token(BaseModel):
|
||||
access_token: str
|
||||
refresh_token: Optional[str] = None
|
||||
token_type: str = "bearer"
|
||||
|
||||
|
||||
class TokenPayload(BaseModel):
|
||||
sub: str # User ID
|
||||
exp: int # Expiration time
|
||||
iat: Optional[int] = None # Issued at
|
||||
jti: Optional[str] = None # JWT ID
|
||||
is_superuser: Optional[bool] = False
|
||||
first_name: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
type: Optional[str] = None # Token type (access/refresh)
|
||||
|
||||
|
||||
class TokenData(BaseModel):
|
||||
user_id: UUID
|
||||
is_superuser: bool = False
|
||||
|
||||
|
||||
class PasswordReset(BaseModel):
|
||||
token: str
|
||||
new_password: str
|
||||
|
||||
@field_validator('new_password')
|
||||
@classmethod
|
||||
def password_strength(cls, v: str) -> str:
|
||||
"""Basic password strength validation"""
|
||||
if len(v) < 8:
|
||||
raise ValueError('Password must be at least 8 characters')
|
||||
if not any(char.isdigit() for char in v):
|
||||
raise ValueError('Password must contain at least one digit')
|
||||
if not any(char.isupper() for char in v):
|
||||
raise ValueError('Password must contain at least one uppercase letter')
|
||||
return v
|
||||
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
class RefreshTokenRequest(BaseModel):
|
||||
refresh_token: str
|
||||
Reference in New Issue
Block a user