Module supertokens_python.recipe.dashboard.api.multitenancy.utils
Expand source code
from typing import List
from supertokens_python.recipe.multifactorauth.recipe import MultiFactorAuthRecipe
from supertokens_python.recipe.multifactorauth.types import FactorIds
from supertokens_python.recipe.multifactorauth.utils import (
is_factor_configured_for_tenant,
)
from supertokens_python.recipe.multitenancy.interfaces import TenantConfig
from supertokens_python.recipe.multitenancy.recipe import MultitenancyRecipe
def get_normalised_first_factors_based_on_tenant_config_from_core_and_sdk_init(
tenant_details_from_core: TenantConfig,
) -> List[str]:
first_factors: List[str]
mt_instance = MultitenancyRecipe.get_instance()
if tenant_details_from_core.first_factors is not None:
first_factors = (
tenant_details_from_core.first_factors
) # highest priority, config from core
elif mt_instance.static_first_factors is not None:
first_factors = mt_instance.static_first_factors # next priority, static config
else:
# Fallback to all available factors (de-duplicated)
first_factors = list(set(mt_instance.all_available_first_factors))
# we now filter out all available first factors by checking if they are valid because
# we want to return the ones that can work. this would be based on what recipes are enabled
# on the core and also first_factors configured in the core and supertokens.init
# Also, this way, in the front end, the developer can just check for first_factors for
# enabled recipes in all cases irrespective of whether they are using MFA or not
valid_first_factors: List[str] = []
for factor_id in first_factors:
if is_factor_configured_for_tenant(
all_available_first_factors=mt_instance.all_available_first_factors,
first_factors=first_factors,
factor_id=factor_id,
):
valid_first_factors.append(factor_id)
return valid_first_factors
def get_factor_not_available_message(
factor_id: str, available_factors: List[str]
) -> str:
recipe_name = factor_id_to_recipe(factor_id)
if recipe_name != "Passwordless":
return f"Please initialise {recipe_name} recipe to be able to use this login method"
passwordless_factors = [
FactorIds.LINK_EMAIL,
FactorIds.LINK_PHONE,
FactorIds.OTP_EMAIL,
FactorIds.OTP_PHONE,
]
passwordless_factors_not_available = [
f for f in passwordless_factors if f not in available_factors
]
if len(passwordless_factors_not_available) == 4:
return (
"Please initialise Passwordless recipe to be able to use this login method"
)
flow_type, contact_method = factor_id.split("-")
return f"Please ensure that Passwordless recipe is initialised with contactMethod: {contact_method.upper()} and flowType: {'USER_INPUT_CODE' if flow_type == 'otp' else 'MAGIC_LINK'}"
def factor_id_to_recipe(factor_id: str) -> str:
factor_id_to_recipe_map = {
"emailpassword": "Emailpassword",
"thirdparty": "ThirdParty",
"otp-email": "Passwordless",
"otp-phone": "Passwordless",
"link-email": "Passwordless",
"link-phone": "Passwordless",
"totp": "Totp",
}
return factor_id_to_recipe_map.get(factor_id, "")
async def get_normalised_required_secondary_factors_based_on_tenant_config_from_core_and_sdk_init(
tenant_details_from_core: TenantConfig,
) -> List[str]:
mfa_instance = MultiFactorAuthRecipe.get_instance()
if mfa_instance is None:
return []
secondary_factors = await mfa_instance.get_all_available_secondary_factor_ids(
tenant_details_from_core
)
secondary_factors = [
factor_id
for factor_id in secondary_factors
if factor_id in (tenant_details_from_core.required_secondary_factors or [])
]
return secondary_factors
Functions
def factor_id_to_recipe(factor_id: str) ‑> str
-
Expand source code
def factor_id_to_recipe(factor_id: str) -> str: factor_id_to_recipe_map = { "emailpassword": "Emailpassword", "thirdparty": "ThirdParty", "otp-email": "Passwordless", "otp-phone": "Passwordless", "link-email": "Passwordless", "link-phone": "Passwordless", "totp": "Totp", } return factor_id_to_recipe_map.get(factor_id, "")
def get_factor_not_available_message(factor_id: str, available_factors: List[str]) ‑> str
-
Expand source code
def get_factor_not_available_message( factor_id: str, available_factors: List[str] ) -> str: recipe_name = factor_id_to_recipe(factor_id) if recipe_name != "Passwordless": return f"Please initialise {recipe_name} recipe to be able to use this login method" passwordless_factors = [ FactorIds.LINK_EMAIL, FactorIds.LINK_PHONE, FactorIds.OTP_EMAIL, FactorIds.OTP_PHONE, ] passwordless_factors_not_available = [ f for f in passwordless_factors if f not in available_factors ] if len(passwordless_factors_not_available) == 4: return ( "Please initialise Passwordless recipe to be able to use this login method" ) flow_type, contact_method = factor_id.split("-") return f"Please ensure that Passwordless recipe is initialised with contactMethod: {contact_method.upper()} and flowType: {'USER_INPUT_CODE' if flow_type == 'otp' else 'MAGIC_LINK'}"
def get_normalised_first_factors_based_on_tenant_config_from_core_and_sdk_init(tenant_details_from_core: TenantConfig) ‑> List[str]
-
Expand source code
def get_normalised_first_factors_based_on_tenant_config_from_core_and_sdk_init( tenant_details_from_core: TenantConfig, ) -> List[str]: first_factors: List[str] mt_instance = MultitenancyRecipe.get_instance() if tenant_details_from_core.first_factors is not None: first_factors = ( tenant_details_from_core.first_factors ) # highest priority, config from core elif mt_instance.static_first_factors is not None: first_factors = mt_instance.static_first_factors # next priority, static config else: # Fallback to all available factors (de-duplicated) first_factors = list(set(mt_instance.all_available_first_factors)) # we now filter out all available first factors by checking if they are valid because # we want to return the ones that can work. this would be based on what recipes are enabled # on the core and also first_factors configured in the core and supertokens.init # Also, this way, in the front end, the developer can just check for first_factors for # enabled recipes in all cases irrespective of whether they are using MFA or not valid_first_factors: List[str] = [] for factor_id in first_factors: if is_factor_configured_for_tenant( all_available_first_factors=mt_instance.all_available_first_factors, first_factors=first_factors, factor_id=factor_id, ): valid_first_factors.append(factor_id) return valid_first_factors
async def get_normalised_required_secondary_factors_based_on_tenant_config_from_core_and_sdk_init(tenant_details_from_core: TenantConfig) ‑> List[str]
-
Expand source code
async def get_normalised_required_secondary_factors_based_on_tenant_config_from_core_and_sdk_init( tenant_details_from_core: TenantConfig, ) -> List[str]: mfa_instance = MultiFactorAuthRecipe.get_instance() if mfa_instance is None: return [] secondary_factors = await mfa_instance.get_all_available_secondary_factor_ids( tenant_details_from_core ) secondary_factors = [ factor_id for factor_id in secondary_factors if factor_id in (tenant_details_from_core.required_secondary_factors or []) ] return secondary_factors