def generate_code(user): code = LoginCode.create_code_for_user(user) while LoginCode.objects.exclude(user=user).filter(code=code).exists() \ or LoginCodeExpired.objects.filter(code=code).exists(): code.delete() code = LoginCode.create_code_for_user(user) return code
def test_login_backend(self): self.code = LoginCode.create_code_for_user(self.user) self.assertEqual(len(self.code.code), 20) self.assertIsNotNone(authenticate(username=self.user.username, code=self.code.code)) self.assertEqual(LoginCode.objects.filter(user=self.user, code=self.code.code).count(), 0) authenticate(username=self.user.username) self.assertEqual(LoginCode.objects.filter(user=self.user).count(), 1) self.assertIsNone(LoginCode.create_code_for_user(self.inactive_user)) self.assertIsNone(authenticate(username=self.inactive_user.username))
def create(self, request, *args, **kwargs): callback = request.data.get('callback', '/login/code') next_uri = request.data.get('next', None) host, is_remote = self.get_host(request) if not is_remote: callback = None serializer = self.get_serializer(data=request.data) try: serializer.is_valid(raise_exception=True) except ValidationError as ex: authentication_failed.send(request=request, data=request.data, sender=self.__class__) raise ex code = LoginCode.create_code_for_user(serializer.user, next_uri) self.send_login_code( code, host, callback ) code_generated.send(request=request, code=code.code, email=code.user.email, sender=self.__class__) return HttpResponse('OK', status=201)
def authenticate(self, code=None, **credentials): try: if "password" in credentials: return None user = get_user_model().objects.get(**credentials) except get_user_model().DoesNotExist: if getattr(settings, 'NOPASSWORD_CREATE_USERS', False): user = self.create_user(**credentials) if not user: return None else: return None try: if not self.verify_user(user): return None if code is None: return LoginCode.create_code_for_user(user) else: timeout = getattr(settings, 'NOPASSWORD_LOGIN_CODE_TIMEOUT', 900) timestamp = datetime.now() - timedelta(seconds=timeout) login_code = LoginCode.objects.get(user=user, code=code, timestamp__gt=timestamp) user = login_code.user user.code = login_code multiuse_logins = getattr(settings, 'NOPASSWORD_MULTIUSE_CODES', False) if (not multiuse_logins): login_code.delete() return user except (TypeError, get_user_model().DoesNotExist, LoginCode.DoesNotExist, FieldError): return None
def setUp(self): self.user = get_user_model().objects.create( username='******', email='*****@*****.**', ) self.code = LoginCode.create_code_for_user(self.user, next='/secrets/') self.backend = EmailBackend()
def setUp(self): self.user = get_user_model().objects.create(username='******') self.code = LoginCode.create_code_for_user(self.user, next='/secrets/') self.assertEqual(len(self.code.code), 20) self.assertIsNotNone( authenticate(username=self.user.username, code=self.code.code)) self.assertEqual( LoginCode.objects.filter(user=self.user, code=self.code.code).count(), 0)
def authenticate(self, code=None, request=None, **credentials): if len(credentials): return None try: login_code = LoginCode.objects.get(code=code) except LoginCode.DoesNotExist(): return None LoginCodeExpired.objects.expire(login_code, code_expire=1) return login_code.user
def create_code_for_user(cls, user, next=None): if not user.is_active: return None code = None params = { 'length': getattr(settings, 'NOPASSWORD_CODE_LENGTH', 20), 'algorithm': getattr(settings, 'NOPASSWORD_HASH_ALGORITHM', 'sha256'), 'numeric': getattr(settings, 'NOPASSWORD_NUMERIC_CODES', False), } params.update({k: getattr(cls, k) for k in params.keys() if hasattr(cls, k)}) while cls.code_is_used(code): code = cls.generate_code(**params) login_code = LoginCode(user=user, code=code) if next is not None: login_code.next = next login_code.save() return login_code
def create_code_for_user(cls, user, next=None): if not user.is_active: return None code = None params = { 'length': getattr(settings, 'NOPASSWORD_CODE_LENGTH', 20), 'algorithm': getattr(settings, 'NOPASSWORD_HASH_ALGORITHM', 'sha256'), 'numeric': getattr(settings, 'NOPASSWORD_NUMERIC_CODES', False), } params.update( {k: getattr(cls, k) for k in params.keys() if hasattr(cls, k)}) while cls.code_is_used(code): code = cls.generate_code(**params) login_code = LoginCode(user=user, code=code) if next is not None: login_code.next = next login_code.save() return login_code
def authenticate(self, code=None, **credentials): try: user = get_user_model().objects.get(**credentials) if not self.verify_user(user): return None if code is None: return LoginCode.create_code_for_user(user) else: timeout = getattr(settings, 'NOPASSWORD_LOGIN_CODE_TIMEOUT', 900) timestamp = datetime.now() - timedelta(seconds=timeout) login_code = LoginCode.objects.get(user=user, code=code, timestamp__gt=timestamp) user = login_code.user user.code = login_code login_code.delete() return user except (TypeError, get_user_model().DoesNotExist, LoginCode.DoesNotExist, FieldError): return None
def test_twilio_backend(self, mock_object): self.user = get_user_model().objects.create(username='******') self.code = LoginCode.create_code_for_user(self.user, next='/secrets/') self.assertEqual(len(self.code.code), 20) self.assertIsNotNone(authenticate(username=self.user.username, code=self.code.code)) self.assertEqual(LoginCode.objects.filter(user=self.user, code=self.code.code).count(), 0) self.backend = TwilioBackend() self.backend.twilio_client.messages.create = MagicMock() self.backend.send_login_code(self.code) self.assertTrue(mock_object.called) self.assertTrue(self.backend.twilio_client.messages.create.called) authenticate(username=self.user.username) self.assertEqual(LoginCode.objects.filter(user=self.user).count(), 1) self.user.delete()
def create(self, request, *args, **kwargs): callback = request.data.get('callback', '/login/code') next_uri = request.data.get('next', None) host, is_remote = self.get_host(request) if not is_remote: callback = None serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) code = LoginCode.create_code_for_user(serializer.user, next_uri) self.send_login_code( code, host, callback ) return HttpResponse('OK', status=201)
def send_invite(self): if not self.user.email: return False login_url = environ.get('INVITE_LOGIN_URL', '') login_code = LoginCode.create_code_for_user(self.user) app_url = environ.get('INVITE_APP_URL', '') send_templated_mail( context={ 'full_name': self.full_name, 'login_url': login_url.format(login_code=login_code.code), 'app_url': app_url }, template_name=environ.get('INVITE_TEMPLATE', 'welcome'), from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[self.user.email], ) return True
def test_twilio_backend(self, mock_object): self.user = get_user_model().objects.create(username='******') self.code = LoginCode.create_code_for_user(self.user, next='/secrets/') self.assertEqual(len(self.code.code), 20) self.assertIsNotNone( authenticate(username=self.user.username, code=self.code.code)) self.assertEqual( LoginCode.objects.filter(user=self.user, code=self.code.code).count(), 0) self.backend = TwilioBackend() self.backend.twilio_client.messages.create = MagicMock() self.backend.send_login_code(self.code) self.assertTrue(mock_object.called) self.assertTrue(self.backend.twilio_client.messages.create.called) authenticate(username=self.user.username) self.assertEqual(LoginCode.objects.filter(user=self.user).count(), 1) self.user.delete()
def create(self, request, *args, **kwargs): callback = request.data.get('callback', '/login/code') next_uri = request.data.get('next', None) host, is_remote = self.get_host(request) if not is_remote: callback = None serializer = self.get_serializer(data=request.data) try: serializer.is_valid(raise_exception=True) except ValidationError as ex: authentication_failed.send(request=request, data=request.data, sender=self.__class__) raise ex code = LoginCode.create_code_for_user(serializer.user, next_uri) self.send_login_code(code, host, callback) code_generated.send(request=request, code=code.code, email=code.user.email, sender=self.__class__) return HttpResponse('OK', status=201)
def test_str(self): code = LoginCode(user=self.user, code='foo', timestamp=datetime(2018, 7, 1)) self.assertEqual(str(code), 'test_user - 2018-07-01 00:00:00')
def test_code_timeout(self): timeout_code = LoginCode.create_code_for_user(self.user) time.sleep(3) self.assertIsNone(authenticate(username=self.user.username, code=timeout_code.code))
def test_next_value(self): code = LoginCode.create_code_for_user(self.user, next='/secrets/') self.assertEqual(code.next, '/secrets/')
def test_numeric_code(self): code = LoginCode.create_code_for_user(self.user) self.assertEqual(len(code.code), 20) self.assertTrue(code.code.isdigit())
def test_shorter_code(self): code = LoginCode.create_code_for_user(self.user) self.assertEqual(len(code.code), 8)
def test_login_backend(self): self.assertEqual(len(self.code.code), 20) self.assertIsNotNone(authenticate(username=self.user.username, code=self.code.code)) self.assertIsNone(LoginCode.create_code_for_user(self.inactive_user))
def setUp(self): self.user = get_user_model().objects.create(username='******') self.inactive_user = get_user_model().objects.create(username='******', is_active=False) self.code = LoginCode.create_code_for_user(self.user)
def setUp(self): self.user = get_user_model().objects.create(username='******') self.code = LoginCode.create_code_for_user(self.user, next='/secrets/') self.assertEqual(len(self.code.code), 20) self.assertIsNotNone(authenticate(username=self.user.username, code=self.code.code)) self.assertEqual(LoginCode.objects.filter(user=self.user, code=self.code.code).count(), 0)