Case-insensitive login, auto-matching after scan, per-library sources
- auth: username lookup is now case-insensitive via func.lower() - scanner: trigger match_audiobook for each newly found item after scan - matcher: read match_sources from library settings; refactored to loop over configured sources in priority order instead of hardcoded sequence - schemas/routers: expose matchSources in LibraryOut API response - Admin UI: pill-toggle for MusicBrainz/Open Library/Google Books per library Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from datetime import datetime
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import select, func
|
||||
from ..database import AsyncSessionLocal
|
||||
from ..dependencies import get_db, get_current_user
|
||||
from ..models.user import User
|
||||
@@ -42,7 +42,7 @@ def _build_user_out(user: User) -> UserOut:
|
||||
@router.post("/login", response_model=LoginResponse)
|
||||
async def login(body: LoginRequest, db: AsyncSession = Depends(get_db)):
|
||||
result = await db.execute(
|
||||
select(User).where(User.username == body.username, User.is_active == True)
|
||||
select(User).where(func.lower(User.username) == body.username.lower(), User.is_active == True)
|
||||
)
|
||||
user = result.scalar_one_or_none()
|
||||
if not user or not verify_password(body.password, user.password_hash):
|
||||
|
||||
Reference in New Issue
Block a user