fix: 管理员可编辑所有用户藏品 - v1.1.22
This commit is contained in:
parent
f3625fa196
commit
17fb08b487
|
|
@ -12,7 +12,7 @@ class JSONFormatter(logging.Formatter):
|
|||
|
||||
def format(self, record):
|
||||
log_data = {
|
||||
'timestamp': datetime.utcnow().isoformat() + 'Z',
|
||||
'timestamp': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
|
||||
'level': record.levelname,
|
||||
'logger': record.name,
|
||||
'message': record.getMessage(),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,43 @@ router = APIRouter(prefix="/api/auth", tags=["认证"])
|
|||
@router.post("/register", response_model=UserResponse)
|
||||
def register(user_data: UserCreate, db: Session = Depends(get_db)):
|
||||
"""用户注册"""
|
||||
# 验证短信验证码
|
||||
if user_data.phone and user_data.verifyCode:
|
||||
from app.services.sms import verify_code
|
||||
if not verify_code(user_data.phone, user_data.verifyCode):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="验证码错误或已过期"
|
||||
)
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="手机号和验证码为必填项"
|
||||
)
|
||||
|
||||
# 验证密码复杂度(至少8位,包含大写、小写、数字)
|
||||
if len(user_data.password) < 8:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="密码至少8位"
|
||||
)
|
||||
import re
|
||||
if not re.search(r'[A-Z]', user_data.password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="密码必须包含大写字母"
|
||||
)
|
||||
if not re.search(r'[a-z]', user_data.password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="密码必须包含小写字母"
|
||||
)
|
||||
if not re.search(r'[0-9]', user_data.password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="密码必须包含数字"
|
||||
)
|
||||
|
||||
# 检查用户名是否已存在
|
||||
existing_user = db.query(User).filter(User.f01_01_name == user_data.f01_01_name).first()
|
||||
if existing_user:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import uuid
|
|||
import re
|
||||
from typing import Optional, List
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query, UploadFile, File
|
||||
from sqlalchemy import func, text
|
||||
from sqlalchemy import or_, func, text
|
||||
from sqlalchemy.orm import Session
|
||||
from app.core.database import get_db
|
||||
from app.core.auth import get_current_user
|
||||
|
|
@ -117,7 +117,7 @@ def get_collections(
|
|||
User, Collection.f99_91_user_id == User.f99_90_id, isouter=True
|
||||
)
|
||||
else:
|
||||
query = db.query(Collection).filter(Collection.f99_91_user_id == current_user.f99_90_id)
|
||||
query = db.query(Collection).filter(or_(Collection.f99_91_user_id == current_user.f99_90_id, current_user.role == "admin"))
|
||||
|
||||
if category:
|
||||
query = query.filter(Collection.f01_03_category == category)
|
||||
|
|
@ -224,7 +224,7 @@ def get_stats(
|
|||
all_collections = db.query(Collection).all()
|
||||
else:
|
||||
all_collections = db.query(Collection).filter(
|
||||
Collection.f99_91_user_id == current_user.f99_90_id
|
||||
or_(Collection.f99_91_user_id == current_user.f99_90_id, current_user.role == "admin")
|
||||
).all()
|
||||
|
||||
# 总数
|
||||
|
|
@ -396,7 +396,7 @@ def create_collection(
|
|||
if not force and final_code:
|
||||
existing_code = db.query(Collection).filter(
|
||||
Collection.f01_02_code == final_code,
|
||||
Collection.f99_91_user_id == current_user.f99_90_id
|
||||
or_(Collection.f99_91_user_id == current_user.f99_90_id, current_user.role == "admin")
|
||||
).first()
|
||||
|
||||
if existing_code:
|
||||
|
|
@ -413,7 +413,7 @@ def create_collection(
|
|||
# 查询当前用户是否有相同冠字号的藏品
|
||||
existing = db.query(Collection).filter(
|
||||
Collection.f02_10_prefix_serial == collection_data.f02_10_prefix_serial,
|
||||
Collection.f99_91_user_id == current_user.f99_90_id
|
||||
or_(Collection.f99_91_user_id == current_user.f99_90_id, current_user.role == "admin")
|
||||
).first()
|
||||
|
||||
if existing:
|
||||
|
|
@ -492,7 +492,7 @@ def update_collection(
|
|||
"""更新藏品"""
|
||||
collection = db.query(Collection).filter(
|
||||
Collection.f99_90_id == collection_id,
|
||||
Collection.f99_91_user_id == current_user.f99_90_id
|
||||
or_(Collection.f99_91_user_id == current_user.f99_90_id, current_user.role == "admin")
|
||||
).first()
|
||||
|
||||
if not collection:
|
||||
|
|
@ -523,7 +523,7 @@ def delete_collection(
|
|||
# 验证权限并检查是否存在
|
||||
collection = db.query(Collection).filter(
|
||||
Collection.f99_90_id == collection_id,
|
||||
Collection.f99_91_user_id == current_user.f99_90_id
|
||||
or_(Collection.f99_91_user_id == current_user.f99_90_id, current_user.role == "admin")
|
||||
).first()
|
||||
|
||||
if not collection:
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ async def claim_temp_image(
|
|||
oss_key = get_oss_path("collection", user_id=current_user.f99_90_id, collection_id=collection_id, filename=final_filename)
|
||||
|
||||
# 尝试从OSS获取临时图片 - 尝试多种扩展名和日期路径
|
||||
temp_extensions = ['jpg', 'jpeg', 'png', 'gif']
|
||||
temp_extensions = ['jpg', 'jpeg', 'png', 'gif', 'JPG', 'JPEG', 'PNG', 'GIF']
|
||||
temp_content = None
|
||||
found_key = None
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,27 @@ def update_current_user(
|
|||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
|
||||
# 处理手机号更换验证码
|
||||
new_phone = user_update.phone
|
||||
verify_code = user_update.verifyCode
|
||||
|
||||
if new_phone and new_phone != user.phone:
|
||||
# 需要验证验证码
|
||||
if not verify_code:
|
||||
raise HTTPException(status_code=400, detail="更换手机号需要验证码")
|
||||
|
||||
# 验证验证码
|
||||
from app.services.sms import verify_code as sms_verify
|
||||
import os
|
||||
if os.getenv("SMS_TEST_MODE") == "true":
|
||||
# 测试模式:任何6位数字有效
|
||||
is_valid = len(verify_code) == 6 and verify_code.isdigit()
|
||||
else:
|
||||
is_valid = sms_verify(new_phone, verify_code)
|
||||
|
||||
if not is_valid:
|
||||
raise HTTPException(status_code=400, detail="验证码错误或已过期")
|
||||
|
||||
# 更新字段
|
||||
update_data = user_update.model_dump(exclude_unset=True)
|
||||
for field, value in update_data.items():
|
||||
|
|
@ -55,6 +76,8 @@ def update_current_user(
|
|||
user.f01_01_name = value
|
||||
elif field == 'username':
|
||||
pass # skip, already handled as f01_01_name
|
||||
elif field == 'verifyCode':
|
||||
pass # skip,验证码不存储
|
||||
elif hasattr(user, field):
|
||||
setattr(user, field, value)
|
||||
|
||||
|
|
@ -62,7 +85,7 @@ def update_current_user(
|
|||
db.flush()
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
logger.info(f"After commit, user email={user.email}")
|
||||
logger.info(f"After commit, user email={user.email}, phone={user.phone}")
|
||||
|
||||
return user
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from datetime import datetime
|
|||
# ============ 用户相关 ============
|
||||
|
||||
class UserBase(BaseModel):
|
||||
f01_01_name: str = Field(..., min_length=3, max_length=255, alias="username")
|
||||
f01_01_name: str = Field(..., min_length=2, max_length=255, alias="username")
|
||||
email: Optional[EmailStr] = None
|
||||
phone: Optional[str] = None
|
||||
avatar: Optional[str] = None
|
||||
|
|
@ -18,13 +18,15 @@ class UserBase(BaseModel):
|
|||
|
||||
|
||||
class UserCreate(UserBase):
|
||||
password: str = Field(..., min_length=6)
|
||||
password: str = Field(..., min_length=8)
|
||||
verifyCode: Optional[str] = Field(None, alias="verifyCode")
|
||||
|
||||
|
||||
class UserUpdate(BaseModel):
|
||||
f01_01_name: Optional[str] = Field(None, alias="username")
|
||||
email: Optional[EmailStr] = None
|
||||
email: Optional[str] = None # 改为字符串,不强制验证EmailStr
|
||||
phone: Optional[str] = None
|
||||
verifyCode: Optional[str] = Field(None, alias="verifyCode") # 更换手机号验证码
|
||||
avatar: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
bio: Optional[str] = None
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ from typing import Optional
|
|||
|
||||
# 阿里云短信配置
|
||||
SMS_CONFIG = {
|
||||
"access_key_id": os.getenv("SMS_ACCESS_KEY_ID", "LTAI5t6HUnpFBLEK9194kPVG"),
|
||||
"access_key_secret": os.getenv("SMS_ACCESS_KEY_SECRET", "LEr4Q8yRxb8D5b24cKfCwlt4MMoke1"),
|
||||
"sign_name": "阿里云",
|
||||
"template_code": "100001",
|
||||
"access_key_id": os.getenv("SMS_ACCESS_KEY_ID", "LTAI5tQAx5niD7JQVqGE5acE"),
|
||||
"access_key_secret": os.getenv("SMS_ACCESS_KEY_SECRET", "QsQFAEKBkaNynIoKyvdIi3BUyWVZu1"),
|
||||
"sign_name": os.getenv("SMS_SIGN_NAME", "苏州算力"),
|
||||
"template_code": os.getenv("SMS_TEMPLATE_CODE", "SMS_501590956"),
|
||||
}
|
||||
|
||||
# 验证码缓存(生产环境建议用Redis)
|
||||
|
|
@ -82,6 +82,11 @@ def send_verification_code(phone: str) -> dict:
|
|||
|
||||
def verify_code(phone: str, code: str) -> bool:
|
||||
"""验证验证码"""
|
||||
# 测试模式:任何6位数字验证码都有效
|
||||
import os
|
||||
if os.getenv("SMS_TEST_MODE") == "true":
|
||||
return len(code) == 6 and code.isdigit()
|
||||
|
||||
if phone not in VERIFICATION_CODES:
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1 @@
|
|||
# 甲辰藏品管理系统 - 版本配置
|
||||
# Version Configuration for Zodiac Collection Management System
|
||||
|
||||
# 当前版本号 (语义化版本:主版本。次版本.修订版)
|
||||
VERSION=1.1.21
|
||||
|
||||
# 版本代号 (可选)
|
||||
VERSION_CODENAME="新生"
|
||||
|
||||
# 发布日期
|
||||
RELEASE_DATE=2026-03-18
|
||||
|
||||
# 版本说明
|
||||
VERSION_NOTES="性能优化 - Nginx反向代理、图片OSS直连、自动压缩、上传限制20MB"
|
||||
v1.1.22
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>甲辰收藏 v1.1.19</title>
|
||||
<title>甲辰收藏 v1.1.21</title>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="/static/icons/favicon.ico" />
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Loading…
Reference in New Issue