修改了API接口定义
parent
91aeeca9c8
commit
a243ee7e39
|
|
@ -1,8 +1,8 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from app.core.auth import get_current_admin_user
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.core.auth import get_current_admin_user, get_current_user
|
||||
from app.core.config import LLM_CONFIG, DEFAULT_RESET_PASSWORD, MAX_FILE_SIZE, MAX_IMAGE_SIZE
|
||||
from app.core.response import create_api_response
|
||||
from pydantic import BaseModel
|
||||
import os
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
|
@ -18,14 +18,6 @@ class SystemConfigModel(BaseModel):
|
|||
MAX_FILE_SIZE: int # 字节为单位
|
||||
MAX_IMAGE_SIZE: int # 字节为单位
|
||||
|
||||
class SystemConfigResponse(BaseModel):
|
||||
model_name: str
|
||||
system_prompt: str
|
||||
DEFAULT_RESET_PASSWORD: str
|
||||
MAX_FILE_SIZE: int
|
||||
MAX_IMAGE_SIZE: int
|
||||
message: str = ""
|
||||
|
||||
def load_config_from_file():
|
||||
"""从文件加载配置,如果文件不存在则返回默认配置"""
|
||||
try:
|
||||
|
|
@ -47,9 +39,7 @@ def load_config_from_file():
|
|||
def save_config_to_file(config_data):
|
||||
"""将配置保存到文件"""
|
||||
try:
|
||||
# 确保配置目录存在
|
||||
CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(config_data, f, ensure_ascii=False, indent=2)
|
||||
return True
|
||||
|
|
@ -57,28 +47,26 @@ def save_config_to_file(config_data):
|
|||
print(f"保存配置文件失败: {e}")
|
||||
return False
|
||||
|
||||
@router.get("/admin/system-config", response_model=SystemConfigResponse)
|
||||
async def get_system_config(current_user=Depends(get_current_admin_user)):
|
||||
@router.get("/admin/system-config")
|
||||
async def get_system_config(current_user=Depends(get_current_user)):
|
||||
"""
|
||||
获取系统配置
|
||||
只有管理员才能访问
|
||||
普通用户也可以获取
|
||||
"""
|
||||
try:
|
||||
# 优先从文件加载配置,然后从内存配置补充
|
||||
config = load_config_from_file()
|
||||
|
||||
return SystemConfigResponse(
|
||||
model_name=config.get('model_name', LLM_CONFIG['model_name']),
|
||||
system_prompt=config.get('system_prompt', LLM_CONFIG['system_prompt']),
|
||||
DEFAULT_RESET_PASSWORD=config.get('DEFAULT_RESET_PASSWORD', DEFAULT_RESET_PASSWORD),
|
||||
MAX_FILE_SIZE=config.get('MAX_FILE_SIZE', MAX_FILE_SIZE),
|
||||
MAX_IMAGE_SIZE=config.get('MAX_IMAGE_SIZE', MAX_IMAGE_SIZE),
|
||||
message="配置获取成功"
|
||||
)
|
||||
response_data = {
|
||||
'model_name': config.get('model_name', LLM_CONFIG['model_name']),
|
||||
'system_prompt': config.get('system_prompt', LLM_CONFIG['system_prompt']),
|
||||
'DEFAULT_RESET_PASSWORD': config.get('DEFAULT_RESET_PASSWORD', DEFAULT_RESET_PASSWORD),
|
||||
'MAX_FILE_SIZE': config.get('MAX_FILE_SIZE', MAX_FILE_SIZE),
|
||||
'MAX_IMAGE_SIZE': config.get('MAX_IMAGE_SIZE', MAX_IMAGE_SIZE),
|
||||
}
|
||||
return create_api_response(code="200", message="配置获取成功", data=response_data)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"获取配置失败: {str(e)}")
|
||||
return create_api_response(code="500", message=f"获取配置失败: {str(e)}")
|
||||
|
||||
@router.put("/admin/system-config", response_model=SystemConfigResponse)
|
||||
@router.put("/admin/system-config")
|
||||
async def update_system_config(
|
||||
config: SystemConfigModel,
|
||||
current_user=Depends(get_current_admin_user)
|
||||
|
|
@ -88,7 +76,6 @@ async def update_system_config(
|
|||
只有管理员才能访问
|
||||
"""
|
||||
try:
|
||||
# 准备要保存的配置数据
|
||||
config_data = {
|
||||
'model_name': config.model_name,
|
||||
'system_prompt': config.system_prompt,
|
||||
|
|
@ -97,49 +84,36 @@ async def update_system_config(
|
|||
'MAX_IMAGE_SIZE': config.MAX_IMAGE_SIZE
|
||||
}
|
||||
|
||||
# 保存到文件
|
||||
if not save_config_to_file(config_data):
|
||||
raise HTTPException(status_code=500, detail="配置保存到文件失败")
|
||||
return create_api_response(code="500", message="配置保存到文件失败")
|
||||
|
||||
# 更新运行时配置
|
||||
LLM_CONFIG['model_name'] = config.model_name
|
||||
LLM_CONFIG['system_prompt'] = config.system_prompt
|
||||
|
||||
# 更新模块级别的配置
|
||||
import app.core.config as config_module
|
||||
config_module.DEFAULT_RESET_PASSWORD = config.DEFAULT_RESET_PASSWORD
|
||||
config_module.MAX_FILE_SIZE = config.MAX_FILE_SIZE
|
||||
config_module.MAX_IMAGE_SIZE = config.MAX_IMAGE_SIZE
|
||||
|
||||
return SystemConfigResponse(
|
||||
model_name=config.model_name,
|
||||
system_prompt=config.system_prompt,
|
||||
DEFAULT_RESET_PASSWORD=config.DEFAULT_RESET_PASSWORD,
|
||||
MAX_FILE_SIZE=config.MAX_FILE_SIZE,
|
||||
MAX_IMAGE_SIZE=config.MAX_IMAGE_SIZE,
|
||||
message="配置更新成功,重启服务后完全生效"
|
||||
return create_api_response(
|
||||
code="200",
|
||||
message="配置更新成功,重启服务后完全生效",
|
||||
data=config_data
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"更新配置失败: {str(e)}")
|
||||
return create_api_response(code="500", message=f"更新配置失败: {str(e)}")
|
||||
|
||||
# 在应用启动时加载配置
|
||||
def load_system_config():
|
||||
"""在应用启动时调用,加载保存的配置"""
|
||||
try:
|
||||
config = load_config_from_file()
|
||||
|
||||
# 更新运行时配置
|
||||
LLM_CONFIG['model_name'] = config.get('model_name', LLM_CONFIG['model_name'])
|
||||
LLM_CONFIG['system_prompt'] = config.get('system_prompt', LLM_CONFIG['system_prompt'])
|
||||
|
||||
# 更新其他配置
|
||||
import app.core.config as config_module
|
||||
config_module.DEFAULT_RESET_PASSWORD = config.get('DEFAULT_RESET_PASSWORD', DEFAULT_RESET_PASSWORD)
|
||||
config_module.MAX_FILE_SIZE = config.get('MAX_FILE_SIZE', MAX_FILE_SIZE)
|
||||
config_module.MAX_IMAGE_SIZE = config.get('MAX_IMAGE_SIZE', MAX_IMAGE_SIZE)
|
||||
|
||||
print(f"系统配置加载成功: model={config.get('model_name')}")
|
||||
except Exception as e:
|
||||
print(f"加载系统配置失败,使用默认配置: {e}")
|
||||
print(f"加载系统配置失败,使用默认配置: {e}")
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
|
||||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from app.models.models import LoginRequest, LoginResponse
|
||||
from app.core.database import get_db_connection
|
||||
from app.services.jwt_service import jwt_service
|
||||
from app.core.auth import get_current_user
|
||||
import hashlib
|
||||
from typing import Union
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
|
||||
from app.core.auth import get_current_user
|
||||
from app.core.database import get_db_connection
|
||||
from app.models.models import LoginRequest, LoginResponse
|
||||
from app.services.jwt_service import jwt_service
|
||||
from app.core.response import create_api_response
|
||||
|
||||
security = HTTPBearer()
|
||||
|
||||
|
|
@ -14,7 +19,7 @@ router = APIRouter()
|
|||
def hash_password(password: str) -> str:
|
||||
return hashlib.sha256(password.encode()).hexdigest()
|
||||
|
||||
@router.post("/auth/login", response_model=LoginResponse)
|
||||
@router.post("/auth/login")
|
||||
def login(request: LoginRequest):
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
|
@ -24,11 +29,11 @@ def login(request: LoginRequest):
|
|||
user = cursor.fetchone()
|
||||
|
||||
if not user:
|
||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||
return create_api_response(code="401", message="用户名或密码错误")
|
||||
|
||||
hashed_input = hash_password(request.password)
|
||||
if user['password_hash'] != hashed_input:
|
||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||
return create_api_response(code="401", message="用户名或密码错误")
|
||||
|
||||
# 创建JWT token
|
||||
token_data = {
|
||||
|
|
@ -39,7 +44,7 @@ def login(request: LoginRequest):
|
|||
}
|
||||
token = jwt_service.create_access_token(token_data)
|
||||
|
||||
return LoginResponse(
|
||||
login_response_data = LoginResponse(
|
||||
user_id=user['user_id'],
|
||||
username=user['username'],
|
||||
caption=user['caption'],
|
||||
|
|
@ -47,71 +52,83 @@ def login(request: LoginRequest):
|
|||
token=token,
|
||||
role_id=user['role_id']
|
||||
)
|
||||
|
||||
return create_api_response(
|
||||
code="200",
|
||||
message="登录成功",
|
||||
data=login_response_data.dict()
|
||||
)
|
||||
|
||||
@router.post("/auth/logout")
|
||||
def logout(credentials: HTTPAuthorizationCredentials = Depends(security)):
|
||||
"""登出接口,撤销当前token"""
|
||||
token = credentials.credentials
|
||||
|
||||
# 验证token并获取用户信息(不查询数据库)
|
||||
|
||||
payload = jwt_service.verify_token(token)
|
||||
if not payload:
|
||||
raise HTTPException(status_code=401, detail="Invalid or expired token")
|
||||
|
||||
return create_api_response(code="401", message="无效或过期的token")
|
||||
|
||||
user_id = payload.get("user_id")
|
||||
if not user_id:
|
||||
raise HTTPException(status_code=401, detail="Invalid token payload")
|
||||
|
||||
# 撤销当前token
|
||||
return create_api_response(code="401", message="无效的token payload")
|
||||
|
||||
revoked = jwt_service.revoke_token(token, user_id)
|
||||
|
||||
|
||||
if revoked:
|
||||
return {"message": "Logged out successfully"}
|
||||
return create_api_response(code="200", message="登出成功")
|
||||
else:
|
||||
return {"message": "Already logged out or token not found"}
|
||||
return create_api_response(code="400", message="已经登出或token未找到")
|
||||
|
||||
|
||||
@router.post("/auth/logout-all")
|
||||
def logout_all(current_user: dict = Depends(get_current_user)):
|
||||
"""登出所有设备"""
|
||||
user_id = current_user['user_id']
|
||||
user_id = current_user["user_id"]
|
||||
revoked_count = jwt_service.revoke_all_user_tokens(user_id)
|
||||
return {"message": f"Logged out from {revoked_count} devices"}
|
||||
return create_api_response(code="200", message=f"从 {revoked_count} 个设备登出")
|
||||
|
||||
|
||||
@router.post("/auth/admin/revoke-user-tokens/{user_id}")
|
||||
def admin_revoke_user_tokens(user_id: int, credentials: HTTPAuthorizationCredentials = Depends(security)):
|
||||
def admin_revoke_user_tokens(
|
||||
user_id: int, credentials: HTTPAuthorizationCredentials = Depends(security)
|
||||
):
|
||||
"""管理员功能:撤销指定用户的所有token"""
|
||||
token = credentials.credentials
|
||||
|
||||
# 验证管理员token(不查询数据库)
|
||||
|
||||
payload = jwt_service.verify_token(token)
|
||||
if not payload:
|
||||
raise HTTPException(status_code=401, detail="Invalid or expired token")
|
||||
|
||||
return create_api_response(code="401", message="无效或过期的token")
|
||||
|
||||
admin_user_id = payload.get("user_id")
|
||||
if not admin_user_id:
|
||||
raise HTTPException(status_code=401, detail="Invalid token payload")
|
||||
|
||||
return create_api_response(code="401", message="无效的token payload")
|
||||
|
||||
# 这里可以添加管理员权限检查,目前暂时允许任何登录用户操作
|
||||
# if not payload.get('is_admin'):
|
||||
# raise HTTPException(status_code=403, detail="需要管理员权限")
|
||||
|
||||
# if payload.get('role_id') != ADMIN_ROLE_ID:
|
||||
# return create_api_response(code="403", message="需要管理员权限")
|
||||
|
||||
revoked_count = jwt_service.revoke_all_user_tokens(user_id)
|
||||
return {"message": f"Revoked {revoked_count} tokens for user {user_id}"}
|
||||
return create_api_response(
|
||||
code="200", message=f"为用户 {user_id} 撤销了 {revoked_count} 个token"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/auth/me")
|
||||
def get_me(current_user: dict = Depends(get_current_user)):
|
||||
"""获取当前用户信息"""
|
||||
return current_user
|
||||
return create_api_response(code="200", message="获取用户信息成功", data=current_user)
|
||||
|
||||
|
||||
@router.post("/auth/refresh")
|
||||
def refresh_token(current_user: dict = Depends(get_current_user)):
|
||||
"""刷新token"""
|
||||
# 这里需要从请求中获取当前token,为简化先返回新token
|
||||
token_data = {
|
||||
"user_id": current_user['user_id'],
|
||||
"username": current_user['username'],
|
||||
"caption": current_user['caption'],
|
||||
"role_id": current_user['role_id']
|
||||
"user_id": current_user["user_id"],
|
||||
"username": current_user["username"],
|
||||
"caption": current_user["caption"],
|
||||
"role_id": current_user["role_id"],
|
||||
}
|
||||
new_token = jwt_service.create_access_token(token_data)
|
||||
return {"token": new_token}
|
||||
return create_api_response(
|
||||
code="200", message="Token刷新成功", data={"token": new_token}
|
||||
)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,13 +1,13 @@
|
|||
|
||||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.core.database import get_db_connection
|
||||
from app.core.response import create_api_response
|
||||
from app.models.models import Tag
|
||||
from typing import List
|
||||
import mysql.connector
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/tags/", response_model=List[Tag])
|
||||
@router.get("/tags/")
|
||||
def get_all_tags():
|
||||
"""_summary_
|
||||
获取所有标签
|
||||
|
|
@ -18,12 +18,12 @@ def get_all_tags():
|
|||
with connection.cursor(dictionary=True) as cursor:
|
||||
cursor.execute(query)
|
||||
tags = cursor.fetchall()
|
||||
return tags
|
||||
return create_api_response(code="200", message="获取标签列表成功", data=tags)
|
||||
except mysql.connector.Error as err:
|
||||
print(f"Error: {err}")
|
||||
raise HTTPException(status_code=500, detail="Failed to retrieve tags from database.")
|
||||
return create_api_response(code="500", message="获取标签失败")
|
||||
|
||||
@router.post("/tags/", response_model=Tag)
|
||||
@router.post("/tags/")
|
||||
def create_tag(tag_in: Tag):
|
||||
"""_summary_
|
||||
创建一个新标签
|
||||
|
|
@ -36,10 +36,11 @@ def create_tag(tag_in: Tag):
|
|||
cursor.execute(query, (tag_in.name, tag_in.color))
|
||||
connection.commit()
|
||||
tag_id = cursor.lastrowid
|
||||
return {"id": tag_id, "name": tag_in.name, "color": tag_in.color}
|
||||
new_tag = {"id": tag_id, "name": tag_in.name, "color": tag_in.color}
|
||||
return create_api_response(code="200", message="标签创建成功", data=new_tag)
|
||||
except mysql.connector.IntegrityError:
|
||||
connection.rollback()
|
||||
raise HTTPException(status_code=400, detail=f"Tag '{tag_in.name}' already exists.")
|
||||
return create_api_response(code="400", message=f"标签 '{tag_in.name}' 已存在")
|
||||
except mysql.connector.Error as err:
|
||||
print(f"Error: {err}")
|
||||
raise HTTPException(status_code=500, detail="Failed to create tag in database.")
|
||||
return create_api_response(code="500", message="创建标签失败")
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.models.models import UserInfo, PasswordChangeRequest, UserListResponse, CreateUserRequest, UpdateUserRequest, RoleInfo
|
||||
from app.core.database import get_db_connection
|
||||
from app.core.auth import get_current_user
|
||||
from app.core.response import create_api_response
|
||||
import app.core.config as config_module
|
||||
import hashlib
|
||||
import datetime
|
||||
|
|
@ -22,68 +22,60 @@ def hash_password(password: str) -> str:
|
|||
def get_all_roles(current_user: dict = Depends(get_current_user)):
|
||||
"""获取所有角色列表"""
|
||||
if current_user['role_id'] != 1: # 1 is admin
|
||||
raise HTTPException(status_code=403, detail="仅管理员有权限查看角色列表")
|
||||
return create_api_response(code="403", message="仅管理员有权限查看角色列表")
|
||||
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
cursor.execute("SELECT role_id, role_name FROM roles ORDER BY role_id")
|
||||
roles = cursor.fetchall()
|
||||
return [RoleInfo(**role) for role in roles]
|
||||
return create_api_response(code="200", message="获取角色列表成功", data=[RoleInfo(**role).dict() for role in roles])
|
||||
|
||||
@router.post("/users", status_code=201)
|
||||
@router.post("/users")
|
||||
def create_user(request: CreateUserRequest, current_user: dict = Depends(get_current_user)):
|
||||
if current_user['role_id'] != 1: # 1 is admin
|
||||
raise HTTPException(status_code=403, detail="仅管理员有权限创建用户")
|
||||
return create_api_response(code="403", message="仅管理员有权限创建用户")
|
||||
|
||||
# Validate email format
|
||||
if not validate_email(request.email):
|
||||
raise HTTPException(status_code=400, detail="邮箱格式不正确")
|
||||
return create_api_response(code="400", message="邮箱格式不正确")
|
||||
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# Check if username exists
|
||||
cursor.execute("SELECT user_id FROM users WHERE username = %s", (request.username,))
|
||||
if cursor.fetchone():
|
||||
raise HTTPException(status_code=400, detail="用户名已存在")
|
||||
return create_api_response(code="400", message="用户名已存在")
|
||||
|
||||
# Use provided password or default password
|
||||
password = request.password if request.password else config_module.DEFAULT_RESET_PASSWORD
|
||||
hashed_password = hash_password(password)
|
||||
|
||||
# Insert new user
|
||||
query = "INSERT INTO users (username, password_hash, caption, email, role_id, created_at) VALUES (%s, %s, %s, %s, %s, %s)"
|
||||
created_at = datetime.datetime.utcnow()
|
||||
cursor.execute(query, (request.username, hashed_password, request.caption, request.email, request.role_id, created_at))
|
||||
connection.commit()
|
||||
|
||||
return {"message": "用户创建成功"}
|
||||
return create_api_response(code="200", message="用户创建成功")
|
||||
|
||||
@router.put("/users/{user_id}", response_model=UserInfo)
|
||||
@router.put("/users/{user_id}")
|
||||
def update_user(user_id: int, request: UpdateUserRequest, current_user: dict = Depends(get_current_user)):
|
||||
if current_user['role_id'] != 1: # 1 is admin
|
||||
raise HTTPException(status_code=403, detail="仅管理员有权限修改用户信息")
|
||||
return create_api_response(code="403", message="仅管理员有权限修改用户信息")
|
||||
|
||||
# Validate email format if provided
|
||||
if request.email and not validate_email(request.email):
|
||||
raise HTTPException(status_code=400, detail="邮箱格式不正确")
|
||||
return create_api_response(code="400", message="邮箱格式不正确")
|
||||
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# Check if user exists
|
||||
cursor.execute("SELECT user_id, username, caption, email, role_id FROM users WHERE user_id = %s", (user_id,))
|
||||
existing_user = cursor.fetchone()
|
||||
if not existing_user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return create_api_response(code="404", message="用户不存在")
|
||||
|
||||
# Check if username is being changed and if it already exists
|
||||
if request.username and request.username != existing_user['username']:
|
||||
cursor.execute("SELECT user_id FROM users WHERE username = %s AND user_id != %s", (request.username, user_id))
|
||||
if cursor.fetchone():
|
||||
raise HTTPException(status_code=400, detail="用户名已存在")
|
||||
return create_api_response(code="400", message="用户名已存在")
|
||||
|
||||
# Prepare update data, using existing values if not provided
|
||||
update_data = {
|
||||
'username': request.username if request.username else existing_user['username'],
|
||||
'caption': request.caption if request.caption else existing_user['caption'],
|
||||
|
|
@ -91,12 +83,10 @@ def update_user(user_id: int, request: UpdateUserRequest, current_user: dict = D
|
|||
'role_id': request.role_id if request.role_id is not None else existing_user['role_id']
|
||||
}
|
||||
|
||||
# Update user
|
||||
query = "UPDATE users SET username = %s, caption = %s, email = %s, role_id = %s WHERE user_id = %s"
|
||||
cursor.execute(query, (update_data['username'], update_data['caption'], update_data['email'], update_data['role_id'], user_id))
|
||||
connection.commit()
|
||||
|
||||
# Return updated user info
|
||||
cursor.execute('''
|
||||
SELECT u.user_id, u.username, u.caption, u.email, u.created_at, u.role_id, r.role_name
|
||||
FROM users u
|
||||
|
|
@ -105,7 +95,7 @@ def update_user(user_id: int, request: UpdateUserRequest, current_user: dict = D
|
|||
''', (user_id,))
|
||||
updated_user = cursor.fetchone()
|
||||
|
||||
return UserInfo(
|
||||
user_info = UserInfo(
|
||||
user_id=updated_user['user_id'],
|
||||
username=updated_user['username'],
|
||||
caption=updated_user['caption'],
|
||||
|
|
@ -113,62 +103,56 @@ def update_user(user_id: int, request: UpdateUserRequest, current_user: dict = D
|
|||
created_at=updated_user['created_at'],
|
||||
role_id=updated_user['role_id'],
|
||||
role_name=updated_user['role_name'],
|
||||
meetings_created=0, # This is not accurate, but it is not displayed in the list
|
||||
meetings_created=0,
|
||||
meetings_attended=0
|
||||
)
|
||||
return create_api_response(code="200", message="用户信息更新成功", data=user_info.dict())
|
||||
|
||||
@router.delete("/users/{user_id}")
|
||||
def delete_user(user_id: int, current_user: dict = Depends(get_current_user)):
|
||||
if current_user['role_id'] != 1: # 1 is admin
|
||||
raise HTTPException(status_code=403, detail="仅管理员有权限删除用户")
|
||||
return create_api_response(code="403", message="仅管理员有权限删除用户")
|
||||
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# Check if user exists
|
||||
cursor.execute("SELECT user_id FROM users WHERE user_id = %s", (user_id,))
|
||||
if not cursor.fetchone():
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return create_api_response(code="404", message="用户不存在")
|
||||
|
||||
# Delete user
|
||||
cursor.execute("DELETE FROM users WHERE user_id = %s", (user_id,))
|
||||
connection.commit()
|
||||
|
||||
return {"message": "用户删除成功"}
|
||||
return create_api_response(code="200", message="用户删除成功")
|
||||
|
||||
@router.post("/users/{user_id}/reset-password")
|
||||
def reset_password(user_id: int, current_user: dict = Depends(get_current_user)):
|
||||
if current_user['role_id'] != 1: # 1 is admin
|
||||
raise HTTPException(status_code=403, detail="仅管理员有权限重置密码")
|
||||
return create_api_response(code="403", message="仅管理员有权限重置密码")
|
||||
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# Check if user exists
|
||||
cursor.execute("SELECT user_id FROM users WHERE user_id = %s", (user_id,))
|
||||
if not cursor.fetchone():
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return create_api_response(code="404", message="用户不存在")
|
||||
|
||||
# Hash password
|
||||
hashed_password = hash_password(config_module.DEFAULT_RESET_PASSWORD)
|
||||
|
||||
# Update user password
|
||||
query = "UPDATE users SET password_hash = %s WHERE user_id = %s"
|
||||
cursor.execute(query, (hashed_password, user_id))
|
||||
connection.commit()
|
||||
|
||||
return {"message": f"用户 {user_id} 的密码已重置"}
|
||||
return create_api_response(code="200", message=f"用户 {user_id} 的密码已重置")
|
||||
|
||||
@router.get("/users", response_model=UserListResponse)
|
||||
@router.get("/users")
|
||||
def get_all_users(page: int = 1, size: int = 10, current_user: dict = Depends(get_current_user)):
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# Get total count
|
||||
cursor.execute("SELECT COUNT(*) as total FROM users")
|
||||
total = cursor.fetchone()['total']
|
||||
|
||||
# Get paginated users with role names
|
||||
offset = (page - 1) * size
|
||||
query = '''
|
||||
SELECT
|
||||
|
|
@ -186,9 +170,10 @@ def get_all_users(page: int = 1, size: int = 10, current_user: dict = Depends(ge
|
|||
|
||||
user_list = [UserInfo(**user) for user in users]
|
||||
|
||||
return UserListResponse(users=user_list, total=total)
|
||||
response_data = UserListResponse(users=user_list, total=total)
|
||||
return create_api_response(code="200", message="获取用户列表成功", data=response_data.dict())
|
||||
|
||||
@router.get("/users/{user_id}", response_model=UserInfo)
|
||||
@router.get("/users/{user_id}")
|
||||
def get_user_info(user_id: int, current_user: dict = Depends(get_current_user)):
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
|
@ -203,7 +188,7 @@ def get_user_info(user_id: int, current_user: dict = Depends(get_current_user)):
|
|||
user = cursor.fetchone()
|
||||
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return create_api_response(code="404", message="用户不存在")
|
||||
|
||||
created_query = "SELECT COUNT(*) as count FROM meetings WHERE user_id = %s"
|
||||
cursor.execute(created_query, (user_id,))
|
||||
|
|
@ -213,7 +198,7 @@ def get_user_info(user_id: int, current_user: dict = Depends(get_current_user)):
|
|||
cursor.execute(attended_query, (user_id,))
|
||||
meetings_attended = cursor.fetchone()['count']
|
||||
|
||||
return UserInfo(
|
||||
user_info = UserInfo(
|
||||
user_id=user['user_id'],
|
||||
username=user['username'],
|
||||
caption=user['caption'],
|
||||
|
|
@ -224,11 +209,12 @@ def get_user_info(user_id: int, current_user: dict = Depends(get_current_user)):
|
|||
meetings_created=meetings_created,
|
||||
meetings_attended=meetings_attended
|
||||
)
|
||||
return create_api_response(code="200", message="获取用户信息成功", data=user_info.dict())
|
||||
|
||||
@router.put("/users/{user_id}/password")
|
||||
def update_password(user_id: int, request: PasswordChangeRequest, current_user: dict = Depends(get_current_user)):
|
||||
if user_id != current_user['user_id'] and current_user['role_id'] != 1:
|
||||
raise HTTPException(status_code=403, detail="没有权限修改其他用户的密码")
|
||||
return create_api_response(code="403", message="没有权限修改其他用户的密码")
|
||||
|
||||
with get_db_connection() as connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
|
@ -237,15 +223,14 @@ def update_password(user_id: int, request: PasswordChangeRequest, current_user:
|
|||
user = cursor.fetchone()
|
||||
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return create_api_response(code="404", message="用户不存在")
|
||||
|
||||
# If not admin, verify old password
|
||||
if current_user['role_id'] != 1:
|
||||
if user['password_hash'] != hash_password(request.old_password):
|
||||
raise HTTPException(status_code=400, detail="旧密码错误")
|
||||
return create_api_response(code="400", message="旧密码错误")
|
||||
|
||||
new_password_hash = hash_password(request.new_password)
|
||||
cursor.execute("UPDATE users SET password_hash = %s WHERE user_id = %s", (new_password_hash, user_id))
|
||||
connection.commit()
|
||||
|
||||
return {"message": "密码修改成功"}
|
||||
return create_api_response(code="200", message="密码修改成功")
|
||||
|
|
@ -23,7 +23,7 @@ DATABASE_CONFIG = {
|
|||
'host': os.getenv('DB_HOST', '10.100.51.161'),
|
||||
'user': os.getenv('DB_USER', 'root'),
|
||||
'password': os.getenv('DB_PASSWORD', 'sagacity'),
|
||||
'database': os.getenv('DB_NAME', 'imeeting'),
|
||||
'database': os.getenv('DB_NAME', 'imeeting_dev'),
|
||||
'port': int(os.getenv('DB_PORT', '3306')),
|
||||
'charset': 'utf8mb4'
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ QINIU_DOMAIN = os.getenv('QINIU_DOMAIN', 't0vogyxkz.hn-bkt.clouddn.com')
|
|||
|
||||
# 应用配置
|
||||
APP_CONFIG = {
|
||||
'base_url': os.getenv('BASE_URL', 'http://imeeting.unisspace.com')
|
||||
'base_url': os.getenv('BASE_URL', 'http://dev.imeeting.unisspace.com')
|
||||
}
|
||||
|
||||
# Redis配置
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
from typing import Union
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
|
||||
def create_api_response(code: str, message: str, data: Union[dict, list, None] = None) -> JSONResponse:
|
||||
"""Creates a standardized API JSON response."""
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={
|
||||
"code": str(code),
|
||||
"message": message,
|
||||
"data": jsonable_encoder(data) if data is not None else {},
|
||||
},
|
||||
)
|
||||
Binary file not shown.
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"model_name": "qwen-plus",
|
||||
"system_prompt": "你是一个专业的会议记录分析助手。请根据提供的会议转录内容,生成简洁明了的会议总结。\n\n总结应该包括以下几部分(生成MD二级目录):\n1. 会议概述 - 简要说明会议的主要目的和背景(生成MD引用)\n2. 主要讨论点 - 列出会议中讨论的重要话题和内容\n3. 决策事项 - 明确记录会议中做出的决定和结论\n4. 待办事项 - 列出需要后续跟进的任务和责任人\n5. 关键信息 - 其他重要的信息点\n\n输出要求:\n- 保持客观中性,不添加个人观点\n- 使用简洁、准确的中文表达\n- 按重要性排序各项内容\n- 如果某个部分没有相关内容,可以说明\"无相关内容\"\n- 总字数控制在500字以内",
|
||||
"DEFAULT_RESET_PASSWORD": "123456",
|
||||
"system_prompt": "你是一个专业的会议记录分析助手。请根据提供的会议转录内容,生成简洁明了的会议总结。\n\n总结包括五个部分(名称严格一致,生成为MD二级目录):\n1. 会议概述 - 简要说明会议的主要目的和背景(生成MD引用)\n2. 主要讨论点 - 列出会议中讨论的重要话题和内容\n3. 决策事项 - 明确记录会议中做出的决定和结论\n4. 待办事项 - 列出需要后续跟进的任务和责任人\n5. 关键信息 - 其他重要的信息点\n\n输出要求:\n- 保持客观中性,不添加个人观点\n- 使用简洁、准确的中文表达\n- 按重要性排序各项内容\n- 如果某个部分没有相关内容,可以说明\"无相关内容\"\n- 总字数控制在500字以内",
|
||||
"DEFAULT_RESET_PASSWORD": "111111",
|
||||
"MAX_FILE_SIZE": 209715200,
|
||||
"MAX_IMAGE_SIZE": 10485760
|
||||
}
|
||||
|
|
@ -46,6 +46,7 @@ services:
|
|||
volumes:
|
||||
# 挂载上传目录保持数据持久化
|
||||
- ./uploads:/app/uploads
|
||||
- ./config:/app/config
|
||||
restart: unless-stopped
|
||||
container_name: imeeting-backend
|
||||
extra_hosts:
|
||||
|
|
|
|||
5
main.py
5
main.py
|
|
@ -3,8 +3,7 @@ from fastapi import FastAPI, Request, HTTPException
|
|||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from app.api.endpoints import auth, users, meetings, tags, admin
|
||||
from app.core.config import UPLOAD_DIR, API_CONFIG, MAX_FILE_SIZE
|
||||
from app.services.async_llm_service import async_llm_service
|
||||
from app.core.config import UPLOAD_DIR, API_CONFIG
|
||||
from app.api.endpoints.admin import load_system_config
|
||||
import os
|
||||
|
||||
|
|
@ -47,7 +46,7 @@ def health_check():
|
|||
return {
|
||||
"status": "healthy",
|
||||
"service": "iMeeting API",
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.2"
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Reference in New Issue