feat(user): add auto-verification option for user creation

This commit is contained in:
Davidson Gomes 2025-05-07 17:33:45 -03:00
parent 93ad731f40
commit 442369505a
3 changed files with 32 additions and 18 deletions

View File

@ -52,7 +52,7 @@ async def register_user(user_data: UserCreate, db: Session = Depends(get_db)):
Raises: Raises:
HTTPException: If there is an error in registration HTTPException: If there is an error in registration
""" """
user, message = create_user(db, user_data, is_admin=False) user, message = create_user(db, user_data, is_admin=False, auto_verify=False)
if not user: if not user:
logger.error(f"Error registering user: {message}") logger.error(f"Error registering user: {message}")
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=message) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=message)

View File

@ -124,7 +124,9 @@ def create_client_with_user(
db.flush() # Get client ID without committing the transaction db.flush() # Get client ID without committing the transaction
# Use client ID to create the associated user # Use client ID to create the associated user
user, message = create_user(db, user_data, is_admin=False, client_id=client.id) user, message = create_user(
db, user_data, is_admin=False, client_id=client.id, auto_verify=True
)
if not user: if not user:
# If there was an error creating the user, rollback # If there was an error creating the user, rollback

View File

@ -20,6 +20,7 @@ def create_user(
user_data: UserCreate, user_data: UserCreate,
is_admin: bool = False, is_admin: bool = False,
client_id: Optional[uuid.UUID] = None, client_id: Optional[uuid.UUID] = None,
auto_verify: bool = False,
) -> Tuple[Optional[User], str]: ) -> Tuple[Optional[User], str]:
""" """
Creates a new user in the system Creates a new user in the system
@ -29,6 +30,7 @@ def create_user(
user_data: User data to be created user_data: User data to be created
is_admin: If the user is an administrator is_admin: If the user is an administrator
client_id: Associated client ID (optional, a new one will be created if not provided) client_id: Associated client ID (optional, a new one will be created if not provided)
auto_verify: If True, user is created with email already verified and active
Returns: Returns:
Tuple[Optional[User], str]: Tuple with the created user (or None in case of error) and status message Tuple[Optional[User], str]: Tuple with the created user (or None in case of error) and status message
@ -42,9 +44,12 @@ def create_user(
) )
return None, "Email already registered" return None, "Email already registered"
# Create verification token # Create verification token if needed
verification_token = generate_token() verification_token = None
token_expiry = datetime.utcnow() + timedelta(hours=24) token_expiry = None
if not auto_verify:
verification_token = generate_token()
token_expiry = datetime.utcnow() + timedelta(hours=24)
# Start transaction # Start transaction
user = None user = None
@ -64,25 +69,32 @@ def create_user(
password_hash=get_password_hash(user_data.password), password_hash=get_password_hash(user_data.password),
client_id=local_client_id, client_id=local_client_id,
is_admin=is_admin, is_admin=is_admin,
is_active=False, # Inactive until email is verified is_active=auto_verify,
email_verified=False, email_verified=auto_verify,
verification_token=verification_token, verification_token=verification_token,
verification_token_expiry=token_expiry, verification_token_expiry=token_expiry,
) )
db.add(user) db.add(user)
db.commit() db.commit()
# Send verification email # Send verification email if not auto-verified
email_sent = send_verification_email(user.email, verification_token) if not auto_verify:
if not email_sent: email_sent = send_verification_email(user.email, verification_token)
logger.error(f"Failed to send verification email to {user.email}") if not email_sent:
# We don't do rollback here, we just log the error logger.error(f"Failed to send verification email to {user.email}")
# We don't do rollback here, we just log the error
logger.info(f"User created successfully: {user.email}") logger.info(f"User created successfully: {user.email}")
return ( return (
user, user,
"User created successfully. Check your email to activate your account.", "User created successfully. Check your email to activate your account.",
) )
else:
logger.info(f"User created and auto-verified: {user.email}")
return (
user,
"User created successfully.",
)
except SQLAlchemyError as e: except SQLAlchemyError as e:
db.rollback() db.rollback()
@ -388,7 +400,7 @@ def create_admin_user(db: Session, user_data: UserCreate) -> Tuple[Optional[User
Returns: Returns:
Tuple[Optional[User], str]: Tuple with the created user (or None in case of error) and status message Tuple[Optional[User], str]: Tuple with the created user (or None in case of error) and status message
""" """
return create_user(db, user_data, is_admin=True) return create_user(db, user_data, is_admin=True, auto_verify=True)
def deactivate_user(db: Session, user_id: uuid.UUID) -> Tuple[bool, str]: def deactivate_user(db: Session, user_id: uuid.UUID) -> Tuple[bool, str]: