Module supertokens_python.recipe.passwordless
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 TYPE_CHECKING, Any, Awaitable, Callable, Dict, Union
from typing_extensions import Literal
from supertokens_python.ingredients.emaildelivery.types import EmailDeliveryConfig
from supertokens_python.ingredients.smsdelivery.types import SMSDeliveryConfig
from supertokens_python.recipe.passwordless.types import (
EmailTemplateVars,
SMSTemplateVars,
)
from .emaildelivery.services import SMTPService
from .recipe import PasswordlessRecipe
from .smsdelivery.services import SuperTokensSMSService, TwilioService
from .types import (
CreateAndSendCustomEmailParameters,
CreateAndSendCustomTextMessageParameters,
EmailDeliveryInterface,
SMSDeliveryInterface,
)
from .utils import (
ContactConfig,
ContactEmailOnlyConfig,
ContactEmailOrPhoneConfig,
ContactPhoneOnlyConfig,
InputOverrideConfig,
PasswordlessOverrideConfig,
PhoneOrEmailInput,
)
if TYPE_CHECKING:
from supertokens_python.supertokens import RecipeInit
def init(
contact_config: ContactConfig,
flow_type: Literal[
"USER_INPUT_CODE", "MAGIC_LINK", "USER_INPUT_CODE_AND_MAGIC_LINK"
],
override: Union[PasswordlessOverrideConfig, None] = None,
get_custom_user_input_code: Union[
Callable[[str, Dict[str, Any]], Awaitable[str]], None
] = None,
email_delivery: Union[EmailDeliveryConfig[EmailTemplateVars], None] = None,
sms_delivery: Union[SMSDeliveryConfig[SMSTemplateVars], None] = None,
) -> RecipeInit:
return PasswordlessRecipe.init(
contact_config,
flow_type,
override,
get_custom_user_input_code,
email_delivery,
sms_delivery,
)
__all__ = [
"ContactConfig",
"ContactEmailOnlyConfig",
"ContactEmailOrPhoneConfig",
"ContactPhoneOnlyConfig",
"CreateAndSendCustomEmailParameters",
"CreateAndSendCustomTextMessageParameters",
"EmailDeliveryInterface",
"InputOverrideConfig", # deprecated, use PasswordlessOverrideConfig instead
"PasswordlessOverrideConfig",
"PhoneOrEmailInput",
"SMSDeliveryInterface",
"SMTPService",
"SuperTokensSMSService",
"TwilioService",
"init",
]
Sub-modules
supertokens_python.recipe.passwordless.apisupertokens_python.recipe.passwordless.asynciosupertokens_python.recipe.passwordless.constantssupertokens_python.recipe.passwordless.emaildeliverysupertokens_python.recipe.passwordless.exceptionssupertokens_python.recipe.passwordless.interfacessupertokens_python.recipe.passwordless.recipesupertokens_python.recipe.passwordless.recipe_implementationsupertokens_python.recipe.passwordless.smsdeliverysupertokens_python.recipe.passwordless.synciosupertokens_python.recipe.passwordless.typessupertokens_python.recipe.passwordless.utils
Functions
def init(contact_config: ContactConfig, flow_type: "Literal['USER_INPUT_CODE', 'MAGIC_LINK', 'USER_INPUT_CODE_AND_MAGIC_LINK']", override: Union[BaseOverrideConfig[RecipeInterface, APIInterface], None] = None, get_custom_user_input_code: Union[Callable[[str, Dict[str, Any]], Awaitable[str]], None] = None, email_delivery: Union[EmailDeliveryConfig[EmailTemplateVars], None] = None, sms_delivery: Union[SMSDeliveryConfig[SMSTemplateVars], None] = None)
Classes
class InputOverrideConfig (**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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- BaseOverrideConfig
- BaseOverrideConfigWithoutAPI
- CamelCaseBaseModel
- APIResponse
- abc.ABC
- pydantic.main.BaseModel
- typing.Generic
Class variables
var model_config-
The type of the None singleton.
class PasswordlessOverrideConfig (**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.selfis explicitly positional-only to allowselfas a field name.Ancestors
- BaseOverrideConfig
- BaseOverrideConfigWithoutAPI
- CamelCaseBaseModel
- APIResponse
- abc.ABC
- pydantic.main.BaseModel
- typing.Generic
Inherited members
class ContactConfig (contact_method: "Literal['PHONE', 'EMAIL', 'EMAIL_OR_PHONE']")-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class ContactConfig(ABC): def __init__(self, contact_method: Literal["PHONE", "EMAIL", "EMAIL_OR_PHONE"]): self.contact_method = contact_methodAncestors
- abc.ABC
Subclasses
class ContactEmailOnlyConfig (validate_email_address: Union[Callable[[str, str], Awaitable[Union[str, None]]], None] = None)-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class ContactEmailOnlyConfig(ContactConfig): def __init__( self, validate_email_address: Union[ Callable[[str, str], Awaitable[Union[str, None]]], None ] = None, ): super().__init__("EMAIL") if validate_email_address is None: self.validate_email_address = default_validate_email else: self.validate_email_address = validate_email_addressAncestors
- ContactConfig
- abc.ABC
class ContactEmailOrPhoneConfig (validate_email_address: Union[Callable[[str, str], Awaitable[Union[str, None]]], None] = None, validate_phone_number: Union[Callable[[str, str], Awaitable[Union[str, None]]], None] = None)-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class ContactEmailOrPhoneConfig(ContactConfig): def __init__( self, validate_email_address: Union[ Callable[[str, str], Awaitable[Union[str, None]]], None ] = None, validate_phone_number: Union[ Callable[[str, str], Awaitable[Union[str, None]]], None ] = None, ): super().__init__("EMAIL_OR_PHONE") if validate_email_address is None: self.validate_email_address = default_validate_email else: self.validate_email_address = validate_email_address if validate_phone_number is None: self.validate_phone_number = default_validate_phone_number else: self.validate_phone_number = validate_phone_numberAncestors
- ContactConfig
- abc.ABC
class ContactPhoneOnlyConfig (validate_phone_number: Union[Callable[[str, str], Awaitable[Union[str, None]]], None] = None)-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class ContactPhoneOnlyConfig(ContactConfig): def __init__( self, validate_phone_number: Union[ Callable[[str, str], Awaitable[Union[str, None]]], None ] = None, ): super().__init__("PHONE") if validate_phone_number is None: self.validate_phone_number = default_validate_phone_number else: self.validate_phone_number = validate_phone_numberAncestors
- ContactConfig
- abc.ABC
class CreateAndSendCustomEmailParameters (tenant_id: str, code_life_time: int, pre_auth_session_id: str, email: str, is_first_factor: bool, user_input_code: Optional[str] = None, url_with_link_code: Optional[str] = None)-
Expand source code
class CreateAndSendCustomEmailParameters: def __init__( self, tenant_id: str, code_life_time: int, pre_auth_session_id: str, email: str, is_first_factor: bool, user_input_code: Union[str, None] = None, url_with_link_code: Union[str, None] = None, ): self.email = email self.code_life_time = code_life_time self.pre_auth_session_id = pre_auth_session_id self.user_input_code = user_input_code self.url_with_link_code = url_with_link_code self.tenant_id = tenant_id self.is_first_factor = is_first_factor class CreateAndSendCustomTextMessageParameters (tenant_id: str, code_life_time: int, pre_auth_session_id: str, phone_number: str, is_first_factor: bool, user_input_code: Optional[str] = None, url_with_link_code: Optional[str] = None)-
Expand source code
class CreateAndSendCustomTextMessageParameters: def __init__( self, tenant_id: str, code_life_time: int, pre_auth_session_id: str, phone_number: str, is_first_factor: bool, user_input_code: Union[str, None] = None, url_with_link_code: Union[str, None] = None, ): self.code_life_time = code_life_time self.pre_auth_session_id = pre_auth_session_id self.phone_number = phone_number self.user_input_code = user_input_code self.url_with_link_code = url_with_link_code self.tenant_id = tenant_id self.is_first_factor = is_first_factor class EmailDeliveryInterface-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class EmailDeliveryInterface(ABC, Generic[_T]): @abstractmethod async def send_email(self, template_vars: _T, user_context: Dict[str, Any]) -> None: passAncestors
- abc.ABC
- typing.Generic
Subclasses
- BackwardCompatibilityService
- SMTPService
- BackwardCompatibilityService
- SMTPService
- BackwardCompatibilityService
- SMTPService
- BackwardCompatibilityService
- SMTPService
Methods
async def send_email(self, template_vars: _T, user_context: Dict[str, Any]) ‑> None
class PhoneOrEmailInput (phone_number: Union[str, None], email: Union[str, None])-
Expand source code
class PhoneOrEmailInput: def __init__(self, phone_number: Union[str, None], email: Union[str, None]): self.phone_number = phone_number self.email = email class SMSDeliveryInterface-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class SMSDeliveryInterface(ABC, Generic[_T]): @abstractmethod async def send_sms(self, template_vars: _T, user_context: Dict[str, Any]) -> None: passAncestors
- abc.ABC
- typing.Generic
Subclasses
Methods
async def send_sms(self, template_vars: ~_T, user_context: Dict[str, Any]) ‑> None
class SMTPService (smtp_settings: SMTPSettings, override: Union[Callable[[SMTPOverrideInput], SMTPOverrideInput], None] = None)-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class SMTPService(EmailDeliveryInterface[PasswordlessLoginEmailTemplateVars]): service_implementation: SMTPServiceInterface[PasswordlessLoginEmailTemplateVars] def __init__( self, smtp_settings: SMTPSettings, override: Union[Callable[[SMTPOverrideInput], SMTPOverrideInput], None] = None, ) -> None: self.transporter = Transporter(smtp_settings) oi = ServiceImplementation(self.transporter) self.service_implementation = oi if override is None else override(oi) async def send_email( self, template_vars: PasswordlessLoginEmailTemplateVars, user_context: Dict[str, Any], ) -> None: content = await self.service_implementation.get_content( template_vars, user_context ) await self.service_implementation.send_raw_email(content, user_context)Ancestors
- EmailDeliveryInterface
- abc.ABC
- typing.Generic
Class variables
var service_implementation : SMTPServiceInterface[CreateAndSendCustomEmailParameters]-
The type of the None singleton.
Methods
async def send_email(self, template_vars: PasswordlessLoginEmailTemplateVars, user_context: Dict[str, Any]) ‑> None
class SuperTokensSMSService (api_key: str)-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class SuperTokensSMSService(SMSDeliveryInterface[PasswordlessLoginSMSTemplateVars]): def __init__(self, api_key: str) -> None: self.api_key = api_key async def send_sms( self, template_vars: PasswordlessLoginSMSTemplateVars, user_context: Dict[str, Any], ) -> None: supertokens = Supertokens.get_instance() app_name = supertokens.app_info.app_name sms_input = { "type": "PASSWORDLESS_LOGIN", "phoneNumber": template_vars.phone_number, "codeLifetime": template_vars.code_life_time, "appName": app_name, } if template_vars.url_with_link_code: sms_input["urlWithLinkCode"] = template_vars.url_with_link_code if template_vars.user_input_code: sms_input["userInputCode"] = template_vars.user_input_code try: async with AsyncClient(timeout=30.0) as client: await client.post( # type: ignore SUPERTOKENS_SMS_SERVICE_URL, json={ "apiKey": self.api_key, "smsInput": sms_input, }, headers={"api-version": "0"}, ) except Exception as e: log_debug_message("Error sending passwordless login SMS") handle_httpx_client_exceptions(e, sms_input) raise eAncestors
- SMSDeliveryInterface
- abc.ABC
- typing.Generic
Methods
async def send_sms(self, template_vars: CreateAndSendCustomTextMessageParameters, user_context: Dict[str, Any]) ‑> None
class TwilioService (twilio_settings: TwilioSettings, override: Union[Callable[[TwilioServiceInterface[_T]], TwilioServiceInterface[_T]], None] = None)-
Helper class that provides a standard way to create an ABC using inheritance.
Expand source code
class TwilioService(SMSDeliveryInterface[PasswordlessLoginSMSTemplateVars]): service_implementation: TwilioServiceInterface[PasswordlessLoginSMSTemplateVars] def __init__( self, twilio_settings: TwilioSettings, override: Union[ Callable[[TwilioServiceInterface[_T]], TwilioServiceInterface[_T]], None ] = None, ) -> None: self.config = normalize_twilio_settings(twilio_settings) otps = twilio_settings.opts if twilio_settings.opts else {} self.twilio_client = Client( # type: ignore twilio_settings.account_sid, twilio_settings.auth_token, **otps ) oi = ServiceImplementation(self.twilio_client) # type: ignore self.service_implementation = oi if override is None else override(oi) # type: ignore async def send_sms( self, template_vars: PasswordlessLoginSMSTemplateVars, user_context: Dict[str, Any], ) -> None: content = await self.service_implementation.get_content( template_vars, user_context ) await self.service_implementation.send_raw_sms( content, user_context, from_=self.config.from_, messaging_service_sid=self.config.messaging_service_sid, )Ancestors
- SMSDeliveryInterface
- abc.ABC
- typing.Generic
Class variables
var service_implementation : TwilioServiceInterface[CreateAndSendCustomTextMessageParameters]-
The type of the None singleton.
Methods
async def send_sms(self, template_vars: PasswordlessLoginSMSTemplateVars, user_context: Dict[str, Any]) ‑> None