Module supertokens_python.recipe.emailpassword.api.utils

Expand source code
# Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
#
# This software is licensed under the Apache License, Version 2.0 (the
# "License") as published by the Apache Software Foundation.
#
# You may not use this file except in compliance with the License. You may
# obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import annotations

from typing import Any, Dict, List, Union

from supertokens_python.exceptions import raise_bad_input_exception
from supertokens_python.recipe.emailpassword.constants import (
    FORM_FIELD_EMAIL_ID,
    FORM_FIELD_PASSWORD_ID,
)
from supertokens_python.recipe.emailpassword.exceptions import (
    raise_form_field_exception,
)
from supertokens_python.recipe.emailpassword.types import (
    ErrorFormField,
    FormField,
    NormalisedFormField,
)
from supertokens_python.utils import find_first_occurrence_in_list


async def validate_form_or_throw_error(
    inputs: List[FormField],
    config_form_fields: List[NormalisedFormField],
    tenant_id: str,
):
    validation_errors: List[ErrorFormField] = []
    if len(config_form_fields) < len(inputs):
        raise_bad_input_exception("Are you sending too many formFields?")

    for field in config_form_fields:
        input_field: Union[None, FormField] = find_first_occurrence_in_list(
            lambda x: x.id == field.id, inputs
        )
        is_invalid_value = input_field is None or (
            isinstance(input_field.value, str) and input_field.value == ""
        )
        if not field.optional and is_invalid_value:
            validation_errors.append(ErrorFormField(field.id, "Field is not optional"))
            continue

        # If the field was invalid and not optional, execution won't reach here.
        # so we need to skip it if  the value is invalid and optional.
        if is_invalid_value:
            continue

        assert input_field is not None

        error = await field.validate(input_field.value, tenant_id)
        if error is not None:
            validation_errors.append(ErrorFormField(field.id, error))

    if len(validation_errors) != 0:
        # raise BadInputError(msg="Error in input formFields")
        raise_form_field_exception("Error in input formFields", validation_errors)


async def validate_form_fields_or_throw_error(
    config_form_fields: List[NormalisedFormField], form_fields_raw: Any, tenant_id: str
) -> List[FormField]:
    if form_fields_raw is None:
        raise_bad_input_exception("Missing input param: formFields")

    if not isinstance(form_fields_raw, List):
        raise_bad_input_exception("formFields must be an array")

    form_fields: List[FormField] = []

    form_fields_list_raw: List[Dict[str, Any]] = form_fields_raw
    for current_form_field in form_fields_list_raw:
        if (
            "id" not in current_form_field
            or not isinstance(current_form_field["id"], str)
            or "value" not in current_form_field
        ):
            raise_bad_input_exception(
                "All elements of formFields must contain an 'id' and 'value' field"
            )

        value = current_form_field["value"]
        if current_form_field["id"] in [
            FORM_FIELD_EMAIL_ID,
            FORM_FIELD_PASSWORD_ID,
        ] and not isinstance(value, str):
            # Ensure that the type is string else we will throw a bad input
            # error.
            raise_bad_input_exception(
                f"{current_form_field['id']} value must be a string"
            )

        if current_form_field["id"] == FORM_FIELD_EMAIL_ID and isinstance(value, str):
            value = value.strip()
        form_fields.append(FormField(current_form_field["id"], value))

    await validate_form_or_throw_error(form_fields, config_form_fields, tenant_id)
    return form_fields

Functions

async def validate_form_fields_or_throw_error(config_form_fields: List[NormalisedFormField], form_fields_raw: Any, tenant_id: str) ‑> List[FormField]
Expand source code
async def validate_form_fields_or_throw_error(
    config_form_fields: List[NormalisedFormField], form_fields_raw: Any, tenant_id: str
) -> List[FormField]:
    if form_fields_raw is None:
        raise_bad_input_exception("Missing input param: formFields")

    if not isinstance(form_fields_raw, List):
        raise_bad_input_exception("formFields must be an array")

    form_fields: List[FormField] = []

    form_fields_list_raw: List[Dict[str, Any]] = form_fields_raw
    for current_form_field in form_fields_list_raw:
        if (
            "id" not in current_form_field
            or not isinstance(current_form_field["id"], str)
            or "value" not in current_form_field
        ):
            raise_bad_input_exception(
                "All elements of formFields must contain an 'id' and 'value' field"
            )

        value = current_form_field["value"]
        if current_form_field["id"] in [
            FORM_FIELD_EMAIL_ID,
            FORM_FIELD_PASSWORD_ID,
        ] and not isinstance(value, str):
            # Ensure that the type is string else we will throw a bad input
            # error.
            raise_bad_input_exception(
                f"{current_form_field['id']} value must be a string"
            )

        if current_form_field["id"] == FORM_FIELD_EMAIL_ID and isinstance(value, str):
            value = value.strip()
        form_fields.append(FormField(current_form_field["id"], value))

    await validate_form_or_throw_error(form_fields, config_form_fields, tenant_id)
    return form_fields
async def validate_form_or_throw_error(inputs: List[FormField], config_form_fields: List[NormalisedFormField], tenant_id: str)
Expand source code
async def validate_form_or_throw_error(
    inputs: List[FormField],
    config_form_fields: List[NormalisedFormField],
    tenant_id: str,
):
    validation_errors: List[ErrorFormField] = []
    if len(config_form_fields) < len(inputs):
        raise_bad_input_exception("Are you sending too many formFields?")

    for field in config_form_fields:
        input_field: Union[None, FormField] = find_first_occurrence_in_list(
            lambda x: x.id == field.id, inputs
        )
        is_invalid_value = input_field is None or (
            isinstance(input_field.value, str) and input_field.value == ""
        )
        if not field.optional and is_invalid_value:
            validation_errors.append(ErrorFormField(field.id, "Field is not optional"))
            continue

        # If the field was invalid and not optional, execution won't reach here.
        # so we need to skip it if  the value is invalid and optional.
        if is_invalid_value:
            continue

        assert input_field is not None

        error = await field.validate(input_field.value, tenant_id)
        if error is not None:
            validation_errors.append(ErrorFormField(field.id, error))

    if len(validation_errors) != 0:
        # raise BadInputError(msg="Error in input formFields")
        raise_form_field_exception("Error in input formFields", validation_errors)