Files
Calendarr/backend/routers/users_router.py
Scarriffle 4f3db6142d Fix: Login case-insensitive, Settings zusammengeführt, SVG-Icon, Copyright einzeilig
- Login: Benutzername wird case-insensitiv verglichen (func.lower auf beiden Seiten)
- Benutzer anlegen: Username wird immer lowercase gespeichert
- Einstellungen: Panels "Darstellung", "Ansicht & Raster" und "Ausgeblendete Kalender" zu einem einzigen Panel zusammengeführt
- App-Icon: Emoji 📅 durch plattformunabhängiges Inline-SVG ersetzt
- Copyright: white-space:nowrap +   damit Zeile nie umbricht
2026-03-27 14:50:16 +01:00

91 lines
2.4 KiB
Python

from typing import Optional
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy import func
from sqlalchemy.orm import Session
import models
from auth import get_current_admin, get_current_user, get_password_hash
from database import get_db
router = APIRouter()
class CreateUserRequest(BaseModel):
username: str
password: str
email: Optional[str] = None
is_admin: bool = False
class ChangePasswordRequest(BaseModel):
password: str
def _user_dict(u: models.User) -> dict:
return {"id": u.id, "username": u.username, "email": u.email, "is_admin": u.is_admin}
@router.get("/")
def list_users(
db: Session = Depends(get_db),
_: models.User = Depends(get_current_admin),
):
return [_user_dict(u) for u in db.query(models.User).all()]
@router.post("/")
def create_user(
req: CreateUserRequest,
db: Session = Depends(get_db),
_: models.User = Depends(get_current_admin),
):
if db.query(models.User).filter(func.lower(models.User.username) == req.username.lower()).first():
raise HTTPException(400, "Username already taken")
user = models.User(
username=req.username.lower(),
email=req.email,
password_hash=get_password_hash(req.password),
is_admin=req.is_admin,
)
db.add(user)
db.flush()
db.add(models.UserSettings(user_id=user.id))
db.commit()
db.refresh(user)
return _user_dict(user)
@router.delete("/{user_id}")
def delete_user(
user_id: int,
db: Session = Depends(get_db),
current_user: models.User = Depends(get_current_admin),
):
if user_id == current_user.id:
raise HTTPException(400, "Cannot delete yourself")
user = db.query(models.User).filter(models.User.id == user_id).first()
if not user:
raise HTTPException(404, "User not found")
db.delete(user)
db.commit()
return {"ok": True}
@router.put("/{user_id}/password")
def change_password(
user_id: int,
req: ChangePasswordRequest,
db: Session = Depends(get_db),
current_user: models.User = Depends(get_current_user),
):
if not current_user.is_admin and current_user.id != user_id:
raise HTTPException(403, "Not authorized")
user = db.query(models.User).filter(models.User.id == user_id).first()
if not user:
raise HTTPException(404, "User not found")
user.password_hash = get_password_hash(req.password)
db.commit()
return {"ok": True}