Files
calminer/schemas/auth.py
zwitschi 3601c2e422 feat: Implement user and role management with repositories
- Added RoleRepository and UserRepository for managing roles and users.
- Implemented methods for creating, retrieving, and assigning roles to users.
- Introduced functions to ensure default roles and an admin user exist in the system.
- Updated UnitOfWork to include user and role repositories.
- Created new security module for password hashing and JWT token management.
- Added tests for authentication flows, including registration, login, and password reset.
- Enhanced HTML templates for user registration, login, and password management with error handling.
- Added a logo image to the static assets.
2025-11-09 21:48:35 +01:00

68 lines
2.2 KiB
Python

from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validator
class FormModel(BaseModel):
"""Base Pydantic model for HTML form submissions."""
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
class RegistrationForm(FormModel):
username: str = Field(min_length=3, max_length=128)
email: str = Field(min_length=5, max_length=255)
password: str = Field(min_length=8, max_length=256)
confirm_password: str
@field_validator("email")
@classmethod
def validate_email(cls, value: str) -> str:
if "@" not in value or value.startswith("@") or value.endswith("@"):
raise ValueError("Invalid email address.")
local, domain = value.split("@", 1)
if not local or "." not in domain:
raise ValueError("Invalid email address.")
return value.lower()
@field_validator("confirm_password")
@classmethod
def passwords_match(cls, value: str, info: ValidationInfo) -> str:
password = info.data.get("password")
if password != value:
raise ValueError("Passwords do not match.")
return value
class LoginForm(FormModel):
username: str = Field(min_length=1, max_length=255)
password: str = Field(min_length=1, max_length=256)
class PasswordResetRequestForm(FormModel):
email: str = Field(min_length=5, max_length=255)
@field_validator("email")
@classmethod
def validate_email(cls, value: str) -> str:
if "@" not in value or value.startswith("@") or value.endswith("@"):
raise ValueError("Invalid email address.")
local, domain = value.split("@", 1)
if not local or "." not in domain:
raise ValueError("Invalid email address.")
return value.lower()
class PasswordResetForm(FormModel):
token: str = Field(min_length=1)
password: str = Field(min_length=8, max_length=256)
confirm_password: str
@field_validator("confirm_password")
@classmethod
def reset_passwords_match(cls, value: str, info: ValidationInfo) -> str:
password = info.data.get("password")
if password != value:
raise ValueError("Passwords do not match.")
return value