diff options
Diffstat (limited to '')
| -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) | 
