modify: auth 插件

This commit is contained in:
2026-07-23 17:45:44 +08:00
parent 95ef842d92
commit 2b7b8ee08c
21 changed files with 753 additions and 43 deletions
+8
View File
@@ -0,0 +1,8 @@
from .login import login
from .register import register
from .me import me
from .update_profile import update_profile
from .change_password import change_password
__all__ = ["login", "register", "me", "update_profile", "change_password"]
+81
View File
@@ -0,0 +1,81 @@
import time
from datetime import datetime
from sqlalchemy import select
from chongming_worker import rpc_method
from chongming_password import hash_password, verify_password
from ..models.pydantic import (
ChangePasswordPostRequest,
ChangePasswordPostResponse
)
from ..models.auth import Users
@rpc_method(
subject="auth.change_password",
method="POST",
summary="修改密码",
response_model=ChangePasswordPostResponse,
)
async def change_password(change_password_post_request: ChangePasswordPostRequest) -> ChangePasswordPostResponse:
from ..global_var import db
if db is None:
raise RuntimeError("Database not initialized")
user_id = change_password_post_request.user_id
old_password = change_password_post_request.old_password
new_password = change_password_post_request.new_password
if not old_password:
return ChangePasswordPostResponse(
result="fail",
message="旧密码不能为空",
timestamp=time.time()
)
if not new_password:
return ChangePasswordPostResponse(
result="fail",
message="新密码不能为空",
timestamp=time.time()
)
if old_password == new_password:
return ChangePasswordPostResponse(
result="fail",
message="新密码不能与旧密码相同",
timestamp=time.time()
)
async with db.get_session() as session:
stmt = select(Users).filter_by(id=user_id)
result = await session.execute(stmt)
user: Users | None = result.scalar_one_or_none()
if user is None:
return ChangePasswordPostResponse(
result="fail",
message="用户不存在",
timestamp=time.time()
)
# 验证旧密码
if not verify_password(old_password, user.hashed_password):
return ChangePasswordPostResponse(
result="fail",
message="旧密码错误",
timestamp=time.time()
)
# 更新密码
user.hashed_password = hash_password(new_password)
user.updated_at = datetime.now()
session.add(user)
await session.commit()
return ChangePasswordPostResponse(
result="success",
message="密码修改成功",
timestamp=time.time()
)
+85
View File
@@ -0,0 +1,85 @@
import time
from datetime import datetime
import json
from sqlalchemy import select
from chongming_worker import rpc_method
from chongming_password import verify_password
from ..models.pydantic import (
LoginPostRequest,
LoginPostResponse
)
from ..models.auth import Users
@rpc_method(
subject="auth.login",
method="POST",
summary="登录",
response_model=LoginPostResponse,
)
async def login(login_post_request: LoginPostRequest) -> LoginPostResponse:
from ..global_var import jwt, db
if db is None:
raise RuntimeError("Database not initialized")
async with db.get_session() as session:
statement = select(Users).filter_by(
username=login_post_request.username,
)
result = await session.execute(statement)
user: Users | None = result.scalar_one_or_none()
if user is None:
return LoginPostResponse(
result="fail",
message="用户名错误",
token="",
timestamp=time.time()
)
if not verify_password(login_post_request.password, user.hashed_password):
return LoginPostResponse(
result="fail",
message="密码错误",
token="",
timestamp=time.time()
)
if not user.is_active:
return LoginPostResponse(
result="fail",
message="用户已经注销或被禁用",
token="",
timestamp=time.time()
)
user.last_login_at = datetime.now()
payload = {
"sub": user.id,
"username": user.username,
"email": user.email,
"full_name": user.full_name,
"avatar_url": user.avatar_url,
"phone": user.phone,
"is_verified": user.is_verified,
"is_superuser": user.is_superuser,
"created_at": user.created_at.isoformat(),
"updated_at": user.updated_at.isoformat(),
"last_login_at": user.last_login_at.isoformat()
}
token = jwt.encode(
json.dumps(payload),
expires_in_seconds=10800 # 3小时有效期
)
return LoginPostResponse(
result="success",
message="登录成功",
token=token,
timestamp=time.time()
)
+56
View File
@@ -0,0 +1,56 @@
import time
from sqlalchemy import select
from chongming_worker import rpc_method
from ..models.pydantic import (
MeGetRequest,
MeGetResponse
)
from ..models.auth import Users
@rpc_method(
subject="auth.me",
method="GET",
summary="获取当前用户信息",
response_model=MeGetResponse,
)
async def me(me_get_request: MeGetRequest) -> MeGetResponse:
from ..global_var import db
if db is None:
raise RuntimeError("Database not initialized")
async with db.get_session() as session:
stmt = select(Users).filter_by(id=me_get_request.user_id)
result = await session.execute(stmt)
user: Users | None = result.scalar_one_or_none()
if user is None:
return MeGetResponse(
result="fail",
id="",
username="",
email="",
is_active=False,
is_verified=False,
is_superuser=False,
)
return MeGetResponse(
result="success",
id=user.id,
username=user.username,
email=user.email,
full_name=user.full_name,
avatar_url=user.avatar_url,
phone=user.phone,
is_active=user.is_active,
is_verified=user.is_verified,
is_superuser=user.is_superuser,
created_at=user.created_at.isoformat() if user.created_at else None,
updated_at=user.updated_at.isoformat() if user.updated_at else None,
last_login_at=user.last_login_at.isoformat() if user.last_login_at else None,
)
+93
View File
@@ -0,0 +1,93 @@
import time
from datetime import datetime
from sqlalchemy import select
from chongming_worker import rpc_method
from chongming_password import hash_password
from ..models.pydantic import (
RegisterPostRequest,
RegisterPostResponse
)
from ..models.auth import Users
@rpc_method(
subject="auth.register",
method="POST",
summary="用户注册",
response_model=RegisterPostResponse,
)
async def register(register_post_request: RegisterPostRequest) -> RegisterPostResponse:
from ..global_var import db
if db is None:
raise RuntimeError("Database not initialized")
username = register_post_request.username.strip()
email = register_post_request.email.strip()
full_name = register_post_request.full_name.strip() or None
phone = register_post_request.phone.strip() or None
# 校验必填字段
if not username:
return RegisterPostResponse(
result="fail",
message="用户名不能为空",
timestamp=time.time()
)
if not email:
return RegisterPostResponse(
result="fail",
message="邮箱不能为空",
timestamp=time.time()
)
if not register_post_request.password:
return RegisterPostResponse(
result="fail",
message="密码不能为空",
timestamp=time.time()
)
async with db.get_session() as session:
# 检查用户名是否已存在
stmt = select(Users).filter_by(username=username)
result = await session.execute(stmt)
if result.scalar_one_or_none() is not None:
return RegisterPostResponse(
result="fail",
message="用户名已存在",
timestamp=time.time()
)
# 检查邮箱是否已存在
stmt = select(Users).filter_by(email=email)
result = await session.execute(stmt)
if result.scalar_one_or_none() is not None:
return RegisterPostResponse(
result="fail",
message="邮箱已被注册",
timestamp=time.time()
)
# 创建新用户
user = Users(
username=username,
hashed_password=hash_password(register_post_request.password),
email=email,
full_name=full_name,
phone=phone,
created_at=datetime.now(),
updated_at=datetime.now(),
)
session.add(user)
await session.commit()
await session.refresh(user)
return RegisterPostResponse(
result="success",
message="注册成功",
user_id=user.id,
timestamp=time.time()
)
+74
View File
@@ -0,0 +1,74 @@
import time
from datetime import datetime
from sqlalchemy import select
from chongming_worker import rpc_method
from ..models.pydantic import (
UpdateProfilePostRequest,
UpdateProfilePostResponse
)
from ..models.auth import Users
@rpc_method(
subject="auth.update_profile",
method="POST",
summary="更新用户资料",
response_model=UpdateProfilePostResponse,
)
async def update_profile(update_profile_post_request: UpdateProfilePostRequest) -> UpdateProfilePostResponse:
from ..global_var import db
if db is None:
raise RuntimeError("Database not initialized")
user_id = update_profile_post_request.user_id
async with db.get_session() as session:
stmt = select(Users).filter_by(id=user_id)
result = await session.execute(stmt)
user: Users | None = result.scalar_one_or_none()
if user is None:
return UpdateProfilePostResponse(
result="fail",
message="用户不存在",
timestamp=time.time()
)
# 更新字段(只更新非空值)
full_name = update_profile_post_request.full_name.strip()
email = update_profile_post_request.email.strip()
avatar_url = update_profile_post_request.avatar_url.strip()
phone = update_profile_post_request.phone.strip()
if full_name:
user.full_name = full_name
if email:
# 检查邮箱是否被其他用户占用
if email != user.email:
check_stmt = select(Users).filter_by(email=email)
check_result = await session.execute(check_stmt)
if check_result.scalar_one_or_none() is not None:
return UpdateProfilePostResponse(
result="fail",
message="邮箱已被其他用户使用",
timestamp=time.time()
)
user.email = email
if avatar_url:
user.avatar_url = avatar_url
if phone:
user.phone = phone
user.updated_at = datetime.now()
session.add(user)
await session.commit()
return UpdateProfilePostResponse(
result="success",
message="资料更新成功",
timestamp=time.time()
)