diff options
author | 2022-06-18 04:41:10 +0400 | |
---|---|---|
committer | 2022-06-18 04:41:10 +0400 | |
commit | fe94892f573828a3c5bf61123d2dd9923e1e1986 (patch) | |
tree | 07782cc28afc74facfa8695b5660a865c0e8799f | |
parent | use Request to generate the state (diff) | |
parent | Merge pull request #177 from python-discord/enable-login-in-prod (diff) |
Merge branch 'main' into asgi-middleware
-rw-r--r-- | backend/discord.py | 2 | ||||
-rw-r--r-- | backend/routes/forms/discover.py | 20 | ||||
-rw-r--r-- | backend/routes/forms/form.py | 17 | ||||
-rw-r--r-- | backend/routes/forms/submit.py | 16 | ||||
-rw-r--r-- | poetry.lock | 38 | ||||
-rw-r--r-- | pyproject.toml | 2 |
6 files changed, 48 insertions, 47 deletions
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 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 567c197..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,14 +35,15 @@ 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)) - raise + return JSONResponse({"error": "not_found"}, status_code=404) except discord.UnauthorizedError: admin = False @@ -53,7 +54,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) 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()) diff --git a/poetry.lock b/poetry.lock index f888575..5271c7d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -35,17 +35,6 @@ optional = false python-versions = "*" [[package]] -name = "charset-normalizer" -version = "2.0.11" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode_backport = ["unicodedata2"] - -[[package]] name = "click" version = "8.0.3" description = "Composable command line interface toolkit" @@ -148,11 +137,11 @@ python-versions = ">=3.6" [[package]] name = "httpcore" -version = "0.14.7" +version = "0.15.0" description = "A minimal low-level HTTP client." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] anyio = ">=3.0.0,<4.0.0" @@ -177,22 +166,21 @@ test = ["Cython (>=0.29.24,<0.30.0)"] [[package]] name = "httpx" -version = "0.22.0" +version = "0.23.0" description = "The next generation HTTP client." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] certifi = "*" -charset-normalizer = "*" -httpcore = ">=0.14.5,<0.15.0" +httpcore = ">=0.15.0,<0.16.0" rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" [package.extras] brotli = ["brotlicffi", "brotli"] -cli = ["click (>=8.0.0,<9.0.0)", "rich (>=10.0.0,<11.0.0)", "pygments (>=2.0.0,<3.0.0)"] +cli = ["click (>=8.0.0,<9.0.0)", "rich (>=10,<13)", "pygments (>=2.0.0,<3.0.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (>=1.0.0,<2.0.0)"] @@ -477,7 +465,7 @@ python-versions = ">=3.7" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "fe20bd8d4a5b82833c0d4389704874b45f2d7adabf4a3c850c03b930a8940afa" +content-hash = "9f20721dc2e5196709693e7ffbc5fe2e7043afeeb40b790a15ccd94d9676b042" [metadata.files] anyio = [ @@ -492,10 +480,6 @@ certifi = [ {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, ] -charset-normalizer = [ - {file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"}, - {file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"}, -] click = [ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, @@ -533,8 +517,8 @@ h11 = [ {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, ] httpcore = [ - {file = "httpcore-0.14.7-py3-none-any.whl", hash = "sha256:47d772f754359e56dd9d892d9593b6f9870a37aeb8ba51e9a88b09b3d68cfade"}, - {file = "httpcore-0.14.7.tar.gz", hash = "sha256:7503ec1c0f559066e7e39bc4003fd2ce023d01cf51793e3c173b864eb456ead1"}, + {file = "httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"}, + {file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"}, ] httptools = [ {file = "httptools-0.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcddfe70553be717d9745990dfdb194e22ee0f60eb8f48c0794e7bfeda30d2d5"}, @@ -573,8 +557,8 @@ httptools = [ {file = "httptools-0.4.0.tar.gz", hash = "sha256:2c9a930c378b3d15d6b695fb95ebcff81a7395b4f9775c4f10a076beb0b2c1ff"}, ] httpx = [ - {file = "httpx-0.22.0-py3-none-any.whl", hash = "sha256:e35e83d1d2b9b2a609ef367cc4c1e66fd80b750348b20cc9e19d1952fc2ca3f6"}, - {file = "httpx-0.22.0.tar.gz", hash = "sha256:d8e778f76d9bbd46af49e7f062467e3157a5a3d2ae4876a4bbfd8a51ed9c9cb4"}, + {file = "httpx-0.23.0-py3-none-any.whl", hash = "sha256:42974f577483e1e932c3cdc3cd2303e883cbfba17fe228b0f63589764d7b9c4b"}, + {file = "httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, diff --git a/pyproject.toml b/pyproject.toml index 5b02228..a6ba3c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ uvicorn = {extras = ["standard"], version = "^0.17.6"} motor = "^2.4.0" python-dotenv = "^0.19.2" pyjwt = "^2.4.0" -httpx = "^0.22.0" +httpx = "^0.23.0" gunicorn = "^20.1.0" pydantic = "^1.8.2" spectree = "^0.7.6" |