diff options
author | 2020-12-18 23:12:33 +0300 | |
---|---|---|
committer | 2020-12-18 23:12:33 +0300 | |
commit | d1cb4200229a7811f21ce44dc427674e4f0b4ff3 (patch) | |
tree | b9f9d9522c3da4d4e05bc8aadfe3973b6cea16d1 /backend/models | |
parent | Uses Builtin User Class (diff) |
Runs Initial Validation Asynchronously
Moves the validation code of webhook urls to an async function that is
called by the route, to avoid blocking code.
Signed-off-by: Hassan Abouelela <[email protected]>
Diffstat (limited to 'backend/models')
-rw-r--r-- | backend/models/form.py | 87 |
1 files changed, 55 insertions, 32 deletions
diff --git a/backend/models/form.py b/backend/models/form.py index 9a3a8a2..96362d4 100644 --- a/backend/models/form.py +++ b/backend/models/form.py @@ -2,8 +2,9 @@ import typing as t import httpx from pydantic import BaseModel, Field, validator +from pydantic.error_wrappers import ErrorWrapper, ValidationError -from backend.constants import FormFeatures +from backend.constants import FormFeatures, Meta, WebHook from .question import Question PUBLIC_FIELDS = ["id", "features", "questions", "name", "description"] @@ -16,40 +17,10 @@ class _WebHook(BaseModel): @validator("url") def validate_url(cls, url: str) -> str: - """Checks if discord webhook urls are valid.""" - if not isinstance(url, str): - raise ValueError("Webhook URL must be a string.") - + """Validates URL parameter.""" if "discord.com/api/webhooks/" not in url: raise ValueError("URL must be a discord webhook.") - # Attempt to connect to URL - try: - httpx.get(url).raise_for_status() - - except httpx.RequestError as e: - # Catch exceptions in request format - raise ValueError( - f"Encountered error while trying to connect to url: `{e}`" - ) - - except httpx.HTTPStatusError as e: - # Catch exceptions in response - status = e.response.status_code - - if status == 401: - raise ValueError( - "Could not authenticate with target. Please check the webhook url." - ) - elif status == 404: - raise ValueError( - "Target could not find webhook url. Please check the webhook url." - ) - else: - raise ValueError( - f"Unknown error ({status}) while connecting to target: {e}" - ) - return url @@ -107,3 +78,55 @@ class Form(BaseModel): class FormList(BaseModel): __root__: t.List[Form] + + +async def validate_hook_url(url: str) -> t.Optional[ValidationError]: + """Validator for discord webhook urls.""" + async def validate(): + if not isinstance(url, str): + raise ValueError("Webhook URL must be a string.") + + if "discord.com/api/webhooks/" not in url: + raise ValueError("URL must be a discord webhook.") + + try: + async with httpx.AsyncClient() as client: + response = await client.get(url) + response.raise_for_status() + + except httpx.RequestError as error: + # Catch exceptions in request format + raise ValueError( + f"Encountered error while trying to connect to url: `{error}`" + ) + + except httpx.HTTPStatusError as error: + # Catch exceptions in response + status = error.response.status_code + + if status == 401: + raise ValueError( + "Could not authenticate with target. Please check the webhook url." + ) + elif status == 404: + raise ValueError( + "Target could not find webhook url. Please check the webhook url." + ) + else: + raise ValueError( + f"Unknown error ({status}) while connecting to target: {error}" + ) + + return url + + # Validate, and return errors, if any + try: + await validate() + except Exception as e: + loc = ( + Meta.__name__.lower(), + WebHook.__name__.lower(), + WebHook.URL.value + ) + + return ValidationError([ErrorWrapper(e, loc=loc)], _WebHook) |