Merge pull request #74 from nitmir/dev

Update to version 1.3.0

v1.3.0 - 2021-06-19
===================

Added
-----

* Support for Dango 3.1 and 3.2
* Implement CAS_LDAP_ATTRS_VIEW set to 0: then using ldap bind mode, user
  attributes can be retreive either using CAS_LDAP_USER or using the
  binded user credentials.
* Added ppc64le architecture support on travis-ci (django-cas-server is
  included in the ppc64le versions of RHEL and Ubuntu)
* Python 3.9 support

Fixes
-----

* Allow to use user attributes if auth by ldap bind
* Fix spelling mistakes in french translation
* Fix bug model datefield Form (Federated User Admin)
* django.conf.urls is deprecated and will be removed in Django 4.0.
  Use django.urls.re_path instead

Removed
-------

* Drop support for Django 3.0 as it reached end of life.
This commit is contained in:
Valentin Samir 2021-06-19 18:42:29 +02:00 committed by GitHub
commit d010e757a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 359 additions and 293 deletions

View file

@ -2,7 +2,7 @@ before_script:
- pip install tox setuptools
flake8:
image: "python:2.7"
image: "python:3.9"
cache:
key: flake8
paths:
@ -11,7 +11,7 @@ flake8:
- tox -e flake8
check_rst:
image: "python:2.7"
image: "python:3.9"
cache:
key: check_rst
paths:
@ -19,107 +19,98 @@ check_rst:
script:
- tox -e check_rst
py27-django17:
py27-django111:
image: "python:2.7"
cache:
key: py27-django17
key: py27-django111
paths:
- .tox/py27-django17
- .tox/py27-django111
script:
- tox -e py27-django17
- tox -e py27-django111
py27-django18:
image: "python:2.7"
cache:
key: py27-django18
paths:
- .tox/py27-django18
script:
- tox -e py27-django18
py27-django19:
image: "python:2.7"
cache:
key: py27-django19
paths:
- .tox/py27-django19
script:
- tox -e py27-django19
py27-django110:
image: "python:2.7"
cache:
key: py27-django110
paths:
- .tox/py27-django110
script:
- tox -e py27-django110
py34-django17:
image: "python:3.4"
cache:
key: py34-django17
paths:
- .tox/py34-django17
script:
- tox -e py34-django17
py34-django18:
image: "python:3.4"
cache:
key: py34-django18
paths:
- .tox/py34-django18
script:
- tox -e py34-django18
py34-django19:
image: "python:3.4"
cache:
key: py34-django19
paths:
- .tox/py34-django19
script:
- tox -e py34-django19
py34-django110:
image: "python:3.4"
cache:
key: py34-django110
paths:
- .tox/py34-django110
script:
- tox -e py34-django110
py35-django18:
py35-django111:
image: "python:3.5"
cache:
key: py35-django18
key: py35-django111
paths:
- .tox/py35-django18
- .tox/py35-django111
script:
- tox -e py35-django18
- tox -e py35-django111
py35-django19:
image: "python:3.5"
py36-django111:
image: "python:3.6"
cache:
key: py35-django19
key: py36-django111
paths:
- .tox/py35-django19
- .tox/py36-django111
script:
- tox -e py35-django19
- tox -e py36-django111
py35-django110:
image: "python:3.5"
py37-django22:
image: "python:3.7"
cache:
key: py35-django110
key: py37-django22
paths:
- .tox/py35-django110
- .tox/py37-django22
script:
- tox -e py35-django110
- tox -e py37-django22
py38-django22:
image: "python:3.8"
cache:
key: py38-django22
paths:
- .tox/py38-django22
script:
- tox -e py38-django22
py38-django30:
image: "python:3.8"
cache:
key: py38-django30
paths:
- .tox/py38-django30
script:
- tox -e py38-django30
py38-django31:
image: "python:3.8"
cache:
key: py38-django31
paths:
- .tox/py38-django31
script:
- tox -e py38-django31
py39-django22:
image: "python:3.9"
cache:
key: py39-django22
paths:
- .tox/py39-django22
script:
- tox -e py39-django22
py39-django30:
image: "python:3.9"
cache:
key: py39-django30
paths:
- .tox/py39-django30
script:
- tox -e py39-django30
py39-django31:
image: "python:3.9"
cache:
key: py39-django31
paths:
- .tox/py39-django31
script:
- tox -e py39-django31
coverage:
image: "python:2.7"
image: "python:3.9"
cache:
key: coverage
paths:

View file

@ -1,39 +1,63 @@
language: python
matrix:
include:
- python: "3.8"
# generic checks
- python: "3.9"
env: TOX_ENV=flake8
- python: "3.8"
- python: "3.9"
env: TOX_ENV=check_rst
- python: "2.7"
env: TOX_ENV=py27-django111
- python: "3.9"
env: TOX_ENV=coverage
# Debian strech support
- python: "3.5"
env: TOX_ENV=py35-django111
- python: "3.5"
env: TOX_ENV=py35-django111
arch: ppc64le
# Ubuntu bionic and EPEL 7 support
- python: "3.6"
env: TOX_ENV=py36-django111
- python: "3.5"
env: TOX_ENV=py35-django20
- python: "3.6"
env: TOX_ENV=py36-django20
- python: "3.5"
env: TOX_ENV=py35-django21
env: TOX_ENV=py36-django111
arch: ppc64le
# RHEL 8 support
- python: "3.6"
env: TOX_ENV=py36-django21
env: TOX_ENV=py36-django22
- python: "3.6"
env: TOX_ENV=py36-django22
arch: ppc64le
# Debian buster support
- python: "3.7"
env: TOX_ENV=py37-django22
env: TOX_ENV=py37-django111
- python: "3.7"
env: TOX_ENV=py37-django111
arch: ppc64le
# Ubuntu focal and Ubuntu groovy support
- python: "3.8"
env: TOX_ENV=py38-django22
- python: "3.8"
env: TOX_ENV=py38-django30
- python: "3.8"
env: TOX_ENV=coverage
env: TOX_ENV=py38-django22
arch: ppc64le
# Debian bullseye and Ubuntu hirsute support
- python: "3.9"
env: TOX_ENV=py39-django22
- python: "3.9"
env: TOX_ENV=py39-django22
arch: ppc64le
# Django additional supported version
- python: "3.9"
env: TOX_ENV=py39-django31
- python: "3.9"
env: TOX_ENV=py39-django32
cache:
directories:
- $HOME/.cache/pip/http/
- $HOME/build/nitmir/django-cas-server/.tox/$TOX_ENV/
install:
- "travis_retry pip install setuptools --upgrade"
- "pip install tox"
- travis_retry pip install setuptools --upgrade
- pip install tox $PKGS
- pip freeze
script:
- tox -e $TOX_ENV
after_script:

View file

@ -6,6 +6,34 @@ All notable changes to this project will be documented in this file.
.. contents:: Table of Contents
:depth: 2
v1.3.0 - 2021-06-19
===================
Added
-----
* Support for Dango 3.1 and 3.2
* Implement CAS_LDAP_ATTRS_VIEW set to 0: then using ldap bind mode, user
attributes can be retreive either using CAS_LDAP_USER or using the
binded user credentials.
* Added ppc64le architecture support on travis-ci (django-cas-server is
included in the ppc64le versions of RHEL and Ubuntu)
* Python 3.9 support
Fixes
-----
* Allow to use user attributes if auth by ldap bind
* Fix spelling mistakes in french translation
* Fix bug model datefield Form (Federated User Admin)
* django.conf.urls is deprecated and will be removed in Django 4.0.
Use django.urls.re_path instead
Removed
-------
* Drop support for Django 3.0 as it reached end of life.
v1.2.0 - 2020-07-05
===================

View file

@ -1,15 +1,15 @@
.PHONY: build dist docs
VERSION=`python setup.py -V`
VERSION=`python3 setup.py -V`
build:
python setup.py build
python3 setup.py build
install: dist
pip -V
pip install --no-cache-dir --no-deps --upgrade --force-reinstall --find-links ./dist/django-cas-server-${VERSION}.tar.gz django-cas-server
pip3 -V
pip3 install --no-cache-dir --no-deps --upgrade --force-reinstall --find-links ./dist/django-cas-server-${VERSION}.tar.gz django-cas-server
uninstall:
pip uninstall django-cas-server || true
pip3 uninstall django-cas-server || true
clean_pyc:
find ./ -name '*.pyc' -delete
@ -34,11 +34,11 @@ clean: clean_pyc clean_build clean_coverage clean_tild_backup
clean_all: clean clean_tox clean_test_venv clean_docs clean_eggs
dist:
python setup.py sdist
python3 setup.py sdist
test_venv/bin/python:
python3 -m venv test_venv
test_venv/bin/pip install -U --requirement requirements-dev.txt 'Django>=2.0,<2.1'
test_venv/bin/pip install -U --requirement requirements-dev.txt 'Django>=3.2,<3.3'
test_venv/cas/manage.py: test_venv
mkdir -p test_venv/cas
@ -61,7 +61,7 @@ run_server: test_project
test_venv/bin/python test_venv/cas/manage.py runserver
run_tests: test_venv
python setup.py check --restructuredtext --stric
python3 setup.py check --restructuredtext --stric
test_venv/bin/py.test -rw -x --cov=cas_server --cov-report html --cov-report term
rm htmlcov/coverage_html.js # I am really pissed off by those keybord shortcuts
@ -72,4 +72,4 @@ docs: test_venv/bin/sphinx-build
bash -c "source test_venv/bin/activate; cd docs; make html"
publish_pypi_release:
python setup.py sdist bdist_wheel upload --sign
python3 setup.py sdist bdist_wheel upload --sign

View file

@ -21,15 +21,15 @@ Features
* Possibility to rename/rewrite attributes per service
* Possibility to require some attribute values per service
* Federated mode between multiple CAS
* Supports Django 1.11, 2.2 and 3.0
* Supports Python 2.7, 3.5+
* Supports Django 1.11, 2.2, 3.1 and 3.2
* Supports Python 3.5+
Dependencies
============
``django-cas-server`` depends on the following python packages:
* Django >= 1.11 < 3.1
* Django >= 1.11 < 3.3
* requests >= 2.4
* requests_futures >= 0.9.5
* lxml >= 3.4
@ -136,13 +136,13 @@ Quick start
)
For internationalization support, add "django.middleware.locale.LocaleMiddleware"
to your MIDDLEWARE_CLASSES setting like this::
to your MIDDLEWARE setting like this::
MIDDLEWARE_CLASSES = (
MIDDLEWARE = [
...
'django.middleware.locale.LocaleMiddleware',
...
)
]
2. Include the cas_server URLconf in your project urls.py like this::
@ -423,16 +423,18 @@ Only useful if you are using the ldap authentication backend:
The hashed password in the database is compared to the hexadecimal digest of the clear
password hashed with the corresponding algorithm.
* ``"plain"``, the password in the database must be in clear.
* ``"bind``, the user credentials are used to bind to the ldap database and retreive the user
* ``"bind"``, the user credentials are used to bind to the ldap database and retreive the user
attribute. In this mode, the settings ``CAS_LDAP_PASSWORD_ATTR`` and ``CAS_LDAP_PASSWORD_CHARSET``
are ignored, and it is the ldap server that performs the password check. The counterpart is that
the user attributes are only available upon user password check and so are cached for later
use. All the other modes directly fetch the user attributes from the database whenever they
are needed. This mean that is you use this mode, there can be some differences between the
attributes in database and the cached ones if changes happen in the database after the user
authentiates. See the parameter ``CAS_TGT_VALIDITY`` to force user to reauthenticate periodically.
are ignored, and it is the ldap server that performs the password check.
The default is ``"ldap"``.
* ``CAS_LDAP_ATTRS_VIEW``: This parameter is only used then ``CAS_LDAP_PASSWORD_CHECK`` is set to
``"bind"``. If ``0`` the user attributes are retrieved by connecting to the ldap as ``CAS_LDAP_USER``.
If ``1`` the user attributes are retrieve then the user authenticate using the user credentials and
are cached for later use. It means there can be some differences between the attributes in database
and the cached ones. See the parameter ``CAS_TGT_VALIDITY`` to force user to reauthenticate
periodically.
The default is ``0``.
* ``CAS_LDAP_PASSWORD_CHARSET``: Charset the LDAP users passwords was hashed with. This is needed to
encode the user submitted password before hashing it for comparison. The default is ``"utf-8"``.
@ -642,8 +644,8 @@ You could for example do as below::
.. |travis| image:: https://badges.genua.fr/travis/nitmir/django-cas-server/master.svg
:target: https://travis-ci.org/nitmir/django-cas-server
.. |travis| image:: https://badges.genua.fr/travis/com/nitmir/django-cas-server/master.svg
:target: https://travis-ci.com/nitmir/django-cas-server
.. |pypi_version| image:: https://badges.genua.fr/pypi/v/django-cas-server.svg
:target: https://pypi.org/project/django-cas-server/

View file

@ -11,7 +11,7 @@
"""A django CAS server application"""
#: version of the application
VERSION = '1.2.0'
VERSION = '1.3.0'
#: path the the application configuration class
default_app_config = 'cas_server.apps.CasAppConfig'

View file

@ -391,11 +391,13 @@ class LdapAuthUser(DBAuthUser): # pragma: no cover
or :class:`list` of :func:`unicode`. If the user do not exists, the returned
:class:`dict` is empty.
:rtype: dict
:raises NotImplementedError: if the password check method in `CAS_LDAP_PASSWORD_CHECK`
do not allow to fetch the attributes without the user credentials.
"""
if settings.CAS_LDAP_PASSWORD_CHECK == "bind":
raise NotImplementedError()
if settings.CAS_LDAP_ATTRS_VIEW == 1:
user = UserAttributes.objects.get(username=self.username)
return user.attributs
else:
return self.user
else:
return super(LdapAuthUser, self).attributs()

View file

@ -165,10 +165,17 @@ CAS_LDAP_USERNAME_ATTR = "uid"
CAS_LDAP_PASSWORD_ATTR = "userPassword"
#: The method used to check the user password. Must be one of ``"crypt"``, ``"ldap"``,
#: ``"hex_md5"``, ``"hex_sha1"``, ``"hex_sha224"``, ``"hex_sha256"``, ``"hex_sha384"``,
#: ``"hex_sha512"``, ``"plain"``.
#: ``"hex_sha512"``, ``"plain"``, ``"bind"``.
CAS_LDAP_PASSWORD_CHECK = "ldap"
#: charset the LDAP users passwords was hash with
CAS_LDAP_PASSWORD_CHARSET = "utf-8"
#: This parameter is only used then ``CAS_LDAP_PASSWORD_CHECK`` is set to ``"bind"``.
#: * if ``0`` the user attributes are retrieved by connecting to the ldap as
#: ``CAS_LDAP_USER``.
#: * if ``1`` the user attributes are retrieve then the user authenticate using
#: the user credentials. These attributes are then cached for the session.
#: The default is ``0``.
CAS_LDAP_ATTRS_VIEW = 0
#: Username of the test user.

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: cas_server\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-18 11:29+0200\n"
"PO-Revision-Date: 2016-09-18 11:30+0200\n"
"PO-Revision-Date: 2020-07-05 16:05+0200\n"
"Last-Translator: Valentin Samir <valentin.samir@crans.org>\n"
"Language-Team: django <LL@li.org>\n"
"Language: fr\n"
@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 1.8.9\n"
"X-Generator: Poedit 2.2.1\n"
#: apps.py:25 templates/cas_server/base.html:7
#: templates/cas_server/base.html:26
@ -36,7 +36,7 @@ msgstr ""
#: forms.py:85
msgid "Identity provider"
msgstr "fournisseur d'identité"
msgstr "Fournisseur d'identité"
#: forms.py:89 forms.py:111
msgid "Warn me before logging me into other sites."
@ -112,7 +112,7 @@ msgstr "Version du protocole CAS"
msgid ""
"Version of the CAS protocol to use when sending requests the the backend CAS."
msgstr ""
"Version du protocole CAS à utiliser lorsque l'on envoie des requête au CAS "
"Version du protocole CAS à utiliser lorsque l'on envoie des requêtes au CAS "
"du fournisseur d'identité."
#: models.py:106
@ -158,7 +158,7 @@ msgstr "Motifs de services"
#: models.py:447
msgid "service patterns are sorted using the position attribute"
msgstr "Les motifs de service sont trié selon l'attribut position"
msgstr "Les motifs de service sont triés selon l'attribut position"
#: models.py:455 models.py:620
msgid "name"
@ -179,7 +179,7 @@ msgid ""
"character must be escaped with a '\\'."
msgstr ""
"Une expression rationnelle reconnaissant un service. Devrait généralement "
"ressemblé à '^https://un\\.serveur\\.fr/chemin/.*$'. Comme il s'agit d'une "
"ressembler à '^https://un\\.serveur\\.fr/chemin/.*$'. Comme il s'agit d'une "
"expression rationnelle, les caractères spéciaux doivent être échappés avec "
"un '\\'."
@ -200,7 +200,7 @@ msgstr "limiter les noms d'utilisateurs"
#: models.py:484
msgid "Limit username allowed to connect to the list provided bellow"
msgstr ""
"Limiter les noms d'utilisateurs autorisé à se connecter à la liste fournie "
"Limiter les noms d'utilisateurs autorisés à se connecter à la liste fournie "
"ci-dessous"
#: models.py:489
@ -376,7 +376,7 @@ msgstr ""
#: views.py:500
msgid "Invalid login ticket, please try to log in again"
msgstr "Ticket de connexion invalide, merci de réessayé de vous connecter"
msgstr "Ticket de connexion invalide, merci de réessayer de vous connecter"
#: views.py:692
#, python-format

View file

@ -180,7 +180,7 @@ class FederatedUser(JsonAttributes):
#: The last ticket used to authenticate :attr:`username` against :attr:`provider`
ticket = models.CharField(max_length=255)
#: Last update timespampt. Usually, the last time :attr:`ticket` has been set.
last_update = models.DateTimeField(auto_now=True)
last_update = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.federated_username

View file

@ -13,10 +13,17 @@ Including another URLconf
1. Import the include() function: from django.conf.urls import url, include, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
try:
from django.urls import re_path
except ImportError:
# re_path is not available in Django 2
from django.conf.urls import url as re_path
from django.conf.urls import include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('cas_server.urls', namespace='cas_server')),
re_path(r'^admin/', admin.site.urls),
re_path(r'^', include('cas_server.urls', namespace='cas_server')),
]

View file

@ -10,7 +10,13 @@
#
# (c) 2015-2016 Valentin Samir
"""urls for the app"""
from django.conf.urls import url
try:
from django.urls import re_path
except ImportError:
# re_path is not available in Django 2
from django.conf.urls import url as re_path
from django.views.generic import RedirectView
from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables
@ -19,42 +25,42 @@ from cas_server import views
app_name = "cas_server"
urlpatterns = [
url(
re_path(
r'^$',
RedirectView.as_view(pattern_name="cas_server:login", permanent=False, query_string=True)
),
url(
re_path(
'^login$',
sensitive_post_parameters('password')(
views.LoginView.as_view()
),
name='login'
),
url('^logout$', views.LogoutView.as_view(), name='logout'),
url('^validate$', views.Validate.as_view(), name='validate'),
url(
re_path('^logout$', views.LogoutView.as_view(), name='logout'),
re_path('^validate$', views.Validate.as_view(), name='validate'),
re_path(
'^serviceValidate$',
views.ValidateService.as_view(allow_proxy_ticket=False),
name='serviceValidate'
),
url(
re_path(
'^proxyValidate$',
views.ValidateService.as_view(allow_proxy_ticket=True),
name='proxyValidate'
),
url('^proxy$', views.Proxy.as_view(), name='proxy'),
url(
re_path('^proxy$', views.Proxy.as_view(), name='proxy'),
re_path(
'^p3/serviceValidate$',
views.ValidateService.as_view(allow_proxy_ticket=False),
name='p3_serviceValidate'
),
url(
re_path(
'^p3/proxyValidate$',
views.ValidateService.as_view(allow_proxy_ticket=True),
name='p3_proxyValidate'
),
url('^samlValidate$', views.SamlValidate.as_view(), name='samlValidate'),
url(
re_path('^samlValidate$', views.SamlValidate.as_view(), name='samlValidate'),
re_path(
'^auth$',
sensitive_variables('password', 'secret')(
sensitive_post_parameters('password', 'secret')(
@ -63,5 +69,6 @@ urlpatterns = [
),
name='auth'
),
url("^federate(?:/(?P<provider>([^/]+)))?$", views.FederateAuth.as_view(), name='federateAuth'),
re_path("^federate(?:/(?P<provider>([^/]+)))?$",
views.FederateAuth.as_view(), name='federateAuth'),
]

View file

@ -409,7 +409,10 @@ def crypt_salt_is_valid(salt):
if '$' not in salt[1:]:
return False
else:
try:
hashed = crypt.crypt("", salt)
except OSError:
return False
if not hashed or '$' not in hashed[1:]:
return False
else:

View file

@ -288,7 +288,8 @@ class FederateAuth(CsrfExemptView):
# else, a User is trying to log in using an identity provider
except FederatedIendityProvider.DoesNotExist:
# Manually checking for csrf to protect the code below
reason = CsrfViewMiddleware().process_view(request, None, (), {})
reason = CsrfViewMiddleware(lambda request: HttpResponse()) \
.process_view(request, None, (), {})
if reason is not None: # pragma: no cover (csrf checks are disabled during tests)
return reason # Failed the test, stop here.
form = forms.FederateSelect(request.POST)

View file

@ -1,4 +1,4 @@
Django >= 1.11,<3.1
Django >= 1.11,<3.3
setuptools>=5.5
requests>=2.4
requests_futures>=0.9.5

View file

@ -36,6 +36,7 @@ if __name__ == '__main__':
'Framework :: Django :: 2.1',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
@ -48,6 +49,7 @@ if __name__ == '__main__':
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
@ -62,7 +64,7 @@ if __name__ == '__main__':
},
keywords=['django', 'cas', 'cas3', 'server', 'sso', 'single sign-on', 'authentication', 'auth'],
install_requires=[
'Django >= 1.11,<3.1', 'requests >= 2.4', 'requests_futures >= 0.9.5',
'Django >= 1.11,<3.2', 'requests >= 2.4', 'requests_futures >= 0.9.5',
'lxml >= 3.4', 'six >= 1'
],
url="https://github.com/nitmir/django-cas-server",

262
tox.ini
View file

@ -3,15 +3,14 @@ envlist=
flake8,
check_rst,
py27-django111,
py35-django111,
py36-django111,
py37-django111,
py36-django22,
py37-django22,
py38-django22,
py36-django30,
py37-django30,
py38-django30,
py3-django111,
py3-django22,
py3-django31,
py3-django32,
##################
# generic config #
##################
[flake8]
max-line-length=100
@ -37,132 +36,9 @@ commands=
{[post_cmd]commands}
whitelist_externals={[post_cmd]whitelist_externals}
[testenv:py27-django17]
basepython=python2.7
deps =
Django>=1.7,<1.8
{[base]deps}
[testenv:py27-django18]
basepython=python2.7
deps =
Django>=1.8,<1.9
{[base]deps}
[testenv:py27-django19]
basepython=python2.7
deps =
Django>=1.9,<1.10
{[base]deps}
[testenv:py27-django110]
basepython=python2.7
deps =
Django>=1.10,<1.11
{[base]deps}
[testenv:py27-django111]
basepython=python2.7
deps =
Django>=1.11,<1.12
{[base]deps}
[testenv:py34-django17]
basepython=python3.4
deps =
Django>=1.7,<1.8
{[base]deps}
[testenv:py34-django18]
basepython=python3.4
deps =
Django>=1.8,<1.9
{[base]deps}
[testenv:py35-django110]
basepython=python3.5
deps =
Django>=1.10,<1.11
{[base]deps}
[testenv:py35-django111]
basepython=python3.5
deps =
Django>=1.11,<1.12
{[base]deps}
[testenv:py36-django111]
basepython=python3.6
deps =
Django>=1.11,<1.12
{[base]deps}
[testenv:py35-django20]
basepython=python3.5
deps =
Django>=2.0,<2.1
{[base]deps}
[testenv:py36-django20]
basepython=python3.6
deps =
Django>=2.0,<2.1
{[base]deps}
[testenv:py35-django21]
basepython=python3.5
deps =
Django>=2.1,<2.2
{[base]deps}
[testenv:py36-django21]
basepython=python3.6
deps =
Django>=2.1,<2.2
{[base]deps}
[testenv:py37-django21]
basepython=python3.7
deps =
Django>=2.1,<2.2
{[base]deps}
[testenv:py36-django22]
basepython=python3.6
deps =
Django>=2.2,<3.0
{[base]deps}
[testenv:py37-django22]
basepython=python3.7
deps =
Django>=2.2,<3.0
{[base]deps}
[testenv:py38-django22]
basepython=python3.8
deps =
Django>=2.2,<3.0
{[base]deps}
[testenv:py36-django30]
basepython=python3.6
deps =
Django>=3.0,<3.1
{[base]deps}
[testenv:py37-django30]
basepython=python3.7
deps =
Django>=3.0,<3.1
{[base]deps}
[testenv:py38-django30]
basepython=python3.8
deps =
Django>=3.0,<3.1
{[base]deps}
###################
# genercic checks #
###################
[testenv:flake8]
basepython=python3
@ -201,3 +77,119 @@ commands=
{toxinidir}/.update_coverage "{toxinidir}" "django-cas-server"
{[post_cmd]commands}
whitelist_externals={[post_cmd]whitelist_externals}
####################
# Python 2 support #
####################
[testenv:py27-django111]
basepython=python2.7
deps =
Django>=1.11,<1.12
{[base]deps}
##################################
# Generic Python 3 for local use #
##################################
[testenv:py3-django111]
basepython=python3
deps =
Django>=1.11,<1.12
{[base]deps}
[testenv:py3-django22]
basepython=python3
deps =
Django>=2.2,<2.3
{[base]deps}
[testenv:py3-django31]
basepython=python3
deps =
Django>=3.1,<3.2
{[base]deps}
[testenv:py3-django32]
basepython=python3
deps =
Django>=3.2,<3.3
{[base]deps}
#########################
# Debian strech support #
#########################
[testenv:py35-django111]
basepython=python3.5
deps =
Django>=1.11,<1.12
{[base]deps}
####################################
# Ubuntu bionic and EPEL 7 support #
####################################
[testenv:py36-django111]
basepython=python3.6
deps =
Django>=1.11,<1.12
{[base]deps}
##################
# RHEL 8 support #
##################
[testenv:py36-django22]
basepython=python3.6
deps =
Django>=2.2,<3.0
{[base]deps}
#########################
# Debian buster support #
#########################
[testenv:py37-django111]
basepython=python3.7
deps =
Django>=1.11,<1.12
{[base]deps}
##########################################
# Ubuntu focal and Ubuntu groovy support #
##########################################
[testenv:py38-django22]
basepython=python3.8
deps =
Django>=2.2,<3.0
{[base]deps}
##############################################
# Debian bullseye and Ubuntu hirsute support #
##############################################
[testenv:py39-django22]
basepython=python3.9
deps =
Django>=2.2,<3.0
{[base]deps}
#######################################
# Django additional supported version #
#######################################
[testenv:py39-django31]
basepython=python3.9
deps =
Django>=3.1,<3.2
{[base]deps}
[testenv:py39-django32]
basepython=python3.9
deps =
Django>=3.2,<3.3
{[base]deps}