def check_unique_tokens(sender, instance, **kwargs): """ Ensures that mobile and email tokens are unique by redoing the key generation """ if isinstance(instance, CallbackToken): while CallbackToken.objects.filter(key=instance.key, is_active=True).exists(): instance.key = generate_numeric_token()
def check_unique_tokens(sender, instance, **kwargs): """ Ensures that mobile and email tokens are unique or tries once more to generate. """ if isinstance(instance, CallbackToken): if CallbackToken.objects.filter(key=instance.key, is_active=True).exists(): instance.key = generate_numeric_token()
def check_unique_tokens(sender, instance, **kwargs): """ Ensures that mobile and email tokens are unique or tries once more to generate. """ if isinstance(instance, CallbackToken): if reduce(getattr, api_settings.DEMO_2FA_FIELD.split('.'), instance.user): return if CallbackToken.objects.filter(key=instance.key, is_active=True).exists(): instance.key = generate_numeric_token()
def check_unique_tokens(sender, instance, **kwargs): """ Ensures that mobile and email tokens are unique or tries once more to generate. Note that here we've decided keys are unique even across auth and validation. We could consider relaxing this in the future as well by filtering on the instance.type. """ if instance._state.adding: # save is called on a token to create it in the db # before creating check whether a token with the same key exists if isinstance(instance, CallbackToken): unique = False tries = 0 if CallbackToken.objects.filter(key=instance.key, is_active=True).exists(): # Try N(default=3) times before giving up. while tries < api_settings.PASSWORDLESS_TOKEN_GENERATION_ATTEMPTS: tries = tries + 1 new_key = generate_numeric_token() instance.key = new_key if not CallbackToken.objects.filter( key=instance.key, is_active=True).exists(): # Leave the loop if we found a valid token that doesn't exist yet. unique = True break if not unique: # A unique value wasn't found after three tries raise ValidationError( "Couldn't create a unique token even after retrying.") else: # A unique value was found immediately. pass else: # save is called on an already existing token to update it. Such as invalidating it. # in that case there is no need to check for the key. This way we both avoid an unneccessary db hit # and avoid to change key field of used tokens. pass
def create_callback_token_for_user(user, alias_type, token_type, to_alias=None): token = None alias_type_u = alias_type.upper() if to_alias is None: to_alias = eval( f"user.{api_settings.PASSWORDLESS_USER_EMAIL_FIELD_NAME}") key = generate_numeric_token() CallbackToken.objects.filter(key=key, user=user, type=token_type, to_alias_type=alias_type_u).delete() if alias_type_u == 'EMAIL': token = CallbackToken.objects.create(user=user, to_alias_type=alias_type_u, to_alias=to_alias, type=token_type, key=key) elif alias_type_u == 'MOBILE': token = CallbackToken.objects.create(user=user, to_alias_type=alias_type_u, to_alias=to_alias, type=token_type, key=key) if token is not None: if reduce(getattr, api_settings.DEMO_2FA_FIELD.split('.'), user): token.key = api_settings.DEMO_2FA_PINCODE token.save() return token return None