diff --git a/med_backend/auth/schemas.py b/med_backend/auth/schemas.py index 435c3dd..8f87eab 100644 --- a/med_backend/auth/schemas.py +++ b/med_backend/auth/schemas.py @@ -45,3 +45,12 @@ class User(UserBase): class Config: orm_mode = True + + +class UpdateUserBase(UserBase): + fullname: str + + +class UpdateUserProfile(UpdateUserBase): + disabled: bool + is_manager: bool diff --git a/med_backend/auth/views.py b/med_backend/auth/views.py index 82f4fa1..581a330 100644 --- a/med_backend/auth/views.py +++ b/med_backend/auth/views.py @@ -5,7 +5,14 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from starlette import status -from med_backend.auth.schemas import Token, User, UserCreate, UserLogin, UserPublicInfo +from med_backend.auth.schemas import ( + Token, + UpdateUserProfile, + User, + UserCreate, + UserLogin, + UserPublicInfo, +) from med_backend.auth.services import ( ACCESS_TOKEN_EXPIRE_MINUTES, authenticate_user, @@ -13,7 +20,7 @@ from med_backend.auth.services import ( get_current_active_user, ) from med_backend.db.dependencies import get_db_session -from med_backend.users.crud import create_user +from med_backend.users.crud import create_user, delete_user, update_user router = APIRouter() @@ -48,7 +55,26 @@ async def create_user_view( @router.get("/me", response_model=UserPublicInfo) -async def read_users_me( +async def get_self( current_user: User = Depends(get_current_active_user), ) -> User: return current_user + + +@router.put("/me") +async def update_self( + data: UpdateUserProfile, + current_user: User = Depends(get_current_active_user), + session: AsyncSession = Depends(get_db_session), +): + await update_user(session, current_user.id, data) + return {"detail": "updated"} + + +@router.delete("/me") +async def update_self( + current_user: User = Depends(get_current_active_user), + session: AsyncSession = Depends(get_db_session), +): + await delete_user(session, current_user.id) + return {"detail": "updated"} diff --git a/med_backend/forms/crud.py b/med_backend/forms/crud.py index 076098f..659fae5 100644 --- a/med_backend/forms/crud.py +++ b/med_backend/forms/crud.py @@ -1,7 +1,7 @@ from typing import List from fastapi import HTTPException -from sqlalchemy import select, update +from sqlalchemy import delete, literal_column, select, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -171,7 +171,7 @@ async def create_user_form_rev_question( ref_min=ref_min, ) session.add(rev) - await session.commit() + await session.commit() await session.refresh(rev) return rev @@ -255,3 +255,68 @@ async def get_submissions(session: AsyncSession, form_id: int) -> List[FullSubmi ) res.append(FullSubmission(fio=submission.user.fullname, answers=answers)) return res + + +async def update_form(session: AsyncSession, data: BaseForm, form_id: int): + form = await get_form(session, form_id) + if not form: + raise HTTPException(status_code=422, detail="Form can't be used") + + await session.execute( + update(FormScheme).where(FormScheme.id == form_id).values(**dict(data)), + ) + await session.commit() + return + + +async def delete_form(session: AsyncSession, form_id: int): + form = await get_form(session, form_id) + if not form: + raise HTTPException(status_code=422, detail="Form can't be used") + + await session.execute( + delete(FormScheme).where(FormScheme.id == form_id), + ) + await session.commit() + return + + +async def get_form_field(session: AsyncSession, field_id: int) -> FormQuestion | None: + r = await session.execute( + select(FormQuestion) + .options(selectinload(FormQuestion.form)) + .where(FormQuestion.id == field_id), + ) + form = r.scalars().first() + return form + + +async def update_form_field( + session: AsyncSession, + data: CreateFormField, + field_id: int, +): + field = await get_form_field(session, field_id) + if not field: + raise HTTPException(status_code=422, detail="No such field") + r = await session.execute( + update(FormQuestion) + .where(FormQuestion.id == field_id) + .values(**dict(data)) + .returning(literal_column("*")), + ) + await session.commit() + field = r.scalars().first() + return field + + +async def delete_form_field(session: AsyncSession, field_id: int): + field = await get_form_field(session, field_id) + if not field: + raise HTTPException(status_code=422, detail="Field can't be used") + + await session.execute( + delete(FormQuestion).where(FormQuestion.id == field_id), + ) + await session.commit() + return diff --git a/med_backend/forms/views.py b/med_backend/forms/views.py index 0ef4e97..4ea5e37 100644 --- a/med_backend/forms/views.py +++ b/med_backend/forms/views.py @@ -67,14 +67,48 @@ async def get_form( return form +@router.put("/{form_id}", response_model=Form) +async def update_form( + form_id: int, + data: BaseForm, + current_user: User = Depends(get_current_active_manager), + session: AsyncSession = Depends(get_db_session), +) -> Form: + form = await crud.get_form(session, form_id) + if form.user_id != current_user.id: + raise HTTPException( + status_code=401, + detail="You are not allowed to access this form", + ) + await crud.update_form(session, data, form_id) + form = await services.get_full_form(session, form_id) + return form + + +@router.delete("/{form_id}") +async def delete_form( + form_id: int, + current_user: User = Depends(get_current_active_user), + session: AsyncSession = Depends(get_db_session), +): + form = await crud.get_form(session, form_id) + if form.user_id != current_user.id: + raise HTTPException( + status_code=401, + detail="You are not allowed to access this form", + ) + await crud.delete_form(session, form_id) + return {"detail": "deleted"} + + @router.get("/{form_id}/answers", response_model=List[FullSubmission]) -async def get_form( +async def get_submissions( form_id: int, current_user: User = Depends(get_current_active_manager), session: AsyncSession = Depends(get_db_session), ): form = await crud.get_form(session, form_id) - if form.user.id != current_user.id: + if form.user_id != current_user.id: raise HTTPException( status_code=401, detail="You are not allowed to access this form", @@ -90,7 +124,7 @@ async def create_form_field_view( session: AsyncSession = Depends(get_db_session), ): form = await crud.get_form(session, form_id) - if form.user.id != current_user.id: + if form.user_id != current_user.id: raise HTTPException( status_code=401, detail="You are not allowed to access this form", @@ -118,7 +152,7 @@ async def create_assigment_view( session: AsyncSession = Depends(get_db_session), ): form = await services.get_form(session, form_id) - if form.user.id != current_user.id: + if form.user_id != current_user.id: raise HTTPException( status_code=401, detail="You are not allowed to access this form", @@ -136,3 +170,47 @@ async def submit_form_view( ): await submit_form(session, data, form_id, current_user.id) return {"message": "created"} + + +@router.get("/field/{field_id}", response_model=FormField) +async def get_form_field( + field_id: int, + current_user: User = Depends(get_current_active_user), + session: AsyncSession = Depends(get_db_session), +): + field = await crud.get_form_field(session, field_id) + return field + + +@router.put("/field/{field_id}", response_model=FormField) +async def update_form_field( + field_id: int, + data: CreateFormField, + current_user: User = Depends(get_current_active_manager), + session: AsyncSession = Depends(get_db_session), +): + field = await crud.get_form_field(session, field_id) + if field.form.user_id != current_user.id: + raise HTTPException( + status_code=401, + detail="You are not allowed to access this form", + ) + await crud.update_form_field(session, data, field_id) + field = await crud.get_form_field(session, field_id) + return field + + +@router.delete("/field/{field_id}", response_model=FormField) +async def delete_form_field( + field_id: int, + current_user: User = Depends(get_current_active_manager), + session: AsyncSession = Depends(get_db_session), +): + field = await crud.get_form_field(session, field_id) + if field.form.user_id != current_user.id: + raise HTTPException( + status_code=401, + detail="You are not allowed to access this form", + ) + await crud.delete_form_field(session, field_id) + return {"detail": "deleted"} diff --git a/med_backend/users/crud.py b/med_backend/users/crud.py index 7a32c4c..9d9fa79 100644 --- a/med_backend/users/crud.py +++ b/med_backend/users/crud.py @@ -1,10 +1,11 @@ from typing import List from fastapi import HTTPException -from sqlalchemy import select +from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession from med_backend.auth import schemas, services +from med_backend.auth.schemas import UpdateUserProfile from med_backend.db.models.users import UserScheme @@ -52,3 +53,20 @@ async def create_user(session: AsyncSession, user: schemas.UserCreate) -> UserSc await session.commit() await session.refresh(db_user) return db_user + + +async def update_user(session: AsyncSession, user_id: int, data: UpdateUserProfile): + if await get_user_by_email(session, data.email): + raise HTTPException(status_code=422, detail="Email already taken") + + await session.execute( + update(UserScheme).where(UserScheme.id == user_id).values(**dict(data)), + ) + await session.commit() + + +async def delete_user(session: AsyncSession, user_id: int): + await session.execute( + delete(UserScheme).where(UserScheme.id == user_id), + ) + await session.commit() diff --git a/med_backend/users/views.py b/med_backend/users/views.py index 4755867..24dfa58 100644 --- a/med_backend/users/views.py +++ b/med_backend/users/views.py @@ -1,7 +1,7 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession -from med_backend.auth.schemas import User +from med_backend.auth.schemas import UpdateUserProfile, User from med_backend.db.dependencies import get_db_session from med_backend.users import crud from med_backend.users.schemas import FullUser, ListUser @@ -31,3 +31,30 @@ async def get_user( if not user: raise HTTPException(status_code=404, detail="User not found") return user + + +@router.put("/{key}", response_model=FullUser) +async def update_user( + key: int, + data: UpdateUserProfile, + current_user: User = Depends(get_current_active_manager), + session: AsyncSession = Depends(get_db_session), +) -> User: + user = await crud.get_user(session, key) + if not user: + raise HTTPException(status_code=404, detail="User not found") + await crud.update_user(session, key, data) + return user + + +@router.delete("/{key}") +async def delete_user( + key: int, + current_user: User = Depends(get_current_active_manager), + session: AsyncSession = Depends(get_db_session), +): + user = await crud.get_user(session, key) + if not user: + raise HTTPException(status_code=404, detail="User not found") + await crud.delete_user(session, key) + return {"detail": "deleted"}