初始化
This commit is contained in:
154
service/user_service.py
Normal file
154
service/user_service.py
Normal file
@ -0,0 +1,154 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from mysql.connector import Error as MySQLError
|
||||
|
||||
from ds.db import db
|
||||
from schema.user_schema import UserRegisterRequest, UserLoginRequest, UserResponse
|
||||
from schema.response_schema import APIResponse
|
||||
from middle.auth_middleware import (
|
||||
get_password_hash,
|
||||
verify_password,
|
||||
create_access_token,
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES,
|
||||
get_current_user
|
||||
)
|
||||
|
||||
# 创建用户接口路由(前缀 /users、标签用于 Swagger 分类)
|
||||
router = APIRouter(
|
||||
prefix="/users",
|
||||
tags=["用户管理"]
|
||||
)
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# 1. 用户注册接口
|
||||
# ------------------------------
|
||||
@router.post("/register", response_model=APIResponse, summary="用户注册")
|
||||
async def user_register(request: UserRegisterRequest):
|
||||
"""
|
||||
用户注册:
|
||||
- 校验用户名是否已存在
|
||||
- 加密密码后插入数据库
|
||||
- 返回注册成功信息
|
||||
"""
|
||||
conn = None
|
||||
cursor = None
|
||||
try:
|
||||
conn = db.get_connection()
|
||||
cursor = conn.cursor(dictionary=True)
|
||||
|
||||
# 1. 检查用户名是否已存在(唯一索引)
|
||||
check_query = "SELECT username FROM users WHERE username = %s"
|
||||
cursor.execute(check_query, (request.username,))
|
||||
existing_user = cursor.fetchone()
|
||||
if existing_user:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"用户名 '{request.username}' 已存在、请更换其他用户名"
|
||||
)
|
||||
|
||||
# 2. 加密密码
|
||||
hashed_password = get_password_hash(request.password)
|
||||
|
||||
# 3. 插入新用户到数据库
|
||||
insert_query = """
|
||||
INSERT INTO users (username, password)
|
||||
VALUES (%s, %s)
|
||||
"""
|
||||
cursor.execute(insert_query, (request.username, hashed_password))
|
||||
conn.commit() # 提交事务
|
||||
|
||||
# 4. 返回注册成功响应
|
||||
return APIResponse(
|
||||
code=201, # 201 表示资源创建成功
|
||||
message=f"用户 '{request.username}' 注册成功",
|
||||
data=None
|
||||
)
|
||||
except MySQLError as e:
|
||||
conn.rollback() # 数据库错误时回滚事务
|
||||
raise Exception(f"注册失败:{str(e)}") from e
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# 2. 用户登录接口
|
||||
# ------------------------------
|
||||
@router.post("/login", response_model=APIResponse, summary="用户登录(获取 Token)")
|
||||
async def user_login(request: UserLoginRequest):
|
||||
"""
|
||||
用户登录:
|
||||
- 校验用户名是否存在
|
||||
- 校验密码是否正确
|
||||
- 生成 JWT Token 并返回
|
||||
"""
|
||||
conn = None
|
||||
cursor = None
|
||||
try:
|
||||
conn = db.get_connection()
|
||||
cursor = conn.cursor(dictionary=True)
|
||||
|
||||
# 修复:SQL查询添加 created_at 和 updated_at 字段
|
||||
query = """
|
||||
SELECT id, username, password, created_at, updated_at
|
||||
FROM users
|
||||
WHERE username = %s
|
||||
"""
|
||||
cursor.execute(query, (request.username,))
|
||||
user = cursor.fetchone()
|
||||
|
||||
# 2. 校验用户名和密码
|
||||
if not user or not verify_password(request.password, user["password"]):
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="用户名或密码错误",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# 3. 生成 Token(过期时间从配置读取)
|
||||
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
access_token = create_access_token(
|
||||
data={"sub": user["username"]},
|
||||
expires_delta=access_token_expires
|
||||
)
|
||||
|
||||
# 4. 返回 Token 和用户基本信息
|
||||
return APIResponse(
|
||||
code=200,
|
||||
message="登录成功",
|
||||
data={
|
||||
"access_token": access_token,
|
||||
"token_type": "bearer",
|
||||
"user": UserResponse(
|
||||
id=user["id"],
|
||||
username=user["username"],
|
||||
created_at=user.get("created_at"),
|
||||
updated_at=user.get("updated_at")
|
||||
)
|
||||
}
|
||||
)
|
||||
except MySQLError as e:
|
||||
raise Exception(f"登录失败:{str(e)}") from e
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# 3. 获取当前登录用户信息(需认证)
|
||||
# ------------------------------
|
||||
@router.get("/me", response_model=APIResponse, summary="获取当前用户信息")
|
||||
async def get_current_user_info(
|
||||
current_user: UserResponse = Depends(get_current_user) # 依赖认证中间件
|
||||
):
|
||||
"""
|
||||
获取当前登录用户信息:
|
||||
- 需在请求头携带 Token(格式:Bearer <token>)
|
||||
- 认证通过后返回用户信息
|
||||
"""
|
||||
return APIResponse(
|
||||
code=200,
|
||||
message="获取用户信息成功",
|
||||
data=current_user
|
||||
)
|
||||
|
Reference in New Issue
Block a user