Module supertokens_python.recipe.multifactorauth.types

Expand source code
# Copyright (c) 2024, 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, Awaitable, Callable, Dict, List, Optional, Union

from typing_extensions import Literal

from supertokens_python.recipe.multitenancy.interfaces import TenantConfig
from supertokens_python.types import RecipeUserId, User
from supertokens_python.types.config import (
    BaseConfig,
    BaseNormalisedConfig,
    BaseNormalisedOverrideConfig,
    BaseOverrideableConfig,
    BaseOverrideConfig,
)

from .interfaces import APIInterface, RecipeInterface

MFARequirementList = List[
    Union[str, Dict[Union[Literal["oneOf"], Literal["allOfInAnyOrder"]], List[str]]]
]


class MFAClaimValue:
    c: Dict[str, int]
    v: bool

    def __init__(self, c: Dict[str, Any], v: bool):
        self.c = c
        self.v = v


MultiFactorAuthOverrideConfig = BaseOverrideConfig[RecipeInterface, APIInterface]
NormalisedMultiFactorAuthOverrideConfig = BaseNormalisedOverrideConfig[
    RecipeInterface, APIInterface
]
OverrideConfig = MultiFactorAuthOverrideConfig
"""Deprecated, use `MultiFactorAuthOverrideConfig` instead."""


class MultiFactorAuthOverrideableConfig(BaseOverrideableConfig):
    """Input config properties overrideable using the plugin config overrides"""

    first_factors: Optional[List[str]] = None


class MultiFactorAuthConfig(
    MultiFactorAuthOverrideableConfig,
    BaseConfig[RecipeInterface, APIInterface, MultiFactorAuthOverrideableConfig],
):
    def to_overrideable_config(self) -> MultiFactorAuthOverrideableConfig:
        """Create a `MultiFactorAuthOverrideableConfig` from the current config."""
        return MultiFactorAuthOverrideableConfig(**self.model_dump())

    def from_overrideable_config(
        self,
        overrideable_config: MultiFactorAuthOverrideableConfig,
    ) -> "MultiFactorAuthConfig":
        """
        Create a `MultiFactorAuthConfig` from a `MultiFactorAuthOverrideableConfig`.
        Not a classmethod since it needs to be used in a dynamic context within plugins.
        """
        return MultiFactorAuthConfig(
            **overrideable_config.model_dump(),
            override=self.override,
        )


class NormalisedMultiFactorAuthConfig(
    BaseNormalisedConfig[RecipeInterface, APIInterface]
):
    first_factors: Optional[List[str]]


class FactorIds:
    EMAILPASSWORD = "emailpassword"
    OTP_EMAIL = "otp-email"
    OTP_PHONE = "otp-phone"
    LINK_EMAIL = "link-email"
    LINK_PHONE = "link-phone"
    THIRDPARTY = "thirdparty"
    TOTP = "totp"
    WEBAUTHN = "webauthn"

    @staticmethod
    def get_all_factors():
        return [
            FactorIds.EMAILPASSWORD,
            FactorIds.OTP_EMAIL,
            FactorIds.OTP_PHONE,
            FactorIds.LINK_EMAIL,
            FactorIds.LINK_PHONE,
            FactorIds.THIRDPARTY,
            FactorIds.TOTP,
            FactorIds.WEBAUTHN,
        ]


class FactorIdsAndType:
    def __init__(
        self,
        factor_ids: List[str],
        type_: Union[Literal["string"], Literal["oneOf"], Literal["allOfInAnyOrder"]],
    ):
        self.factor_ids = factor_ids
        self.type_ = type_


class GetFactorsSetupForUserFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[[User, Dict[str, Any]], Awaitable[List[str]]],
    ):
        self.func = func


class GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[[TenantConfig], Awaitable[List[str]]],
    ):
        self.func = func


class GetEmailsForFactorOkResult:
    status: Literal["OK"] = "OK"

    def __init__(self, factor_id_to_emails_map: Dict[str, List[str]]):
        self.factor_id_to_emails_map = factor_id_to_emails_map


class GetEmailsForFactorUnknownSessionRecipeUserIdResult:
    status: Literal["UNKNOWN_SESSION_RECIPE_USER_ID"] = "UNKNOWN_SESSION_RECIPE_USER_ID"


class GetEmailsForFactorFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[
            [User, RecipeUserId],
            Awaitable[
                Union[
                    GetEmailsForFactorOkResult,
                    GetEmailsForFactorUnknownSessionRecipeUserIdResult,
                ]
            ],
        ],
    ):
        self.func = func


class GetPhoneNumbersForFactorsOkResult:
    status: Literal["OK"] = "OK"

    def __init__(self, factor_id_to_phone_number_map: Dict[str, List[str]]):
        self.factor_id_to_phone_number_map = factor_id_to_phone_number_map


class GetPhoneNumbersForFactorsUnknownSessionRecipeUserIdResult:
    status: Literal["UNKNOWN_SESSION_RECIPE_USER_ID"] = "UNKNOWN_SESSION_RECIPE_USER_ID"


class GetPhoneNumbersForFactorsFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[
            [User, RecipeUserId],
            Awaitable[
                Union[
                    GetPhoneNumbersForFactorsOkResult,
                    GetPhoneNumbersForFactorsUnknownSessionRecipeUserIdResult,
                ]
            ],
        ],
    ):
        self.func = func

Classes

class OverrideConfig (**data: Any)

Base class for input override config with API overrides.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Ancestors

Inherited members

class FactorIds
Expand source code
class FactorIds:
    EMAILPASSWORD = "emailpassword"
    OTP_EMAIL = "otp-email"
    OTP_PHONE = "otp-phone"
    LINK_EMAIL = "link-email"
    LINK_PHONE = "link-phone"
    THIRDPARTY = "thirdparty"
    TOTP = "totp"
    WEBAUTHN = "webauthn"

    @staticmethod
    def get_all_factors():
        return [
            FactorIds.EMAILPASSWORD,
            FactorIds.OTP_EMAIL,
            FactorIds.OTP_PHONE,
            FactorIds.LINK_EMAIL,
            FactorIds.LINK_PHONE,
            FactorIds.THIRDPARTY,
            FactorIds.TOTP,
            FactorIds.WEBAUTHN,
        ]

Class variables

var EMAILPASSWORD

The type of the None singleton.

The type of the None singleton.

The type of the None singleton.

var OTP_EMAIL

The type of the None singleton.

var OTP_PHONE

The type of the None singleton.

var THIRDPARTY

The type of the None singleton.

var TOTP

The type of the None singleton.

var WEBAUTHN

The type of the None singleton.

Static methods

def get_all_factors()
class FactorIdsAndType (factor_ids: List[str], type_: "Union[Literal['string'], Literal['oneOf'], Literal['allOfInAnyOrder']]")
Expand source code
class FactorIdsAndType:
    def __init__(
        self,
        factor_ids: List[str],
        type_: Union[Literal["string"], Literal["oneOf"], Literal["allOfInAnyOrder"]],
    ):
        self.factor_ids = factor_ids
        self.type_ = type_
class GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc (func: Callable[[TenantConfig], Awaitable[List[str]]])
Expand source code
class GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[[TenantConfig], Awaitable[List[str]]],
    ):
        self.func = func
class GetEmailsForFactorFromOtherRecipesFunc (func: Callable[[User, RecipeUserId], Awaitable[Union[GetEmailsForFactorOkResultGetEmailsForFactorUnknownSessionRecipeUserIdResult]]])
Expand source code
class GetEmailsForFactorFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[
            [User, RecipeUserId],
            Awaitable[
                Union[
                    GetEmailsForFactorOkResult,
                    GetEmailsForFactorUnknownSessionRecipeUserIdResult,
                ]
            ],
        ],
    ):
        self.func = func
class GetEmailsForFactorOkResult (factor_id_to_emails_map: Dict[str, List[str]])
Expand source code
class GetEmailsForFactorOkResult:
    status: Literal["OK"] = "OK"

    def __init__(self, factor_id_to_emails_map: Dict[str, List[str]]):
        self.factor_id_to_emails_map = factor_id_to_emails_map

Class variables

var status : Literal['OK']

The type of the None singleton.

class GetEmailsForFactorUnknownSessionRecipeUserIdResult
Expand source code
class GetEmailsForFactorUnknownSessionRecipeUserIdResult:
    status: Literal["UNKNOWN_SESSION_RECIPE_USER_ID"] = "UNKNOWN_SESSION_RECIPE_USER_ID"

Class variables

var status : Literal['UNKNOWN_SESSION_RECIPE_USER_ID']

The type of the None singleton.

class GetFactorsSetupForUserFromOtherRecipesFunc (func: Callable[[User, Dict[str, Any]], Awaitable[List[str]]])
Expand source code
class GetFactorsSetupForUserFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[[User, Dict[str, Any]], Awaitable[List[str]]],
    ):
        self.func = func
class GetPhoneNumbersForFactorsFromOtherRecipesFunc (func: Callable[[User, RecipeUserId], Awaitable[Union[GetPhoneNumbersForFactorsOkResultGetPhoneNumbersForFactorsUnknownSessionRecipeUserIdResult]]])
Expand source code
class GetPhoneNumbersForFactorsFromOtherRecipesFunc:
    def __init__(
        self,
        func: Callable[
            [User, RecipeUserId],
            Awaitable[
                Union[
                    GetPhoneNumbersForFactorsOkResult,
                    GetPhoneNumbersForFactorsUnknownSessionRecipeUserIdResult,
                ]
            ],
        ],
    ):
        self.func = func
class GetPhoneNumbersForFactorsOkResult (factor_id_to_phone_number_map: Dict[str, List[str]])
Expand source code
class GetPhoneNumbersForFactorsOkResult:
    status: Literal["OK"] = "OK"

    def __init__(self, factor_id_to_phone_number_map: Dict[str, List[str]]):
        self.factor_id_to_phone_number_map = factor_id_to_phone_number_map

Class variables

var status : Literal['OK']

The type of the None singleton.

class GetPhoneNumbersForFactorsUnknownSessionRecipeUserIdResult
Expand source code
class GetPhoneNumbersForFactorsUnknownSessionRecipeUserIdResult:
    status: Literal["UNKNOWN_SESSION_RECIPE_USER_ID"] = "UNKNOWN_SESSION_RECIPE_USER_ID"

Class variables

var status : Literal['UNKNOWN_SESSION_RECIPE_USER_ID']

The type of the None singleton.

class MFAClaimValue (c: Dict[str, Any], v: bool)
Expand source code
class MFAClaimValue:
    c: Dict[str, int]
    v: bool

    def __init__(self, c: Dict[str, Any], v: bool):
        self.c = c
        self.v = v

Class variables

var c : Dict[str, int]

The type of the None singleton.

var v : bool

The type of the None singleton.

class MultiFactorAuthConfig (**data: Any)

Input config properties overrideable using the plugin config overrides

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Expand source code
class MultiFactorAuthConfig(
    MultiFactorAuthOverrideableConfig,
    BaseConfig[RecipeInterface, APIInterface, MultiFactorAuthOverrideableConfig],
):
    def to_overrideable_config(self) -> MultiFactorAuthOverrideableConfig:
        """Create a `MultiFactorAuthOverrideableConfig` from the current config."""
        return MultiFactorAuthOverrideableConfig(**self.model_dump())

    def from_overrideable_config(
        self,
        overrideable_config: MultiFactorAuthOverrideableConfig,
    ) -> "MultiFactorAuthConfig":
        """
        Create a `MultiFactorAuthConfig` from a `MultiFactorAuthOverrideableConfig`.
        Not a classmethod since it needs to be used in a dynamic context within plugins.
        """
        return MultiFactorAuthConfig(
            **overrideable_config.model_dump(),
            override=self.override,
        )

Ancestors

Methods

def from_overrideable_config(self, overrideable_config: MultiFactorAuthOverrideableConfig) ‑> MultiFactorAuthConfig

Create a MultiFactorAuthConfig from a MultiFactorAuthOverrideableConfig. Not a classmethod since it needs to be used in a dynamic context within plugins.

def to_overrideable_config(self) ‑> MultiFactorAuthOverrideableConfig

Create a MultiFactorAuthOverrideableConfig from the current config.

Inherited members

class MultiFactorAuthOverrideableConfig (**data: Any)

Input config properties overrideable using the plugin config overrides

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Expand source code
class MultiFactorAuthOverrideableConfig(BaseOverrideableConfig):
    """Input config properties overrideable using the plugin config overrides"""

    first_factors: Optional[List[str]] = None

Ancestors

Subclasses

Class variables

var first_factors : Optional[List[str]]

The type of the None singleton.

Inherited members

class NormalisedMultiFactorAuthConfig (**data: Any)

Base class for normalized config of a Recipe with API overrides.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Expand source code
class NormalisedMultiFactorAuthConfig(
    BaseNormalisedConfig[RecipeInterface, APIInterface]
):
    first_factors: Optional[List[str]]

Ancestors

Class variables

var first_factors : Optional[List[str]]

The type of the None singleton.

Inherited members