"""Self-service user endpoints (the authenticated caller acts on themselves).""" from fastapi import APIRouter, status from app.api.deps import CurrentUser, SubsonicAuthServiceDep, UserServiceDep from app.api.schemas.subsonic import SubsonicPasswordResponse from app.api.schemas.user import ChangePasswordRequest router = APIRouter(prefix="/users", tags=["users"]) @router.patch("/me/password", status_code=status.HTTP_204_NO_CONTENT) async def change_my_password( body: ChangePasswordRequest, user: CurrentUser, users: UserServiceDep ) -> None: await users.change_password( user.id, current_password=body.current_password, new_password=body.new_password, ) @router.get("/me/subsonic-password", response_model=SubsonicPasswordResponse) async def reveal_my_subsonic_password( user: CurrentUser, subsonic: SubsonicAuthServiceDep ) -> SubsonicPasswordResponse: """Reveal the caller's Subsonic app-password for copying into a client. It's recoverable, so it can be read on demand; one is generated lazily on first access. Paste it (with the username) into Symfonium/DSub.""" return SubsonicPasswordResponse(password=await subsonic.reveal(user.id)) @router.post("/me/subsonic-password", response_model=SubsonicPasswordResponse) async def rotate_my_subsonic_password( user: CurrentUser, subsonic: SubsonicAuthServiceDep ) -> SubsonicPasswordResponse: """Rotate the caller's Subsonic app-password (invalidates the previous one).""" return SubsonicPasswordResponse(password=await subsonic.rotate(user.id))