diff --git a/app/auth.py b/app/auth.py index 73bdb15..356a73c 100644 --- a/app/auth.py +++ b/app/auth.py @@ -111,13 +111,15 @@ async def authenticate_user_legacy(db: AsyncSession, name: str, password: str) - pw_md5 = hashlib.md5(password.encode()).hexdigest() # 2. 根据用户名查找用户 - statement = select(User).where(User.username == name).options() - user = (await db.exec(statement)).first() - if not user: + user = None + user = (await db.exec(select(User).where(User.username == name))).first() + if user is None: + user = (await db.exec(select(User).where(User.email == name))).first() + if user is None and name.isdigit(): + user = (await db.exec(select(User).where(User.id == int(name)))).first() + if user is None: return None - await db.refresh(user) - # 3. 验证密码 if user.pw_bcrypt is None or user.pw_bcrypt == "": return None diff --git a/app/router/auth.py b/app/router/auth.py index ca92c91..b667324 100644 --- a/app/router/auth.py +++ b/app/router/auth.py @@ -42,7 +42,7 @@ from fastapi import APIRouter, Depends, Form, Request from fastapi.responses import JSONResponse from redis.asyncio import Redis from sqlalchemy import text -from sqlmodel import select +from sqlmodel import exists, select def create_oauth_error_response(error: str, description: str, hint: str, status_code: int = 400): @@ -101,12 +101,12 @@ async def register_user( email_errors = validate_email(user_email) password_errors = validate_password(user_password) - result = await db.exec(select(User).where(User.username == user_username)) + result = await db.exec(select(exists()).where(User.username == user_username)) existing_user = result.first() if existing_user: username_errors.append("Username is already taken") - result = await db.exec(select(User).where(User.email == user_email)) + result = await db.exec(select(exists()).where(User.email == user_email)) existing_email = result.first() if existing_email: email_errors.append("Email is already taken") diff --git a/app/router/private/username.py b/app/router/private/username.py index 312d257..dd6a7b7 100644 --- a/app/router/private/username.py +++ b/app/router/private/username.py @@ -11,7 +11,7 @@ from app.utils import utcnow from .router import router from fastapi import Body, HTTPException, Security -from sqlmodel import select +from sqlmodel import exists, select @router.post( @@ -34,7 +34,7 @@ async def user_rename( 返回: - 成功: None """ - samename_user = (await session.exec(select(User).where(User.username == new_name))).first() + samename_user = (await session.exec(select(exists()).where(User.username == new_name))).first() if samename_user: raise HTTPException(409, "Username Exisits") errors = validate_username(new_name) diff --git a/migrations/versions/af88493881eb_user_change_collation_for_username_and_.py b/migrations/versions/af88493881eb_user_change_collation_for_username_and_.py new file mode 100644 index 0000000..6bdaece --- /dev/null +++ b/migrations/versions/af88493881eb_user_change_collation_for_username_and_.py @@ -0,0 +1,54 @@ +"""user: change collation for username and email + +Revision ID: af88493881eb +Revises: 34a563187e47 +Create Date: 2025-08-26 11:31:07.183273 + +""" + +from __future__ import annotations + +from collections.abc import Sequence + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "af88493881eb" +down_revision: str | Sequence[str] | None = "34a563187e47" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + """Upgrade schema.""" + # 1. 删除现有索引 + op.drop_index("ix_lazer_users_email", table_name="lazer_users") + op.drop_index("ix_lazer_users_username", table_name="lazer_users") + + # 2. 修改字段 collation 为 utf8mb4_general_ci + op.execute(""" + ALTER TABLE lazer_users + MODIFY username VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + MODIFY email VARCHAR(254) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL; + """) + + # 3. 重新创建唯一索引(大小写不敏感) + op.create_index(op.f("ix_lazer_users_email"), "lazer_users", ["email"], unique=True) + op.create_index(op.f("ix_lazer_users_username"), "lazer_users", ["username"], unique=True) + + +def downgrade() -> None: + # 1. 删除索引 + op.drop_index("ix_lazer_users_email", table_name="lazer_users") + op.drop_index("ix_lazer_users_username", table_name="lazer_users") + + # 2. 恢复原 collation(假设原来是 utf8mb4_bin) + op.execute(""" + ALTER TABLE lazer_users + MODIFY username VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, + MODIFY email VARCHAR(254) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL; + """) + + # 3. 恢复原索引 + op.create_index(op.f("ix_lazer_users_email"), "lazer_users", ["email"], unique=True) + op.create_index(op.f("ix_lazer_users_username"), "lazer_users", ["username"], unique=True)