gitscope
← marzneshin / v0.3.2 / app/routes/admin.py
https://dev.kronoz.win/r/marzneshin.git
app/routes/admin.py · Python
Blame Raw
  1from typing import Optional, Annotated
  2
  3import sqlalchemy
  4from fastapi import APIRouter
  5from fastapi import Depends, HTTPException, status
  6from fastapi.security import OAuth2PasswordRequestForm
  7from fastapi_pagination import Page
  8from fastapi_pagination.ext.sqlalchemy import paginate
  9
 10from app.db import Session, crud
 11from app.db.models import Admin as DBAdmin
 12from app.dependencies import AdminDep, SudoAdminDep, DBDep
 13from app.models.admin import Admin, AdminCreate, AdminInDB, AdminModify, Token
 14from app.utils.auth import create_admin_token
 15
 16router = APIRouter(tags=["Admin"], prefix="/admins")
 17
 18
 19def authenticate_admin(
 20    db: Session, username: str, password: str
 21) -> Optional[Admin]:
 22    dbadmin = crud.get_admin(db, username)
 23    if not dbadmin:
 24        return None
 25
 26    return (
 27        dbadmin
 28        if AdminInDB.model_validate(dbadmin).verify_password(password)
 29        else None
 30    )
 31
 32
 33@router.get("", response_model=Page[Admin])
 34def get_admins(db: DBDep, admin: SudoAdminDep, username: str | None = None):
 35    query = db.query(DBAdmin)
 36    if username:
 37        query = query.filter(DBAdmin.username.ilike(f"%{username}%"))
 38    return paginate(db, query)
 39
 40
 41@router.post("", response_model=Admin)
 42def create_admin(new_admin: AdminCreate, db: DBDep, admin: SudoAdminDep):
 43    try:
 44        dbadmin = crud.create_admin(db, new_admin)
 45    except sqlalchemy.exc.IntegrityError:
 46        db.rollback()
 47        raise HTTPException(status_code=409, detail="Admin already exists")
 48
 49    return dbadmin
 50
 51
 52@router.get("/current", response_model=Admin)
 53def get_current_admin(admin: AdminDep):
 54    return admin
 55
 56
 57@router.post("/token", response_model=Token)
 58def admin_token(
 59    form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db: DBDep
 60):
 61    if dbadmin := authenticate_admin(
 62        db, form_data.username, form_data.password
 63    ):
 64        return Token(
 65            is_sudo=dbadmin.is_sudo,
 66            access_token=create_admin_token(
 67                form_data.username, is_sudo=dbadmin.is_sudo
 68            ),
 69        )
 70
 71    raise HTTPException(
 72        status_code=status.HTTP_401_UNAUTHORIZED,
 73        detail="Incorrect username or password",
 74        headers={"WWW-Authenticate": "Bearer"},
 75    )
 76
 77
 78@router.put("/{username}", response_model=Admin)
 79def modify_admin(
 80    username: str, modified_admin: AdminModify, db: DBDep, admin: AdminDep
 81):
 82    if not (admin.is_sudo or admin.username == username):
 83        raise HTTPException(status_code=403, detail="You're not allowed")
 84
 85    # If a non-sudoer admin is making itself a sudoer
 86    if (admin.username == username) and (
 87        modified_admin.is_sudo and not admin.is_sudo
 88    ):
 89        raise HTTPException(
 90            status_code=403, detail="You can't make yourself sudoer!"
 91        )
 92
 93    dbadmin = crud.get_admin(db, username)
 94    if not dbadmin:
 95        raise HTTPException(status_code=404, detail="Admin not found")
 96
 97    # If a sudoer admin wants to edit another sudoer
 98    if username != admin.username and dbadmin.is_sudo:
 99        raise HTTPException(
100            status_code=403,
101            detail="You're not allowed to edit another sudoers account. Use marzneshin-cli instead.",
102        )
103
104    dbadmin = crud.update_admin(db, dbadmin, modified_admin)
105    return dbadmin
106
107
108@router.delete("/{username}")
109def remove_admin(username: str, db: DBDep, admin: SudoAdminDep):
110    dbadmin = crud.get_admin(db, username)
111    if not dbadmin:
112        raise HTTPException(status_code=404, detail="Admin not found")
113
114    if dbadmin.is_sudo:
115        raise HTTPException(
116            status_code=403,
117            detail="You're not allowed to delete sudoers accounts. Use marzneshin-cli instead.",
118        )
119
120    crud.remove_admin(db, dbadmin)
121    return {}