Automated Action 5b55eedd2b Implement User Authentication and Authorization Service
This commit includes:
- User registration and authentication API with JWT
- Password reset functionality
- Role-based access control system
- Database models and migrations with SQLAlchemy and Alembic
- API documentation in README

generated with BackendIM... (backend.im)
2025-05-15 19:46:38 +00:00

116 lines
3.0 KiB
Python

from datetime import datetime, timedelta
import secrets
from typing import Optional
from sqlalchemy.orm import Session
from app.core.config import settings
from app.models.password_reset import PasswordReset
from app.models.user import User
from app.services.user import get_user_by_email, get_user_by_id
from app.utils.security import create_access_token, create_refresh_token, get_password_hash, verify_password
def generate_password_reset_token(db: Session, email: str) -> Optional[str]:
"""Generate a password reset token for a user."""
user = get_user_by_email(db, email=email)
if not user:
return None
# Generate token
token = secrets.token_urlsafe(32)
expires_at = datetime.utcnow() + timedelta(hours=settings.PASSWORD_RESET_TOKEN_EXPIRE_HOURS)
# Create password reset record
password_reset = PasswordReset(
user_id=user.id,
token=token,
expires_at=expires_at,
)
db.add(password_reset)
db.commit()
return token
def verify_password_reset_token(db: Session, token: str) -> Optional[User]:
"""Verify a password reset token."""
password_reset = db.query(PasswordReset).filter(
PasswordReset.token == token,
PasswordReset.is_used == 0
).first()
if not password_reset:
return None
# Check if token is expired
if password_reset.is_expired():
return None
# Get user
user = get_user_by_id(db, user_id=password_reset.user_id)
if not user:
return None
return user
def reset_password(db: Session, token: str, new_password: str) -> Optional[User]:
"""Reset a user's password."""
password_reset = db.query(PasswordReset).filter(
PasswordReset.token == token,
PasswordReset.is_used == 0
).first()
if not password_reset:
return None
# Check if token is expired
if password_reset.is_expired():
return None
# Get user
user = get_user_by_id(db, user_id=password_reset.user_id)
if not user:
return None
# Update password
user.hashed_password = get_password_hash(new_password)
user.updated_at = datetime.utcnow()
# Mark token as used
password_reset.is_used = 1
db.add(user)
db.add(password_reset)
db.commit()
db.refresh(user)
return user
def authenticate_user(db: Session, email: str, password: str) -> Optional[User]:
"""Authenticate a user."""
user = get_user_by_email(db, email=email)
if not user:
return None
if not user.is_active:
return None
if not verify_password(password, user.hashed_password):
return None
return user
def create_tokens_for_user(user_id: int) -> dict:
"""Create JWT tokens for a user."""
access_token = create_access_token(subject=user_id)
refresh_token = create_refresh_token(subject=user_id)
return {
"access_token": access_token,
"refresh_token": refresh_token,
"token_type": "bearer"
}