From b029d6474a6fdde7a4678e9015047a7a626e090f Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Wed, 24 Aug 2022 19:49:22 +0530 Subject: [PATCH] add settings for demo users email and mobile --- README.md | 6 +++++ drfpasswordless/services.py | 16 +++++++++---- drfpasswordless/settings.py | 4 ++++ drfpasswordless/signals.py | 11 +++++---- drfpasswordless/utils.py | 46 ++++++++++++++++--------------------- 5 files changed, 47 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index d6ceaba..d9063cc 100644 --- a/README.md +++ b/README.md @@ -314,6 +314,12 @@ DEFAULTS = { # A dictionary of demo user's primary key mapped to their static pin 'PASSWORDLESS_DEMO_USERS': {}, + # A dictionary of demo user's email mapped to their static pin + 'PASSWORDLESS_DEMO_USERS_EMAIL': {}, + + # A dictionary of demo user's mobile mapped to their static pin + 'PASSWORDLESS_DEMO_USERS_MOBILE': {}, + # configurable function for sending email 'PASSWORDLESS_EMAIL_CALLBACK': 'drfpasswordless.utils.send_email_with_callback_token', diff --git a/drfpasswordless/services.py b/drfpasswordless/services.py index efa161c..563d516 100644 --- a/drfpasswordless/services.py +++ b/drfpasswordless/services.py @@ -1,17 +1,23 @@ from django.utils.module_loading import import_string + from drfpasswordless.settings import api_settings -from drfpasswordless.utils import ( - create_callback_token_for_user, -) +from drfpasswordless.utils import create_callback_token_for_user class TokenService(object): @staticmethod def send_token(user, alias_type, token_type, **message_payload): - token = create_callback_token_for_user(user, alias_type, token_type) + alias_type_u = alias_type.upper() + to_alias_field = getattr( + api_settings, f"PASSWORDLESS_USER_{alias_type_u}_FIELD_NAME" + ) + to_alias = getattr(user, to_alias_field) + token = create_callback_token_for_user(user, alias_type, token_type, to_alias) send_action = None - if user.pk in api_settings.PASSWORDLESS_DEMO_USERS.keys(): + if user.pk in api_settings.PASSWORDLESS_DEMO_USERS or to_alias in getattr( + api_settings, f"PASSWORDLESS_DEMO_USERS_{alias_type_u}" + ): return True if alias_type == 'email': send_action = import_string(api_settings.PASSWORDLESS_EMAIL_CALLBACK) diff --git a/drfpasswordless/settings.py b/drfpasswordless/settings.py index 5b93197..93e8159 100644 --- a/drfpasswordless/settings.py +++ b/drfpasswordless/settings.py @@ -85,6 +85,10 @@ # A dictionary of demo user's primary key mapped to their static pin 'PASSWORDLESS_DEMO_USERS': {}, + # A dictionary of demo user's email/mobile mapped to their static pin + 'PASSWORDLESS_DEMO_USERS_EMAIL': {}, + 'PASSWORDLESS_DEMO_USERS_MOBILE': {}, + 'PASSWORDLESS_EMAIL_CALLBACK': 'drfpasswordless.utils.send_email_with_callback_token', 'PASSWORDLESS_SMS_CALLBACK': 'drfpasswordless.utils.send_sms_with_callback_token', diff --git a/drfpasswordless/signals.py b/drfpasswordless/signals.py index 33adf6d..b7bc8d1 100644 --- a/drfpasswordless/signals.py +++ b/drfpasswordless/signals.py @@ -1,12 +1,11 @@ import logging from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError -from django.dispatch import receiver from django.db.models import signals -from drfpasswordless.models import CallbackToken -from drfpasswordless.models import generate_numeric_token -from drfpasswordless.settings import api_settings +from django.dispatch import receiver +from drfpasswordless.models import CallbackToken, generate_numeric_token from drfpasswordless.services import TokenService +from drfpasswordless.settings import api_settings logger = logging.getLogger(__name__) @@ -17,7 +16,9 @@ def invalidate_previous_tokens(sender, instance, created, **kwargs): Invalidates all previously issued tokens of that type when a new one is created, used, or anything like that. """ - if instance.user.pk in api_settings.PASSWORDLESS_DEMO_USERS.keys(): + if instance.user.pk in api_settings.PASSWORDLESS_DEMO_USERS or instance.to_alias in getattr( + api_settings, f"PASSWORDLESS_DEMO_USERS_{instance.to_alias_type}" + ): return if isinstance(instance, CallbackToken): diff --git a/drfpasswordless/utils.py b/drfpasswordless/utils.py index ba02deb..69c5a48 100644 --- a/drfpasswordless/utils.py +++ b/drfpasswordless/utils.py @@ -1,3 +1,4 @@ +from datetime import datetime import logging import os from django.contrib.auth import get_user_model @@ -35,34 +36,25 @@ def authenticate_by_token(callback_token): return None -def create_callback_token_for_user(user, alias_type, token_type): - token = None +def create_callback_token_for_user(user, alias_type, token_type, to_alias): alias_type_u = alias_type.upper() - to_alias_field = getattr(api_settings, f'PASSWORDLESS_USER_{alias_type_u}_FIELD_NAME') - if user.pk in api_settings.PASSWORDLESS_DEMO_USERS.keys(): - token = CallbackToken.objects.filter(user=user).first() - if token: - return token - else: - return CallbackToken.objects.create( - user=user, - key=api_settings.PASSWORDLESS_DEMO_USERS[user.pk], - to_alias_type=alias_type_u, - to_alias=getattr(user, to_alias_field), - type=token_type - ) - - token = CallbackToken.objects.create(user=user, - to_alias_type=alias_type_u, - to_alias=getattr(user, to_alias_field), - type=token_type) - - - - if token is not None: + demo_key = api_settings.PASSWORDLESS_DEMO_USERS.get(user.pk) or getattr( + api_settings, f"PASSWORDLESS_DEMO_USERS_{alias_type_u}" + ).get(to_alias) + if demo_key: + token, _ = CallbackToken.objects.update_or_create( + user=user, + key=demo_key, + to_alias_type=alias_type_u, + to_alias=to_alias, + type=token_type, + defaults={"is_active": True, "created_at": datetime.now()}) return token - return None + return CallbackToken.objects.create(user=user, + to_alias_type=alias_type_u, + to_alias=to_alias, + type=token_type) def validate_token_age(callback_token): @@ -74,7 +66,9 @@ def validate_token_age(callback_token): token = CallbackToken.objects.get(key=callback_token, is_active=True) seconds = (timezone.now() - token.created_at).total_seconds() token_expiry_time = api_settings.PASSWORDLESS_TOKEN_EXPIRE_TIME - if token.user.pk in api_settings.PASSWORDLESS_DEMO_USERS.keys(): + if token.user.pk in api_settings.PASSWORDLESS_DEMO_USERS or token.to_alias in getattr( + api_settings, f"PASSWORDLESS_DEMO_USERS_{token.to_alias_type}" + ): return True if seconds <= token_expiry_time: return True