feat: Add frontend permission option for user creation and enhance validation error handling

This commit introduces a new `give_frontend_permission` field in the user creation request, allowing admins to create users with frontend access. The frontend has been updated to include validation for required fields and improved error messaging for Pydantic validation errors. Additionally, the backend has been modified to handle the creation of users in the auth database if frontend permission is granted. Documentation has been updated to reflect these changes.
This commit is contained in:
tanyar09
2025-11-24 14:21:56 -05:00
parent 100d39c556
commit dbffaef298
4 changed files with 289 additions and 18 deletions
+82 -2
View File
@@ -5,10 +5,11 @@ from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
from sqlalchemy import text
from sqlalchemy.orm import Session
from src.web.api.auth import get_current_user
from src.web.db.session import get_db
from src.web.db.session import get_auth_db, get_db
from src.web.db.models import User
from src.web.schemas.users import (
UserCreateRequest,
@@ -21,6 +22,15 @@ from src.web.utils.password import hash_password
router = APIRouter(prefix="/users", tags=["users"])
def get_auth_db_optional() -> Session | None:
"""Get auth database session if available, otherwise return None."""
try:
return next(get_auth_db())
except ValueError:
# Auth database not configured
return None
def get_current_admin_user(
current_user: Annotated[dict, Depends(get_current_user)],
db: Session = Depends(get_db),
@@ -104,7 +114,11 @@ def create_user(
request: UserCreateRequest,
db: Session = Depends(get_db),
) -> UserResponse:
"""Create a new user - admin only."""
"""Create a new user - admin only.
If give_frontend_permission is True, also creates the user in the auth database
for frontend access.
"""
# Check if username already exists
existing_user = db.query(User).filter(User.username == request.username).first()
if existing_user:
@@ -137,6 +151,72 @@ def create_user(
db.commit()
db.refresh(user)
# If frontend permission is requested, create user in auth database
if request.give_frontend_permission:
auth_db = get_auth_db_optional()
if auth_db is None:
# Auth database not configured - this is okay, just continue
# The backend user was created successfully
pass
else:
try:
# Check if user with same email already exists in auth db
check_result = auth_db.execute(text("""
SELECT id FROM users
WHERE email = :email
"""), {"email": request.email})
existing_auth = check_result.first()
if existing_auth:
# User already exists in auth db, skip creation
# This is not an error - user might have been created separately
pass
else:
# Insert new user in auth database
# Check database dialect for RETURNING support
dialect = auth_db.bind.dialect.name if auth_db.bind else 'postgresql'
supports_returning = dialect == 'postgresql'
# Set has_write_access based on admin status
# Admins get write access by default, regular users don't
has_write_access = request.is_admin
# Use the same password hash
if supports_returning:
auth_db.execute(text("""
INSERT INTO users (email, name, password_hash, is_admin, has_write_access)
VALUES (:email, :name, :password_hash, :is_admin, :has_write_access)
"""), {
"email": request.email,
"name": request.full_name,
"password_hash": password_hash,
"is_admin": request.is_admin,
"has_write_access": has_write_access,
})
auth_db.commit()
else:
# SQLite - insert then select
auth_db.execute(text("""
INSERT INTO users (email, name, password_hash, is_admin, has_write_access)
VALUES (:email, :name, :password_hash, :is_admin, :has_write_access)
"""), {
"email": request.email,
"name": request.full_name,
"password_hash": password_hash,
"is_admin": request.is_admin,
"has_write_access": has_write_access,
})
auth_db.commit()
except Exception as e:
# If auth user creation fails, rollback and log but don't fail the whole request
# The backend user was already created successfully
auth_db.rollback()
# In production, you might want to log this to a proper logging system
import traceback
print(f"Warning: Failed to create auth user: {str(e)}\n{traceback.format_exc()}")
finally:
auth_db.close()
return UserResponse.model_validate(user)
+1
View File
@@ -35,6 +35,7 @@ class UserCreateRequest(BaseModel):
full_name: str = Field(..., min_length=1, max_length=200, description="Full name (required)")
is_active: bool = True
is_admin: bool = False
give_frontend_permission: bool = Field(False, description="Create user in auth database for frontend access")
class UserUpdateRequest(BaseModel):