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 - pip install tox setuptools
flake8: flake8:
image: "python:2.7" image: "python:3.9"
cache: cache:
key: flake8 key: flake8
paths: paths:
@ -11,7 +11,7 @@ flake8:
- tox -e flake8 - tox -e flake8
check_rst: check_rst:
image: "python:2.7" image: "python:3.9"
cache: cache:
key: check_rst key: check_rst
paths: paths:
@ -19,107 +19,98 @@ check_rst:
script: script:
- tox -e check_rst - tox -e check_rst
py27-django17: py27-django111:
image: "python:2.7" image: "python:2.7"
cache: cache:
key: py27-django17 key: py27-django111
paths: paths:
- .tox/py27-django17 - .tox/py27-django111
script: script:
- tox -e py27-django17 - tox -e py27-django111
py27-django18: py35-django111:
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:
image: "python:3.5" image: "python:3.5"
cache: cache:
key: py35-django18 key: py35-django111
paths: paths:
- .tox/py35-django18 - .tox/py35-django111
script: script:
- tox -e py35-django18 - tox -e py35-django111
py35-django19: py36-django111:
image: "python:3.5" image: "python:3.6"
cache: cache:
key: py35-django19 key: py36-django111
paths: paths:
- .tox/py35-django19 - .tox/py36-django111
script: script:
- tox -e py35-django19 - tox -e py36-django111
py35-django110: py37-django22:
image: "python:3.5" image: "python:3.7"
cache: cache:
key: py35-django110 key: py37-django22
paths: paths:
- .tox/py35-django110 - .tox/py37-django22
script: 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: coverage:
image: "python:2.7" image: "python:3.9"
cache: cache:
key: coverage key: coverage
paths: paths:

View file

@ -1,39 +1,63 @@
language: python language: python
matrix: matrix:
include: include:
- python: "3.8" # generic checks
- python: "3.9"
env: TOX_ENV=flake8 env: TOX_ENV=flake8
- python: "3.8" - python: "3.9"
env: TOX_ENV=check_rst env: TOX_ENV=check_rst
- python: "2.7" - python: "3.9"
env: TOX_ENV=py27-django111 env: TOX_ENV=coverage
# Debian strech support
- python: "3.5" - python: "3.5"
env: TOX_ENV=py35-django111 env: TOX_ENV=py35-django111
- python: "3.5"
env: TOX_ENV=py35-django111
arch: ppc64le
# Ubuntu bionic and EPEL 7 support
- python: "3.6" - python: "3.6"
env: TOX_ENV=py36-django111 env: TOX_ENV=py36-django111
- python: "3.5"
env: TOX_ENV=py35-django20
- python: "3.6" - python: "3.6"
env: TOX_ENV=py36-django20 env: TOX_ENV=py36-django111
- python: "3.5" arch: ppc64le
env: TOX_ENV=py35-django21 # RHEL 8 support
- python: "3.6" - 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" - 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" - python: "3.8"
env: TOX_ENV=py38-django22 env: TOX_ENV=py38-django22
- python: "3.8" - python: "3.8"
env: TOX_ENV=py38-django30 env: TOX_ENV=py38-django22
- python: "3.8" arch: ppc64le
env: TOX_ENV=coverage # 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: cache:
directories: directories:
- $HOME/.cache/pip/http/ - $HOME/.cache/pip/http/
- $HOME/build/nitmir/django-cas-server/.tox/$TOX_ENV/ - $HOME/build/nitmir/django-cas-server/.tox/$TOX_ENV/
install: install:
- "travis_retry pip install setuptools --upgrade" - travis_retry pip install setuptools --upgrade
- "pip install tox" - pip install tox $PKGS
- pip freeze
script: script:
- tox -e $TOX_ENV - tox -e $TOX_ENV
after_script: after_script:

View file

@ -6,6 +6,34 @@ All notable changes to this project will be documented in this file.
.. contents:: Table of Contents .. contents:: Table of Contents
:depth: 2 :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 v1.2.0 - 2020-07-05
=================== ===================

View file

@ -1,15 +1,15 @@
.PHONY: build dist docs .PHONY: build dist docs
VERSION=`python setup.py -V` VERSION=`python3 setup.py -V`
build: build:
python setup.py build python3 setup.py build
install: dist install: dist
pip -V pip3 -V
pip install --no-cache-dir --no-deps --upgrade --force-reinstall --find-links ./dist/django-cas-server-${VERSION}.tar.gz django-cas-server pip3 install --no-cache-dir --no-deps --upgrade --force-reinstall --find-links ./dist/django-cas-server-${VERSION}.tar.gz django-cas-server
uninstall: uninstall:
pip uninstall django-cas-server || true pip3 uninstall django-cas-server || true
clean_pyc: clean_pyc:
find ./ -name '*.pyc' -delete 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 clean_all: clean clean_tox clean_test_venv clean_docs clean_eggs
dist: dist:
python setup.py sdist python3 setup.py sdist
test_venv/bin/python: test_venv/bin/python:
python3 -m venv test_venv 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 test_venv/cas/manage.py: test_venv
mkdir -p test_venv/cas mkdir -p test_venv/cas
@ -61,7 +61,7 @@ run_server: test_project
test_venv/bin/python test_venv/cas/manage.py runserver test_venv/bin/python test_venv/cas/manage.py runserver
run_tests: test_venv 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 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 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" bash -c "source test_venv/bin/activate; cd docs; make html"
publish_pypi_release: 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 rename/rewrite attributes per service
* Possibility to require some attribute values per service * Possibility to require some attribute values per service
* Federated mode between multiple CAS * Federated mode between multiple CAS
* Supports Django 1.11, 2.2 and 3.0 * Supports Django 1.11, 2.2, 3.1 and 3.2
* Supports Python 2.7, 3.5+ * Supports Python 3.5+
Dependencies Dependencies
============ ============
``django-cas-server`` depends on the following python packages: ``django-cas-server`` depends on the following python packages:
* Django >= 1.11 < 3.1 * Django >= 1.11 < 3.3
* requests >= 2.4 * requests >= 2.4
* requests_futures >= 0.9.5 * requests_futures >= 0.9.5
* lxml >= 3.4 * lxml >= 3.4
@ -136,13 +136,13 @@ Quick start
) )
For internationalization support, add "django.middleware.locale.LocaleMiddleware" 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', 'django.middleware.locale.LocaleMiddleware',
... ...
) ]
2. Include the cas_server URLconf in your project urls.py like this:: 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 The hashed password in the database is compared to the hexadecimal digest of the clear
password hashed with the corresponding algorithm. password hashed with the corresponding algorithm.
* ``"plain"``, the password in the database must be in clear. * ``"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`` 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 are ignored, and it is the ldap server that performs the password check.
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.
The default is ``"ldap"``. 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 * ``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"``. 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 .. |travis| image:: https://badges.genua.fr/travis/com/nitmir/django-cas-server/master.svg
:target: https://travis-ci.org/nitmir/django-cas-server :target: https://travis-ci.com/nitmir/django-cas-server
.. |pypi_version| image:: https://badges.genua.fr/pypi/v/django-cas-server.svg .. |pypi_version| image:: https://badges.genua.fr/pypi/v/django-cas-server.svg
:target: https://pypi.org/project/django-cas-server/ :target: https://pypi.org/project/django-cas-server/

View file

@ -11,7 +11,7 @@
"""A django CAS server application""" """A django CAS server application"""
#: version of the application #: version of the application
VERSION = '1.2.0' VERSION = '1.3.0'
#: path the the application configuration class #: path the the application configuration class
default_app_config = 'cas_server.apps.CasAppConfig' 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 or :class:`list` of :func:`unicode`. If the user do not exists, the returned
:class:`dict` is empty. :class:`dict` is empty.
:rtype: dict :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": 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: else:
return super(LdapAuthUser, self).attributs() return super(LdapAuthUser, self).attributs()

View file

@ -165,10 +165,17 @@ CAS_LDAP_USERNAME_ATTR = "uid"
CAS_LDAP_PASSWORD_ATTR = "userPassword" CAS_LDAP_PASSWORD_ATTR = "userPassword"
#: The method used to check the user password. Must be one of ``"crypt"``, ``"ldap"``, #: 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_md5"``, ``"hex_sha1"``, ``"hex_sha224"``, ``"hex_sha256"``, ``"hex_sha384"``,
#: ``"hex_sha512"``, ``"plain"``. #: ``"hex_sha512"``, ``"plain"``, ``"bind"``.
CAS_LDAP_PASSWORD_CHECK = "ldap" CAS_LDAP_PASSWORD_CHECK = "ldap"
#: charset the LDAP users passwords was hash with #: charset the LDAP users passwords was hash with
CAS_LDAP_PASSWORD_CHARSET = "utf-8" 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. #: Username of the test user.

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: cas_server\n" "Project-Id-Version: cas_server\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-18 11:29+0200\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" "Last-Translator: Valentin Samir <valentin.samir@crans.org>\n"
"Language-Team: django <LL@li.org>\n" "Language-Team: django <LL@li.org>\n"
"Language: fr\n" "Language: fr\n"
@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\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 #: apps.py:25 templates/cas_server/base.html:7
#: templates/cas_server/base.html:26 #: templates/cas_server/base.html:26
@ -36,7 +36,7 @@ msgstr ""
#: forms.py:85 #: forms.py:85
msgid "Identity provider" msgid "Identity provider"
msgstr "fournisseur d'identité" msgstr "Fournisseur d'identité"
#: forms.py:89 forms.py:111 #: forms.py:89 forms.py:111
msgid "Warn me before logging me into other sites." msgid "Warn me before logging me into other sites."
@ -112,7 +112,7 @@ msgstr "Version du protocole CAS"
msgid "" msgid ""
"Version of the CAS protocol to use when sending requests the the backend CAS." "Version of the CAS protocol to use when sending requests the the backend CAS."
msgstr "" 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é." "du fournisseur d'identité."
#: models.py:106 #: models.py:106
@ -158,7 +158,7 @@ msgstr "Motifs de services"
#: models.py:447 #: models.py:447
msgid "service patterns are sorted using the position attribute" 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 #: models.py:455 models.py:620
msgid "name" msgid "name"
@ -179,7 +179,7 @@ msgid ""
"character must be escaped with a '\\'." "character must be escaped with a '\\'."
msgstr "" msgstr ""
"Une expression rationnelle reconnaissant un service. Devrait généralement " "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 " "expression rationnelle, les caractères spéciaux doivent être échappés avec "
"un '\\'." "un '\\'."
@ -200,7 +200,7 @@ msgstr "limiter les noms d'utilisateurs"
#: models.py:484 #: models.py:484
msgid "Limit username allowed to connect to the list provided bellow" msgid "Limit username allowed to connect to the list provided bellow"
msgstr "" 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" "ci-dessous"
#: models.py:489 #: models.py:489
@ -376,7 +376,7 @@ msgstr ""
#: views.py:500 #: views.py:500
msgid "Invalid login ticket, please try to log in again" 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 #: views.py:692
#, python-format #, python-format

View file

@ -180,7 +180,7 @@ class FederatedUser(JsonAttributes):
#: The last ticket used to authenticate :attr:`username` against :attr:`provider` #: The last ticket used to authenticate :attr:`username` against :attr:`provider`
ticket = models.CharField(max_length=255) ticket = models.CharField(max_length=255)
#: Last update timespampt. Usually, the last time :attr:`ticket` has been set. #: 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): def __str__(self):
return self.federated_username 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 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')) 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 from django.contrib import admin
urlpatterns = [ urlpatterns = [
url(r'^admin/', admin.site.urls), re_path(r'^admin/', admin.site.urls),
url(r'^', include('cas_server.urls', namespace='cas_server')), re_path(r'^', include('cas_server.urls', namespace='cas_server')),
] ]

View file

@ -10,7 +10,13 @@
# #
# (c) 2015-2016 Valentin Samir # (c) 2015-2016 Valentin Samir
"""urls for the app""" """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.generic import RedirectView
from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables
@ -19,42 +25,42 @@ from cas_server import views
app_name = "cas_server" app_name = "cas_server"
urlpatterns = [ urlpatterns = [
url( re_path(
r'^$', r'^$',
RedirectView.as_view(pattern_name="cas_server:login", permanent=False, query_string=True) RedirectView.as_view(pattern_name="cas_server:login", permanent=False, query_string=True)
), ),
url( re_path(
'^login$', '^login$',
sensitive_post_parameters('password')( sensitive_post_parameters('password')(
views.LoginView.as_view() views.LoginView.as_view()
), ),
name='login' name='login'
), ),
url('^logout$', views.LogoutView.as_view(), name='logout'), re_path('^logout$', views.LogoutView.as_view(), name='logout'),
url('^validate$', views.Validate.as_view(), name='validate'), re_path('^validate$', views.Validate.as_view(), name='validate'),
url( re_path(
'^serviceValidate$', '^serviceValidate$',
views.ValidateService.as_view(allow_proxy_ticket=False), views.ValidateService.as_view(allow_proxy_ticket=False),
name='serviceValidate' name='serviceValidate'
), ),
url( re_path(
'^proxyValidate$', '^proxyValidate$',
views.ValidateService.as_view(allow_proxy_ticket=True), views.ValidateService.as_view(allow_proxy_ticket=True),
name='proxyValidate' name='proxyValidate'
), ),
url('^proxy$', views.Proxy.as_view(), name='proxy'), re_path('^proxy$', views.Proxy.as_view(), name='proxy'),
url( re_path(
'^p3/serviceValidate$', '^p3/serviceValidate$',
views.ValidateService.as_view(allow_proxy_ticket=False), views.ValidateService.as_view(allow_proxy_ticket=False),
name='p3_serviceValidate' name='p3_serviceValidate'
), ),
url( re_path(
'^p3/proxyValidate$', '^p3/proxyValidate$',
views.ValidateService.as_view(allow_proxy_ticket=True), views.ValidateService.as_view(allow_proxy_ticket=True),
name='p3_proxyValidate' name='p3_proxyValidate'
), ),
url('^samlValidate$', views.SamlValidate.as_view(), name='samlValidate'), re_path('^samlValidate$', views.SamlValidate.as_view(), name='samlValidate'),
url( re_path(
'^auth$', '^auth$',
sensitive_variables('password', 'secret')( sensitive_variables('password', 'secret')(
sensitive_post_parameters('password', 'secret')( sensitive_post_parameters('password', 'secret')(
@ -63,5 +69,6 @@ urlpatterns = [
), ),
name='auth' 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:]: if '$' not in salt[1:]:
return False return False
else: else:
hashed = crypt.crypt("", salt) try:
hashed = crypt.crypt("", salt)
except OSError:
return False
if not hashed or '$' not in hashed[1:]: if not hashed or '$' not in hashed[1:]:
return False return False
else: else:

View file

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

View file

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

View file

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

262
tox.ini
View file

@ -3,15 +3,14 @@ envlist=
flake8, flake8,
check_rst, check_rst,
py27-django111, py27-django111,
py35-django111, py3-django111,
py36-django111, py3-django22,
py37-django111, py3-django31,
py36-django22, py3-django32,
py37-django22,
py38-django22, ##################
py36-django30, # generic config #
py37-django30, ##################
py38-django30,
[flake8] [flake8]
max-line-length=100 max-line-length=100
@ -37,132 +36,9 @@ commands=
{[post_cmd]commands} {[post_cmd]commands}
whitelist_externals={[post_cmd]whitelist_externals} whitelist_externals={[post_cmd]whitelist_externals}
[testenv:py27-django17] ###################
basepython=python2.7 # genercic checks #
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}
[testenv:flake8] [testenv:flake8]
basepython=python3 basepython=python3
@ -201,3 +77,119 @@ commands=
{toxinidir}/.update_coverage "{toxinidir}" "django-cas-server" {toxinidir}/.update_coverage "{toxinidir}" "django-cas-server"
{[post_cmd]commands} {[post_cmd]commands}
whitelist_externals={[post_cmd]whitelist_externals} 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}