diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cffb395..0394afa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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: diff --git a/.travis.yml b/.travis.yml index 7f0543b..4c39d04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d493dd9..315506f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -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 =================== diff --git a/Makefile b/Makefile index 62773c5..363f117 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.rst b/README.rst index 87b663f..50bc8c7 100644 --- a/README.rst +++ b/README.rst @@ -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/ diff --git a/cas_server/__init__.py b/cas_server/__init__.py index 66d4a2c..b8ffce2 100644 --- a/cas_server/__init__.py +++ b/cas_server/__init__.py @@ -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' diff --git a/cas_server/auth.py b/cas_server/auth.py index 0e07d74..2741c97 100644 --- a/cas_server/auth.py +++ b/cas_server/auth.py @@ -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() diff --git a/cas_server/default_settings.py b/cas_server/default_settings.py index 744a6f7..8cd092c 100644 --- a/cas_server/default_settings.py +++ b/cas_server/default_settings.py @@ -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. diff --git a/cas_server/locale/fr/LC_MESSAGES/django.mo b/cas_server/locale/fr/LC_MESSAGES/django.mo index 74d9ce9..078033d 100644 Binary files a/cas_server/locale/fr/LC_MESSAGES/django.mo and b/cas_server/locale/fr/LC_MESSAGES/django.mo differ diff --git a/cas_server/locale/fr/LC_MESSAGES/django.po b/cas_server/locale/fr/LC_MESSAGES/django.po index 406da03..8be90da 100644 --- a/cas_server/locale/fr/LC_MESSAGES/django.po +++ b/cas_server/locale/fr/LC_MESSAGES/django.po @@ -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 \n" "Language-Team: django \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 diff --git a/cas_server/models.py b/cas_server/models.py index b8950a6..1b38383 100644 --- a/cas_server/models.py +++ b/cas_server/models.py @@ -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 diff --git a/cas_server/tests/urls.py b/cas_server/tests/urls.py index a9ed25c..72a5cb2 100644 --- a/cas_server/tests/urls.py +++ b/cas_server/tests/urls.py @@ -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')), ] diff --git a/cas_server/urls.py b/cas_server/urls.py index 1e874c0..63a6067 100644 --- a/cas_server/urls.py +++ b/cas_server/urls.py @@ -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([^/]+)))?$", views.FederateAuth.as_view(), name='federateAuth'), + re_path("^federate(?:/(?P([^/]+)))?$", + views.FederateAuth.as_view(), name='federateAuth'), ] diff --git a/cas_server/utils.py b/cas_server/utils.py index f2bb4db..4ec2333 100644 --- a/cas_server/utils.py +++ b/cas_server/utils.py @@ -409,7 +409,10 @@ def crypt_salt_is_valid(salt): if '$' not in salt[1:]: return False else: - hashed = crypt.crypt("", salt) + try: + hashed = crypt.crypt("", salt) + except OSError: + return False if not hashed or '$' not in hashed[1:]: return False else: diff --git a/cas_server/views.py b/cas_server/views.py index a1f2873..bbf5490 100644 --- a/cas_server/views.py +++ b/cas_server/views.py @@ -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) diff --git a/requirements.txt b/requirements.txt index 22b409b..ced9200 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 diff --git a/setup.py b/setup.py index 38cfb70..417892e 100644 --- a/setup.py +++ b/setup.py @@ -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", diff --git a/tox.ini b/tox.ini index c398c06..265b4ef 100644 --- a/tox.ini +++ b/tox.ini @@ -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}