commit
902dd103f1
19 changed files with 737 additions and 134 deletions
420
CHANGELOG.rst
Normal file
420
CHANGELOG.rst
Normal file
|
@ -0,0 +1,420 @@
|
|||
Change Log
|
||||
##########
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:depth: 2
|
||||
|
||||
v0.7.0 - 2016-08-24
|
||||
===================
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add a CHANGELOG.rst file.
|
||||
* Add a validator to models CharField that should be regular expressions checking that user input
|
||||
are valids regular expressions.
|
||||
* Add a CAS_INFO_MESSAGES and CAS_INFO_MESSAGES_ORDER settings allowing to display messages in
|
||||
info-boxes on the html pages of the default templates.
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Allow the user defined CAS_COMPONENT_URLS to omit not changed values.
|
||||
* replace code-block without language indication by literal blocks.
|
||||
* Update french translation
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Some README.rst typos.
|
||||
* some english typos
|
||||
|
||||
|
||||
v0.6.4 - 2016-08-14
|
||||
===================
|
||||
|
||||
commit: 282e3a831b3c0b0818881c2f16d056850d572b89
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add a forgotten migration (only change help_text)
|
||||
|
||||
|
||||
v0.6.3 - 2016-08-14
|
||||
===================
|
||||
|
||||
commit: 07a537b403c5c5e39a4ddd084f90e3a4de88a54e
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add powered by footer
|
||||
* Add a github version badge
|
||||
* documents templatetags
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Usage of the documented API for models _meta in auth.DjangoAuthUser
|
||||
* set warn cookie using javascript if possible
|
||||
* Unfold many to many attributes in auth.DjangoAuthUser attributes
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* typos in README.rst
|
||||
* w3c validation
|
||||
|
||||
Cleaned
|
||||
-------
|
||||
* Code factorisation (models.py, views.py)
|
||||
|
||||
|
||||
v0.6.2 - 2016-08-02
|
||||
===================
|
||||
|
||||
commit: 773707e6c3c3fa20f697c946e31cafc591e8fee8
|
||||
|
||||
Added
|
||||
-----
|
||||
* Support authentication renewal in federate mode
|
||||
* Add new version email and info box then new version is available
|
||||
* Add SqlAuthUser and LdapAuthUser auth classes.
|
||||
Deprecate the usage of MysqlAuthUser in favor of SqlAuthUser.
|
||||
* Add pytest-warning to tests
|
||||
* Add a checkbox to forget the identity provider if we checked "remember the identity provider"
|
||||
* Add dependancies correspondance between python pypi, debian and centos packages in README
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Move coverage computation last in travis
|
||||
* Enable logging to stderr then running tests
|
||||
* Remember "warn me before…" using a cookie
|
||||
* Put favicon (shortcut icon) URL in settings
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
* The auth class MysqlAuthUser is deprecated in favor of the SqlAuthUser class.
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Use custom templatetags instead settings custom attributes to Boundfields
|
||||
(As it do not work with django 1.7)
|
||||
* Display an error message on bad response from identity provider in federate mode
|
||||
instead of crashing. (e.g. Bad XML document)
|
||||
* Catch base64 decode error on b64decode to raise our custom exception BadHash
|
||||
* Add secret as sensitive variables/post parameter for /auth
|
||||
* Only set "remember my provider" in federated mode upon successful authentication
|
||||
* Since we drop django-boostrap3 dependancies, Django default minimal version is 1.7.1
|
||||
* [cas.py] Append renew=true when validating tickets
|
||||
|
||||
Cleaned
|
||||
-------
|
||||
* code factorization (cas.py, forms.py)
|
||||
|
||||
|
||||
v0.6.1 - 2016-07-27
|
||||
===================
|
||||
|
||||
commit: b168e0a6423c53de31aae6c444fa1d1c5083afa6
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add sphinx docs + autodoc
|
||||
* Add the possibility to run tests with "setup.py test"
|
||||
* Include docs, Makefile, coverage config and tests config to source package
|
||||
* Add serviceValidate ProxyTicket tests
|
||||
* Add python 3.5 tox/travis tests
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Use https://badges.genua.fr for badges
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Keep LoginTicket list upon fail authentication
|
||||
(It prevent the next login attemps to fail because of bad LT)
|
||||
|
||||
Cleaned
|
||||
-------
|
||||
* Compact federated mode migration
|
||||
* Reformat default_settings.py for documentation using sphinx autodoc
|
||||
* Factorize some code (from views.py to Ticket models class methods)
|
||||
* Update urlpattern for django 1.10
|
||||
* Drop dependancies django-picklefield and django-bootstrap3
|
||||
|
||||
|
||||
v0.6.0 - 2016-07-06
|
||||
===================
|
||||
|
||||
commit: 4ad4d13baa4236c5cd72cc5216d7ff08dd361476
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add a section describing service patterns options to README.rst
|
||||
* Add a federation mode:
|
||||
When the settings CAS_FEDERATE is True, django-cas-server will offer to the user to choose its
|
||||
CAS backend to authenticate. Hence the login page do not display anymore a username/password form
|
||||
but a select form with configured CASs backend.
|
||||
This allow to give access to CAS supported applications to users from multiple organization
|
||||
seamlessly.
|
||||
|
||||
It was originally developped to mach the need of https://ares.fr (Federated CAS at
|
||||
https://cas.ares.fr, example of an application using it as https://chat.myares.fr)
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Then a ticket was marked as obtained with the user entering its credentials (aka not by SSO), and
|
||||
the service did not require it, ticket validation was failing. Now, if the service do not require
|
||||
authentication to be renewed, both ticket with renewed authentication and non renewed
|
||||
authentication validate successfully.
|
||||
|
||||
|
||||
|
||||
v0.5.0 - 2016-07-01
|
||||
===================
|
||||
|
||||
commit: e3ab64271b718a17e4cbbbabda0a2453107a83df
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add more password scheme support to the mysql authentication backend: ldap user
|
||||
attribute scheme encoding and simple password hash in hexa for md5, sha1, sha224,
|
||||
sha256, sha384, sha512.
|
||||
* Add a main heading to template "Central Authentication Service" with a logo controled
|
||||
by CAS_LOGO_URL
|
||||
* Add logos to the project (svg, png)
|
||||
* Add coverage computation
|
||||
* link project to codacy
|
||||
* Update doc: add debian requirement, correct typos, correct links
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Use settings to set tests username password and attributes
|
||||
* Tweak the css and html for small screens
|
||||
* Update travis cache for faster build
|
||||
* clean Makefile, use pip to install, add target for tests
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Fix "warn me": we generate the ticket after the user agree to be connected to the service.
|
||||
we were generating first and the connect button was a link to the service url with the ?ticket=
|
||||
this could lead to situation where the ticket validity expire if the user is slow to click the
|
||||
connect button.
|
||||
* Fix authentication renewal: the renew parameter were not transmited when POST the login request
|
||||
and self.renew (aks for auth renewal) was use instead of self.renewed (auth was renewd)
|
||||
when generating a ticket.
|
||||
* Fix attribute value replacement when generating a ticket: we were using the 'name' attribute
|
||||
instead of the 'attribut' attribut on ReplaceAttributValue
|
||||
* Fix attribute value replacement when generating a ticket then the value is a list: iterate over
|
||||
each element of the list.
|
||||
* Fix a NameError in utils.import_attr
|
||||
* Fix serviceValidate and samlValidate when user_field is an attribute that is a list: we use
|
||||
the first element of the list as username. we were serializing the list before that.
|
||||
* Correct typos
|
||||
|
||||
|
||||
Cleaned
|
||||
-------
|
||||
* Clean some useless conditional branches found with coverage
|
||||
* Clean cas.js: use compact object declararion
|
||||
* Use six for python{2|3} compatibility
|
||||
* Move all unit tests to cas_server.tests and use django primitive. We also have a 100% tests
|
||||
coverage now. Using the django classes for tests, we do not need to use our own dirty mock.
|
||||
* Move mysql backend password check to a function in utils
|
||||
|
||||
|
||||
v0.4.4 - 2016-04-30
|
||||
===================
|
||||
|
||||
commit: 77d1607b0beefe8b171adcd8e2dcd974e3cdc72a
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add sensitive_post_parameters and sensitive_variables for passwords, so passwords are anonymised
|
||||
before django send an error report.
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Before commit 77fc5b5 the User model had a foreign key to the Session model. After the commit,
|
||||
Only the session_key is store, allowing to use different backend than the Session SQL backend.
|
||||
So the first migration (which is 21 migrations combined) was creating the User model with the
|
||||
foreign key, then delete it and add the field session_key. Somehow, MySQL did not like it.
|
||||
Now the first migration directly create the User model with the session_key and without the
|
||||
foreign key to the Session SQL backend.
|
||||
* Evaluate attributes variables in the template samlValidate.xml. the {{ }} was missing causing
|
||||
the variable name to be displyed instead of the variable content.
|
||||
* Return username in CAS 1.0 on the second ligne of the CAS response as specified.
|
||||
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Update tests
|
||||
|
||||
|
||||
v0.4.3 - 2016-03-18
|
||||
===================
|
||||
|
||||
commit: f6d436acb49f8d32b5457c316c18c4892accfd3b
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Currently, one of our dependancy, django-boostrap3, do not support django 1.7 in its last version.
|
||||
So there is some detection of the current django installed version in setup.py to pin
|
||||
django-boostrap3 to a version supported by django 1.7 if django 1.7 is installed, or to require
|
||||
at least django 1.8.
|
||||
The detection did not handle the case where django was not installed.
|
||||
* [PEP8] Put line breaks after binary operator and not before.
|
||||
|
||||
|
||||
v0.4.2 - 2016-03-18
|
||||
===================
|
||||
|
||||
commit: d1cd17d6103281b03a8c57013671057eab80d21c
|
||||
|
||||
Added
|
||||
-----
|
||||
* On logout, display the number of sessions we are logged out from.
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* One of our dependancy, django-boostrap3, do not support django 1.7 in its last version.
|
||||
Some django version detection is added to setup.py to handle that.
|
||||
* Some typos
|
||||
* Make errors returned by utils.import_attr clearer (as they are likely to be displayed to the
|
||||
django admin)
|
||||
|
||||
|
||||
v0.4.1 - 2015-12-23
|
||||
===================
|
||||
|
||||
commit: 5e63f39f9b7c678a300ad2f8132166be34d1d35b
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add a run_test_server target to make file. Running make run_test_server will build a virtualenv,
|
||||
create a django projet with django-cas-server and lauch ./management.py runserver. It is quite
|
||||
handy to test developement version.
|
||||
* Add verbose name for cas_server app and models
|
||||
* Add Makefile clean targets for tox tests and test virtualenv.
|
||||
* Add link on license badge to the GPLv3
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Make Makefile clean targets modular
|
||||
* Use img.shields.io for PyPi badges
|
||||
* Get django-cas-server version in Makefile directly from setup.py (so now, the version is only
|
||||
written in one place)
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Fix MysqlAuthUser when number of results != 1: In that case, call super anyway this the provided
|
||||
username.
|
||||
|
||||
|
||||
v0.4.0 - 2015-12-15
|
||||
===================
|
||||
|
||||
commit: 7b4fac575449e50c2caff07f5798dba7f4e4857c
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add a help_text to pattern of ServicePattern
|
||||
* Add a timeout to SLO requests
|
||||
* Add logging capabilities (see README.rst for instruction)
|
||||
* Add management commands that should be called on a regular basis to README.rst
|
||||
|
||||
|
||||
v0.3.5 - 2015-12-12
|
||||
===================
|
||||
|
||||
commit: 51fa0861f550723171e52d58025fa789dccb8cde
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add badges to README.rst
|
||||
* Document settings parameter in README.rst
|
||||
* Add a "Features" section in README.rst
|
||||
|
||||
Changed
|
||||
-------
|
||||
* Add a AuthUser auth class and use it as auth classes base class instead of DummyAuthUser
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Fix minor errors and typos in README.rst
|
||||
|
||||
|
||||
|
||||
v0.3.4 - 2015-12-12
|
||||
===================
|
||||
|
||||
commit: 9fbfe19c550b147e8d0377108cdac8231cf0fb27
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add static files, templates and locales to the PyPi release by adding them to MANIFEST.in
|
||||
* Add a Makefile with the build/install/clean/dist targets
|
||||
|
||||
|
||||
v0.3.3 - 2015-12-12
|
||||
===================
|
||||
|
||||
commit: 16b700d0127abe33a1eabf5d5fe890aeb5167e5a
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add management commands and migrations to the package by adding there packages to setup.py
|
||||
packages list.
|
||||
|
||||
|
||||
v0.3.2 - 2015-12-12 [YANKED]
|
||||
============================
|
||||
|
||||
commit: eef9490885bf665a53349573ddb9cbe844319b3e
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add migrations to setup.py package_data
|
||||
|
||||
|
||||
v0.3.1 - 2015-12-12
|
||||
===================
|
||||
|
||||
commit: d0f6ed9ea3a4b3e2bf715fd218c460892c32e39f
|
||||
|
||||
Added
|
||||
-----
|
||||
* Add a forgotten migration (remove auto_now_add=True from the User model)
|
||||
|
||||
|
||||
v0.3.0 - 2015-12-12
|
||||
===================
|
||||
|
||||
commit: b69769d71a99806a69e300eca0d7c6744a2b327e
|
||||
|
||||
Added
|
||||
-----
|
||||
* Django 1.9 compatibility (add tox and travis tests and fix some decrecated)
|
||||
|
||||
|
||||
v0.2.1 - 2015-12-12
|
||||
===================
|
||||
|
||||
commit: 90e077dedb991d651822e9bb283470de8bddd7dd
|
||||
|
||||
First github and PyPi release
|
||||
|
||||
Fixed
|
||||
-----
|
||||
* Prune .tox in MANIFEST.in
|
||||
* add dist/ to .gitignore
|
||||
* typo in setup.cfg
|
||||
|
||||
|
||||
v0.2.0 - 2015-12-12 [YANKED]
|
||||
============================
|
||||
|
||||
commit: a071ad46d7cd76fc97eb86f2f538d330457c6767
|
||||
|
||||
|
||||
v0.1.0 - 2015-05-22 [YANKED]
|
||||
============================
|
||||
|
||||
commit: 6981433bdf8a406992ba0c5e844a47d06ccc08fb
|
|
@ -1,6 +1,7 @@
|
|||
include tox.ini
|
||||
include LICENSE
|
||||
include README.rst
|
||||
include CHANGELOG.rst
|
||||
include .coveragerc
|
||||
include Makefile
|
||||
include pytest.ini
|
||||
|
@ -15,6 +16,7 @@ include docs/conf.py
|
|||
include docs/index.rst
|
||||
include docs/Makefile
|
||||
include docs/README.rst
|
||||
include docs/CHANGELOG.rst
|
||||
recursive-include docs/_ext *
|
||||
recursive-include docs/package *
|
||||
recursive-include docs/_static *
|
||||
|
|
62
README.rst
62
README.rst
|
@ -7,7 +7,7 @@ CAS Server is a Django application implementing the `CAS Protocol 3.0 Specificat
|
|||
<https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html>`_.
|
||||
|
||||
By default, the authentication process use django internal users but you can easily
|
||||
use any sources (see auth classes in the auth.py file)
|
||||
use any sources (see the `Authentication backend`_ section and auth classes in the auth.py file)
|
||||
|
||||
.. contents:: Table of Contents
|
||||
|
||||
|
@ -38,7 +38,7 @@ Dependencies
|
|||
Minimal version of packages dependancy are just indicative and meens that ``django-cas-server`` has
|
||||
been tested with it. Previous versions of dependencies may or may not work.
|
||||
|
||||
Additionally, denpending of the authentication backend you plan to use, you may need the following
|
||||
Additionally, denpending of the `Authentication backend`_ you plan to use, you may need the following
|
||||
python packages:
|
||||
|
||||
* ldap3
|
||||
|
@ -174,13 +174,11 @@ Quick start
|
|||
inactive since more than ``SESSION_COOKIE_AGE``. The default value for is ``1209600``
|
||||
seconds (2 weeks). You probably should reduce it to something like ``86400`` seconds (1 day).
|
||||
|
||||
You could for example do as bellow :
|
||||
You could for example do as bellow::
|
||||
|
||||
.. code-block::
|
||||
|
||||
0 0 * * * cas-user /path/to/project/manage.py clearsessions
|
||||
*/5 * * * * cas-user /path/to/project/manage.py cas_clean_tickets
|
||||
5 0 * * * cas-user /path/to/project/manage.py cas_clean_sessions
|
||||
0 0 * * * cas-user /path/to/project/manage.py clearsessions
|
||||
*/5 * * * * cas-user /path/to/project/manage.py cas_clean_tickets
|
||||
5 0 * * * cas-user /path/to/project/manage.py cas_clean_sessions
|
||||
|
||||
5. Run ``python manage.py createsuperuser`` to create an administrator user.
|
||||
|
||||
|
@ -208,7 +206,7 @@ Template settings
|
|||
Default is a key icon. Set it to ``False`` to disable it.
|
||||
* ``CAS_SHOW_POWERED``: Set it to ``False`` to hide the powered by footer. The default is ``True``.
|
||||
* ``CAS_COMPONENT_URLS``: URLs to css and javascript external components. It is a dictionnary
|
||||
and it must have the five following keys: ``"bootstrap3_css"``, ``"bootstrap3_js"``,
|
||||
having the five following keys: ``"bootstrap3_css"``, ``"bootstrap3_js"``,
|
||||
``"html5shiv"``, ``"respond"``, ``"jquery"``. The default is::
|
||||
|
||||
{
|
||||
|
@ -219,6 +217,32 @@ Template settings
|
|||
"jquery": "//code.jquery.com/jquery.min.js",
|
||||
}
|
||||
|
||||
if you omit some keys of the dictionnary, the default value for these keys is used.
|
||||
|
||||
* ``CAS_INFO_MESSAGES``: Messages displayed in info-boxes on the html pages of the default templates.
|
||||
It is a dictionnary mapping message name to a message dict. A message dict has 3 keys:
|
||||
|
||||
* ``message``: A unicode message to display, potentially wrapped around ugettex_lazy
|
||||
* ``discardable``: A boolean, specify if the users can close the message info-box
|
||||
* ``type``: One of info, success, info, warning, danger. The type of the info-box.
|
||||
|
||||
``CAS_INFO_MESSAGES`` contains by default one message, ``cas_explained``, which explain
|
||||
roughly the purpose of a CAS. The default is::
|
||||
|
||||
{
|
||||
"cas_explained": {
|
||||
"message":_(
|
||||
u"The Central Authentication Service grants you access to most of our websites by "
|
||||
u"authenticating only once, so you don't need to type your credentials again unless "
|
||||
u"your session expires or you logout."
|
||||
),
|
||||
"discardable": True,
|
||||
"type": "info", # one of info, success, info, warning, danger
|
||||
},
|
||||
}
|
||||
|
||||
* ``CAS_INFO_MESSAGES_ORDER``: A list of message names. Order in which info-box messages are
|
||||
displayed. Use an empty list to disable messages display. The default is ``[]``.
|
||||
* ``CAS_LOGIN_TEMPLATE``: Path to the template showed on ``/login`` then the user
|
||||
is not autenticated. The default is ``"cas_server/login.html"``.
|
||||
* ``CAS_WARN_TEMPLATE``: Path to the template showed on ``/login?service=...`` then
|
||||
|
@ -228,7 +252,7 @@ Template settings
|
|||
authenticated. The default is ``"cas_server/logged.html"``.
|
||||
* ``CAS_LOGOUT_TEMPLATE``: Path to the template showed on ``/logout`` then to user
|
||||
is being disconnected. The default is ``"cas_server/logout.html"``
|
||||
* ``CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT``: Should we redirect users to `/login` after they
|
||||
* ``CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT``: Should we redirect users to ``/login`` after they
|
||||
logged out instead of displaying ``CAS_LOGOUT_TEMPLATE``. The default is ``False``.
|
||||
|
||||
|
||||
|
@ -271,7 +295,7 @@ New version warnings settings
|
|||
* ``CAS_NEW_VERSION_HTML_WARNING``: A boolean for diplaying a warning on html pages then a new
|
||||
version of the application is avaible. Once closed by a user, it is not displayed to this user
|
||||
until the next new version. The default is ``True``.
|
||||
* ``CAS_NEW_VERSION_EMAIL_WARNING``: A bolean sot sending a email to ``settings.ADMINS`` when a new
|
||||
* ``CAS_NEW_VERSION_EMAIL_WARNING``: A boolean for sending a email to ``settings.ADMINS`` when a new
|
||||
version is available. The default is ``True``.
|
||||
|
||||
|
||||
|
@ -545,10 +569,10 @@ A service pattern has 4 associated models:
|
|||
an email address to connect to it. To do so, put ``email`` in ``Attribute`` and ``.*`` in ``pattern``.
|
||||
|
||||
Then a user ask a ticket for a service, the service URL is compare against each service patterns
|
||||
sorted by `position`. The first service pattern that matches the service URL is chosen.
|
||||
Hence, you should give low `position` to very specific patterns like
|
||||
``^https://www\.example\.com(/.*)?$`` and higher `position` to generic patterns like ``^https://.*``.
|
||||
So the service URL `https://www.examle.com` will use the service pattern for
|
||||
sorted by ``position``. The first service pattern that matches the service URL is chosen.
|
||||
Hence, you should give low ``position`` to very specific patterns like
|
||||
``^https://www\.example\.com(/.*)?$`` and higher ``position`` to generic patterns like ``^https://.*``.
|
||||
So the service URL ``https://www.examle.com`` will use the service pattern for
|
||||
``^https://www\.example\.com(/.*)?$`` and not the one for ``^https://.*``.
|
||||
|
||||
|
||||
|
@ -572,7 +596,7 @@ An identity provider comes with 5 fields:
|
|||
* ``Suffix``: the suffix that will be append to the username returned by the identity provider.
|
||||
It must be unique.
|
||||
* ``Server url``: the URL to the identity provider CAS. For instance, if you are using
|
||||
``https://cas.example.org/login`` to authenticate on the CAS, the `server url` is
|
||||
``https://cas.example.org/login`` to authenticate on the CAS, the ``server url`` is
|
||||
``https://cas.example.org``
|
||||
* ``CAS protocol version``: the version of the CAS protocol to use to contact the identity provider.
|
||||
The default is version 3.
|
||||
|
@ -593,11 +617,9 @@ Then using federate mode, you should add one command to a daily crontab: ``cas_c
|
|||
This command clean the local cache of federated user from old unused users.
|
||||
|
||||
|
||||
You could for example do as bellow :
|
||||
You could for example do as bellow::
|
||||
|
||||
.. code-block::
|
||||
|
||||
10 0 * * * cas-user /path/to/project/manage.py cas_clean_federate
|
||||
10 0 * * * cas-user /path/to/project/manage.py cas_clean_federate
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"""A django CAS server application"""
|
||||
|
||||
#: version of the application
|
||||
VERSION = '0.6.4'
|
||||
VERSION = '0.7.0'
|
||||
|
||||
#: path the the application configuration class
|
||||
default_app_config = 'cas_server.apps.CasAppConfig'
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"""Default values for the app's settings"""
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles.templatetags.staticfiles import static
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from importlib import import_module
|
||||
|
||||
|
@ -180,13 +181,45 @@ CAS_NEW_VERSION_EMAIL_WARNING = True
|
|||
#: You should not change it.
|
||||
CAS_NEW_VERSION_JSON_URL = "https://pypi.python.org/pypi/django-cas-server/json"
|
||||
|
||||
|
||||
#: Messages displayed in a info-box on the html pages of the default templates.
|
||||
#: ``CAS_INFO_MESSAGES`` is a :class:`dict` mapping message name to a message :class:`dict`.
|
||||
#: A message :class:`dict` has 3 keys:
|
||||
#: * ``message``: A :class:`unicode`, the message to display, potentially wrapped around
|
||||
#: ugettex_lazy
|
||||
#: * ``discardable``: A :class:`bool`, specify if the users can close the message info-box
|
||||
#: * ``type``: One of info, success, info, warning, danger. The type of the info-box.
|
||||
#: ``CAS_INFO_MESSAGES`` contains by default one message, ``cas_explained``, which explain
|
||||
#: roughly the purpose of a CAS.
|
||||
CAS_INFO_MESSAGES = {
|
||||
"cas_explained": {
|
||||
"message": _(
|
||||
u"The Central Authentication Service grants you access to most of our websites by "
|
||||
u"authenticating only once, so you don't need to type your credentials again unless "
|
||||
u"your session expires or you logout."
|
||||
),
|
||||
"discardable": True,
|
||||
"type": "info", # one of info, success, info, warning, danger
|
||||
},
|
||||
}
|
||||
#: :class:`list` of message names. Order in which info-box messages are displayed.
|
||||
#: Let the list empty to disable messages display.
|
||||
CAS_INFO_MESSAGES_ORDER = []
|
||||
|
||||
|
||||
GLOBALS = globals().copy()
|
||||
for name, default_value in GLOBALS.items():
|
||||
# get the current setting value, falling back to default_value
|
||||
value = getattr(settings, name, default_value)
|
||||
# set the setting value to its value if defined, ellse to the default_value.
|
||||
setattr(settings, name, value)
|
||||
# only care about parameter begining by CAS_
|
||||
if name.startswith("CAS_"):
|
||||
# get the current setting value, falling back to default_value
|
||||
value = getattr(settings, name, default_value)
|
||||
# set the setting value to its value if defined, ellse to the default_value.
|
||||
setattr(settings, name, value)
|
||||
|
||||
# Allow the user defined CAS_COMPONENT_URLS to omit not changed values
|
||||
MERGED_CAS_COMPONENT_URLS = CAS_COMPONENT_URLS.copy()
|
||||
MERGED_CAS_COMPONENT_URLS.update(settings.CAS_COMPONENT_URLS)
|
||||
settings.CAS_COMPONENT_URLS = MERGED_CAS_COMPONENT_URLS
|
||||
|
||||
# if the federated mode is enabled, we must use the :class`cas_server.auth.CASFederateAuth` auth
|
||||
# backend.
|
||||
|
|
Binary file not shown.
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: cas_server\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-08-01 12:01+0200\n"
|
||||
"PO-Revision-Date: 2016-08-01 12:01+0200\n"
|
||||
"POT-Creation-Date: 2016-08-24 17:18+0200\n"
|
||||
"PO-Revision-Date: 2016-08-24 17:18+0200\n"
|
||||
"Last-Translator: Valentin Samir <valentin.samir@crans.org>\n"
|
||||
"Language-Team: django <LL@li.org>\n"
|
||||
"Language: fr\n"
|
||||
|
@ -18,70 +18,81 @@ msgstr ""
|
|||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Poedit 1.8.8\n"
|
||||
|
||||
#: apps.py:25 templates/cas_server/base.html:9
|
||||
#: templates/cas_server/base.html:27
|
||||
#: apps.py:25 templates/cas_server/base.html:7
|
||||
#: templates/cas_server/base.html:26
|
||||
msgid "Central Authentication Service"
|
||||
msgstr "Service Central d'Authentification"
|
||||
|
||||
#: forms.py:88
|
||||
#: default_settings.py:197
|
||||
msgid ""
|
||||
"The Central Authentication Service grants you access to most of our websites "
|
||||
"by authenticating only once, so you don't need to type your credentials "
|
||||
"again unless your session expires or you logout."
|
||||
msgstr ""
|
||||
"Le Service Central d'Authentification permet, en vous authentifiant une "
|
||||
"seule fois, d'accéder à la plupart de nos sites sans avoir à retaper votre "
|
||||
"identifiant et votre mot de passe chaque fois que vous changez de site, "
|
||||
"jusqu'à ce que votre session expire ou que vous vous déconnectiez."
|
||||
|
||||
#: forms.py:84
|
||||
msgid "Identity provider"
|
||||
msgstr "fournisseur d'identité"
|
||||
|
||||
#: forms.py:92 forms.py:111
|
||||
#: forms.py:88 forms.py:107
|
||||
msgid "Warn me before logging me into other sites."
|
||||
msgstr "Prévenez-moi avant d'accéder à d'autres services."
|
||||
|
||||
#: forms.py:96
|
||||
#: forms.py:92
|
||||
msgid "Remember the identity provider"
|
||||
msgstr "Se souvenir du fournisseur d'identité"
|
||||
|
||||
#: forms.py:106 models.py:600
|
||||
#: forms.py:102 models.py:594
|
||||
msgid "username"
|
||||
msgstr "nom d'utilisateur"
|
||||
|
||||
#: forms.py:108
|
||||
#: forms.py:104
|
||||
msgid "password"
|
||||
msgstr "mot de passe"
|
||||
|
||||
#: forms.py:130
|
||||
#: forms.py:126
|
||||
msgid "The credentials you provided cannot be determined to be authentic."
|
||||
msgstr "Les informations transmises n'ont pas permis de vous authentifier."
|
||||
|
||||
#: forms.py:182
|
||||
#: forms.py:178
|
||||
msgid "User not found in the temporary database, please try to reconnect"
|
||||
msgstr ""
|
||||
"Utilisateur non trouvé dans la base de donnée temporaire, essayez de vous "
|
||||
"reconnecter"
|
||||
|
||||
#: forms.py:196
|
||||
#: forms.py:192
|
||||
msgid "service"
|
||||
msgstr "service"
|
||||
|
||||
#: management/commands/cas_clean_federate.py:20
|
||||
msgid "Clean old federated users"
|
||||
msgstr "Nettoyer les anciens utilisateurs fédéré"
|
||||
msgstr "Nettoyer les anciens utilisateurs fédérés"
|
||||
|
||||
#: management/commands/cas_clean_sessions.py:22
|
||||
msgid "Clean deleted sessions"
|
||||
msgstr "Nettoyer les sessions supprimées"
|
||||
|
||||
#: management/commands/cas_clean_tickets.py:22
|
||||
msgid "Clean old trickets"
|
||||
msgid "Clean old tickets"
|
||||
msgstr "Nettoyer les vieux tickets"
|
||||
|
||||
#: models.py:46
|
||||
#: models.py:71
|
||||
msgid "identity provider"
|
||||
msgstr "fournisseur d'identité"
|
||||
|
||||
#: models.py:47
|
||||
#: models.py:72
|
||||
msgid "identity providers"
|
||||
msgstr "fournisseurs d'identités"
|
||||
|
||||
#: models.py:53
|
||||
#: models.py:78
|
||||
msgid "suffix"
|
||||
msgstr "suffixe"
|
||||
|
||||
#: models.py:55
|
||||
#: models.py:80
|
||||
msgid ""
|
||||
"Suffix append to backend CAS returned username: ``returned_username`` @ "
|
||||
"``suffix``."
|
||||
|
@ -89,46 +100,46 @@ msgstr ""
|
|||
"Suffixe ajouté au nom d'utilisateur retourné par le CAS du fournisseur "
|
||||
"d'identité : `nom retourné`@`suffixe`."
|
||||
|
||||
#: models.py:62
|
||||
#: models.py:87
|
||||
msgid "server url"
|
||||
msgstr "url du serveur"
|
||||
|
||||
#: models.py:72
|
||||
#: models.py:97
|
||||
msgid "CAS protocol version"
|
||||
msgstr "Version du protocole CAS"
|
||||
|
||||
#: models.py:74
|
||||
#: models.py:99
|
||||
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 "
|
||||
"du fournisseur d'identité."
|
||||
|
||||
#: models.py:81
|
||||
#: models.py:106
|
||||
msgid "verbose name"
|
||||
msgstr "Nom du fournisseur"
|
||||
|
||||
#: models.py:82
|
||||
#: models.py:107
|
||||
msgid "Name for this identity provider displayed on the login page."
|
||||
msgstr "Nom affiché pour ce fournisseur d'identité sur la page de connexion."
|
||||
|
||||
#: models.py:88 models.py:446
|
||||
#: models.py:113 models.py:446
|
||||
msgid "position"
|
||||
msgstr "position"
|
||||
|
||||
#: models.py:102
|
||||
#: models.py:127
|
||||
msgid "display"
|
||||
msgstr "afficher"
|
||||
|
||||
#: models.py:103
|
||||
#: models.py:128
|
||||
msgid "Display the provider on the login page."
|
||||
msgstr "Afficher le fournisseur d'identité sur la page de connexion."
|
||||
|
||||
#: models.py:233
|
||||
#: models.py:245
|
||||
msgid "User"
|
||||
msgstr "Utilisateur"
|
||||
|
||||
#: models.py:234
|
||||
#: models.py:246
|
||||
msgid "Users"
|
||||
msgstr "Utilisateurs"
|
||||
|
||||
|
@ -149,7 +160,7 @@ msgstr "Motifs de services"
|
|||
msgid "service patterns are sorted using the position attribute"
|
||||
msgstr "Les motifs de service sont trié selon l'attribut position"
|
||||
|
||||
#: models.py:455 models.py:626
|
||||
#: models.py:455 models.py:620
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
|
@ -157,7 +168,7 @@ msgstr "nom"
|
|||
msgid "A name for the service"
|
||||
msgstr "Un nom pour le service"
|
||||
|
||||
#: models.py:464 models.py:669 models.py:698
|
||||
#: models.py:464 models.py:663 models.py:693
|
||||
msgid "pattern"
|
||||
msgstr "motif"
|
||||
|
||||
|
@ -172,108 +183,108 @@ msgstr ""
|
|||
"expression rationnelle, les caractères spéciaux doivent être échappés avec "
|
||||
"un '\\'."
|
||||
|
||||
#: models.py:476
|
||||
#: models.py:477
|
||||
msgid "user field"
|
||||
msgstr "champ utilisateur"
|
||||
|
||||
#: models.py:477
|
||||
#: models.py:478
|
||||
msgid "Name of the attribute to transmit as username, empty = login"
|
||||
msgstr ""
|
||||
"Nom de l'attribut devant être transmis comme nom d'utilisateur au service. "
|
||||
"vide = nom de connexion"
|
||||
|
||||
#: models.py:482
|
||||
#: models.py:483
|
||||
msgid "restrict username"
|
||||
msgstr "limiter les noms d'utilisateurs"
|
||||
|
||||
#: models.py:483
|
||||
#: 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 "
|
||||
"ci-dessous"
|
||||
|
||||
#: models.py:488
|
||||
#: models.py:489
|
||||
msgid "proxy"
|
||||
msgstr "proxy"
|
||||
|
||||
#: models.py:489
|
||||
#: models.py:490
|
||||
msgid "Proxy tickets can be delivered to the service"
|
||||
msgstr "des proxy tickets peuvent être délivrés au service"
|
||||
|
||||
#: models.py:495
|
||||
#: models.py:496
|
||||
msgid "proxy callback"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:496
|
||||
#: models.py:497
|
||||
msgid "can be used as a proxy callback to deliver PGT"
|
||||
msgstr "peut être utilisé comme un callback pour recevoir un PGT"
|
||||
|
||||
#: models.py:503
|
||||
#: models.py:504
|
||||
msgid "single log out"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:504
|
||||
#: models.py:505
|
||||
msgid "Enable SLO for the service"
|
||||
msgstr "Active le SLO pour le service"
|
||||
|
||||
#: models.py:512
|
||||
#: models.py:513
|
||||
msgid "single log out callback"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:513
|
||||
#: models.py:514
|
||||
msgid ""
|
||||
"URL where the SLO request will be POST. empty = service url\n"
|
||||
"This is usefull for non HTTP proxied services."
|
||||
msgstr ""
|
||||
"URL a laquelle la requête de déconnexion sera postée. vide = l'url du "
|
||||
"URL à laquelle la requête de déconnexion sera postée. vide = l'url du "
|
||||
"service\n"
|
||||
"Ceci n'est utilise que pour des services non HTTP proxifiés"
|
||||
"Ceci n'est en général utilisé que pour des services non HTTP proxifiés"
|
||||
|
||||
#: models.py:601
|
||||
#: models.py:595
|
||||
msgid "username allowed to connect to the service"
|
||||
msgstr "noms d'utilisateurs autorisé à se connecter au service"
|
||||
msgstr "noms d'utilisateurs autorisés à se connecter au service"
|
||||
|
||||
#: models.py:627
|
||||
#: models.py:621
|
||||
msgid "name of an attribute to send to the service, use * for all attributes"
|
||||
msgstr ""
|
||||
"nom d'un attribut a envoyer au service, utiliser * pour tous les attributs"
|
||||
"nom d'un attribut à envoyer au service, utiliser * pour tous les attributs"
|
||||
|
||||
#: models.py:634 models.py:705
|
||||
#: models.py:628 models.py:701
|
||||
msgid "replace"
|
||||
msgstr "remplacement"
|
||||
|
||||
#: models.py:635
|
||||
#: models.py:629
|
||||
msgid ""
|
||||
"name under which the attribute will be showto the service. empty = default "
|
||||
"name under which the attribute will be show to the service. empty = default "
|
||||
"name of the attribut"
|
||||
msgstr ""
|
||||
"nom sous lequel l'attribut sera rendu visible au service. vide = inchangé"
|
||||
|
||||
#: models.py:662 models.py:692
|
||||
#: models.py:656 models.py:687
|
||||
msgid "attribute"
|
||||
msgstr "attribut"
|
||||
|
||||
#: models.py:663
|
||||
#: models.py:657
|
||||
msgid "Name of the attribute which must verify pattern"
|
||||
msgstr "Nom de l'attribut devant vérifier un motif"
|
||||
|
||||
#: models.py:670
|
||||
#: models.py:664
|
||||
msgid "a regular expression"
|
||||
msgstr "une expression régulière"
|
||||
|
||||
#: models.py:693
|
||||
#: models.py:688
|
||||
msgid "Name of the attribute for which the value must be replace"
|
||||
msgstr "nom de l'attribut pour lequel la valeur doit être remplacé"
|
||||
msgstr "Nom de l'attribut pour lequel la valeur doit être remplacé"
|
||||
|
||||
#: models.py:699
|
||||
#: models.py:694
|
||||
msgid "An regular expression maching whats need to be replaced"
|
||||
msgstr "une expression régulière reconnaissant ce qui doit être remplacé"
|
||||
msgstr "Une expression régulière reconnaissant ce qui doit être remplacé"
|
||||
|
||||
#: models.py:706
|
||||
#: models.py:702
|
||||
msgid "replace expression, groups are capture by \\1, \\2 …"
|
||||
msgstr "expression de remplacement, les groupe sont capturé par \\1, \\2"
|
||||
|
||||
#: templates/cas_server/base.html:38
|
||||
#: templates/cas_server/base.html:43
|
||||
#, python-format
|
||||
msgid ""
|
||||
"A new version of the application is available. This instance runs "
|
||||
|
@ -282,7 +293,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Une nouvelle version de l'application est disponible. Cette instance utilise "
|
||||
"la version %(VERSION)s et la dernière version est %(LAST_VERSION)s. Merci de "
|
||||
"vous mettre a jour."
|
||||
"vous mettre à jour."
|
||||
|
||||
#: templates/cas_server/logged.html:4
|
||||
msgid ""
|
||||
|
@ -291,10 +302,10 @@ msgid ""
|
|||
"your web browser when you are done accessing services that require "
|
||||
"authentication!"
|
||||
msgstr ""
|
||||
"<h3>Déconnexion réussie</h3>Vous vous êtes déconnecté(e) du Service Central "
|
||||
"d'Authentification. Pour des raisons de sécurité, veuillez fermer votre "
|
||||
"navigateur après avoir fini d'accéder a des services demandant une "
|
||||
"authentification !"
|
||||
"<h3>Connexion réussie</h3>Vous vous êtes connecté(e) auprès du Service "
|
||||
"Central d'Authentification.<br/>Pour des raisons de sécurité, veuillez vous "
|
||||
"déconnecter et fermer votre navigateur après avoir fini d'accéder à des "
|
||||
"services demandant une authentification !"
|
||||
|
||||
#: templates/cas_server/logged.html:8
|
||||
msgid "Log me out from all my sessions"
|
||||
|
@ -310,7 +321,7 @@ msgstr "Se déconnecter"
|
|||
|
||||
#: templates/cas_server/login.html:6
|
||||
msgid "Please log in"
|
||||
msgstr "Merci de se connecter"
|
||||
msgstr "Veuillez vous authentifier"
|
||||
|
||||
#: templates/cas_server/login.html:14
|
||||
msgid "Login"
|
||||
|
@ -320,7 +331,12 @@ msgstr "Connexion"
|
|||
msgid "Connect to the service"
|
||||
msgstr "Se connecter au service"
|
||||
|
||||
#: views.py:168
|
||||
#: utils.py:736
|
||||
#, python-format
|
||||
msgid "\"%(value)s\" is not a valid regular expression"
|
||||
msgstr "\"%(value)s\" n'est pas une expression rationnelle valide"
|
||||
|
||||
#: views.py:185
|
||||
msgid ""
|
||||
"<h3>Logout successful</h3>You have successfully logged out from the Central "
|
||||
"Authentication Service. For security reasons, exit your web browser."
|
||||
|
@ -329,7 +345,7 @@ msgstr ""
|
|||
"d'Authentification. Pour des raisons de sécurité, veuillez fermer votre "
|
||||
"navigateur."
|
||||
|
||||
#: views.py:174
|
||||
#: views.py:191
|
||||
#, python-format
|
||||
msgid ""
|
||||
"<h3>Logout successful</h3>You have successfully logged out from %s sessions "
|
||||
|
@ -340,7 +356,7 @@ msgstr ""
|
|||
"Service Central d'Authentification. Pour des raisons de sécurité, veuillez "
|
||||
"fermer votre navigateur."
|
||||
|
||||
#: views.py:181
|
||||
#: views.py:198
|
||||
msgid ""
|
||||
"<h3>Logout successful</h3>You were already logged out from the Central "
|
||||
"Authentication Service. For security reasons, exit your web browser."
|
||||
|
@ -349,7 +365,7 @@ msgstr ""
|
|||
"d'Authentification. Pour des raisons de sécurité, veuillez fermer votre "
|
||||
"navigateur."
|
||||
|
||||
#: views.py:361
|
||||
#: views.py:378
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Invalid response from your identity provider CAS upon ticket %(ticket)s "
|
||||
|
@ -358,48 +374,48 @@ msgstr ""
|
|||
"Réponse invalide du CAS du fournisseur d'identité lors de la validation du "
|
||||
"ticket %(ticket)s: %(error)r"
|
||||
|
||||
#: views.py:483
|
||||
#: views.py:500
|
||||
msgid "Invalid login ticket, please retry to login"
|
||||
msgstr "Ticket de connexion invalide, merci de réessayé de vous connecter"
|
||||
|
||||
#: views.py:675
|
||||
#: views.py:692
|
||||
#, python-format
|
||||
msgid "Authentication has been required by service %(name)s (%(url)s)"
|
||||
msgstr ""
|
||||
"Une demande d'authentification a été émise pour le service %(name)s "
|
||||
"(%(url)s)."
|
||||
|
||||
#: views.py:713
|
||||
#: views.py:730
|
||||
#, python-format
|
||||
msgid "Service %(url)s non allowed."
|
||||
msgid "Service %(url)s not allowed."
|
||||
msgstr "le service %(url)s n'est pas autorisé."
|
||||
|
||||
#: views.py:720
|
||||
msgid "Username non allowed"
|
||||
#: views.py:737
|
||||
msgid "Username not allowed"
|
||||
msgstr "Nom d'utilisateur non authorisé"
|
||||
|
||||
#: views.py:727
|
||||
msgid "User characteristics non allowed"
|
||||
#: views.py:744
|
||||
msgid "User characteristics not allowed"
|
||||
msgstr "Caractéristique utilisateur non autorisée"
|
||||
|
||||
#: views.py:734
|
||||
#: views.py:751
|
||||
#, python-format
|
||||
msgid "The attribute %(field)s is needed to use that service"
|
||||
msgstr "L'attribut %(field)s est nécessaire pour se connecter à ce service"
|
||||
|
||||
#: views.py:824
|
||||
#: views.py:841
|
||||
#, python-format
|
||||
msgid "Authentication renewal required by service %(name)s (%(url)s)."
|
||||
msgstr "Demande de réauthentification pour le service %(name)s (%(url)s)."
|
||||
|
||||
#: views.py:831
|
||||
#: views.py:848
|
||||
#, python-format
|
||||
msgid "Authentication required by service %(name)s (%(url)s)."
|
||||
msgstr "Authentification requise par le service %(name)s (%(url)s)."
|
||||
|
||||
#: views.py:838
|
||||
#: views.py:855
|
||||
#, python-format
|
||||
msgid "Service %s non allowed"
|
||||
msgid "Service %s not allowed"
|
||||
msgstr "Le service %s n'est pas autorisé"
|
||||
|
||||
#~ msgid "Logged"
|
||||
|
|
|
@ -19,7 +19,7 @@ from ... import models
|
|||
class Command(BaseCommand):
|
||||
"""Clean old trickets"""
|
||||
args = ''
|
||||
help = _(u"Clean old trickets")
|
||||
help = _(u"Clean old tickets")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
models.User.clean_old_entries()
|
||||
|
|
|
@ -466,7 +466,8 @@ class ServicePattern(models.Model):
|
|||
"A regular expression matching services. "
|
||||
"Will usually looks like '^https://some\\.server\\.com/path/.*$'."
|
||||
"As it is a regular expression, special character must be escaped with a '\\'."
|
||||
)
|
||||
),
|
||||
validators=[utils.regexpr_validator]
|
||||
)
|
||||
#: Name of the attribute to transmit as username, if empty the user login is used
|
||||
user_field = models.CharField(
|
||||
|
@ -625,7 +626,7 @@ class ReplaceAttributName(models.Model):
|
|||
max_length=255,
|
||||
blank=True,
|
||||
verbose_name=_(u"replace"),
|
||||
help_text=_(u"name under which the attribute will be show"
|
||||
help_text=_(u"name under which the attribute will be show "
|
||||
u"to the service. empty = default name of the attribut")
|
||||
)
|
||||
#: ForeignKey to a :class:`ServicePattern`. :class:`ReplaceAttributName` instances for a
|
||||
|
@ -660,7 +661,8 @@ class FilterAttributValue(models.Model):
|
|||
pattern = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_(u"pattern"),
|
||||
help_text=_(u"a regular expression")
|
||||
help_text=_(u"a regular expression"),
|
||||
validators=[utils.regexpr_validator]
|
||||
)
|
||||
#: ForeignKey to a :class:`ServicePattern`. :class:`FilterAttributValue` instances for a
|
||||
#: :class:`ServicePattern` are accessible thought its :attr:`ServicePattern.filters`
|
||||
|
@ -689,7 +691,8 @@ class ReplaceAttributValue(models.Model):
|
|||
pattern = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_(u"pattern"),
|
||||
help_text=_(u"An regular expression maching whats need to be replaced")
|
||||
help_text=_(u"An regular expression maching whats need to be replaced"),
|
||||
validators=[utils.regexpr_validator]
|
||||
)
|
||||
#: The replacement to what is mached by :attr:`pattern`. groups are capture by \\1, \\2 …
|
||||
replace = models.CharField(
|
||||
|
|
|
@ -31,14 +31,14 @@ function eraseCookie(name) {
|
|||
createCookie(name,"",-1);
|
||||
}
|
||||
|
||||
function alert_version(last_version){
|
||||
function discard_and_remember(id, cookie_name, token, days=10*365){
|
||||
jQuery(function( $ ){
|
||||
$("#alert-version").click(function( e ){
|
||||
$(id).click(function( e ){
|
||||
e.preventDefault();
|
||||
createCookie("cas-alert-version", last_version, 10*365);
|
||||
createCookie(cookie_name, token, days);
|
||||
});
|
||||
if(readCookie("cas-alert-version") === last_version){
|
||||
$("#alert-version").parent().hide();
|
||||
if(readCookie(cookie_name) === token){
|
||||
$(id).parent().hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -31,10 +31,16 @@
|
|||
<div class="col-lg-3 col-md-3 col-sm-2 col-xs-12"></div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-8 col-xs-12">
|
||||
{% if auto_submit %}<noscript>{% endif %}
|
||||
{% for msg in CAS_INFO_RENDER %}
|
||||
<div class="alert alert-{{msg.type}}{% if msg.discardable %} alert-dismissable{% endif %}">
|
||||
{% if msg.discardable %}<button type="button" class="close" data-dismiss="alert" aria-hidden="true" id="info-{{msg.name}}">×</button>{% endif %}
|
||||
<p>{{msg.message}}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
|
||||
<div class="alert alert-info alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true" id="alert-version">×</button>
|
||||
{% blocktrans %}A new version of the application is available. This instance runs {{VERSION}} and the last version is {{LAST_VERSION}}. Please consider upgrading.{% endblocktrans %}
|
||||
<p>{% blocktrans %}A new version of the application is available. This instance runs {{VERSION}} and the last version is {{LAST_VERSION}}. Please consider upgrading.{% endblocktrans %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block ante_messages %}{% endblock %}
|
||||
|
@ -52,7 +58,7 @@
|
|||
class="alert alert-danger"
|
||||
{% endif %}
|
||||
{% endspaceless %}>
|
||||
{{message|safe}}
|
||||
<p>{{message|safe}}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if auto_submit %}</noscript>{% endif %}
|
||||
|
@ -71,9 +77,17 @@
|
|||
<script src="{{settings.CAS_COMPONENT_URLS.jquery}}"></script>
|
||||
<script src="{{settings.CAS_COMPONENT_URLS.bootstrap3_js}}"></script>
|
||||
<script src="{% static "cas_server/functions.js" %}"></script>
|
||||
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
|
||||
<script type="text/javascript">alert_version("{{LAST_VERSION}}")</script>
|
||||
{% endif %}
|
||||
<script type="text/javascript">
|
||||
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
|
||||
discard_and_remember("#alert-version", "cas-alert-version", "{{LAST_VERSION}}");
|
||||
{% endif %}
|
||||
{% for msg in CAS_INFO_RENDER %}
|
||||
{% if msg.discardable %}
|
||||
discard_and_remember("#info-{{msg.name}}", "cas-info-{{msg.name}}", "{{msg.hash}}");
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% block javascript_inline %}{% endblock %}
|
||||
</script>
|
||||
{% block javascript %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{% if auto_submit %}</noscript>{% endif %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block javascript %}<script type="text/javascript">
|
||||
{% block javascript_inline %}
|
||||
jQuery(function( $ ){
|
||||
$("#id_warn").click(function(e){
|
||||
if($("#id_warn").is(':checked')){
|
||||
|
@ -26,5 +26,5 @@ jQuery(function( $ ){
|
|||
});
|
||||
});{% if auto_submit %}
|
||||
document.getElementById('login_form').submit(); // SUBMIT FORM{% endif %}
|
||||
</script>{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -255,3 +255,9 @@ class UtilsTestCase(TestCase):
|
|||
self.assertIsInstance(result, dict)
|
||||
self.assertIn('applied', result)
|
||||
self.assertIsInstance(result['applied'], datetime.datetime)
|
||||
|
||||
def test_regexpr_validator(self):
|
||||
"""test the function regexpr_validator"""
|
||||
utils.regexpr_validator("^a$")
|
||||
with self.assertRaises(utils.ValidationError):
|
||||
utils.regexpr_validator("[")
|
||||
|
|
|
@ -75,6 +75,45 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin):
|
|||
response = client.get("/login")
|
||||
self.assertNotIn(b"A new version of the application is available", response.content)
|
||||
|
||||
@override_settings(CAS_INFO_MESSAGES_ORDER=["cas_explained"])
|
||||
def test_messages_info_box_enabled(self):
|
||||
"""test that the message info-box is displayed then enabled"""
|
||||
client = Client()
|
||||
response = client.get("/login")
|
||||
self.assertIn(
|
||||
b"The Central Authentication Service grants you access to most of our websites by ",
|
||||
response.content
|
||||
)
|
||||
|
||||
@override_settings(CAS_INFO_MESSAGES_ORDER=[])
|
||||
def test_messages_info_box_disabled(self):
|
||||
"""test that the message info-box is not displayed then disabled"""
|
||||
client = Client()
|
||||
response = client.get("/login")
|
||||
self.assertNotIn(
|
||||
b"The Central Authentication Service grants you access to most of our websites by ",
|
||||
response.content
|
||||
)
|
||||
|
||||
# test1 and test2 are malformed and should be ignored, test3 is ok, test5 do not
|
||||
# exists and should be ignored
|
||||
@override_settings(CAS_INFO_MESSAGES_ORDER=["test1", "test2", "test3", "test5"])
|
||||
@override_settings(CAS_INFO_MESSAGES={
|
||||
"test1": "test", # not a dict, should be ignored
|
||||
"test2": {"type": "success"}, # not "message" key, should be ignored
|
||||
"test3": {"message": "test3"},
|
||||
"test4": {"message": "test4"},
|
||||
})
|
||||
def test_messages_info_box_bad_messages(self):
|
||||
"""test that mal formated messages dict are ignored"""
|
||||
client = Client()
|
||||
# not errors should be raises
|
||||
response = client.get("/login")
|
||||
# test3 is ok est should be there
|
||||
self.assertIn(b"test3", response.content)
|
||||
# test4 is not in CAS_INFO_MESSAGES_ORDER and should not be there
|
||||
self.assertNotIn(b"test4", response.content)
|
||||
|
||||
def test_login_view_post_goodpass_goodlt(self):
|
||||
"""Test a successul login"""
|
||||
# we get a client who fetch a frist time the login page and the login form default
|
||||
|
@ -234,7 +273,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin):
|
|||
response = client.get("/login?service=https://www.example.net")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# we warn the user that https://www.example.net is not an allowed service url
|
||||
self.assertTrue(b"Service https://www.example.net non allowed" in response.content)
|
||||
self.assertTrue(b"Service https://www.example.net not allowed" in response.content)
|
||||
|
||||
def test_view_login_get_auth_allowed_service(self):
|
||||
"""Request a ticket for an allowed service by an authenticated client"""
|
||||
|
@ -280,7 +319,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
# we warn the user that https://www.example.net is not an allowed service url
|
||||
# NO ticket are created
|
||||
self.assertTrue(b"Service https://www.example.org non allowed" in response.content)
|
||||
self.assertTrue(b"Service https://www.example.org not allowed" in response.content)
|
||||
|
||||
def test_user_logged_not_in_db(self):
|
||||
"""If the user is logged but has been delete from the database, it should be logged out"""
|
||||
|
@ -314,7 +353,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin):
|
|||
response = client.get("/login", {'service': self.service_restrict_user_fail})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# the ticket is not created and a warning is displayed to the user
|
||||
self.assertTrue(b"Username non allowed" in response.content)
|
||||
self.assertTrue(b"Username not allowed" in response.content)
|
||||
|
||||
# same but with the tes user username being one of the allowed usernames
|
||||
response = client.get("/login", {'service': self.service_restrict_user_success})
|
||||
|
@ -337,7 +376,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin):
|
|||
response = client.get("/login", {'service': service})
|
||||
# the ticket is not created and a warning is displayed to the user
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(b"User characteristics non allowed" in response.content)
|
||||
self.assertTrue(b"User characteristics not allowed" in response.content)
|
||||
|
||||
# same but with rectriction that a valid upon the test user attributes
|
||||
response = client.get("/login", {'service': self.service_filter_success})
|
||||
|
@ -546,7 +585,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin):
|
|||
self.assertEqual(data["messages"][0]["level"], "error")
|
||||
self.assertEqual(
|
||||
data["messages"][0]["message"],
|
||||
"Service https://www.example.org non allowed."
|
||||
"Service https://www.example.org not allowed."
|
||||
)
|
||||
|
||||
@override_settings(CAS_ENABLE_AJAX_AUTH=True)
|
||||
|
|
|
@ -18,7 +18,10 @@ from django.contrib import messages
|
|||
from django.contrib.messages import constants as DEFAULT_MESSAGE_LEVELS
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.utils import timezone
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import re
|
||||
import random
|
||||
import string
|
||||
import json
|
||||
|
@ -61,6 +64,7 @@ def context(params):
|
|||
"""
|
||||
params["settings"] = settings
|
||||
params["message_levels"] = DEFAULT_MESSAGE_LEVELS
|
||||
|
||||
if settings.CAS_NEW_VERSION_HTML_WARNING:
|
||||
LAST_VERSION = last_version()
|
||||
params["VERSION"] = VERSION
|
||||
|
@ -69,6 +73,27 @@ def context(params):
|
|||
params["upgrade_available"] = decode_version(VERSION) < decode_version(LAST_VERSION)
|
||||
else:
|
||||
params["upgrade_available"] = False
|
||||
|
||||
if settings.CAS_INFO_MESSAGES_ORDER:
|
||||
params["CAS_INFO_RENDER"] = []
|
||||
for msg_name in settings.CAS_INFO_MESSAGES_ORDER:
|
||||
if msg_name in settings.CAS_INFO_MESSAGES:
|
||||
if not isinstance(settings.CAS_INFO_MESSAGES[msg_name], dict):
|
||||
continue
|
||||
msg = settings.CAS_INFO_MESSAGES[msg_name].copy()
|
||||
if "message" in msg:
|
||||
msg["name"] = msg_name
|
||||
# use info as default infox type
|
||||
msg["type"] = msg.get("type", "info")
|
||||
# make box discardable by default
|
||||
msg["discardable"] = msg.get("discardable", True)
|
||||
msg_hash = (
|
||||
six.text_type(msg["message"]).encode("utf-8") +
|
||||
msg["type"].encode("utf-8")
|
||||
)
|
||||
# hash depend of the rendering language
|
||||
msg["hash"] = hashlib.md5(msg_hash).hexdigest()
|
||||
params["CAS_INFO_RENDER"].append(msg)
|
||||
return params
|
||||
|
||||
|
||||
|
@ -700,3 +725,19 @@ def logout_request(ticket):
|
|||
'datetime': timezone.now().isoformat(),
|
||||
'ticket': ticket
|
||||
}
|
||||
|
||||
|
||||
def regexpr_validator(value):
|
||||
"""
|
||||
Test that ``value`` is a valid regular expression
|
||||
|
||||
:param unicode value: A regular expression to test
|
||||
:raises ValidationError: if ``value`` is not a valid regular expression
|
||||
"""
|
||||
try:
|
||||
re.compile(value)
|
||||
except re.error:
|
||||
raise ValidationError(
|
||||
_('"%(value)s" is not a valid regular expression'),
|
||||
params={'value': value}
|
||||
)
|
||||
|
|
|
@ -727,21 +727,21 @@ class LoginView(View, LogoutMixin):
|
|||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u'Service %(url)s non allowed.') % {'url': self.service}
|
||||
_(u'Service %(url)s not allowed.') % {'url': self.service}
|
||||
)
|
||||
except models.BadUsername:
|
||||
error = 2
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u"Username non allowed")
|
||||
_(u"Username not allowed")
|
||||
)
|
||||
except models.BadFilter:
|
||||
error = 3
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u"User characteristics non allowed")
|
||||
_(u"User characteristics not allowed")
|
||||
)
|
||||
except models.UserFieldNotDefined:
|
||||
error = 4
|
||||
|
@ -852,7 +852,7 @@ class LoginView(View, LogoutMixin):
|
|||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u'Service %s non allowed') % self.service
|
||||
_(u'Service %s not allowed') % self.service
|
||||
)
|
||||
if self.ajax:
|
||||
data = {
|
||||
|
|
1
docs/CHANGELOG.rst
Normal file
1
docs/CHANGELOG.rst
Normal file
|
@ -0,0 +1 @@
|
|||
.. include:: ../CHANGELOG.rst
|
|
@ -14,6 +14,11 @@ Contents:
|
|||
README
|
||||
package/cas_server
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
CHANGELOG
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
|
|
1
tox.ini
1
tox.ini
|
@ -101,6 +101,7 @@ deps=
|
|||
skip_install=True
|
||||
commands=
|
||||
rst2html.py --strict {toxinidir}/README.rst /dev/null
|
||||
rst2html.py --halt=warning {toxinidir}/CHANGELOG.rst /dev/null
|
||||
{[post_cmd]commands}
|
||||
whitelist_externals={[post_cmd]whitelist_externals}
|
||||
|
||||
|
|
Loading…
Reference in a new issue