diff options
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/models/form.py | 7 | ||||
| -rw-r--r-- | backend/routes/forms/discover.py | 2 | ||||
| -rw-r--r-- | backend/routes/forms/form.py | 36 | ||||
| -rw-r--r-- | backend/routes/forms/index.py | 19 | ||||
| -rw-r--r-- | backend/routes/forms/new.py | 35 | 
5 files changed, 62 insertions, 37 deletions
| diff --git a/backend/models/form.py b/backend/models/form.py index 8d7fe9b..400f8ad 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -5,6 +5,8 @@ from pydantic import BaseModel, Field, validator  from backend.constants import FormFeatures  from .question import Question +PUBLIC_FIELDS = ["id", "features", "questions", "name", "description"] +  class Form(BaseModel):      """Schema model for form.""" @@ -31,3 +33,8 @@ class Form(BaseModel):              raise ValueError("COLLECT_EMAIL feature require REQUIRES_LOGIN feature.")          return value + +    def dict(self, admin: bool = True, **kwargs: t.Dict) -> t.Dict[str, t.Any]: +        """Wrapper for original function to exclude private data for public access.""" +        data = super().dict(**kwargs) +        return {field: data[field] for field in PUBLIC_FIELDS} if admin else data diff --git a/backend/routes/forms/discover.py b/backend/routes/forms/discover.py index af6066e..bba6fd4 100644 --- a/backend/routes/forms/discover.py +++ b/backend/routes/forms/discover.py @@ -25,7 +25,7 @@ class DiscoverableFormsList(Route):          for form in await cursor.to_list(None):              forms.append(Form(**form)) -        forms = [form.dict() for form in forms] +        forms = [form.dict(admin=False) for form in forms]          return JSONResponse(              forms diff --git a/backend/routes/forms/form.py b/backend/routes/forms/form.py new file mode 100644 index 0000000..599632e --- /dev/null +++ b/backend/routes/forms/form.py @@ -0,0 +1,36 @@ +""" +Returns single form information by ID. +""" +from starlette.requests import Request +from starlette.responses import JSONResponse + +from backend.route import Route +from backend.models import Form + + +class SingleForm(Route): +    """ +    Returns single form information by ID. + +    Returns all fields for admins, otherwise only public fields. +    """ + +    name = "form" +    path = "/{form_id:str}" + +    async def get(self, request: Request) -> JSONResponse: +        """Returns single form information by ID.""" +        admin = request.user.payload["admin"] if request.user.is_authenticated else False  # noqa + +        filters = { +            "_id": request.path_params["form_id"] +        } + +        if not admin: +            filters["features"] = "OPEN" + +        if raw_form := await request.state.db.forms.find_one(filters): +            form = Form(**raw_form) +            return JSONResponse(form.dict(admin=admin)) + +        return JSONResponse({"error": "not_found"}, status_code=404) diff --git a/backend/routes/forms/index.py b/backend/routes/forms/index.py index f1df210..bb2b299 100644 --- a/backend/routes/forms/index.py +++ b/backend/routes/forms/index.py @@ -1,6 +1,7 @@  """  Return a list of all forms to authenticated users.  """ +from pydantic import ValidationError  from starlette.authentication import requires  from starlette.requests import Request  from starlette.responses import JSONResponse @@ -14,7 +15,7 @@ class FormsList(Route):      List all available forms for administrator viewing.      """ -    name = "forms_list" +    name = "forms_list_create"      path = "/"      @requires(["authenticated", "admin"]) @@ -31,3 +32,19 @@ class FormsList(Route):          return JSONResponse(              forms          ) + +    @requires(["authenticated", "admin"]) +    async def post(self, request: Request) -> JSONResponse: +        form_data = await request.json() +        try: +            form = Form(**form_data) +        except ValidationError as e: +            return JSONResponse(e.errors()) + +        if await request.state.db.forms.find_one({"_id": form.id}): +            return JSONResponse({ +                "error": "id_taken" +            }, status_code=400) + +        await request.state.db.forms.insert_one(form.dict(by_alias=True)) +        return JSONResponse(form.dict()) diff --git a/backend/routes/forms/new.py b/backend/routes/forms/new.py deleted file mode 100644 index 6437a4a..0000000 --- a/backend/routes/forms/new.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Creates new form based on data provided. -""" -from pydantic import ValidationError -from starlette.authentication import requires -from starlette.requests import Request -from starlette.responses import JSONResponse - -from backend.models import Form -from backend.route import Route - - -class FormCreate(Route): -    """ -    Creates new form from JSON data. -    """ - -    name = "forms_create" -    path = "/new" - -    @requires(["authenticated", "admin"]) -    async def post(self, request: Request) -> JSONResponse: -        form_data = await request.json() -        try: -            form = Form(**form_data) -        except ValidationError as e: -            return JSONResponse(e.errors()) - -        if await request.state.db.forms.find_one({"_id": form.id}): -            return JSONResponse({ -                "error": "Form with same ID already exists." -            }, status_code=400) - -        await request.state.db.forms.insert_one(form.dict(by_alias=True)) -        return JSONResponse(form.dict()) | 
