diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6ef7b5..9717435e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +3.5.0 +===== + +- The context, token TTL and tokens per user settings in `LoginView` are now dynamic + + 3.4.0 ===== diff --git a/docs/changes.md b/docs/changes.md index d71937a5..c9149bb0 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,5 +1,9 @@ # Changelog +## 3.5.0 + +- The context, token TTL and tokens per user settings in `LoginView` are now dynamic + ## 3.4.0 Our release cycle was broken since 3.1.5, hence you can not find the previous releases on pypi. We now fixed the problem. diff --git a/docs/views.md b/docs/views.md index 9dbdb521..f313cf27 100644 --- a/docs/views.md +++ b/docs/views.md @@ -13,6 +13,12 @@ schemes. If you would like to use a different authentication scheme to the default, you can extend this class to provide your own value for `authentication_classes` +It is possible to customize LoginView behaviour by overriding the following +helper methods: +- `get_context`, to change the context passed to the `UserSerializer` +- `get_token_ttl`, to change the token ttl +- `get_token_limit_per_user`, to change the number of tokens available for a user + --- When the endpoint authenticates a request, a json object will be returned containing the `token` key along with the actual value for the key by default. @@ -22,8 +28,8 @@ containing the `token` key along with the actual value for the key by default. If you wish to return custom data upon successful authentication like `first_name`, `last_name`, and `username` then the included `UserSerializer` class can be used inside `REST_KNOX` settings by adding `knox.serializers.UserSerializer` ---- +--- Obviously, if your app uses a custom user model that does not have these fields, a custom serializer must be used. diff --git a/knox/auth.py b/knox/auth.py index 4c019b15..0bb2e9e7 100644 --- a/knox/auth.py +++ b/knox/auth.py @@ -74,7 +74,7 @@ def authenticate_credentials(self, token): except (TypeError, binascii.Error): raise exceptions.AuthenticationFailed(msg) if compare_digest(digest, auth_token.digest): - if knox_settings.AUTO_REFRESH: + if knox_settings.AUTO_REFRESH and auth_token.expires: self.renew_token(auth_token) return self.validate_user(auth_token) raise exceptions.AuthenticationFailed(msg) diff --git a/knox/views.py b/knox/views.py index f7c899ea..db464a74 100644 --- a/knox/views.py +++ b/knox/views.py @@ -16,24 +16,35 @@ class LoginView(APIView): authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES permission_classes = (IsAuthenticated,) + def get_context(self): + return {'request': self.request, 'format': self.format_kwarg, 'view': self} + + def get_token_ttl(self): + return knox_settings.TOKEN_TTL + + def get_token_limit_per_user(self): + return knox_settings.TOKEN_LIMIT_PER_USER + def post(self, request, format=None): - if knox_settings.TOKEN_LIMIT_PER_USER is not None: + token_limit_per_user = self.get_token_limit_per_user() + if token_limit_per_user is not None: now = timezone.now() token = request.user.auth_token_set.filter(expires__gt=now) - if token.count() >= knox_settings.TOKEN_LIMIT_PER_USER: + if token.count() >= token_limit_per_user: return Response( {"error": "Maximum amount of tokens allowed per user exceeded."}, status=status.HTTP_403_FORBIDDEN ) - token = AuthToken.objects.create(request.user) + token_ttl = self.get_token_ttl() + token = AuthToken.objects.create(request.user, token_ttl) user_logged_in.send(sender=request.user.__class__, request=request, user=request.user) UserSerializer = knox_settings.USER_SERIALIZER - context = {'request': self.request, 'format': self.format_kwarg, 'view': self} if UserSerializer is None: return Response( {'token': token} ) + context = self.get_context() return Response({ 'user': UserSerializer(request.user, context=context).data, 'token': token, diff --git a/setup.py b/setup.py index 10bd3640..71b7eab0 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html - version='3.4.0', + version='3.5.0', description='Authentication for django rest framework', long_description=long_description, long_description_content_type='text/markdown',