barker/barker/barker/routers/user.py

200 lines
6.5 KiB
Python

import uuid
import barker.schemas.user as schemas
from barker.core.security import get_current_active_user as get_user
from barker.db.session import SessionFuture
from barker.models.kot import Kot
from barker.models.login_history import LoginHistory
from barker.models.reprint import Reprint
from barker.models.role import Role
from barker.models.user import User
from barker.models.user_roles import user_roles
from barker.models.voucher import Voucher
from barker.schemas.user_token import UserToken
from fastapi import APIRouter, Depends, HTTPException, Security, status
from sqlalchemy import delete, select, update
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
router = APIRouter()
@router.post("", response_model=schemas.User)
def save(
data: schemas.UserIn,
user: UserToken = Security(get_user, scopes=["users"]),
) -> schemas.User:
try:
with SessionFuture() as db:
item = User(name=data.name, password=data.password, locked_out=data.locked_out)
db.add(item)
add_roles(item, data.roles, db)
db.commit()
return user_info(item, db, user)
except SQLAlchemyError as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e),
)
@router.get("/me", response_model=schemas.UserMe)
def show_me(
user: UserToken = Depends(get_user),
) -> schemas.UserMe:
with SessionFuture() as db:
item = db.execute(select(User).where(User.id == user.id_)).scalar_one()
return user_me(item)
@router.put("/me", response_model=schemas.UserMe)
def update_me(
data: schemas.UserIn,
user: UserToken = Depends(get_user),
) -> schemas.UserMe:
try:
with SessionFuture() as db:
item: User = db.execute(select(User).where(User.id == user.id_)).scalar_one()
if data.password and item.password != data.password:
item.password = data.password
db.commit()
return user_me(item)
except SQLAlchemyError as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e),
)
@router.put("/{id_}", response_model=schemas.User)
def update_route(
id_: uuid.UUID,
data: schemas.UserIn,
user: UserToken = Security(get_user, scopes=["users"]),
) -> schemas.User:
try:
with SessionFuture() as db:
item: User = db.execute(select(User).where(User.id == id_)).scalar_one()
item.name = data.name
if data.password and item.password != data.password:
item.password = data.password
item.locked_out = data.locked_out
add_roles(item, data.roles, db)
db.commit()
return user_info(item, db, user)
except SQLAlchemyError as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e),
)
def add_roles(user: User, roles: list[schemas.RoleItem], db: Session):
for role in roles:
ug = next((g for g in user.roles if g.id == role.id_), None)
if role.enabled and ug is None:
user.roles.append(db.execute(select(Role).where(Role.id == role.id_)).scalar_one())
elif not role.enabled and ug:
user.roles.remove(ug)
@router.delete("/{id_}")
def delete_route(
id_: uuid.UUID,
user: UserToken = Security(get_user, scopes=["users"]),
):
if id_ == user.id_:
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="You cannot delete yourself",
)
with SessionFuture() as db:
item: User = db.execute(select(User).where(User.id == id_)).scalar_one()
admin: User = db.execute(select(User).where(User.name.ilike("admin"))).scalar_one()
db.execute(update(Voucher).where(Voucher.user_id == item.id).values(user_id=admin.id))
db.execute(update(Kot).where(Kot.user_id == item.id).values(user_id=admin.id))
db.execute(update(Reprint).where(Reprint.user_id == item.id).values(user_id=admin.id))
db.execute(delete(LoginHistory).where(LoginHistory.user_id == item.id))
db.execute(delete(user_roles).where(user_roles.c.user_id == item.id))
db.execute(delete(User).where(User.id == item.id))
db.commit()
@router.get("", response_model=schemas.UserIn)
def show_blank(
user: UserToken = Security(get_user, scopes=["users"]),
) -> schemas.UserIn:
with SessionFuture() as db:
return blank_user_info(db)
@router.get("/list", response_model=list[schemas.UserList])
def show_list(
user: UserToken = Security(get_user, scopes=["users"]),
) -> list[schemas.UserList]:
with SessionFuture() as db:
return [
schemas.UserList(
id=item.id,
name=item.name,
lockedOut=item.locked_out,
roles=[p.name for p in sorted(item.roles, key=lambda p: p.name)],
lastDevice=item.login_history[0].device.name if len(item.login_history) else "Never",
lastDate=item.login_history[0].date if len(item.login_history) else None,
)
for item in db.execute(select(User).order_by(User.name)).scalars().all()
]
@router.get("/{id_}", response_model=schemas.User)
def show_id(
id_: uuid.UUID,
user: UserToken = Security(get_user, scopes=["users"]),
) -> schemas.User:
with SessionFuture() as db:
item = db.execute(select(User).where(User.id == id_)).scalar_one()
return user_info(item, db, user)
def user_info(item: User, db: Session, user: UserToken) -> schemas.User:
return schemas.User(
id=item.id,
name=item.name,
password="",
lockedOut=item.locked_out,
roles=[
{
"id": r.id,
"name": r.name,
"enabled": True if r in item.roles else False,
}
for r in db.execute(select(Role).order_by(Role.name)).scalars().all()
]
if "users" in user.permissions
else [],
)
def user_me(item: User) -> schemas.UserMe:
return schemas.UserMe(
id="me",
name=item.name,
password="",
lockedOut=item.locked_out,
roles=[],
)
def blank_user_info(db: Session) -> schemas.UserIn:
return schemas.UserIn(
name="",
password="",
lockedOut=False,
roles=[
{"id": r.id, "name": r.name, "enabled": False}
for r in db.execute(select(Role).order_by(Role.name)).scalars().all()
],
)