From 6b0619b4d1ff1e779ebeeb1a418b9d13d62fd1d3 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Mon, 13 Jun 2022 22:28:58 +0400 Subject: Fix NoneType Access Error For Form Editors Signed-off-by: Hassan Abouelela --- backend/discord.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/discord.py b/backend/discord.py index be12109..ff6c1bb 100644 --- a/backend/discord.py +++ b/backend/discord.py @@ -175,7 +175,7 @@ async def _verify_access_helper( form = models.Form(**form) - for role_id in getattr(form, attribute, []): + for role_id in getattr(form, attribute, None) or []: role = await request.state.db.roles.find_one({"id": role_id}) if not role: continue -- cgit v1.2.3 From f886a7f279cf29e2997ad8ef721e0cd1d1a2529c Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Mon, 13 Jun 2022 22:48:41 +0400 Subject: Fix Error For Unauthorized Form Access Fixes an error where accessing a form without having the proper authorization would cause an unexpected state and raise a 500. Closes #175. Signed-off-by: Hassan Abouelela --- backend/routes/forms/form.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'backend') diff --git a/backend/routes/forms/form.py b/backend/routes/forms/form.py index 567c197..369dc9f 100644 --- a/backend/routes/forms/form.py +++ b/backend/routes/forms/form.py @@ -42,7 +42,7 @@ class SingleForm(Route): if not constants.PRODUCTION and form_id == EMPTY_FORM.id: # Empty form to help with authentication in development. return JSONResponse(EMPTY_FORM.dict(admin=False)) - raise + return JSONResponse({"error": "not_found"}, status_code=404) except discord.UnauthorizedError: admin = False @@ -53,7 +53,11 @@ class SingleForm(Route): if not admin: filters["features"] = {"$in": ["OPEN", "DISCOVERABLE"]} - form = Form(**await request.state.db.forms.find_one(filters)) + form = await request.state.db.forms.find_one(filters) + if not form: + return JSONResponse({"error": "not_found"}, status_code=404) + + form = Form(**form) if not admin: form = filter_unittests(form) -- cgit v1.2.3 From 42f3f0262d06f50d730c55c232362c8ddd984d55 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Fri, 17 Jun 2022 22:20:40 +0400 Subject: Enable Login Form In Production Adds a non-discoverable login form in all environments to make it easier to authenticate. Ideally, we'd have an actual login button, but this is an easy solution in the meantime. Signed-off-by: Hassan Abouelela --- backend/routes/forms/discover.py | 20 +++++++++++--------- backend/routes/forms/form.py | 9 +++++---- backend/routes/forms/submit.py | 16 +++++++++++++--- 3 files changed, 29 insertions(+), 16 deletions(-) (limited to 'backend') diff --git a/backend/routes/forms/discover.py b/backend/routes/forms/discover.py index b993075..75ff495 100644 --- a/backend/routes/forms/discover.py +++ b/backend/routes/forms/discover.py @@ -11,25 +11,27 @@ from backend.route import Route from backend.validation import api __FEATURES = [ - constants.FormFeatures.DISCOVERABLE.value, constants.FormFeatures.OPEN.value, constants.FormFeatures.REQUIRES_LOGIN.value ] +if not constants.PRODUCTION: + __FEATURES.append(constants.FormFeatures.DISCOVERABLE.value) __QUESTION = Question( id="description", - name="Check your cookies after pressing the button.", + name="Click the button below to log into the forms application.", type="section", - data={"text": "You can find cookies under \"Application\" in dev tools."}, + data={"text": ""}, required=False ) -EMPTY_FORM = Form( - id="empty_auth", +AUTH_FORM = Form( + id="login", features=__FEATURES, questions=[__QUESTION], - name="Auth form", - description="An empty form to help you get a token.", + name="Login", + description="Log into Python Discord Forms.", + submitted_text="This page can't be submitted." ) @@ -55,7 +57,7 @@ class DiscoverableFormsList(Route): forms = [form.dict(admin=False) for form in forms] # Return an empty form in development environments to help with authentication. - if not forms and not constants.PRODUCTION: - forms.append(EMPTY_FORM.dict(admin=False)) + if not constants.PRODUCTION: + forms.append(AUTH_FORM.dict(admin=False)) return JSONResponse(forms) diff --git a/backend/routes/forms/form.py b/backend/routes/forms/form.py index 369dc9f..8349d4e 100644 --- a/backend/routes/forms/form.py +++ b/backend/routes/forms/form.py @@ -13,7 +13,7 @@ from starlette.responses import JSONResponse from backend import constants, discord from backend.models import Form from backend.route import Route -from backend.routes.forms.discover import EMPTY_FORM +from backend.routes.forms.discover import AUTH_FORM from backend.routes.forms.unittesting import filter_unittests from backend.validation import ErrorMessage, OkayResponse, api @@ -35,13 +35,14 @@ class SingleForm(Route): """Returns single form information by ID.""" form_id = request.path_params["form_id"].lower() + if form_id == AUTH_FORM.id: + # Empty form for login purposes + return JSONResponse(AUTH_FORM.dict(admin=False)) + try: await discord.verify_edit_access(form_id, request) admin = True except discord.FormNotFoundError: - if not constants.PRODUCTION and form_id == EMPTY_FORM.id: - # Empty form to help with authentication in development. - return JSONResponse(EMPTY_FORM.dict(admin=False)) return JSONResponse({"error": "not_found"}, status_code=404) except discord.UnauthorizedError: admin = False diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py index baf403d..5c500b5 100644 --- a/backend/routes/forms/submit.py +++ b/backend/routes/forms/submit.py @@ -22,6 +22,7 @@ from backend.authentication.user import User from backend.models import Form, FormResponse from backend.route import Route from backend.routes.auth.authorize import set_response_token +from backend.routes.forms.discover import AUTH_FORM from backend.routes.forms.unittesting import execute_unittest from backend.validation import ErrorMessage, api @@ -106,9 +107,18 @@ class SubmitForm(Route): data = await request.json() data["timestamp"] = None - if form := await request.state.db.forms.find_one( - {"_id": request.path_params["form_id"], "features": "OPEN"} - ): + form_id = request.path_params["form_id"] + + if form_id == AUTH_FORM.id: + response = FormResponse( + id="not-submitted", + form_id=AUTH_FORM.id, + response={question.id: None for question in AUTH_FORM.questions}, + timestamp=datetime.datetime.now().isoformat() + ).dict() + return JSONResponse({"form": AUTH_FORM.dict(admin=False), "response": response}) + + if form := await request.state.db.forms.find_one({"_id": form_id, "features": "OPEN"}): form = Form(**form) response = data.copy() response["id"] = str(uuid.uuid4()) -- cgit v1.2.3