fix: 软删除字段NULL兼容,用COALESCE避免已有用户无法登录
All checks were successful
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 10s
Test / e2e-test (push) Successful in 50s
All checks were successful
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 10s
Test / e2e-test (push) Successful in 50s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -248,6 +248,7 @@ def init_db():
|
||||
# Migration: soft-delete for users
|
||||
if "deleted" not in user_cols:
|
||||
c.execute("ALTER TABLE users ADD COLUMN deleted INTEGER DEFAULT 0")
|
||||
c.execute("UPDATE users SET deleted = 0 WHERE deleted IS NULL")
|
||||
if "deleted_at" not in user_cols:
|
||||
c.execute("ALTER TABLE users ADD COLUMN deleted_at TEXT")
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ def get_current_user(request: Request):
|
||||
if not token:
|
||||
return ANON_USER
|
||||
conn = get_db()
|
||||
user = conn.execute("SELECT id, username, role, display_name, password, business_verified FROM users WHERE token = ? AND NOT deleted", (token,)).fetchone()
|
||||
user = conn.execute("SELECT id, username, role, display_name, password, business_verified FROM users WHERE token = ? AND COALESCE(deleted,0)=0", (token,)).fetchone()
|
||||
conn.close()
|
||||
if not user:
|
||||
return ANON_USER
|
||||
@@ -373,7 +373,7 @@ def login(body: dict):
|
||||
if not username or not password:
|
||||
raise HTTPException(400, "请输入用户名和密码")
|
||||
conn = get_db()
|
||||
user = conn.execute("SELECT id, token, password, display_name, role FROM users WHERE username = ? AND NOT deleted", (username,)).fetchone()
|
||||
user = conn.execute("SELECT id, token, password, display_name, role FROM users WHERE username = ? AND COALESCE(deleted,0)=0", (username,)).fetchone()
|
||||
if not user:
|
||||
conn.close()
|
||||
raise HTTPException(401, "用户名不存在")
|
||||
@@ -747,7 +747,7 @@ def list_recipes(user=Depends(get_current_user)):
|
||||
if user["role"] == "admin":
|
||||
rows = conn.execute("SELECT id, name, note, owner_id, version, en_name FROM recipes ORDER BY id").fetchall()
|
||||
else:
|
||||
admin = conn.execute("SELECT id FROM users WHERE role = 'admin' AND NOT deleted LIMIT 1").fetchone()
|
||||
admin = conn.execute("SELECT id FROM users WHERE role = 'admin' AND COALESCE(deleted,0)=0 LIMIT 1").fetchone()
|
||||
admin_id = admin["id"] if admin else 1
|
||||
user_id = user.get("id")
|
||||
if user_id:
|
||||
@@ -786,7 +786,7 @@ def create_recipe(recipe: RecipeIn, user=Depends(get_current_user)):
|
||||
# Senior editors adding directly to public library: set owner to admin so everyone can see
|
||||
owner_id = user["id"]
|
||||
if user["role"] in ("senior_editor",):
|
||||
admin = c.execute("SELECT id FROM users WHERE role = 'admin' AND NOT deleted LIMIT 1").fetchone()
|
||||
admin = c.execute("SELECT id FROM users WHERE role = 'admin' AND COALESCE(deleted,0)=0 LIMIT 1").fetchone()
|
||||
if admin:
|
||||
owner_id = admin["id"]
|
||||
c.execute("INSERT INTO recipes (name, note, owner_id) VALUES (?, ?, ?)",
|
||||
@@ -1063,7 +1063,7 @@ def delete_tag(name: str, user=Depends(require_role("admin"))):
|
||||
@app.get("/api/users")
|
||||
def list_users(user=Depends(require_role("admin"))):
|
||||
conn = get_db()
|
||||
rows = conn.execute("SELECT id, username, token, role, display_name, created_at, business_verified FROM users WHERE NOT deleted ORDER BY id").fetchall()
|
||||
rows = conn.execute("SELECT id, username, token, role, display_name, created_at, business_verified FROM users WHERE COALESCE(deleted,0)=0 ORDER BY id").fetchall()
|
||||
conn.close()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
@@ -1092,7 +1092,7 @@ def delete_user(user_id: int, user=Depends(require_role("admin"))):
|
||||
if user_id == user["id"]:
|
||||
raise HTTPException(400, "不能删除自己")
|
||||
conn = get_db()
|
||||
target = conn.execute("SELECT id, username, display_name FROM users WHERE id = ? AND NOT deleted", (user_id,)).fetchone()
|
||||
target = conn.execute("SELECT id, username, display_name FROM users WHERE id = ? AND COALESCE(deleted,0)=0", (user_id,)).fetchone()
|
||||
if not target:
|
||||
conn.close()
|
||||
raise HTTPException(404, "User not found")
|
||||
@@ -1690,7 +1690,7 @@ def mark_notification_added(nid: int, user=Depends(get_current_user)):
|
||||
requester_name = body_text.split(" 搜索了")[0].strip()
|
||||
# Find the user
|
||||
requester = conn.execute(
|
||||
"SELECT id, role FROM users WHERE (display_name = ? OR username = ?) AND NOT deleted",
|
||||
"SELECT id, role FROM users WHERE (display_name = ? OR username = ?) AND COALESCE(deleted,0)=0",
|
||||
(requester_name, requester_name)
|
||||
).fetchone()
|
||||
if requester:
|
||||
@@ -1734,7 +1734,7 @@ def weekly_review(user=Depends(require_role("admin"))):
|
||||
conn = get_db()
|
||||
|
||||
# 1. Pending recipes for admin review
|
||||
admin = conn.execute("SELECT id FROM users WHERE role = 'admin' AND NOT deleted LIMIT 1").fetchone()
|
||||
admin = conn.execute("SELECT id FROM users WHERE role = 'admin' AND COALESCE(deleted,0)=0 LIMIT 1").fetchone()
|
||||
admin_id = admin["id"] if admin else 1
|
||||
pending = conn.execute(
|
||||
"SELECT COUNT(*) as cnt FROM recipes WHERE owner_id != ?", (admin_id,)
|
||||
|
||||
Reference in New Issue
Block a user