mirror of
https://github.com/FutureOfMedTech-FITM-hack/backend.git
synced 2024-11-21 22:16:33 +03:00
added forms
This commit is contained in:
parent
5961d7dbe0
commit
145c322fb5
|
@ -9,10 +9,9 @@ from passlib.context import CryptContext
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from med_backend.auth.schemas import TokenData, User
|
from med_backend.auth.schemas import TokenData, User
|
||||||
|
from med_backend.db.dependencies import get_db_session
|
||||||
from med_backend.settings import settings
|
from med_backend.settings import settings
|
||||||
|
from med_backend.users.crud import get_user_by_email
|
||||||
from ..db.dependencies import get_db_session
|
|
||||||
from . import crud
|
|
||||||
|
|
||||||
SECRET_KEY = config("SECRET")
|
SECRET_KEY = config("SECRET")
|
||||||
JWT_ALGORITHM = settings.JWT_ALGORITHM
|
JWT_ALGORITHM = settings.JWT_ALGORITHM
|
||||||
|
@ -33,7 +32,7 @@ def get_password_hash(password: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
async def get_user(session: AsyncSession, email: str) -> User:
|
async def get_user(session: AsyncSession, email: str) -> User:
|
||||||
db_user = await crud.get_user_by_email(session, email=email)
|
db_user = await get_user_by_email(session, email=email)
|
||||||
if db_user is None:
|
if db_user is None:
|
||||||
raise HTTPException(status_code=404, detail="User not found")
|
raise HTTPException(status_code=404, detail="User not found")
|
||||||
return db_user
|
return db_user
|
||||||
|
@ -96,16 +95,3 @@ async def get_current_active_user(
|
||||||
if current_user.disabled:
|
if current_user.disabled:
|
||||||
raise HTTPException(status_code=400, detail="Inactive user")
|
raise HTTPException(status_code=400, detail="Inactive user")
|
||||||
return current_user
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
async def get_current_active_manager(
|
|
||||||
current_user: User = Depends(get_current_user),
|
|
||||||
) -> User:
|
|
||||||
if current_user.disabled:
|
|
||||||
raise HTTPException(status_code=400, detail="Inactive user")
|
|
||||||
if not current_user.is_manager:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
||||||
detail="You are not allowed to access this info",
|
|
||||||
)
|
|
||||||
return current_user
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from starlette import status
|
from starlette import status
|
||||||
|
|
||||||
from med_backend.auth.crud import create_user
|
|
||||||
from med_backend.auth.schemas import Token, User, UserCreate, UserLogin, UserPublicInfo
|
from med_backend.auth.schemas import Token, User, UserCreate, UserLogin, UserPublicInfo
|
||||||
from med_backend.auth.services import (
|
from med_backend.auth.services import (
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES,
|
ACCESS_TOKEN_EXPIRE_MINUTES,
|
||||||
|
@ -14,6 +13,7 @@ from med_backend.auth.services import (
|
||||||
get_current_active_user,
|
get_current_active_user,
|
||||||
)
|
)
|
||||||
from med_backend.db.dependencies import get_db_session
|
from med_backend.db.dependencies import get_db_session
|
||||||
|
from med_backend.users.crud import create_user
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
147
med_backend/db/models/forms.py
Normal file
147
med_backend/db/models/forms.py
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from sqlalchemy import Column, ForeignKey, Integer, String
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
from med_backend.db.base import Base
|
||||||
|
from med_backend.db.models.users import UserScheme
|
||||||
|
|
||||||
|
|
||||||
|
class FormScheme(Base):
|
||||||
|
__tablename__ = "forms"
|
||||||
|
|
||||||
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
name: str = Column(String, nullable=False)
|
||||||
|
|
||||||
|
# user
|
||||||
|
user_id: int = Column(Integer, ForeignKey(UserScheme.id), primary_key=True)
|
||||||
|
user: UserScheme = relationship("UserScheme", foreign_keys="FormScheme.user_id")
|
||||||
|
|
||||||
|
questions: List["FormQuestion"] = relationship(
|
||||||
|
"FormQuestion",
|
||||||
|
back_populates="form",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FormQuestion(Base):
|
||||||
|
__tablename__ = "form_questions"
|
||||||
|
|
||||||
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# form
|
||||||
|
form_id: int = Column(Integer, ForeignKey(FormScheme.id), primary_key=True)
|
||||||
|
form: FormScheme = relationship("FormScheme", foreign_keys="FormQuestion.form_id")
|
||||||
|
|
||||||
|
type: str = Column(String, default="number")
|
||||||
|
question: str = Column(String, nullable=False)
|
||||||
|
ref_min: int = Column(Integer, nullable=True)
|
||||||
|
ref_max: int = Column(Integer, nullable=True)
|
||||||
|
|
||||||
|
|
||||||
|
class FormAssignment(Base):
|
||||||
|
__tablename__ = "form_assignment"
|
||||||
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
form_id: int = Column(Integer, ForeignKey(FormScheme.id), primary_key=True)
|
||||||
|
form: FormScheme = relationship("FormScheme", foreign_keys="FormAssignment.form_id")
|
||||||
|
|
||||||
|
user_id: int = Column(Integer, ForeignKey(UserScheme.id), primary_key=True)
|
||||||
|
user: UserScheme = relationship("UserScheme", foreign_keys="FormAssignment.user_id")
|
||||||
|
|
||||||
|
|
||||||
|
class UserRevQuestion(Base):
|
||||||
|
__tablename__ = "user_form_rev_question"
|
||||||
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# question
|
||||||
|
question_id: int = Column(Integer, ForeignKey(FormQuestion.id), primary_key=True)
|
||||||
|
question: FormQuestion = relationship(
|
||||||
|
"FormQuestion",
|
||||||
|
foreign_keys="UserRevQuestion.question_id",
|
||||||
|
)
|
||||||
|
|
||||||
|
# user
|
||||||
|
user_id: int = Column(Integer, ForeignKey(UserScheme.id), primary_key=True)
|
||||||
|
user: UserScheme = relationship(
|
||||||
|
"UserScheme",
|
||||||
|
foreign_keys="UserRevQuestion.user_id",
|
||||||
|
)
|
||||||
|
|
||||||
|
ref_min: int = Column(Integer, nullable=False)
|
||||||
|
ref_max: int = Column(Integer, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
class UserFormSubmission(Base):
|
||||||
|
__tablename__ = "user_form_submission"
|
||||||
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# form
|
||||||
|
form_id: int = Column(Integer, ForeignKey(FormScheme.id), primary_key=True)
|
||||||
|
form: FormScheme = relationship(
|
||||||
|
"FormScheme",
|
||||||
|
foreign_keys="UserFormSubmission.form_id",
|
||||||
|
)
|
||||||
|
|
||||||
|
# user
|
||||||
|
user_id: int = Column(Integer, ForeignKey(UserScheme.id), primary_key=True)
|
||||||
|
user: UserScheme = relationship(
|
||||||
|
"UserScheme",
|
||||||
|
foreign_keys="UserFormSubmission.user_id",
|
||||||
|
)
|
||||||
|
|
||||||
|
answers: List["UserFormFieldSubmission"] = relationship(
|
||||||
|
"UserFormFieldSubmission",
|
||||||
|
back_populates="submission",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserFormFieldSubmission(Base):
|
||||||
|
__tablename__ = "user_form_field_submission"
|
||||||
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# submission
|
||||||
|
submission_id: int = Column(
|
||||||
|
Integer,
|
||||||
|
ForeignKey(UserFormSubmission.id),
|
||||||
|
primary_key=True,
|
||||||
|
)
|
||||||
|
submission: UserFormSubmission = relationship(
|
||||||
|
"UserFormSubmission",
|
||||||
|
foreign_keys="UserFormFieldSubmission.submission_id",
|
||||||
|
)
|
|
@ -11,7 +11,13 @@ class UserScheme(Base):
|
||||||
|
|
||||||
__tablename__ = "users"
|
__tablename__ = "users"
|
||||||
|
|
||||||
id: int = Column(Integer, primary_key=True, index=True)
|
id: int = Column(
|
||||||
|
Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=True,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
email: EmailStr = Column(String, unique=True, index=True, nullable=False)
|
email: EmailStr = Column(String, unique=True, index=True, nullable=False)
|
||||||
fullname: str = Column(String, default="")
|
fullname: str = Column(String, default="")
|
||||||
hashed_password: str = Column(String)
|
hashed_password: str = Column(String)
|
||||||
|
|
5
med_backend/forms/__init__.py
Normal file
5
med_backend/forms/__init__.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
"""API for form creation and submitting"""
|
||||||
|
|
||||||
|
from med_backend.forms.views import router
|
||||||
|
|
||||||
|
__all__ = ["router"]
|
168
med_backend/forms/crud.py
Normal file
168
med_backend/forms/crud.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from fastapi import HTTPException
|
||||||
|
from sqlalchemy import select, update
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
|
from med_backend.db.models.forms import (
|
||||||
|
FormAssignment,
|
||||||
|
FormQuestion,
|
||||||
|
FormScheme,
|
||||||
|
UserRevQuestion,
|
||||||
|
)
|
||||||
|
from med_backend.forms.schemas import BaseForm, CreateFormField
|
||||||
|
from med_backend.users.crud import get_user
|
||||||
|
|
||||||
|
|
||||||
|
async def get_forms(
|
||||||
|
session: AsyncSession,
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
) -> List[FormScheme] | None:
|
||||||
|
r = await session.execute(
|
||||||
|
select(FormScheme).offset(skip).limit(limit),
|
||||||
|
)
|
||||||
|
forms = r.scalars().all()
|
||||||
|
return forms
|
||||||
|
|
||||||
|
|
||||||
|
async def get_form(session: AsyncSession, form_id: int) -> FormScheme | None:
|
||||||
|
r = await session.execute(select(FormScheme).where(FormScheme.id == form_id))
|
||||||
|
form = r.scalars().first()
|
||||||
|
return form
|
||||||
|
|
||||||
|
|
||||||
|
async def filter_form_assigment(
|
||||||
|
session: AsyncSession,
|
||||||
|
user_id: int,
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
) -> List[FormScheme] | None:
|
||||||
|
r = await session.execute(
|
||||||
|
select(FormScheme)
|
||||||
|
.outerjoin(FormAssignment)
|
||||||
|
.where(FormAssignment.user_id == user_id)
|
||||||
|
.offset(skip)
|
||||||
|
.limit(limit),
|
||||||
|
)
|
||||||
|
forms = r.scalars().fetchall()
|
||||||
|
return forms
|
||||||
|
|
||||||
|
|
||||||
|
async def get_questions(session: AsyncSession, form_id: int) -> List[FormQuestion]:
|
||||||
|
r = await session.execute(
|
||||||
|
select(FormQuestion).where(FormQuestion.form_id == form_id),
|
||||||
|
)
|
||||||
|
questions = r.scalars().all()
|
||||||
|
return questions
|
||||||
|
|
||||||
|
|
||||||
|
async def create_form(
|
||||||
|
session: AsyncSession,
|
||||||
|
form: BaseForm,
|
||||||
|
user_id: int,
|
||||||
|
) -> FormScheme:
|
||||||
|
user = await get_user(session, user_id)
|
||||||
|
if not user or not user.is_manager:
|
||||||
|
raise HTTPException(status_code=422, detail="User can't be used")
|
||||||
|
|
||||||
|
db_form = FormScheme(name=form.name, user_id=user_id)
|
||||||
|
session.add(db_form)
|
||||||
|
await session.commit()
|
||||||
|
await session.refresh(db_form)
|
||||||
|
return db_form
|
||||||
|
|
||||||
|
|
||||||
|
async def create_form_field(
|
||||||
|
session: AsyncSession,
|
||||||
|
field: CreateFormField,
|
||||||
|
user_id: int,
|
||||||
|
form_id: int,
|
||||||
|
) -> FormQuestion:
|
||||||
|
user = await get_user(session, user_id)
|
||||||
|
if not user or not user.is_manager:
|
||||||
|
raise HTTPException(status_code=422, detail="User can't be used")
|
||||||
|
|
||||||
|
form = await get_form(session, form_id)
|
||||||
|
if not form:
|
||||||
|
raise HTTPException(status_code=422, detail="Form can't be used")
|
||||||
|
|
||||||
|
if user.id != form.user_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=401,
|
||||||
|
detail="You are not allowed to access this form",
|
||||||
|
)
|
||||||
|
|
||||||
|
obj = FormQuestion(
|
||||||
|
form_id=form_id,
|
||||||
|
type=field.type,
|
||||||
|
question=field.question,
|
||||||
|
ref_min=field.ref_min,
|
||||||
|
ref_max=field.ref_max,
|
||||||
|
)
|
||||||
|
session.add(obj)
|
||||||
|
await session.commit()
|
||||||
|
await session.refresh(obj)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
async def create_form_assigment(session: AsyncSession, form_id: int, user_id: int):
|
||||||
|
user = await get_user(session, user_id)
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(status_code=422, detail="User can't be used")
|
||||||
|
|
||||||
|
form = await get_form(session, form_id)
|
||||||
|
if not form:
|
||||||
|
raise HTTPException(status_code=422, detail="Form can't be used")
|
||||||
|
|
||||||
|
assigment = await session.execute(
|
||||||
|
select(FormAssignment)
|
||||||
|
.where(FormAssignment.form_id == form_id)
|
||||||
|
.where(FormAssignment.user_id == user_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
if assigment.scalars().first():
|
||||||
|
return True
|
||||||
|
|
||||||
|
obj = FormAssignment(form_id=form_id, user_id=user_id)
|
||||||
|
session.add(obj)
|
||||||
|
await session.commit()
|
||||||
|
await session.refresh(obj)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def create_user_form_rev_question(
|
||||||
|
session: AsyncSession,
|
||||||
|
field_id: int,
|
||||||
|
user_id: int,
|
||||||
|
ref_min: int,
|
||||||
|
ref_max: int,
|
||||||
|
):
|
||||||
|
r = await session.execute(select(FormQuestion).where(FormQuestion.id == field_id))
|
||||||
|
field = r.scalars().first()
|
||||||
|
if not field:
|
||||||
|
raise HTTPException(status_code=422, detail="Such field doesn't exist")
|
||||||
|
|
||||||
|
r = await session.execute(
|
||||||
|
select(UserRevQuestion)
|
||||||
|
.where(UserRevQuestion.user_id == user_id)
|
||||||
|
.where(UserRevQuestion.question_id == field_id),
|
||||||
|
)
|
||||||
|
rev = r.scalars().first()
|
||||||
|
if rev:
|
||||||
|
await session.execute(
|
||||||
|
update(UserRevQuestion)
|
||||||
|
.where(UserRevQuestion.id == rev.id)
|
||||||
|
.values(ref_max=ref_max, ref_min=ref_min),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
rev = UserRevQuestion(
|
||||||
|
question_id=field_id,
|
||||||
|
user_id=user_id,
|
||||||
|
ref_max=ref_max,
|
||||||
|
ref_min=ref_min,
|
||||||
|
)
|
||||||
|
session.add(rev)
|
||||||
|
await session.commit()
|
||||||
|
await session.refresh(rev)
|
||||||
|
return rev
|
64
med_backend/forms/schemas.py
Normal file
64
med_backend/forms/schemas.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from med_backend.auth.schemas import UserPublicInfo
|
||||||
|
|
||||||
|
|
||||||
|
class Question(BaseModel):
|
||||||
|
id: int
|
||||||
|
type: str
|
||||||
|
question: str
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFormField(BaseModel):
|
||||||
|
type: str
|
||||||
|
question: str
|
||||||
|
ref_min: int | None
|
||||||
|
ref_max: int | None
|
||||||
|
|
||||||
|
|
||||||
|
class CreateFormField(BaseFormField):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class FormField(BaseFormField):
|
||||||
|
id: int
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class QuestionRef(BaseModel):
|
||||||
|
id: int
|
||||||
|
ref_min: int | None
|
||||||
|
ref_max: int | None
|
||||||
|
|
||||||
|
|
||||||
|
class FormAssigment(BaseModel):
|
||||||
|
user_id: int
|
||||||
|
question_refs: List[QuestionRef]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseForm(BaseModel):
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
|
class FormCreate(BaseForm):
|
||||||
|
user_id: int
|
||||||
|
|
||||||
|
|
||||||
|
class ListForm(BaseForm):
|
||||||
|
id: int
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Form(BaseForm):
|
||||||
|
id: int
|
||||||
|
user: UserPublicInfo
|
||||||
|
questions: List[Question]
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
43
med_backend/forms/services.py
Normal file
43
med_backend/forms/services.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
from fastapi import HTTPException
|
||||||
|
from pydantic import parse_obj_as
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
|
from med_backend.auth.schemas import UserPublicInfo
|
||||||
|
from med_backend.forms.crud import (
|
||||||
|
create_form_assigment,
|
||||||
|
create_user_form_rev_question,
|
||||||
|
get_form,
|
||||||
|
get_questions,
|
||||||
|
)
|
||||||
|
from med_backend.forms.schemas import Form, FormAssigment, Question
|
||||||
|
|
||||||
|
|
||||||
|
async def get_full_form(session: AsyncSession, form_id: int) -> Form:
|
||||||
|
form = await get_form(session, form_id)
|
||||||
|
if not form:
|
||||||
|
raise HTTPException(status_code=404, detail="Form doesn't exist")
|
||||||
|
questions = await get_questions(session, form_id)
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
id=form_id,
|
||||||
|
name=form.name,
|
||||||
|
user=parse_obj_as(UserPublicInfo, form.user),
|
||||||
|
questions=[
|
||||||
|
Question(id=q.id, type=q.type, question=q.question) for q in questions
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def assign_form(session: AsyncSession, data: FormAssigment, form_id: int):
|
||||||
|
form = await get_form(session, form_id)
|
||||||
|
if not form:
|
||||||
|
raise HTTPException(status_code=404, detail="Form doesn't exist")
|
||||||
|
await create_form_assigment(session, form_id, data.user_id)
|
||||||
|
for field in data.question_refs:
|
||||||
|
await create_user_form_rev_question(
|
||||||
|
session,
|
||||||
|
field.id,
|
||||||
|
data.user_id,
|
||||||
|
field.ref_min,
|
||||||
|
field.ref_max,
|
||||||
|
)
|
109
med_backend/forms/views.py
Normal file
109
med_backend/forms/views.py
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from starlette import status
|
||||||
|
|
||||||
|
from med_backend.auth.schemas import User
|
||||||
|
from med_backend.auth.services import get_current_active_user
|
||||||
|
from med_backend.db.dependencies import get_db_session
|
||||||
|
from med_backend.forms import crud, services
|
||||||
|
from med_backend.forms.schemas import (
|
||||||
|
BaseForm,
|
||||||
|
CreateFormField,
|
||||||
|
Form,
|
||||||
|
FormAssigment,
|
||||||
|
FormField,
|
||||||
|
ListForm,
|
||||||
|
)
|
||||||
|
from med_backend.forms.services import assign_form
|
||||||
|
from med_backend.users.services import get_current_active_manager
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/all", response_model=list[ListForm])
|
||||||
|
async def get_all_forms(
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
current_user: User = Depends(get_current_active_manager),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
):
|
||||||
|
forms = await crud.get_forms(session, skip, limit)
|
||||||
|
return forms
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/list", response_model=list[ListForm])
|
||||||
|
async def get_all_forms(
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
):
|
||||||
|
forms = await crud.filter_form_assigment(session, current_user.id, skip, limit)
|
||||||
|
return forms
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/create", response_model=Form)
|
||||||
|
async def create_form_view(
|
||||||
|
data: BaseForm,
|
||||||
|
current_user: User = Depends(get_current_active_manager),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
) -> Form:
|
||||||
|
db_form = await crud.create_form(session, data, current_user.id)
|
||||||
|
form = await services.get_full_form(session, db_form.id)
|
||||||
|
return form
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{form_id}", response_model=Form)
|
||||||
|
async def get_form(
|
||||||
|
form_id: int,
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
) -> Form:
|
||||||
|
form = await services.get_full_form(session, form_id)
|
||||||
|
return form
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{form_id}/fields", response_model=List[FormField])
|
||||||
|
async def create_form_field_view(
|
||||||
|
form_id: int,
|
||||||
|
current_user: User = Depends(get_current_active_manager),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
):
|
||||||
|
form = await services.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",
|
||||||
|
)
|
||||||
|
fields = await services.get_questions(session, form_id)
|
||||||
|
return fields
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{form_id}/fields", response_model=FormField)
|
||||||
|
async def create_form_field_view(
|
||||||
|
form_id: int,
|
||||||
|
data: CreateFormField,
|
||||||
|
current_user: User = Depends(get_current_active_manager),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
):
|
||||||
|
field = await crud.create_form_field(session, data, current_user.id, form_id)
|
||||||
|
return field
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{form_id}/assign", status_code=status.HTTP_201_CREATED)
|
||||||
|
async def create_assigment_view(
|
||||||
|
form_id: int,
|
||||||
|
data: FormAssigment,
|
||||||
|
current_user: User = Depends(get_current_active_manager),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
):
|
||||||
|
form = await services.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 assign_form(session, data, form_id)
|
||||||
|
return {"message": "created"}
|
|
@ -28,7 +28,7 @@ class Settings(BaseSettings):
|
||||||
with environment variables.
|
with environment variables.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
host: str = "127.0.0.1"
|
host: str = "0.0.0.0"
|
||||||
port: int = 8000
|
port: int = 8000
|
||||||
# quantity of workers for uvicorn
|
# quantity of workers for uvicorn
|
||||||
workers_count: int = 1
|
workers_count: int = 1
|
||||||
|
|
|
@ -4,18 +4,17 @@ from fastapi import HTTPException
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from ..db.models.users import UserScheme
|
from med_backend.auth import schemas, services
|
||||||
from . import schemas, services
|
from med_backend.db.models.users import UserScheme
|
||||||
from .schemas import User
|
|
||||||
|
|
||||||
|
|
||||||
async def get_user_by_email(session: AsyncSession, email: str) -> User | None:
|
async def get_user_by_email(session: AsyncSession, email: str) -> schemas.User | None:
|
||||||
r = await session.execute(select(UserScheme).where(UserScheme.email == email))
|
r = await session.execute(select(UserScheme).where(UserScheme.email == email))
|
||||||
user = r.scalars().first()
|
user = r.scalars().first()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
async def get_user(session: AsyncSession, pk: int) -> User | None:
|
async def get_user(session: AsyncSession, pk: int) -> schemas.User | None:
|
||||||
r = await session.execute(select(UserScheme).where(UserScheme.id == pk))
|
r = await session.execute(select(UserScheme).where(UserScheme.id == pk))
|
||||||
user = r.scalars().first()
|
user = r.scalars().first()
|
||||||
return user
|
return user
|
||||||
|
@ -25,7 +24,7 @@ async def get_users(
|
||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
skip: int = 0,
|
skip: int = 0,
|
||||||
limit: int = 100,
|
limit: int = 100,
|
||||||
) -> List[User] | None:
|
) -> List[schemas.User] | None:
|
||||||
r = await session.execute(
|
r = await session.execute(
|
||||||
select(UserScheme)
|
select(UserScheme)
|
||||||
.where(UserScheme.is_manager == False)
|
.where(UserScheme.is_manager == False)
|
42
med_backend/users/services.py
Normal file
42
med_backend/users/services.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
from fastapi import Depends, HTTPException
|
||||||
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
|
from jose import JWTError, jwt
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from starlette import status
|
||||||
|
|
||||||
|
from med_backend.auth import schemas, services
|
||||||
|
from med_backend.db.dependencies import get_db_session
|
||||||
|
|
||||||
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||||
|
|
||||||
|
|
||||||
|
async def get_current_active_manager(
|
||||||
|
token: str = Depends(oauth2_scheme),
|
||||||
|
session: AsyncSession = Depends(get_db_session),
|
||||||
|
) -> schemas.User:
|
||||||
|
credentials_exception = HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail="Could not validate credentials",
|
||||||
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(
|
||||||
|
token,
|
||||||
|
services.SECRET_KEY,
|
||||||
|
algorithms=[services.JWT_ALGORITHM],
|
||||||
|
)
|
||||||
|
email: str = payload.get("sub")
|
||||||
|
if email is None:
|
||||||
|
raise credentials_exception
|
||||||
|
token_data = schemas.TokenData(email=email)
|
||||||
|
except JWTError:
|
||||||
|
raise credentials_exception
|
||||||
|
user = await services.get_user(session, token_data.email)
|
||||||
|
if user is None:
|
||||||
|
raise credentials_exception
|
||||||
|
if not user.is_manager:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail="You are not allowed to access this info",
|
||||||
|
)
|
||||||
|
return user
|
|
@ -1,11 +1,11 @@
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from med_backend.auth import crud
|
|
||||||
from med_backend.auth.schemas import User
|
from med_backend.auth.schemas import User
|
||||||
from med_backend.auth.services import get_current_active_manager
|
|
||||||
from med_backend.db.dependencies import get_db_session
|
from med_backend.db.dependencies import get_db_session
|
||||||
|
from med_backend.users import crud
|
||||||
from med_backend.users.schemas import FullUser, ListUser
|
from med_backend.users.schemas import FullUser, ListUser
|
||||||
|
from med_backend.users.services import get_current_active_manager
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
"""Echo API."""
|
|
||||||
from med_backend.web.api.echo.views import router
|
|
||||||
|
|
||||||
__all__ = ["router"]
|
|
|
@ -1,7 +0,0 @@
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
class Message(BaseModel):
|
|
||||||
"""Simple message model."""
|
|
||||||
|
|
||||||
message: str
|
|
|
@ -1,18 +0,0 @@
|
||||||
from fastapi import APIRouter
|
|
||||||
|
|
||||||
from med_backend.web.api.echo.schema import Message
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/", response_model=Message)
|
|
||||||
async def send_echo_message(
|
|
||||||
incoming_message: Message,
|
|
||||||
) -> Message:
|
|
||||||
"""
|
|
||||||
Sends echo back to user.
|
|
||||||
|
|
||||||
:param incoming_message: incoming message.
|
|
||||||
:returns: message same as the incoming.
|
|
||||||
"""
|
|
||||||
return incoming_message
|
|
|
@ -1,4 +0,0 @@
|
||||||
"""API for checking project status."""
|
|
||||||
from med_backend.web.api.monitoring.views import router
|
|
||||||
|
|
||||||
__all__ = ["router"]
|
|
|
@ -1,12 +0,0 @@
|
||||||
from fastapi import APIRouter
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/health")
|
|
||||||
def health_check() -> None:
|
|
||||||
"""
|
|
||||||
Checks the health of a project.
|
|
||||||
|
|
||||||
It returns 200 if the project is healthy.
|
|
||||||
"""
|
|
|
@ -1,4 +0,0 @@
|
||||||
"""Redis API."""
|
|
||||||
from med_backend.web.api.redis.views import router
|
|
||||||
|
|
||||||
__all__ = ["router"]
|
|
|
@ -1,10 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
class RedisValueDTO(BaseModel):
|
|
||||||
"""DTO for redis values."""
|
|
||||||
|
|
||||||
key: str
|
|
||||||
value: Optional[str] # noqa: WPS110
|
|
|
@ -1,44 +0,0 @@
|
||||||
from fastapi import APIRouter
|
|
||||||
from fastapi.param_functions import Depends
|
|
||||||
from redis.asyncio import ConnectionPool, Redis
|
|
||||||
|
|
||||||
from med_backend.services.redis.dependency import get_redis_pool
|
|
||||||
from med_backend.web.api.redis.schema import RedisValueDTO
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", response_model=RedisValueDTO)
|
|
||||||
async def get_redis_value(
|
|
||||||
key: str,
|
|
||||||
redis_pool: ConnectionPool = Depends(get_redis_pool),
|
|
||||||
) -> RedisValueDTO:
|
|
||||||
"""
|
|
||||||
Get value from redis.
|
|
||||||
|
|
||||||
:param key: redis key, to get data from.
|
|
||||||
:param redis_pool: redis connection pool.
|
|
||||||
:returns: information from redis.
|
|
||||||
"""
|
|
||||||
async with Redis(connection_pool=redis_pool) as redis:
|
|
||||||
redis_value = await redis.get(key)
|
|
||||||
return RedisValueDTO(
|
|
||||||
key=key,
|
|
||||||
value=redis_value,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.put("/")
|
|
||||||
async def set_redis_value(
|
|
||||||
redis_value: RedisValueDTO,
|
|
||||||
redis_pool: ConnectionPool = Depends(get_redis_pool),
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Set value in redis.
|
|
||||||
|
|
||||||
:param redis_value: new value data.
|
|
||||||
:param redis_pool: redis connection pool.
|
|
||||||
"""
|
|
||||||
if redis_value.value is not None:
|
|
||||||
async with Redis(connection_pool=redis_pool) as redis:
|
|
||||||
await redis.set(name=redis_value.key, value=redis_value.value)
|
|
|
@ -1,10 +1,8 @@
|
||||||
from fastapi.routing import APIRouter
|
from fastapi.routing import APIRouter
|
||||||
|
|
||||||
from med_backend import auth, users
|
from med_backend import auth, forms, users
|
||||||
from med_backend.web.api import echo, monitoring
|
|
||||||
|
|
||||||
api_router = APIRouter()
|
api_router = APIRouter()
|
||||||
api_router.include_router(monitoring.router)
|
|
||||||
api_router.include_router(echo.router, prefix="/echo", tags=["echo"])
|
|
||||||
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
||||||
api_router.include_router(users.router, prefix="/users", tags=["users"])
|
api_router.include_router(users.router, prefix="/users", tags=["users"])
|
||||||
|
api_router.include_router(forms.router, prefix="/forms", tags=["forms"])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user