diff options
author | 2021-03-09 08:48:58 +0200 | |
---|---|---|
committer | 2021-03-09 08:48:58 +0200 | |
commit | 0ec4a370d476f3f8b7453c887b0b02fe83aced9c (patch) | |
tree | e7fb0e7a71369affd79222445a35438815ad4cd3 /backend/routes/forms/submit.py | |
parent | Add missing "is" to error message (diff) | |
parent | Fixes Production URL Constant (diff) |
Merge branch 'main' into ks123/role-assigning
Diffstat (limited to 'backend/routes/forms/submit.py')
-rw-r--r-- | backend/routes/forms/submit.py | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py index 37f76e0..23444a0 100644 --- a/backend/routes/forms/submit.py +++ b/backend/routes/forms/submit.py @@ -4,6 +4,7 @@ Submit a form. import asyncio import binascii +import datetime import hashlib import uuid from typing import Any, Optional @@ -17,10 +18,12 @@ from starlette.requests import Request from starlette.responses import JSONResponse from backend import constants -from backend.authentication import User +from backend.authentication.user import User from backend.models import Form, FormResponse from backend.route import Route -from backend.validation import AuthorizationHeaders, ErrorMessage, api +from backend.routes.auth.authorize import set_response_token +from backend.routes.forms.unittesting import execute_unittest +from backend.validation import ErrorMessage, api HCAPTCHA_VERIFY_URL = "https://hcaptcha.com/siteverify" HCAPTCHA_HEADERS = { @@ -57,13 +60,37 @@ class SubmitForm(Route): HTTP_404=ErrorMessage, HTTP_400=ErrorMessage ), - headers=AuthorizationHeaders, tags=["forms", "responses"] ) async def post(self, request: Request) -> JSONResponse: """Submit a response to the form.""" - data = await request.json() + response = await self.submit(request) + + # Silently try to update user data + try: + if hasattr(request.user, User.refresh_data.__name__): + old = request.user.token + await request.user.refresh_data() + + if old != request.user.token: + try: + expiry = datetime.datetime.fromisoformat( + request.user.decoded_token.get("expiry") + ) + except ValueError: + expiry = None + + expiry_seconds = (expiry - datetime.datetime.now()).seconds + await set_response_token(response, request, request.user.token, expiry_seconds) + + except httpx.HTTPStatusError: + pass + return response + + async def submit(self, request: Request) -> JSONResponse: + """Helper method for handling submission logic.""" + data = await request.json() data["timestamp"] = None if form := await request.state.db.forms.find_one( @@ -104,8 +131,12 @@ class SubmitForm(Route): if constants.FormFeatures.REQUIRES_LOGIN.value in form.features: if request.user.is_authenticated: response["user"] = request.user.payload + response["user"]["admin"] = request.user.admin - if constants.FormFeatures.COLLECT_EMAIL.value in form.features and "email" not in response["user"]: # noqa + if ( + constants.FormFeatures.COLLECT_EMAIL.value in form.features + and "email" not in response["user"] + ): return JSONResponse({ "error": "email_required" }, status_code=400) @@ -133,6 +164,23 @@ class SubmitForm(Route): except ValidationError as e: return JSONResponse(e.errors(), status_code=422) + # Run unittests if needed + if any("unittests" in question.data for question in form.questions): + unittest_results = await execute_unittest(response_obj, form) + + if not all(test.passed for test in unittest_results): + # Return 500 if we encountered an internal error (code 99). + status_code = 500 if any( + test.return_code == 99 for test in unittest_results + ) else 403 + + return JSONResponse({ + "error": "failed_tests", + "test_results": [ + test._asdict() for test in unittest_results if not test.passed + ] + }, status_code=status_code) + await request.state.db.responses.insert_one( response_obj.dict(by_alias=True) ) |