Hello community,
here is the log from the commit of package python-django-rest-knox for
openSUSE:Factory checked in at 2020-04-07 10:28:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-rest-knox (Old)
and /work/SRC/openSUSE:Factory/.python-django-rest-knox.new.3248 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-rest-knox"
Tue Apr 7 10:28:04 2020 rev:4 rq:791487 version:4.1.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-django-rest-knox/python-django-rest-knox.changes
2019-10-08 19:57:57.328192969 +0200
+++
/work/SRC/openSUSE:Factory/.python-django-rest-knox.new.3248/python-django-rest-knox.changes
2020-04-07 10:28:30.654308771 +0200
@@ -1,0 +2,12 @@
+Sun Apr 5 07:54:00 UTC 2020 - Tomáš Chvátal <[email protected]>
+
+- Update to 4.1.0:
+ * Expiry format now defaults to whatever is used Django REST framework
+ * The behavior can be overriden via EXPIRY_DATETIME_FORMAT setting
+ * Fully customizable expiry format via format_expiry_datetime
+ * Fully customizable response payload via get_post_response_data
+ * Changes have been made to the create() method on the AuthToken model.
+ It now returns the model instance and the raw token instead of just
+ the token to allow the expiry field to be included in the success response.
+
+-------------------------------------------------------------------
Old:
----
django-rest-knox-3.6.0.tar.gz
New:
----
django-rest-knox-4.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-rest-knox.spec ++++++
--- /var/tmp/diff_new_pack.C9gWv6/_old 2020-04-07 10:28:31.242309425 +0200
+++ /var/tmp/diff_new_pack.C9gWv6/_new 2020-04-07 10:28:31.246309429 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-django-rest-knox
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,10 +19,8 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define skip_python2 1
Name: python-django-rest-knox
-Version: 3.6.0
+Version: 4.1.0
Release: 0
-# Please, do not update to the current version, 4.x, as it is a breaking
-# change that at least breaks drf-jwt-knox
Summary: Authentication for Django REST framework
License: MIT
URL: https://github.com/James1345/django-rest-knox
++++++ django-rest-knox-3.6.0.tar.gz -> django-rest-knox-4.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/.isort.cfg
new/django-rest-knox-4.1.0/.isort.cfg
--- old/django-rest-knox-3.6.0/.isort.cfg 1970-01-01 01:00:00.000000000
+0100
+++ new/django-rest-knox-4.1.0/.isort.cfg 2019-06-01 08:24:05.000000000
+0200
@@ -0,0 +1,7 @@
+[settings]
+combine_as_imports = true
+default_section = THIRDPARTY
+include_trailing_comma = true
+known_first_party = knox
+multi_line_output = 5
+not_skip = __init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/.travis.yml
new/django-rest-knox-4.1.0/.travis.yml
--- old/django-rest-knox-3.6.0/.travis.yml 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/.travis.yml 2019-06-01 08:24:05.000000000
+0200
@@ -12,8 +12,12 @@
env: TOX_ENVS=py35-django111,py35-django20,py35-django20,py35-django21
- python: "3.6"
env: TOX_ENVS=py36-django111,py36-django20,py36-django21
+ - python: "3.6"
+ dist: xenial
+ sudo: true
+ env: TOX_ENVS=py36-django22
- python: "3.7"
- env: TOX_ENVS=py37-django20,py37-django21
+ env: TOX_ENVS=py37-django20,py37-django21,py37-django22
dist: xenial
sudo: true
before_script:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/CHANGELOG.md
new/django-rest-knox-4.1.0/CHANGELOG.md
--- old/django-rest-knox-3.6.0/CHANGELOG.md 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/CHANGELOG.md 2019-06-01 08:24:05.000000000
+0200
@@ -1,153 +1,134 @@
-3.6.0
-=====
+## 4.1.0
-- The user serializer for each `LoginView`is now dynamic
+- Expiry format now defaults to whatever is used Django REST framework
+- The behavior can be overriden via EXPIRY_DATETIME_FORMAT setting
+- Fully customizable expiry format via format_expiry_datetime
+- Fully customizable response payload via get_post_response_data
-3.5.0
-=====
+## 4.0.1
-- The context, token TTL and tokens per user settings in `LoginView` are now
dynamic
+- Fix for tox config to build Django 2.2 on python 3.6
+
+## 4.0.0
+
+**BREAKING** This is a major release version because it
+breaks the existing API.
+Changes have been made to the `create()` method on the `AuthToken` model.
+It now returns the model instance and the raw `token` instead
+of just the `token` to allow the `expiry` field to be included in the
+success response.
+
+Model field of `AuthToken` has been renamed from `expires` to `expiry`
+to remain consistent across the code base. This patch requires you
+to run a migration.
+
+Depending on your usage you might have to adjust your code
+to fit these new changes.
+
+- `AuthToken` model field has been changed from `expires` to `expiry`
+- Successful login now always returns a `expiry` field for when the token
expires
+
+## 3.6.0
+- The user serializer for each `LoginView`is now dynamic
+
+## 3.5.0
-3.4.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.
- Adds optional token limit
-- #129, #128 fixed
+- \#129, \#128 fixed
- Changelog and Readme converted to markdown
- Auth header prefix is now configurable
- We ensure not to have flake8 errors in our code during our build
- MIN_REFRESH_INTERVAL is now a configurable setting
+## 3.3.1
+- Ensure compatibility with Django 2.1 up to Python 3.7
-3.3.1
-=====
-
-- Ensure compatibility with Django 2.1 up to Python 3.7
-
-3.3.0
-=====
+## 3.3.0
- **Breaking changes**: Successful authentication **ONLY** returns
`Token` object by default
now.`USER_SERIALIZER` must be overridden to return more
data.
-
+
- Introduce new setting `MIN_REFRESH_INTERVAL` to configure the time
interval (in seconds) to wait before a token is automatically refreshed.
-3.2.1
-=====
-
-- Fix !111: Avoid knox failing if settings are not overwritten
-
-3.2.0
-=====
+## 3.2.1
+- Fix !111: Avoid knox failing if settings are not overwritten
-- Introduce new setting AUTO_REFRESH for controlling if token expiry
- time should be extended automatically
+## 3.2.0
+- Introduce new setting AUTO_REFRESH for controlling if token expiry time
should be extended automatically
-3.1.5
-=====
+## 3.1.5
+- Make AuthTokenAdmin more compatible with big user tables
+- Extend docs regarding usage of Token Authentication as single authentication
method.
-- Make AuthTokenAdmin more compatible with big user tables
-- Extend docs regarding usage of Token Authentication as single
- authentication method.
+## 3.1.4
+- Fix compability with django-rest-swagger (bad inheritance)
-3.1.4
-=====
+## 3.1.3
+- Avoid 500 error response for invalid-length token requests
-- Fix compability with django-rest-swagger (bad inheritance)
+## 3.1.2
+- restore compability with Python <2.7.7
-3.1.3
-=====
+## 3.1.1
+- use hmac.compare_digest instead of == for comparing hashes for more security
-- Avoid 500 error response for invalid-length token requests
+## 3.1.0
+- drop Django 1.8 support as djangorestframework did so too in v.3.7.0
+- build rest-knox on Django 1.11 and 2.0
-3.1.2
-=====
+## 3.0.3
+- drop using OpenSSL in favor of urandom
-- restore compability with Python <2.7.7
+## 3.0.2
+- Add context to UserSerializer
+- improve docs
-3.1.1
-=====
+## 3.0.1
+- improved docs and readme
+- login response better supporting hyperlinked fields
-- use hmac.compare_digest instead of == for comparing hashes for more
- security
+## 3.0.0
+**Please be aware: updating to this version requires applying a database
migration. All clients will need to reauthenticate.**
-3.1.0
-=====
+- Big performance fix: Introduction of token_key field to avoid having to
compare a login request's token against each and every token in the database
(issue #21)
+- increased test coverage
-- drop Django 1.8 support as djangorestframework did so too in v.3.7.0
-- build rest-knox on Django 1.11 and 2.0
+## 2.2.2
+- Bugfix: invalid token length does no longer trigger a server error
+- Extending documentation
-3.0.3
-=====
+## 2.2.1
+**Please be aware: updating to his version requires applying a database
migration**
-- drop using OpenSSL in favor of urandom
-
-3.0.2
-=====
-
-- Add context to UserSerializer
-- improve docs
-
-3.0.1
-=====
-
-- improved docs and readme
-- login response better supporting hyperlinked fields
-
-3.0.3
-=====
-
-- drop using OpenSSL in favor of urandom
-
-3.0.2
-=====
-
-- Add context to UserSerializer
-- improve docs
-
-3.0.1
-=====
-
-- improved docs and readme
-- login response better supporting hyperlinked fields
-
-3.0.0
-=====
-
-**Please be aware: updating to this version requires applying a database
-migration. All clients will need to reauthenticate.**
-
-- Big performance fix: Introduction of token_key field to avoid
- having to compare a login request's token against each and every
- token in the database (issue #21)
-- increased test coverage
-
-2.2.2
-=====
+- Introducing token_key to avoid loop over all tokens on login-requests
+- Signals are sent on login/logout
+- Test for invalid token length
+- Cleanup in code and documentation
- Bugfix: invalid token length does no longer trigger a server error
- Extending documentation
-2.2.1
-=====
+## 2.2.0
-**Please be aware: updating to this version requires applying a database
-migration**
+- Change to support python 2.7
-- Introducing token_key to avoid loop over all tokens on
- login-requests
-- Signals are sent on login/logout
-- Test for invalid token length
-- Cleanup in code and documentation
+## 2.0.0
+- Hashing of tokens on the server introduced.
+- Updating to this version will clean the AuthToken table. In real terms,
this
+ means all users will be forced to log in again.
-2.2.0
-=====
+## 1.1.0
+- `LoginView` changed to respect `DEFAULT_AUTHENTICATION_CLASSES`
-- Change to support python 2.7
+## 1.0.0
+- Initial release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/README.md
new/django-rest-knox-4.1.0/README.md
--- old/django-rest-knox-3.6.0/README.md 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/README.md 2019-06-01 08:24:05.000000000
+0200
@@ -50,3 +50,31 @@
You could also simply run regular ``tox`` in the root folder as well, but that
would make testing the matrix of
Python / Django versions a bit more tricky.
+
+# Work on the documentation
+
+Our documentation is generated by [Mkdocs](https://www.mkdocs.org).
+
+You can refer to their documentation on how to install it locally.
+
+Another option is to use `mkdocs.sh` in this repository.
+It will run mkdocs in a [docker](https://www.docker.com/) container.
+
+Running the script without any params triggers the `serve` command.
+The server is exposed on localhost on port 8000.
+
+To configure the port the `serve` command will be exposing the server to, you
+can use the following env var:
+
+```
+MKDOCS_DEV_PORT="8080"
+```
+
+You can also pass any `mkdocs` command like this:
+
+```
+./mkdocs build
+./mkdocs --help
+```
+
+Check the [Mkdocs documentation](https://www.mkdocs.org/) for more.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/docs/changelog.md
new/django-rest-knox-4.1.0/docs/changelog.md
--- old/django-rest-knox-3.6.0/docs/changelog.md 1970-01-01
01:00:00.000000000 +0100
+++ new/django-rest-knox-4.1.0/docs/changelog.md 2020-04-07
10:28:31.306309495 +0200
@@ -0,0 +1 @@
+symbolic link to ../CHANGELOG.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/docs/changes.md
new/django-rest-knox-4.1.0/docs/changes.md
--- old/django-rest-knox-3.6.0/docs/changes.md 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/docs/changes.md 1970-01-01 01:00:00.000000000
+0100
@@ -1,92 +0,0 @@
-# Changelog
-
-## 3.6.0
-
-- The user serializer for each `LoginView`is now dynamic
-
-## 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.
-
-- Adds optional token limit
-- #129, #128 fixed
-- Changelog and Readme converted to markdown
-- Auth header prefix is now configurable
-- We ensure not to have flake8 errors in our code during our build
-- MIN_REFRESH_INTERVAL is now a configurable setting
-
-## 3.3.1
-- Ensure compatibility with Django 2.1 up to Python 3.7
-
-## 3.3.0
-- **Breaking changes**: Successful authentication **ONLY** returns `Token`
object by default now.
-`USER_SERIALIZER` must be overridden to return more data.
-
-## 3.2.1
-- Fix !111: Avoid knox failing if settings are not overwritten
-
-## 3.2.0
-- Introduce new setting AUTO_REFRESH for controlling if token expiry time
should be extended automatically
-
-## 3.1.5
-- Make AuthTokenAdmin more compatible with big user tables
-- Extend docs regarding usage of Token Authentication as single authentication
method.
-
-## 3.1.4
-- Fix compability with django-rest-swagger (bad inheritance)
-
-## 3.1.3
-- Avoid 500 error response for invalid-length token requests
-
-## 3.1.2
-- restore compability with Python <2.7.7
-
-## 3.1.1
-- use hmac.compare_digest instead of == for comparing hashes for more security
-
-## 3.1.0
-- drop Django 1.8 support as djangorestframework did so too in v.3.7.0
-- build rest-knox on Django 1.11 and 2.0
-
-## 3.0.3
-- drop using OpenSSL in favor of urandom
-
-## 3.0.2
-- Add context to UserSerializer
-- improve docs
-
-## 3.0.1
-- improved docs and readme
-- login response better supporting hyperlinked fields
-
-## 3.0.0
-**Please be aware: updating to this version requires applying a database
migration. All clients will need to reauthenticate.**
-
-- Big performance fix: Introduction of token_key field to avoid having to
compare a login request's token against each and every token in the database
(issue #21)
-- increased test coverage
-
-## 2.2.2
-- Bugfix: invalid token length does no longer trigger a server error
-- Extending documentation
-
-## 2.2.1
-**Please be aware: updating to his version requires applying a database
migration**
-
-- Introducing token_key to avoid loop over all tokens on login-requests
-- Signals are sent on login/logout
-- Test for invalid token length
-- Cleanup in code and documentation
-
-## 2.0.0
-- Hashing of tokens on the server introduced.
-- Updating to this version will clean the AuthToken table. In real terms,
this
- means all users will be forced to log in again.
-
-## 1.1.0
-- `LoginView` changed to respect `DEFAULT_AUTHENTICATION_CLASSES`
-
-## 1.0.0
-- Initial release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/docs/settings.md
new/django-rest-knox-4.1.0/docs/settings.md
--- old/django-rest-knox-3.6.0/docs/settings.md 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/docs/settings.md 2019-06-01 08:24:05.000000000
+0200
@@ -9,13 +9,15 @@
#...snip...
# These are the default values if none are set
from datetime import timedelta
+from rest_framework.settings import api_settings
REST_KNOX = {
'SECURE_HASH_ALGORITHM': 'cryptography.hazmat.primitives.hashes.SHA512',
'AUTH_TOKEN_CHARACTER_LENGTH': 64,
'TOKEN_TTL': timedelta(hours=10),
'USER_SERIALIZER': 'knox.serializers.UserSerializer',
'TOKEN_LIMIT_PER_USER': None,
- 'AUTO_REFRESH': FALSE,
+ 'AUTO_REFRESH': False,
+ 'EXPIRY_DATETIME_FORMAT': api_settings.DATETME_FORMAT,
}
#...snip...
```
@@ -74,6 +76,14 @@
## AUTH_HEADER_PREFIX
This is the Authorization header value prefix. The default is `Token`
+## EXPIRY_DATETIME_FORMAT
+This is the expiry datetime format returned in the login view. The default is
the
+[DATETIME_FORMAT][DATETIME_FORMAT] of Django REST framework. May be any of
`None`, `iso-8601`
+or a Python [strftime format][strftime format] string.
+
+[DATETIME_FORMAT]:
https://www.django-rest-framework.org/api-guide/settings/#date-and-time-formatting
+[strftime format]: https://docs.python.org/3/library/time.html#time.strftime
+
# Constants `knox.settings`
Knox also provides some constants for information. These must not be changed in
external code; they are used in the model definitions in knox and an error will
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/docs/views.md
new/django-rest-knox-4.1.0/docs/views.md
--- old/django-rest-knox-3.6.0/docs/views.md 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/docs/views.md 2019-06-01 08:24:05.000000000
+0200
@@ -15,14 +15,39 @@
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
-- `get_user_serializer_class`, to change the class used for serializing the
user
+- `get_context(self)`, to change the context passed to the `UserSerializer`
+- `get_token_ttl(self)`, to change the token ttl
+- `get_token_limit_per_user(self)`, to change the number of tokens available
for a user
+- `get_user_serializer_class(self)`, to change the class used for serializing
the user
+- `get_expiry_datetime_format(self)`, to change the datetime format used for
expiry
+- `format_expiry_datetime(self, expiry)`, to format the expiry `datetime`
object at your convinience
+
+Finally, if none of these helper methods are sufficient, you can also override
`get_post_response_data`
+to return a fully customized payload.
+
+```python
+...snip...
+ def get_post_response_data(self, request, token, instance):
+ UserSerializer = self.get_user_serializer_class()
+
+ data = {
+ 'expiry': self.format_expiry_datetime(instance.expiry),
+ 'token': token
+ }
+ if UserSerializer is not None:
+ data["user"] = UserSerializer(
+ request.user,
+ context=self.get_context()
+ ).data
+ return data
+...snip...
+```
---
-When the endpoint authenticates a request, a json object will be returned
+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.
+The success response also includes a `expiry` key with a timestamp for when
+the token expires.
> *This is because `USER_SERIALIZER` setting is `None` by default.*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/admin.py
new/django-rest-knox-4.1.0/knox/admin.py
--- old/django-rest-knox-3.6.0/knox/admin.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/knox/admin.py 2019-06-01 08:24:05.000000000
+0200
@@ -1,4 +1,5 @@
from django.contrib import admin
+
from knox import models
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/auth.py
new/django-rest-knox-4.1.0/knox/auth.py
--- old/django-rest-knox-3.6.0/knox/auth.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/knox/auth.py 2019-06-01 08:24:05.000000000
+0200
@@ -6,14 +6,12 @@
import binascii
-from django.utils.translation import ugettext_lazy as _
-from django.utils import timezone
from django.contrib.auth import get_user_model
-
+from django.utils import timezone
+from django.utils.translation import ugettext_lazy as _
from rest_framework import exceptions
from rest_framework.authentication import (
- BaseAuthentication,
- get_authorization_header
+ BaseAuthentication, get_authorization_header,
)
from knox.crypto import hash_token
@@ -74,19 +72,19 @@
except (TypeError, binascii.Error):
raise exceptions.AuthenticationFailed(msg)
if compare_digest(digest, auth_token.digest):
- if knox_settings.AUTO_REFRESH and auth_token.expires:
+ if knox_settings.AUTO_REFRESH and auth_token.expiry:
self.renew_token(auth_token)
return self.validate_user(auth_token)
raise exceptions.AuthenticationFailed(msg)
def renew_token(self, auth_token):
- current_expiry = auth_token.expires
+ current_expiry = auth_token.expiry
new_expiry = timezone.now() + knox_settings.TOKEN_TTL
- auth_token.expires = new_expiry
+ auth_token.expiry = new_expiry
# Throttle refreshing of token to avoid db writes
delta = (new_expiry - current_expiry).total_seconds()
if delta > knox_settings.MIN_REFRESH_INTERVAL:
- auth_token.save(update_fields=('expires',))
+ auth_token.save(update_fields=('expiry',))
def validate_user(self, auth_token):
if not auth_token.user.is_active:
@@ -99,14 +97,14 @@
def _cleanup_token(self, auth_token):
for other_token in auth_token.user.auth_token_set.all():
- if other_token.digest != auth_token.digest and other_token.expires:
- if other_token.expires < timezone.now():
+ if other_token.digest != auth_token.digest and other_token.expiry:
+ if other_token.expiry < timezone.now():
other_token.delete()
username = other_token.user.get_username()
token_expired.send(sender=self.__class__,
username=username, source="other_token")
- if auth_token.expires is not None:
- if auth_token.expires < timezone.now():
+ if auth_token.expiry is not None:
+ if auth_token.expiry < timezone.now():
username = auth_token.user.get_username()
auth_token.delete()
token_expired.send(sender=self.__class__,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/crypto.py
new/django-rest-knox-4.1.0/knox/crypto.py
--- old/django-rest-knox-3.6.0/knox/crypto.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/knox/crypto.py 2019-06-01 08:24:05.000000000
+0200
@@ -1,10 +1,10 @@
import binascii
+from os import urandom as generate_bytes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
-from os import urandom as generate_bytes
-from knox.settings import knox_settings, CONSTANTS
+from knox.settings import CONSTANTS, knox_settings
sha = knox_settings.SECURE_HASH_ALGORITHM
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rest-knox-3.6.0/knox/migrations/0001_initial.py
new/django-rest-knox-4.1.0/knox/migrations/0001_initial.py
--- old/django-rest-knox-3.6.0/knox/migrations/0001_initial.py 2018-12-31
12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/knox/migrations/0001_initial.py 2019-06-01
08:24:05.000000000 +0200
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
-from django.db import models, migrations
from django.conf import settings
+from django.db import migrations, models
class Migration(migrations.Migration):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rest-knox-3.6.0/knox/migrations/0002_auto_20150916_1425.py
new/django-rest-knox-4.1.0/knox/migrations/0002_auto_20150916_1425.py
--- old/django-rest-knox-3.6.0/knox/migrations/0002_auto_20150916_1425.py
2018-12-31 12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/knox/migrations/0002_auto_20150916_1425.py
2019-06-01 08:24:05.000000000 +0200
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
-from django.db import models, migrations
from django.conf import settings
+from django.db import migrations, models
class Migration(migrations.Migration):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rest-knox-3.6.0/knox/migrations/0003_auto_20150916_1526.py
new/django-rest-knox-4.1.0/knox/migrations/0003_auto_20150916_1526.py
--- old/django-rest-knox-3.6.0/knox/migrations/0003_auto_20150916_1526.py
2018-12-31 12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/knox/migrations/0003_auto_20150916_1526.py
2019-06-01 08:24:05.000000000 +0200
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rest-knox-3.6.0/knox/migrations/0007_auto_20190111_0542.py
new/django-rest-knox-4.1.0/knox/migrations/0007_auto_20190111_0542.py
--- old/django-rest-knox-3.6.0/knox/migrations/0007_auto_20190111_0542.py
1970-01-01 01:00:00.000000000 +0100
+++ new/django-rest-knox-4.1.0/knox/migrations/0007_auto_20190111_0542.py
2019-06-01 08:24:05.000000000 +0200
@@ -0,0 +1,18 @@
+# Generated by Django 2.1 on 2019-01-11 05:42
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('knox', '0006_auto_20160818_0932'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='authtoken',
+ old_name='expires',
+ new_name='expiry',
+ ),
+ ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/models.py
new/django-rest-knox-4.1.0/knox/models.py
--- old/django-rest-knox-3.6.0/knox/models.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/knox/models.py 2019-06-01 08:24:05.000000000
+0200
@@ -9,19 +9,18 @@
class AuthTokenManager(models.Manager):
- def create(self, user, expires=knox_settings.TOKEN_TTL):
+ def create(self, user, expiry=knox_settings.TOKEN_TTL):
token = crypto.create_token_string()
salt = crypto.create_salt_string()
digest = crypto.hash_token(token, salt)
- if expires is not None:
- expires = timezone.now() + expires
+ if expiry is not None:
+ expiry = timezone.now() + expiry
- super(AuthTokenManager, self).create(
+ instance = super(AuthTokenManager, self).create(
token_key=token[:CONSTANTS.TOKEN_KEY_LENGTH], digest=digest,
- salt=salt, user=user, expires=expires)
- # Note only the token - not the AuthToken object - is returned
- return token
+ salt=salt, user=user, expiry=expiry)
+ return instance, token
class AuthToken(models.Model):
@@ -37,7 +36,7 @@
user = models.ForeignKey(User, null=False, blank=False,
related_name='auth_token_set',
on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
- expires = models.DateTimeField(null=True, blank=True)
+ expiry = models.DateTimeField(null=True, blank=True)
def __str__(self):
return '%s : %s' % (self.digest, self.user)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/serializers.py
new/django-rest-knox-4.1.0/knox/serializers.py
--- old/django-rest-knox-3.6.0/knox/serializers.py 2018-12-31
12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/knox/serializers.py 2019-06-01
08:24:05.000000000 +0200
@@ -1,5 +1,4 @@
from django.contrib.auth import get_user_model
-
from rest_framework import serializers
User = get_user_model()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/settings.py
new/django-rest-knox-4.1.0/knox/settings.py
--- old/django-rest-knox-3.6.0/knox/settings.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/knox/settings.py 2019-06-01 08:24:05.000000000
+0200
@@ -1,7 +1,8 @@
from datetime import timedelta
+
from django.conf import settings
from django.test.signals import setting_changed
-from rest_framework.settings import APISettings
+from rest_framework.settings import APISettings, api_settings
USER_SETTINGS = getattr(settings, 'REST_KNOX', None)
@@ -14,6 +15,7 @@
'AUTO_REFRESH': False,
'MIN_REFRESH_INTERVAL': 60,
'AUTH_HEADER_PREFIX': 'Token',
+ 'EXPIRY_DATETIME_FORMAT': api_settings.DATETIME_FORMAT,
}
IMPORT_STRINGS = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox/views.py
new/django-rest-knox-4.1.0/knox/views.py
--- old/django-rest-knox-3.6.0/knox/views.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/knox/views.py 2019-06-01 08:24:05.000000000
+0200
@@ -1,9 +1,9 @@
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.utils import timezone
-
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
+from rest_framework.serializers import DateTimeField
from rest_framework.settings import api_settings
from rest_framework.views import APIView
@@ -28,30 +28,43 @@
def get_user_serializer_class(self):
return knox_settings.USER_SERIALIZER
+ def get_expiry_datetime_format(self):
+ return knox_settings.EXPIRY_DATETIME_FORMAT
+
+ def format_expiry_datetime(self, expiry):
+ datetime_format = self.get_expiry_datetime_format()
+ return DateTimeField(format=datetime_format).to_representation(expiry)
+
+ def get_post_response_data(self, request, token, instance):
+ UserSerializer = self.get_user_serializer_class()
+
+ data = {
+ 'expiry': self.format_expiry_datetime(instance.expiry),
+ 'token': token
+ }
+ if UserSerializer is not None:
+ data["user"] = UserSerializer(
+ request.user,
+ context=self.get_context()
+ ).data
+ return data
+
def post(self, request, format=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)
+ token = request.user.auth_token_set.filter(expiry__gt=now)
if token.count() >= token_limit_per_user:
return Response(
{"error": "Maximum amount of tokens allowed per user
exceeded."},
status=status.HTTP_403_FORBIDDEN
)
token_ttl = self.get_token_ttl()
- token = AuthToken.objects.create(request.user, token_ttl)
+ instance, token = AuthToken.objects.create(request.user, token_ttl)
user_logged_in.send(sender=request.user.__class__,
request=request, user=request.user)
- UserSerializer = self.get_user_serializer_class()
- if UserSerializer is None:
- return Response({
- 'token': token
- })
- context = self.get_context()
- return Response({
- 'user': UserSerializer(request.user, context=context).data,
- 'token': token,
- })
+ data = self.get_post_response_data(request, token, instance)
+ return Response(data)
class LogoutView(APIView):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/knox_project/views.py
new/django-rest-knox-4.1.0/knox_project/views.py
--- old/django-rest-knox-3.6.0/knox_project/views.py 2018-12-31
12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/knox_project/views.py 2019-06-01
08:24:05.000000000 +0200
@@ -1,8 +1,9 @@
-from knox.auth import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
+from knox.auth import TokenAuthentication
+
class RootView(APIView):
authentication_classes = (TokenAuthentication,)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/mkdocs.sh
new/django-rest-knox-4.1.0/mkdocs.sh
--- old/django-rest-knox-3.6.0/mkdocs.sh 1970-01-01 01:00:00.000000000
+0100
+++ new/django-rest-knox-4.1.0/mkdocs.sh 2019-06-01 08:24:05.000000000
+0200
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+set -e
+MOUNT_FOLDER=/app
+MKDOCS_DEV_ADDR=${MKDOCS_DEV_ADDR-"0.0.0.0"}
+MKDOCS_DEV_PORT=${MKDOCS_DEV_PORT-"8000"}
+
+docker run --rm -it \
+ -v $(pwd):$MOUNT_FOLDER \
+ -w $MOUNT_FOLDER \
+ -p $MKDOCS_DEV_PORT:$MKDOCS_DEV_PORT \
+ -e MKDOCS_DEV_ADDR="$MKDOCS_DEV_ADDR:$MKDOCS_DEV_PORT" \
+ squidfunk/mkdocs-material:3.2.0 $*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/mkdocs.yml
new/django-rest-knox-4.1.0/mkdocs.yml
--- old/django-rest-knox-3.6.0/mkdocs.yml 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/mkdocs.yml 2019-06-01 08:24:05.000000000
+0200
@@ -1,7 +1,7 @@
site_name: Django-Rest-Knox
repo_url: https://github.com/James1345/django-rest-knox
theme: readthedocs
-pages:
+nav:
- Home: 'index.md'
- Installation: 'installation.md'
- API Guide:
@@ -9,4 +9,6 @@
- URLs: 'urls.md'
- Authentication: 'auth.md'
- Settings: 'settings.md'
- - Changes: 'changes.md'
+ - Changelog: 'changelog.md'
+
+dev_addr: !!python/object/apply:os.getenv ["MKDOCS_DEV_ADDR"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/setup.py
new/django-rest-knox-4.1.0/setup.py
--- old/django-rest-knox-3.6.0/setup.py 2018-12-31 12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/setup.py 2019-06-01 08:24:05.000000000 +0200
@@ -1,9 +1,10 @@
# Always prefer setuptools over distutils
-from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
+from setuptools import find_packages, setup
+
here = path.abspath(path.dirname(__file__))
# Get the long description from the relevant file
@@ -16,7 +17,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.6.0',
+ version='4.1.0',
description='Authentication for django rest framework',
long_description=long_description,
long_description_content_type='text/markdown',
@@ -66,7 +67,7 @@
# your project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
- install_requires=['django', 'djangorestframework', 'pyOpenSSL'],
+ install_requires=['django', 'djangorestframework', 'cryptography'],
# List additional groups of dependencies here (e.g. development
# dependencies). You can install these using the following syntax,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/tests/tests.py
new/django-rest-knox-4.1.0/tests/tests.py
--- old/django-rest-knox-3.6.0/tests/tests.py 2018-12-31 12:58:08.000000000
+0100
+++ new/django-rest-knox-4.1.0/tests/tests.py 2019-06-01 08:24:05.000000000
+0200
@@ -1,10 +1,19 @@
import base64
from datetime import datetime, timedelta
-from django.utils.six.moves import reload_module
from django.contrib.auth import get_user_model
from django.test import override_settings
+from django.utils.six.moves import reload_module
+from freezegun import freeze_time
+from rest_framework.serializers import DateTimeField
+from rest_framework.test import APIRequestFactory, APITestCase as TestCase
+
from knox import auth, views
+from knox.auth import TokenAuthentication
+from knox.models import AuthToken
+from knox.serializers import UserSerializer
+from knox.settings import CONSTANTS, knox_settings
+from knox.signals import token_expired
try:
# For django >= 2.0
@@ -13,19 +22,6 @@
# For django < 2.0
from django.conf.urls import reverse
-from freezegun import freeze_time
-
-from rest_framework.test import (
- APIRequestFactory,
- APITestCase as TestCase
-)
-
-from knox.auth import TokenAuthentication
-from knox.signals import token_expired
-from knox.models import AuthToken
-from knox.settings import CONSTANTS, knox_settings
-from knox.serializers import UserSerializer
-
User = get_user_model()
root_url = reverse('api-root')
@@ -47,6 +43,13 @@
auth_header_prefix_knox = knox_settings.defaults.copy()
auth_header_prefix_knox["AUTH_HEADER_PREFIX"] = 'Baerer'
+token_no_expiration_knox = knox_settings.defaults.copy()
+token_no_expiration_knox["TOKEN_TTL"] = None
+
+EXPIRY_DATETIME_FORMAT = '%H:%M %d/%m/%y'
+expiry_datetime_format_knox = knox_settings.defaults.copy()
+expiry_datetime_format_knox["EXPIRY_DATETIME_FORMAT"] = EXPIRY_DATETIME_FORMAT
+
class AuthTestCase(TestCase):
@@ -103,10 +106,35 @@
self.assertIn('user', response.data)
self.assertIn(username_field, response.data['user'])
+ def test_login_returns_configured_expiry_datetime_format(self):
+
+ with override_settings(REST_KNOX=expiry_datetime_format_knox):
+ reload_module(views)
+ self.assertEqual(AuthToken.objects.count(), 0)
+ url = reverse('knox_login')
+ self.client.credentials(
+ HTTP_AUTHORIZATION=get_basic_auth_header(self.username,
self.password)
+ )
+ response = self.client.post(url, {}, format='json')
+ self.assertEqual(
+ expiry_datetime_format_knox["EXPIRY_DATETIME_FORMAT"],
+ EXPIRY_DATETIME_FORMAT
+ )
+ reload_module(views)
+ self.assertEqual(response.status_code, 200)
+ self.assertIn('token', response.data)
+ self.assertNotIn('user', response.data)
+ self.assertEqual(
+ response.data['expiry'],
+ DateTimeField(format=EXPIRY_DATETIME_FORMAT).to_representation(
+ AuthToken.objects.first().expiry
+ )
+ )
+
def test_logout_deletes_keys(self):
self.assertEqual(AuthToken.objects.count(), 0)
for _ in range(2):
- token = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
self.assertEqual(AuthToken.objects.count(), 2)
url = reverse('knox_logout')
@@ -118,7 +146,7 @@
def test_logout_all_deletes_keys(self):
self.assertEqual(AuthToken.objects.count(), 0)
for _ in range(10):
- token = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
self.assertEqual(AuthToken.objects.count(), 10)
url = reverse('knox_logoutall')
@@ -129,7 +157,7 @@
def test_logout_all_deletes_only_targets_keys(self):
self.assertEqual(AuthToken.objects.count(), 0)
for _ in range(10):
- token = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
AuthToken.objects.create(user=self.user2)
self.assertEqual(AuthToken.objects.count(), 20)
@@ -141,8 +169,8 @@
def test_expired_tokens_login_fails(self):
self.assertEqual(AuthToken.objects.count(), 0)
- token = AuthToken.objects.create(
- user=self.user, expires=timedelta(seconds=0))
+ instance, token = AuthToken.objects.create(
+ user=self.user, expiry=timedelta(seconds=0))
self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token))
response = self.client.post(root_url, {}, format='json')
self.assertEqual(response.status_code, 401)
@@ -152,8 +180,8 @@
self.assertEqual(AuthToken.objects.count(), 0)
for _ in range(10):
# 0 TTL gives an expired token
- token = AuthToken.objects.create(
- user=self.user, expires=timedelta(seconds=0))
+ instance, token = AuthToken.objects.create(
+ user=self.user, expiry=timedelta(seconds=0))
self.assertEqual(AuthToken.objects.count(), 10)
# Attempting a single logout should delete all tokens
@@ -164,14 +192,15 @@
def test_update_token_key(self):
self.assertEqual(AuthToken.objects.count(), 0)
- token = AuthToken.objects.create(self.user)
+ instance, token = AuthToken.objects.create(self.user)
rf = APIRequestFactory()
request = rf.get('/')
request.META = {'HTTP_AUTHORIZATION': 'Token {}'.format(token)}
(self.user, auth_token) = TokenAuthentication().authenticate(request)
self.assertEqual(
token[:CONSTANTS.TOKEN_KEY_LENGTH],
- auth_token.token_key)
+ auth_token.token_key,
+ )
def test_invalid_token_length_returns_401_code(self):
invalid_token = "1" * (CONSTANTS.TOKEN_KEY_LENGTH - 1)
@@ -181,7 +210,7 @@
self.assertEqual(response.data, {"detail": "Invalid token."})
def test_invalid_odd_length_token_returns_401_code(self):
- token = AuthToken.objects.create(self.user)
+ instance, token = AuthToken.objects.create(self.user)
odd_length_token = token + '1'
self.client.credentials(HTTP_AUTHORIZATION=('Token %s' %
odd_length_token))
response = self.client.post(root_url, {}, format='json')
@@ -193,9 +222,9 @@
original_time = datetime(2018, 7, 25, 0, 0, 0, 0)
with freeze_time(original_time):
- token_key = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
- self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token_key))
+ self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token))
five_hours_later = original_time + timedelta(hours=5)
with override_settings(REST_KNOX=auto_refresh_knox):
reload_module(auth) # necessary to reload settings in core code
@@ -205,7 +234,7 @@
self.assertEqual(response.status_code, 200)
# original expiry date was extended:
- new_expiry = AuthToken.objects.get().expires
+ new_expiry = AuthToken.objects.get().expiry
expected_expiry = original_time + ttl + timedelta(hours=5)
self.assertEqual(new_expiry.replace(tzinfo=None), expected_expiry,
"Expiry time should have been extended to {} but is
{}."
@@ -218,7 +247,7 @@
self.assertEqual(response.status_code, 200)
# token does not work after new expiry:
- new_expiry = AuthToken.objects.get().expires
+ new_expiry = AuthToken.objects.get().expiry
with freeze_time(new_expiry + timedelta(seconds=1)):
response = self.client.get(root_url, {}, format='json')
self.assertEqual(response.status_code, 401)
@@ -229,25 +258,25 @@
now = datetime.now()
with freeze_time(now):
- token_key = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
- original_expiry = AuthToken.objects.get().expires
+ original_expiry = AuthToken.objects.get().expiry
- self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token_key))
+ self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token))
with freeze_time(now + timedelta(hours=1)):
response = self.client.get(root_url, {}, format='json')
self.assertEqual(response.status_code, 200)
- self.assertEqual(original_expiry, AuthToken.objects.get().expires)
+ self.assertEqual(original_expiry, AuthToken.objects.get().expiry)
def test_token_expiry_is_not_extended_within_MIN_REFRESH_INTERVAL(self):
now = datetime.now()
with freeze_time(now):
- token_key = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
- original_expiry = AuthToken.objects.get().expires
+ original_expiry = AuthToken.objects.get().expiry
- self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token_key))
+ self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token))
in_min_interval = now +
timedelta(seconds=knox_settings.MIN_REFRESH_INTERVAL - 10)
with override_settings(REST_KNOX=auto_refresh_knox):
reload_module(auth) # necessary to reload settings in core code
@@ -256,7 +285,7 @@
reload_module(auth) # necessary to reload settings in core code
self.assertEqual(response.status_code, 200)
- self.assertEqual(original_expiry, AuthToken.objects.get().expires)
+ self.assertEqual(original_expiry, AuthToken.objects.get().expiry)
def test_expiry_signals(self):
self.signal_was_called = False
@@ -266,7 +295,7 @@
token_expired.connect(handler)
- token = AuthToken.objects.create(user=self.user, expires=timedelta(0))
+ instance, token = AuthToken.objects.create(user=self.user,
expiry=timedelta(0))
self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token))
self.client.post(root_url, {}, format='json')
@@ -294,7 +323,7 @@
reload_module(views)
for _ in range(9):
AuthToken.objects.create(user=self.user)
- AuthToken.objects.create(user=self.user,
expires=timedelta(seconds=0))
+ AuthToken.objects.create(user=self.user,
expiry=timedelta(seconds=0))
# now 10 keys, but only 9 valid so request should succeed.
url = reverse('knox_login')
self.client.credentials(
@@ -313,11 +342,57 @@
with override_settings(REST_KNOX=auth_header_prefix_knox):
reload_module(auth)
- token = AuthToken.objects.create(user=self.user)
+ instance, token = AuthToken.objects.create(user=self.user)
self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % token))
failed_response = self.client.get(root_url)
- self.client.credentials(HTTP_AUTHORIZATION=('Baerer %s' % token))
+ self.client.credentials(
+ HTTP_AUTHORIZATION=(
+ 'Baerer %s' % token
+ )
+ )
response = self.client.get(root_url)
reload_module(auth)
self.assertEqual(failed_response.status_code, 401)
self.assertEqual(response.status_code, 200)
+
+ def test_expiry_present_also_when_none(self):
+ with override_settings(REST_KNOX=token_no_expiration_knox):
+ reload_module(views)
+ self.assertEqual(AuthToken.objects.count(), 0)
+ url = reverse('knox_login')
+ self.client.credentials(
+ HTTP_AUTHORIZATION=get_basic_auth_header(self.username,
self.password)
+ )
+ response = self.client.post(
+ url,
+ {},
+ format='json'
+ )
+ self.assertEqual(token_no_expiration_knox["TOKEN_TTL"], None)
+ self.assertEqual(response.status_code, 200)
+ self.assertIn('token', response.data)
+ self.assertIn('expiry', response.data)
+ self.assertEqual(
+ response.data['expiry'],
+ None
+ )
+ reload_module(views)
+
+ def test_expiry_is_present(self):
+ self.assertEqual(AuthToken.objects.count(), 0)
+ url = reverse('knox_login')
+ self.client.credentials(
+ HTTP_AUTHORIZATION=get_basic_auth_header(self.username,
self.password)
+ )
+ response = self.client.post(
+ url,
+ {},
+ format='json'
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertIn('token', response.data)
+ self.assertIn('expiry', response.data)
+ self.assertEqual(
+ response.data['expiry'],
+ DateTimeField().to_representation(AuthToken.objects.first().expiry)
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rest-knox-3.6.0/tox.ini
new/django-rest-knox-4.1.0/tox.ini
--- old/django-rest-knox-3.6.0/tox.ini 2018-12-31 12:58:08.000000000 +0100
+++ new/django-rest-knox-4.1.0/tox.ini 2019-06-01 08:24:05.000000000 +0200
@@ -1,8 +1,25 @@
[tox]
envlist =
- py{27,34,35,36}-django111,
- py{34,35,36}-django20,
- py{35,36,37}-django21,
+ isort
+ flake8,
+ py{27,34,35,36}-django111,
+ py{34,35,36}-django20,
+ py{35,36,37}-django21,
+ py{35,36,37}-django22,
+
+[testenv:flake8]
+deps = flake8
+changedir = {toxinidir}
+commands = flake8 knox
+
+[testenv:isort]
+deps = isort
+changedir = {toxinidir}
+commands = isort --recursive --check-only --diff \
+ knox \
+ knox_project/views.py \
+ setup.py \
+ tests
[testenv]
commands =
@@ -15,12 +32,14 @@
django111: Django>=1.11,<2.0
django20: Django>=2.0,<2.1
django21: Django>=2.1,<2.2
+ django22: Django>=2.2,<2.3
django-nose
markdown<3.0
+ isort
djangorestframework
freezegun
mkdocs
- pyOpenSSL
+ cryptography
pytest-django
setuptools
twine