From e347944b997dd1dd808cb1cc5df388e4a9bba85e Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 15:34:41 +0200 Subject: Add Discord bot token constant from environment --- backend/constants.py | 1 + 1 file changed, 1 insertion(+) (limited to 'backend') diff --git a/backend/constants.py b/backend/constants.py index fedab64..d9d2735 100644 --- a/backend/constants.py +++ b/backend/constants.py @@ -23,6 +23,7 @@ FORMS_BACKEND_DSN = os.getenv("FORMS_BACKEND_DSN") DOCS_PASSWORD = os.getenv("DOCS_PASSWORD") SECRET_KEY = os.getenv("SECRET_KEY", binascii.hexlify(os.urandom(30)).decode()) +DISCORD_BOT_TOKEN = os.getenv("DISCORD_BOT_TOKEN") HCAPTCHA_API_SECRET = os.getenv("HCAPTCHA_API_SECRET") -- cgit v1.2.3 From 5ced1c97d9553528b32d84ac819f53dffa0419b8 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 15:38:26 +0200 Subject: Add ASSIGN_ROLE flag to schema and to enum --- SCHEMA.md | 1 + backend/constants.py | 1 + 2 files changed, 2 insertions(+) (limited to 'backend') diff --git a/SCHEMA.md b/SCHEMA.md index c3edf35..11b4b89 100644 --- a/SCHEMA.md +++ b/SCHEMA.md @@ -31,6 +31,7 @@ In this document: | `COLLECT_EMAIL` | The form should collect the email from submissions. Requires `REQUIRES_LOGIN` | | `DISABLE_ANTISPAM` | Disable the anti-spam checks from running on a form submission. | | `WEBHOOK_ENABLED` | The form should notify the webhook. Has no effect if no webhook is set. | +| `ASSIGN_ROLE` | The form should assign role to user. Requires `REQUIRES_LOGIN`. | ### Webhooks Discord webhooks to send information upon form submission. diff --git a/backend/constants.py b/backend/constants.py index d9d2735..e6ff127 100644 --- a/backend/constants.py +++ b/backend/constants.py @@ -66,6 +66,7 @@ class FormFeatures(Enum): COLLECT_EMAIL = "COLLECT_EMAIL" DISABLE_ANTISPAM = "DISABLE_ANTISPAM" WEBHOOK_ENABLED = "WEBHOOK_ENABLED" + ASSIGN_ROLE = "ASSIGN_ROLE" class WebHook(Enum): -- cgit v1.2.3 From d18b21a242f1154f900ac827a01300b99fc77717 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 15:45:32 +0200 Subject: Add discord_role field to form and it's schema --- SCHEMA.md | 13 +++++++------ backend/models/form.py | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'backend') diff --git a/SCHEMA.md b/SCHEMA.md index 11b4b89..a1e9698 100644 --- a/SCHEMA.md +++ b/SCHEMA.md @@ -14,12 +14,13 @@ In this document: | Field | Type | Description | Example | | ------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------- | -| `id` | Unique identifier | A user selected, unique, descriptive identifier (used in URL routes, so no spaces) | `"ban-appeals"` | -| `features` | List of [form features](#form-features) | A list of features to change the behaviour of the form, described in the features section | `["OPEN", "COLLECT_EMAIL"]` | -| `questions` | List of [form questions](#form-question) | The list of questions to render on a specific form | Too long! See below | -| `name` | String | Name of the form | `"Summer Code Jam 2100"` | -| `description` | String | Form description | `"This is my amazing form description."` | -| `webhook` | [Webhook object](#webhooks) | An optional discord webhook. | See webhook documentation. | +| `id` | Unique identifier | A user selected, unique, descriptive identifier (used in URL routes, so no spaces) | `"ban-appeals"` | +| `features` | List of [form features](#form-features) | A list of features to change the behaviour of the form, described in the features section | `["OPEN", "COLLECT_EMAIL"]` | +| `questions` | List of [form questions](#form-question) | The list of questions to render on a specific form | Too long! See below | +| `name` | String | Name of the form | `"Summer Code Jam 2100"` | +| `description` | String | Form description | `"This is my amazing form description."` | +| `webhook` | [Webhook object](#webhooks) | An optional discord webhook. | See webhook documentation. | +| `discord_role` | String (optional) | Discord role ID what will be assigned, required when `ASSIGN_ROLE` flag provided. | `784467518298259466` | ### Form features diff --git a/backend/models/form.py b/backend/models/form.py index 57372ea..64b198b 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -33,6 +33,7 @@ class Form(BaseModel): name: str description: str webhook: _WebHook = None + discord_role: t.Optional[str] class Config: allow_population_by_field_name = True -- cgit v1.2.3 From ba176f044adf1cf2b9c884830fe4f4d1cd5bbe9f Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 18:31:22 +0200 Subject: Add Discord API base URL constant --- backend/constants.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backend') diff --git a/backend/constants.py b/backend/constants.py index e6ff127..fda92b9 100644 --- a/backend/constants.py +++ b/backend/constants.py @@ -56,6 +56,8 @@ REQUIRED_QUESTION_TYPE_DATA = { }, } +DISCORD_API_BASE_URL = "https://discord.com/api/v8" + class FormFeatures(Enum): """Lists form features. Read more in SCHEMA.md.""" -- cgit v1.2.3 From 68a753f4b79b46eb2c10f6177e4e717a143c4b22 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 18:32:24 +0200 Subject: Add PyDis guild constant from environment --- backend/constants.py | 1 + 1 file changed, 1 insertion(+) (limited to 'backend') diff --git a/backend/constants.py b/backend/constants.py index fda92b9..70f3df1 100644 --- a/backend/constants.py +++ b/backend/constants.py @@ -24,6 +24,7 @@ DOCS_PASSWORD = os.getenv("DOCS_PASSWORD") SECRET_KEY = os.getenv("SECRET_KEY", binascii.hexlify(os.urandom(30)).decode()) DISCORD_BOT_TOKEN = os.getenv("DISCORD_BOT_TOKEN") +DISCORD_GUILD = os.getenv("DISCORD_GUILD") HCAPTCHA_API_SECRET = os.getenv("HCAPTCHA_API_SECRET") -- cgit v1.2.3 From 085dc8c536a5968342d9632b3adb57ef4cd1d5bc Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 18:54:25 +0200 Subject: Add validator for Discord role field for form --- backend/models/form.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index 64b198b..5aacc8b 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -1,7 +1,7 @@ import typing as t import httpx -from pydantic import BaseModel, Field, validator +from pydantic import BaseModel, Field, root_validator, validator from pydantic.error_wrappers import ErrorWrapper, ValidationError from backend.constants import FormFeatures, WebHook @@ -52,6 +52,16 @@ class Form(BaseModel): return value + @root_validator + def validate_role(cls, values: dict[str, t.Any]) -> t.Optional[dict[str, t.Any]]: + """Validates does Discord role provided when flag provided.""" + if FormFeatures.ASSIGN_ROLE.value in values.get("features", []) and not values.get("discord_role"): # noqa + raise ValueError( + "discord_role field is required when ASSIGN_ROLE flag provided." + ) + + return values + def dict(self, admin: bool = True, **kwargs: t.Any) -> dict[str, t.Any]: """Wrapper for original function to exclude private data for public access.""" data = super().dict(**kwargs) -- cgit v1.2.3 From 7b0cb70a233b2cb904af38414039e3cee6f43e93 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:22:03 +0200 Subject: Implement roles assigning to submit route --- backend/routes/forms/submit.py | 52 ++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 12 deletions(-) (limited to 'backend') diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py index d8e6d35..0ed248d 100644 --- a/backend/routes/forms/submit.py +++ b/backend/routes/forms/submit.py @@ -11,11 +11,12 @@ import httpx from pydantic import ValidationError from pydantic.main import BaseModel from spectree import Response -from starlette.background import BackgroundTask +from starlette.background import BackgroundTasks from starlette.requests import Request from starlette.responses import JSONResponse -from backend.constants import FRONTEND_URL, FormFeatures, HCAPTCHA_API_SECRET +from backend import constants +from backend.authentication import User from backend.models import Form, FormResponse from backend.route import Route from backend.validation import AuthorizationHeaders, ErrorMessage, api @@ -68,7 +69,7 @@ class SubmitForm(Route): response["id"] = str(uuid.uuid4()) response["form_id"] = form.id - if FormFeatures.DISABLE_ANTISPAM.value not in form.features: + if constants.FormFeatures.DISABLE_ANTISPAM.value not in form.features: ip_hash_ctx = hashlib.md5() ip_hash_ctx.update(request.client.host.encode()) ip_hash = binascii.hexlify(ip_hash_ctx.digest()) @@ -78,7 +79,7 @@ class SubmitForm(Route): async with httpx.AsyncClient() as client: query_params = { - "secret": HCAPTCHA_API_SECRET, + "secret": constants.HCAPTCHA_API_SECRET, "response": data.get("captcha") } r = await client.post( @@ -95,11 +96,11 @@ class SubmitForm(Route): "captcha_pass": captcha_data["success"] } - if FormFeatures.REQUIRES_LOGIN.value in form.features: + if constants.FormFeatures.REQUIRES_LOGIN.value in form.features: if request.user.is_authenticated: response["user"] = request.user.payload - if 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"]: # noqa return JSONResponse({ "error": "email_required" }, status_code=400) @@ -131,19 +132,26 @@ class SubmitForm(Route): response_obj.dict(by_alias=True) ) - send_webhook = None - if FormFeatures.WEBHOOK_ENABLED.value in form.features: - send_webhook = BackgroundTask( + tasks = BackgroundTasks() + if constants.FormFeatures.WEBHOOK_ENABLED.value in form.features: + tasks.add_task( self.send_submission_webhook, form=form, response=response_obj, request_user=request.user ) + if constants.FormFeatures.ASSIGN_ROLE.value in form.features: + tasks.add_task( + self.assign_role, + form=form, + request_user=request.user + ) + return JSONResponse({ "form": form.dict(admin=False), "response": response_obj.dict() - }, background=send_webhook) + }, background=tasks) else: return JSONResponse({ @@ -154,7 +162,7 @@ class SubmitForm(Route): async def send_submission_webhook( form: Form, response: FormResponse, - request_user: Request.user + request_user: User ) -> None: """Helper to send a submission message to a discord webhook.""" # Stop if webhook is not available @@ -172,7 +180,7 @@ class SubmitForm(Route): embed = { "title": "New Form Response", "description": f"{mention} submitted a response to `{form.name}`.", - "url": f"{FRONTEND_URL}/path_to_view_form/{response.id}", # noqa # TODO: Enter Form View URL + "url": f"{constants.FRONTEND_URL}/path_to_view_form/{response.id}", # noqa # TODO: Enter Form View URL "timestamp": response.timestamp, "color": 7506394, } @@ -213,3 +221,23 @@ class SubmitForm(Route): async with httpx.AsyncClient() as client: r = await client.post(form.webhook.url, json=hook) r.raise_for_status() + + @staticmethod + async def assign_role(form: Form, request_user: User) -> None: + """Assigns Discord role to user when user submitted response.""" + if not form.discord_role: + raise ValueError("Got empty Discord role ID.") + + url = ( + f"{constants.DISCORD_API_BASE_URL}/guilds/{constants.DISCORD_GUILD}" + f"/members/{request_user.payload['id']}/roles/{form.discord_role}" + ) + + async with httpx.AsyncClient() as client: + resp = await client.put( + url, + headers={ + "Authorization": f"Bot {constants.DISCORD_BOT_TOKEN}" + } + ) + resp.raise_for_status() -- cgit v1.2.3 From 0c110ab1dcde1916c870a6d1796bbff31606dd62 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:27:18 +0200 Subject: Add check for REQUIRES_LOGIN when ASSIGN_ROLE provided --- backend/models/form.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index 5aacc8b..d95cabd 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -47,8 +47,12 @@ class Form(BaseModel): if any(v not in allowed_values for v in value): raise ValueError("Form features list contains one or more invalid values.") - if FormFeatures.COLLECT_EMAIL in value and FormFeatures.REQUIRES_LOGIN not in value: # noqa - raise ValueError("COLLECT_EMAIL feature require REQUIRES_LOGIN feature.") + if FormFeatures.REQUIRES_LOGIN not in value: + if FormFeatures.COLLECT_EMAIL in value: + raise ValueError("COLLECT_EMAIL feature require REQUIRES_LOGIN feature.") + + if FormFeatures.ASSIGN_ROLE in value: + raise ValueError("ASSIGN_ROLE feature require REQUIRES_LOGIN feature.") return value -- cgit v1.2.3 From 4bce32330ecd298e610e4249e327ddb502542844 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:31:01 +0200 Subject: Add default value to guild ID --- backend/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/constants.py b/backend/constants.py index 70f3df1..812bef4 100644 --- a/backend/constants.py +++ b/backend/constants.py @@ -24,7 +24,7 @@ DOCS_PASSWORD = os.getenv("DOCS_PASSWORD") SECRET_KEY = os.getenv("SECRET_KEY", binascii.hexlify(os.urandom(30)).decode()) DISCORD_BOT_TOKEN = os.getenv("DISCORD_BOT_TOKEN") -DISCORD_GUILD = os.getenv("DISCORD_GUILD") +DISCORD_GUILD = os.getenv("DISCORD_GUILD", 267624335836053506) HCAPTCHA_API_SECRET = os.getenv("HCAPTCHA_API_SECRET") -- cgit v1.2.3 From 5b9f289cf415b2e60fa1550d5763367926b7bf6a Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:33:37 +0200 Subject: Fix too long line --- backend/models/form.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index d95cabd..f006544 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -49,7 +49,9 @@ class Form(BaseModel): if FormFeatures.REQUIRES_LOGIN not in value: if FormFeatures.COLLECT_EMAIL in value: - raise ValueError("COLLECT_EMAIL feature require REQUIRES_LOGIN feature.") + raise ValueError( + "COLLECT_EMAIL feature require REQUIRES_LOGIN feature." + ) if FormFeatures.ASSIGN_ROLE in value: raise ValueError("ASSIGN_ROLE feature require REQUIRES_LOGIN feature.") -- cgit v1.2.3 From b51ef608658ab7026d3bbd38ed5c6f6615f5fe31 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:47:42 +0200 Subject: Handle ratelimits for role assigning --- backend/routes/forms/submit.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'backend') diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py index 0ed248d..37f76e0 100644 --- a/backend/routes/forms/submit.py +++ b/backend/routes/forms/submit.py @@ -2,6 +2,7 @@ Submit a form. """ +import asyncio import binascii import hashlib import uuid @@ -26,6 +27,10 @@ HCAPTCHA_HEADERS = { "Content-Type": "application/x-www-form-urlencoded" } +DISCORD_HEADERS = { + "Authorization": f"Bot {constants.DISCORD_BOT_TOKEN}" +} + class SubmissionResponse(BaseModel): form: Form @@ -234,10 +239,17 @@ class SubmitForm(Route): ) async with httpx.AsyncClient() as client: - resp = await client.put( - url, - headers={ - "Authorization": f"Bot {constants.DISCORD_BOT_TOKEN}" - } - ) - resp.raise_for_status() + resp = await client.put(url, headers=DISCORD_HEADERS) + if resp.status_code == 429: # We are rate limited + status = resp.status_code + retry_after = float(resp.headers["X-Ratelimit-Reset-After"]) + while status == 429: + await asyncio.sleep(retry_after) + r = await client.put(url, headers=DISCORD_HEADERS) + status = r.status_code + if status == 429: + retry_after = float(r.headers["X-Ratelimit-Reset-After"]) + else: + r.raise_for_status() + else: # For any other unexpected status, raise error. + resp.raise_for_status() -- cgit v1.2.3 From cf9cef443b597b6126eb11b51d9d7dabdee4e0d0 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 29 Dec 2020 19:48:36 +0200 Subject: Use Discord API base URL from constants --- backend/discord.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'backend') diff --git a/backend/discord.py b/backend/discord.py index d6310b7..1dc8ed7 100644 --- a/backend/discord.py +++ b/backend/discord.py @@ -2,11 +2,9 @@ import httpx from backend.constants import ( - OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, OAUTH2_REDIRECT_URI + DISCORD_API_BASE_URL, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, OAUTH2_REDIRECT_URI ) -API_BASE_URL = "https://discord.com/api/v8" - async def fetch_bearer_token(access_code: str) -> dict: async with httpx.AsyncClient() as client: @@ -18,7 +16,7 @@ async def fetch_bearer_token(access_code: str) -> dict: "redirect_uri": OAUTH2_REDIRECT_URI } - r = await client.post(f"{API_BASE_URL}/oauth2/token", headers={ + r = await client.post(f"{DISCORD_API_BASE_URL}/oauth2/token", headers={ "Content-Type": "application/x-www-form-urlencoded" }, data=data) @@ -29,7 +27,7 @@ async def fetch_bearer_token(access_code: str) -> dict: async def fetch_user_details(bearer_token: str) -> dict: async with httpx.AsyncClient() as client: - r = await client.get(f"{API_BASE_URL}/users/@me", headers={ + r = await client.get(f"{DISCORD_API_BASE_URL}/users/@me", headers={ "Authorization": f"Bearer {bearer_token}" }) -- cgit v1.2.3 From 7bb9f530242bba9bd3ee028f248511e63afcae0f Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 9 Mar 2021 08:43:57 +0200 Subject: Add missing "is" to error message Co-authored-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- backend/models/form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index 04b535f..7e1a673 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -64,7 +64,7 @@ class Form(BaseModel): """Validates does Discord role provided when flag provided.""" if FormFeatures.ASSIGN_ROLE.value in values.get("features", []) and not values.get("discord_role"): # noqa raise ValueError( - "discord_role field is required when ASSIGN_ROLE flag provided." + "discord_role field is required when ASSIGN_ROLE flag is provided." ) return values -- cgit v1.2.3 From e096c708ee25a5a915462cf35a6d63d3ef68e26f Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 9 Mar 2021 08:50:07 +0200 Subject: Simplify role assigning rate limit handling Co-authored-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- backend/routes/forms/submit.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'backend') diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py index 23444a0..4d15ab7 100644 --- a/backend/routes/forms/submit.py +++ b/backend/routes/forms/submit.py @@ -288,16 +288,10 @@ class SubmitForm(Route): async with httpx.AsyncClient() as client: resp = await client.put(url, headers=DISCORD_HEADERS) - if resp.status_code == 429: # We are rate limited - status = resp.status_code + # Handle Rate Limits + while resp.status_code == 429: retry_after = float(resp.headers["X-Ratelimit-Reset-After"]) - while status == 429: - await asyncio.sleep(retry_after) - r = await client.put(url, headers=DISCORD_HEADERS) - status = r.status_code - if status == 429: - retry_after = float(r.headers["X-Ratelimit-Reset-After"]) - else: - r.raise_for_status() - else: # For any other unexpected status, raise error. - resp.raise_for_status() + await asyncio.sleep(retry_after) + resp = await client.put(url, headers=DISCORD_HEADERS) + + resp.raise_for_status() -- cgit v1.2.3 From a8bba220c26462dbc5c32171e769a267e7240583 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 16 Mar 2021 09:26:27 +0200 Subject: Add discord_role to public fields --- backend/models/form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index 7e1a673..accd9b1 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -7,7 +7,7 @@ from pydantic.error_wrappers import ErrorWrapper, ValidationError from backend.constants import FormFeatures, WebHook from .question import Question -PUBLIC_FIELDS = ["id", "features", "questions", "name", "description", "submitted_text"] +PUBLIC_FIELDS = ["id", "features", "questions", "name", "description", "submitted_text", "discord_role"] class _WebHook(BaseModel): -- cgit v1.2.3 From ffee0e4702925ec91b9c411e18fdac24633302cc Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 16 Mar 2021 09:27:41 +0200 Subject: Use value of enum member instead of member itself --- backend/models/form.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index accd9b1..edeb936 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -48,13 +48,13 @@ class Form(BaseModel): if any(v not in allowed_values for v in value): raise ValueError("Form features list contains one or more invalid values.") - if FormFeatures.REQUIRES_LOGIN not in value: - if FormFeatures.COLLECT_EMAIL in value: + if FormFeatures.REQUIRES_LOGIN.value not in value: + if FormFeatures.COLLECT_EMAIL.value in value: raise ValueError( "COLLECT_EMAIL feature require REQUIRES_LOGIN feature." ) - if FormFeatures.ASSIGN_ROLE in value: + if FormFeatures.ASSIGN_ROLE.value in value: raise ValueError("ASSIGN_ROLE feature require REQUIRES_LOGIN feature.") return value -- cgit v1.2.3 From 8731e7dc3a0a25bdf8e66e00b74fb73460089250 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 16 Mar 2021 09:28:24 +0200 Subject: Split public fields constant to multiple lines --- backend/models/form.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index edeb936..8780aa7 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -7,7 +7,15 @@ from pydantic.error_wrappers import ErrorWrapper, ValidationError from backend.constants import FormFeatures, WebHook from .question import Question -PUBLIC_FIELDS = ["id", "features", "questions", "name", "description", "submitted_text", "discord_role"] +PUBLIC_FIELDS = [ + "id", + "features", + "questions", + "name", + "description", + "submitted_text", + "discord_role" +] class _WebHook(BaseModel): -- cgit v1.2.3 From 535ca293b9448006dce2bf92a202ce6679ece86b Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 16 Mar 2021 09:29:34 +0200 Subject: Split if statement to multiple lines to avoid noqa --- backend/models/form.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index 8780aa7..a6fe888 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -70,7 +70,10 @@ class Form(BaseModel): @root_validator def validate_role(cls, values: dict[str, t.Any]) -> t.Optional[dict[str, t.Any]]: """Validates does Discord role provided when flag provided.""" - if FormFeatures.ASSIGN_ROLE.value in values.get("features", []) and not values.get("discord_role"): # noqa + if ( + FormFeatures.ASSIGN_ROLE.value in values.get("features", []) + and not values.get("discord_role" + ): raise ValueError( "discord_role field is required when ASSIGN_ROLE flag is provided." ) -- cgit v1.2.3 From 0b0a18b68cec9ffd2e354d9f7c91eb5697c273bf Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 16 Mar 2021 09:31:51 +0200 Subject: Add back removed parenthesis --- backend/models/form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/models/form.py b/backend/models/form.py index a6fe888..30ae0e7 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -72,7 +72,7 @@ class Form(BaseModel): """Validates does Discord role provided when flag provided.""" if ( FormFeatures.ASSIGN_ROLE.value in values.get("features", []) - and not values.get("discord_role" + and not values.get("discord_role") ): raise ValueError( "discord_role field is required when ASSIGN_ROLE flag is provided." -- cgit v1.2.3