新增用户注册功能

This commit is contained in:
Cheng Zhou
2025-12-22 21:19:48 +08:00
parent 03fddba406
commit 6ddf9901a0
33 changed files with 1389 additions and 138 deletions
+70 -23
View File
@@ -1,17 +1,17 @@
import uuid
from typing import Sequence
from sqlalchemy import select, update, delete
from sqlalchemy import delete, func, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.security import hash_password
from app.models.user import User
from app.schemas.user import UserCreate, UserUpdate
from app.models.study_member import StudyMember
from app.models.user import User, UserRole, UserStatus
from app.schemas.user import UserCreate, UserRegisterRequest, UserUpdate
async def get_by_username(db: AsyncSession, username: str) -> User | None:
result = await db.execute(select(User).where(User.username == username))
async def get_by_email(db: AsyncSession, email: str) -> User | None:
result = await db.execute(select(User).where(User.email == email))
return result.scalar_one_or_none()
@@ -20,12 +20,17 @@ async def get_by_id(db: AsyncSession, user_id: uuid.UUID) -> User | None:
return result.scalar_one_or_none()
async def create_user(db: AsyncSession, user_in: UserCreate) -> User:
async def create_user(
db: AsyncSession, user_in: UserCreate, *, status: UserStatus | None = UserStatus.ACTIVE
) -> User:
status_value = status or UserStatus(user_in.status)
user = User(
username=user_in.username,
hashed_password=hash_password(user_in.password),
role=user_in.role,
is_active=True,
email=user_in.email,
password_hash=hash_password(user_in.password),
full_name=user_in.full_name,
role=UserRole(user_in.role),
department=user_in.department,
status=status_value,
)
db.add(user)
await db.commit()
@@ -33,21 +38,29 @@ async def create_user(db: AsyncSession, user_in: UserCreate) -> User:
return user
async def create_pending_user(db: AsyncSession, user_in: UserRegisterRequest) -> User:
return await create_user(db, UserCreate(**user_in.model_dump()), status=UserStatus.PENDING)
async def update_user(db: AsyncSession, user: User, user_in: UserUpdate) -> User:
update_data = {}
if user_in.role is not None:
update_data["role"] = user_in.role
update_data["role"] = UserRole(user_in.role)
if user_in.status is not None:
update_data["status"] = UserStatus(user_in.status)
if user_in.is_active is not None:
update_data["is_active"] = user_in.is_active
update_data["status"] = UserStatus.ACTIVE if user_in.is_active else UserStatus.DISABLED
if user_in.avatar_url is not None:
update_data["avatar_url"] = user_in.avatar_url
if user_in.password:
update_data["hashed_password"] = hash_password(user_in.password)
update_data["password_hash"] = hash_password(user_in.password)
if user_in.full_name is not None:
update_data["full_name"] = user_in.full_name
if user_in.department is not None:
update_data["department"] = user_in.department
if update_data:
await db.execute(
update(User)
.where(User.id == user.id)
.values(**update_data)
)
await db.execute(update(User).where(User.id == user.id).values(**update_data))
await db.commit()
await db.refresh(user)
return user
@@ -58,16 +71,28 @@ async def list_users(db: AsyncSession, skip: int = 0, limit: int = 100) -> Seque
return result.scalars().all()
async def list_users_by_status(
db: AsyncSession, status: UserStatus | None = None, skip: int = 0, limit: int = 100
) -> Sequence[User]:
stmt = select(User).offset(skip).limit(limit)
if status:
stmt = stmt.where(User.status == status)
result = await db.execute(stmt.order_by(User.created_at.desc()))
return result.scalars().all()
async def ensure_admin_exists(db: AsyncSession, *, default_password: str = "admin123") -> None:
result = await db.execute(select(User).where(User.username == "admin"))
result = await db.execute(select(User).where(User.role == UserRole.ADMIN))
admin = result.scalar_one_or_none()
if admin:
return
new_admin = User(
username="admin",
hashed_password=hash_password(default_password),
role="ADMIN",
is_active=True,
email="admin@ctms.local",
password_hash=hash_password(default_password),
full_name="System Admin",
role=UserRole.ADMIN,
department="SYSTEM",
status=UserStatus.ACTIVE,
)
db.add(new_admin)
await db.commit()
@@ -85,3 +110,25 @@ async def delete_user(db: AsyncSession, user: User) -> None:
await db.execute(delete(StudyMember).where(StudyMember.user_id == user.id))
await db.delete(user)
await db.commit()
async def approve_user(db: AsyncSession, user: User, admin_id: uuid.UUID) -> User:
await db.execute(
update(User)
.where(User.id == user.id)
.values(status=UserStatus.ACTIVE, approved_by=admin_id, approved_at=func.now())
)
await db.commit()
await db.refresh(user)
return user
async def reject_user(db: AsyncSession, user: User, admin_id: uuid.UUID) -> User:
await db.execute(
update(User)
.where(User.id == user.id)
.values(status=UserStatus.REJECTED, approved_by=admin_id, approved_at=func.now())
)
await db.commit()
await db.refresh(user)
return user