From 4c15b51612a33b615c9bed1b4e9b80dd63df4c65 Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Wed, 29 Mar 2017 14:24:52 +0200 Subject: [PATCH 01/12] Update CHANGELOG with dutch translation --- CHANGELOG.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index beff5bd..6e57a76 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,15 @@ All notable changes to this project will be documented in this file. .. contents:: Table of Contents :depth: 2 + +Unreleased +========== + +Added +----- +* Dutch translation + + v0.8.0 - 2017-03-08 =================== From 443c87fa402ef6d086066412e4a047f54a45889f Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Wed, 29 Mar 2017 14:28:36 +0200 Subject: [PATCH 02/12] Do not try to bind if the user dn was not found with LDAP auth backend Then using the LDAP auth backend with ``bind`` method for password check, do not try to bind if the user dn was not found. This was causing the exception ``'NoneType' object has no attribute 'getitem'`` describe in #21 --- CHANGELOG.rst | 6 ++++++ cas_server/auth.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6e57a76..36025eb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,12 @@ Added ----- * Dutch translation +Fixed +----- +* Then using the LDAP auth backend with ``bind`` method for password check, do not try to bind + if the user dn was not found. This was causing the exception + ``'NoneType' object has no attribute 'getitem'`` describe in #21 + v0.8.0 - 2017-03-08 =================== diff --git a/cas_server/auth.py b/cas_server/auth.py index bcdce71..9a0893e 100644 --- a/cas_server/auth.py +++ b/cas_server/auth.py @@ -321,7 +321,7 @@ class LdapAuthUser(DBAuthUser): # pragma: no cover correct, ``False`` otherwise. :rtype: bool """ - if settings.CAS_LDAP_PASSWORD_CHECK == "bind": + if self.user and settings.CAS_LDAP_PASSWORD_CHECK == "bind": try: conn = ldap3.Connection( settings.CAS_LDAP_SERVER, From 1dba4fea95047eff6b9233a1a0079e0f00512b25 Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Wed, 29 Mar 2017 14:31:45 +0200 Subject: [PATCH 03/12] Support for ldap3 version 2 or more (changes in the API) All exception are now in ldap3.core.exceptions, methodes for fetching attritutes and dn are renamed. --- CHANGELOG.rst | 3 +++ cas_server/auth.py | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 36025eb..ca9637e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,9 @@ Unreleased Added ----- * Dutch translation +* Support for ldap3 version 2 or more (changes in the API) + All exception are now in ldap3.core.exceptions, methodes for fetching attritutes and + dn are renamed. Fixed ----- diff --git a/cas_server/auth.py b/cas_server/auth.py index 9a0893e..4a5b141 100644 --- a/cas_server/auth.py +++ b/cas_server/auth.py @@ -27,6 +27,7 @@ except ImportError: try: # pragma: no cover import ldap3 + import ldap3.core.exceptions except ImportError: ldap3 = None @@ -297,9 +298,19 @@ class LdapAuthUser(DBAuthUser): # pragma: no cover settings.CAS_LDAP_USER_QUERY % ldap3.utils.conv.escape_bytes(username), attributes=ldap3.ALL_ATTRIBUTES ) and len(conn.entries) == 1: - user = conn.entries[0].entry_get_attributes_dict() - # store the user dn - user["dn"] = conn.entries[0].entry_get_dn() + # try the new ldap3>=2 API + try: + user = conn.entries[0].entry_attributes_as_dict + # store the user dn + user["dn"] = conn.entries[0].entry_dn + # fallback to ldap3<2 API + except ( + ldap3.core.exceptions.LDAPKeyError, # ldap3<1 exception + ldap3.core.exceptions.LDAPAttributeError # ldap3<2 exception + ): + user = conn.entries[0].entry_get_attributes_dict() + # store the user dn + user["dn"] = conn.entries[0].entry_get_dn() if user.get(settings.CAS_LDAP_USERNAME_ATTR): self.user = user super(LdapAuthUser, self).__init__(user[settings.CAS_LDAP_USERNAME_ATTR][0]) @@ -308,7 +319,7 @@ class LdapAuthUser(DBAuthUser): # pragma: no cover else: super(LdapAuthUser, self).__init__(username) break - except ldap3.LDAPCommunicationError: + except ldap3.core.exceptions.LDAPCommunicationError: if retry_nb == 2: raise @@ -336,8 +347,18 @@ class LdapAuthUser(DBAuthUser): # pragma: no cover settings.CAS_LDAP_USER_QUERY % ldap3.utils.conv.escape_bytes(self.username), attributes=ldap3.ALL_ATTRIBUTES ) and len(conn.entries) == 1: - attributes = conn.entries[0].entry_get_attributes_dict() - attributes["dn"] = conn.entries[0].entry_get_dn() + # try the ldap3>=2 API + try: + attributes = conn.entries[0].entry_attributes_as_dict + # store the user dn + attributes["dn"] = conn.entries[0].entry_dn + # fallback to ldap<2 API + except ( + ldap3.core.exceptions.LDAPKeyError, # ldap3<1 exception + ldap3.core.exceptions.LDAPAttributeError # ldap3<2 exception + ): + attributes = conn.entries[0].entry_get_attributes_dict() + attributes["dn"] = conn.entries[0].entry_get_dn() # cache the attributes locally as we wont have access to the user password # later. user = UserAttributes.objects.get_or_create(username=self.username)[0] @@ -346,7 +367,10 @@ class LdapAuthUser(DBAuthUser): # pragma: no cover finally: conn.unbind() return True - except (ldap3.LDAPBindError, ldap3.LDAPCommunicationError): + except ( + ldap3.core.exceptions.LDAPBindError, + ldap3.core.exceptions.LDAPCommunicationError + ): return False elif self.user and self.user.get(settings.CAS_LDAP_PASSWORD_ATTR): return check_password( From 224202c5c2448366583503134ba349a6bcb31b0f Mon Sep 17 00:00:00 2001 From: Jorik Kraaikamp Date: Wed, 29 Mar 2017 15:36:12 +0200 Subject: [PATCH 04/12] Added a setting to turn of the messages about the service --- cas_server/tests/test_view.py | 64 +++++++++++++++++++++++++++++++++++ cas_server/views.py | 41 +++++++++++----------- 2 files changed, 86 insertions(+), 19 deletions(-) diff --git a/cas_server/tests/test_view.py b/cas_server/tests/test_view.py index c1ffe01..3320968 100644 --- a/cas_server/tests/test_view.py +++ b/cas_server/tests/test_view.py @@ -295,6 +295,24 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin): ) in response.content ) + @override_settings(CAS_SHOW_SERVER_MESSAGES=False) + def test_view_login_get_allowed_service_no_message(self): + """Request a ticket for an allowed service by an unauthenticated client""" + # get a bare new http client + client = Client() + # we are not authenticated and are asking for a ticket for https://www.example.com + # which is a valid service matched by self.service_pattern + response = client.get("/login?service=https://www.example.com") + # the login page should be displayed + self.assertEqual(response.status_code, 200) + # we warn the user why it need to authenticated + self.assertFalse( + ( + b"Authentication required by service " + b"example (https://www.example.com)" + ) in response.content + ) + def test_view_login_get_denied_service(self): """Request a ticket for an denied service by an unauthenticated client""" # get a bare new http client @@ -306,6 +324,18 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin): # we warn the user that https://www.example.net is not an allowed service url self.assertTrue(b"Service https://www.example.net not allowed" in response.content) + @override_settings(CAS_SHOW_SERVER_MESSAGES=False) + def test_view_login_get_denied_service_no_message(self): + """Request a ticket for an denied service by an unauthenticated client""" + # get a bare new http client + client = Client() + # we are not authenticated and are asking for a ticket for https://www.example.net + # which is NOT a valid service + 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.assertFalse(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""" # get a client that is already authenticated @@ -505,6 +535,40 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin): # renewing authentication is done in the validate and serviceValidate views tests self.assertEqual(ticket.renew, True) + @override_settings(CAS_SHOW_SERVER_MESSAGES=False) + def test_renew_message_disabled(self): + """test the authentication renewal request from a service""" + # use the default test service + service = "https://www.example.com" + # get a client that is already authenticated + client = get_auth_client() + # ask for a ticket for the service but aks for authentication renewal + response = client.get("/login", {'service': service, 'renew': 'on'}) + # we are ask to reauthenticate and tell the user why + self.assertEqual(response.status_code, 200) + self.assertFalse( + ( + b"Authentication renewal required by " + b"service example (https://www.example.com)" + ) in response.content + ) + # get the form default parameter + params = copy_form(response.context["form"]) + # set valid username/password + params["username"] = settings.CAS_TEST_USER + params["password"] = settings.CAS_TEST_PASSWORD + # the renew parameter from the form should be True + self.assertEqual(params["renew"], True) + # post the authentication request + response = client.post("/login", params) + # the request succed, a ticket is created and we are redirected to the service url + self.assertEqual(response.status_code, 302) + ticket_value = response['Location'].split('ticket=')[-1] + ticket = models.ServiceTicket.objects.get(value=ticket_value) + # the created ticket is marked has being gottent after a renew. Futher testing about + # renewing authentication is done in the validate and serviceValidate views tests + self.assertEqual(ticket.renew, True) + @override_settings(CAS_ENABLE_AJAX_AUTH=True) def test_ajax_login_required(self): """ diff --git a/cas_server/views.py b/cas_server/views.py index b3d3a1e..70eb618 100644 --- a/cas_server/views.py +++ b/cas_server/views.py @@ -835,26 +835,29 @@ class LoginView(View, LogoutMixin): # clean messages before leaving django list(messages.get_messages(self.request)) return HttpResponseRedirect(self.service) - if self.request.session.get("authenticated") and self.renew: - messages.add_message( - self.request, - messages.WARNING, - _(u"Authentication renewal required by service %(name)s (%(url)s).") % - {'name': service_pattern.name, 'url': self.service} - ) - else: - messages.add_message( - self.request, - messages.WARNING, - _(u"Authentication required by service %(name)s (%(url)s).") % - {'name': service_pattern.name, 'url': self.service} - ) + + if settings.CAS_SHOW_SERVICE_MESSAGES: + if self.request.session.get("authenticated") and self.renew: + messages.add_message( + self.request, + messages.WARNING, + _(u"Authentication renewal required by service %(name)s (%(url)s).") % + {'name': service_pattern.name, 'url': self.service} + ) + else: + messages.add_message( + self.request, + messages.WARNING, + _(u"Authentication required by service %(name)s (%(url)s).") % + {'name': service_pattern.name, 'url': self.service} + ) except ServicePattern.DoesNotExist: - messages.add_message( - self.request, - messages.ERROR, - _(u'Service %s not allowed') % self.service - ) + if settings.CAS_SHOW_SERVICE_MESSAGES: + messages.add_message( + self.request, + messages.ERROR, + _(u'Service %s not allowed') % self.service + ) if self.ajax: data = { "status": "error", From 81ebc74ecd90c038d3112909310808fb7c499e8a Mon Sep 17 00:00:00 2001 From: Jorik Kraaikamp Date: Wed, 29 Mar 2017 15:38:21 +0200 Subject: [PATCH 05/12] updated the readme --- README.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 715bf3e..8bddb08 100644 --- a/README.rst +++ b/README.rst @@ -218,7 +218,8 @@ Template settings } if you omit some keys of the dictionnary, the default value for these keys is used. - +* ``CAS_SHOW_SERVICE_MESSAGES``: Messages displayed about the state of the service on the login page. + The default is ``True``. * ``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: From 951dc60e99708bfbd5e727308128d14038ef0b60 Mon Sep 17 00:00:00 2001 From: Jorik Kraaikamp Date: Wed, 29 Mar 2017 16:57:27 +0200 Subject: [PATCH 06/12] Fixed some major mistyping and added the default setting. --- cas_server/default_settings.py | 2 ++ cas_server/tests/test_view.py | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cas_server/default_settings.py b/cas_server/default_settings.py index 737bb84..3cda3e3 100644 --- a/cas_server/default_settings.py +++ b/cas_server/default_settings.py @@ -185,6 +185,8 @@ 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" +#: If the service message should be displayed on the login page +CAS_SHOW_SERVICE_MESSAGES = True #: 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`. diff --git a/cas_server/tests/test_view.py b/cas_server/tests/test_view.py index 3320968..016db3e 100644 --- a/cas_server/tests/test_view.py +++ b/cas_server/tests/test_view.py @@ -295,7 +295,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin): ) in response.content ) - @override_settings(CAS_SHOW_SERVER_MESSAGES=False) + @override_settings(CAS_SHOW_SERVICE_MESSAGES=False) def test_view_login_get_allowed_service_no_message(self): """Request a ticket for an allowed service by an unauthenticated client""" # get a bare new http client @@ -324,7 +324,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin): # we warn the user that https://www.example.net is not an allowed service url self.assertTrue(b"Service https://www.example.net not allowed" in response.content) - @override_settings(CAS_SHOW_SERVER_MESSAGES=False) + @override_settings(CAS_SHOW_SERVICE_MESSAGES=False) def test_view_login_get_denied_service_no_message(self): """Request a ticket for an denied service by an unauthenticated client""" # get a bare new http client @@ -535,7 +535,7 @@ class LoginTestCase(TestCase, BaseServicePattern, CanLogin): # renewing authentication is done in the validate and serviceValidate views tests self.assertEqual(ticket.renew, True) - @override_settings(CAS_SHOW_SERVER_MESSAGES=False) + @override_settings(CAS_SHOW_SERVICE_MESSAGES=False) def test_renew_message_disabled(self): """test the authentication renewal request from a service""" # use the default test service From 13af3ccd1d976e5a02aa9a233400af133e28c711 Mon Sep 17 00:00:00 2001 From: Jorik Kraaikamp Date: Wed, 29 Mar 2017 17:52:12 +0200 Subject: [PATCH 07/12] added the bigger username migration and change --- .../migrations/0013_auto_20170329_1748.py | 20 +++++++++++++++++++ cas_server/models.py | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 cas_server/migrations/0013_auto_20170329_1748.py diff --git a/cas_server/migrations/0013_auto_20170329_1748.py b/cas_server/migrations/0013_auto_20170329_1748.py new file mode 100644 index 0000000..a49f908 --- /dev/null +++ b/cas_server/migrations/0013_auto_20170329_1748.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-03-29 15:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cas_server', '0012_auto_20170328_1610'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='username', + field=models.CharField(max_length=250), + ), + ] diff --git a/cas_server/models.py b/cas_server/models.py index be871b6..4b6596f 100644 --- a/cas_server/models.py +++ b/cas_server/models.py @@ -273,7 +273,7 @@ class User(models.Model): #: The session key of the current authenticated user session_key = models.CharField(max_length=40, blank=True, null=True) #: The username of the current authenticated user - username = models.CharField(max_length=30) + username = models.CharField(max_length=250) #: Last time the authenticated user has do something (auth, fetch ticket, etc…) date = models.DateTimeField(auto_now=True) #: last time the user logged From 92bba0da499aa99bd1388f26601500f0b38e0362 Mon Sep 17 00:00:00 2001 From: Jorik Kraaikamp Date: Thu, 30 Mar 2017 15:25:29 +0200 Subject: [PATCH 08/12] added the missing migration --- .../migrations/0012_auto_20170328_1610.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 cas_server/migrations/0012_auto_20170328_1610.py diff --git a/cas_server/migrations/0012_auto_20170328_1610.py b/cas_server/migrations/0012_auto_20170328_1610.py new file mode 100644 index 0000000..207348e --- /dev/null +++ b/cas_server/migrations/0012_auto_20170328_1610.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-03-28 14:10 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cas_server', '0011_auto_20161007_1258'), + ] + + operations = [ + migrations.AlterField( + model_name='federatediendityprovider', + name='cas_protocol_version', + field=models.CharField(choices=[('1', 'CAS 1.0'), ('2', 'CAS 2.0'), ('3', 'CAS 3.0'), ('CAS_2_SAML_1_0', 'SAML 1.1')], default='3', help_text='Version of the CAS protocol to use when sending requests the the backend CAS.', max_length=30, verbose_name='CAS protocol version'), + ), + migrations.AlterField( + model_name='servicepattern', + name='single_log_out_callback', + field=models.CharField(blank=True, default='', help_text='URL where the SLO request will be POST. empty = service url\nThis is usefull for non HTTP proxied services.', max_length=255, verbose_name='single log out callback'), + ), + migrations.AlterField( + model_name='servicepattern', + name='user_field', + field=models.CharField(blank=True, default='', help_text='Name of the attribute to transmit as username, empty = login', max_length=255, verbose_name='user field'), + ), + ] From 60ae92cc5ad87575cbb89c5fc363174044b9163d Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Tue, 25 Apr 2017 16:26:39 +0200 Subject: [PATCH 09/12] Add changelog for merges 03a069268aaa441a4773c3b055b207e7c33eebe5 and 253b4311941ce84b8d44a3919da59aedff73f412 --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ca9637e..39d1cc1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,12 +16,15 @@ Added * Support for ldap3 version 2 or more (changes in the API) All exception are now in ldap3.core.exceptions, methodes for fetching attritutes and dn are renamed. +* Possibility to disable service message boxes on the login pages Fixed ----- * Then using the LDAP auth backend with ``bind`` method for password check, do not try to bind if the user dn was not found. This was causing the exception ``'NoneType' object has no attribute 'getitem'`` describe in #21 +* Increase the max size of usernames (30 chars to 250) + v0.8.0 - 2017-03-08 From f1a47e77660f13797ad6e1694c56472be97a59b5 Mon Sep 17 00:00:00 2001 From: Roberto Morati Date: Tue, 29 Aug 2017 18:11:33 +0200 Subject: [PATCH 10/12] Added protuguese translation (brazilian variant) --- CHANGELOG.rst | 1 + cas_server/locale/pt_BR/django.mo | Bin 0 -> 5272 bytes cas_server/locale/pt_BR/django.po | 398 ++++++++++++++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 cas_server/locale/pt_BR/django.mo create mode 100644 cas_server/locale/pt_BR/django.po diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 39d1cc1..cfe1791 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,7 @@ Unreleased Added ----- * Dutch translation +* Protuguese translation (brazilian variant) * Support for ldap3 version 2 or more (changes in the API) All exception are now in ldap3.core.exceptions, methodes for fetching attritutes and dn are renamed. diff --git a/cas_server/locale/pt_BR/django.mo b/cas_server/locale/pt_BR/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..e0cfa6b7a72ff88bcd8900d27be74ced2a6cccd6 GIT binary patch literal 5272 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 Oe6Yo)fkf6Oss8|3^4UB9 literal 0 HcmV?d00001 diff --git a/cas_server/locale/pt_BR/django.po b/cas_server/locale/pt_BR/django.po new file mode 100644 index 0000000..06c998a --- /dev/null +++ b/cas_server/locale/pt_BR/django.po @@ -0,0 +1,398 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-08-22 08:18-0300\n" +"PO-Revision-Date: 2017-08-29 18:09+0200\n" +"Language-Team: Roberto Morati \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Last-Translator: Valentin Samir \n" +"X-Generator: Poedit 1.8.11\n" + +#: cas_server/apps.py:25 cas_server/templates/cas_server/base.html:7 +#: cas_server/templates/cas_server/base.html:26 +msgid "Central Authentication Service" +msgstr "Central de Autenticação de Serviços" + +#: cas_server/default_settings.py:201 +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 "" +"A Central de Autenticação de Serviços garante seu acesso à maioria dos nossos sitespor " +"meio de uma única autenticação, então você não precisa digitar suas " +"credenciaisnovamente, ao menos que sua sessão expire ou seu logout." + +#: cas_server/forms.py:85 +msgid "Identity provider" +msgstr "Provedor de identidade" + +#: cas_server/forms.py:89 cas_server/forms.py:111 +msgid "Warn me before logging me into other sites." +msgstr "Avise-me antes de me registrar em outros sites" + +#: cas_server/forms.py:93 +msgid "Remember the identity provider" +msgstr "Relembrar o provedor de identidade" + +#: cas_server/forms.py:104 cas_server/models.py:638 +msgid "username" +msgstr "usuário" + +#: cas_server/forms.py:108 +msgid "password" +msgstr "senha" + +#: cas_server/forms.py:131 +msgid "The credentials you provided cannot be determined to be authentic." +msgstr "As credenciais que você forneceu não podem ser determinadas como autênticas." + +#: cas_server/forms.py:183 +msgid "User not found in the temporary database, please try to reconnect" +msgstr "Usuário não encontrado na base de dados temporária, por favor, tente se reconectar" + +#: cas_server/forms.py:197 +msgid "service" +msgstr "" + +#: cas_server/management/commands/cas_clean_federate.py:20 +msgid "Clean old federated users" +msgstr "" + +#: cas_server/management/commands/cas_clean_sessions.py:22 +msgid "Clean deleted sessions" +msgstr "" + +#: cas_server/management/commands/cas_clean_tickets.py:22 +msgid "Clean old tickets" +msgstr "" + +#: cas_server/models.py:71 +msgid "identity provider" +msgstr "provedor de identidade" + +#: cas_server/models.py:72 +msgid "identity providers" +msgstr "provedores de identidade" + +#: cas_server/models.py:78 +msgid "suffix" +msgstr "" + +#: cas_server/models.py:80 +msgid "Suffix append to backend CAS returned username: ``returned_username`` @ ``suffix``." +msgstr "" + +#: cas_server/models.py:87 +msgid "server url" +msgstr "" + +#: cas_server/models.py:97 +msgid "CAS protocol version" +msgstr "" + +#: cas_server/models.py:99 +msgid "Version of the CAS protocol to use when sending requests the the backend CAS." +msgstr "" + +#: cas_server/models.py:106 +msgid "verbose name" +msgstr "" + +#: cas_server/models.py:107 +msgid "Name for this identity provider displayed on the login page." +msgstr "Nome para exibir o provedor de identidade na página de login." + +#: cas_server/models.py:113 cas_server/models.py:490 +msgid "position" +msgstr "" + +#: cas_server/models.py:127 +msgid "display" +msgstr "" + +#: cas_server/models.py:128 +msgid "Display the provider on the login page." +msgstr "" + +#: cas_server/models.py:166 +msgid "Federated user" +msgstr "" + +#: cas_server/models.py:167 +msgid "Federated users" +msgstr "" + +#: cas_server/models.py:246 +msgid "User attributes cache" +msgstr "" + +#: cas_server/models.py:247 +msgid "User attributes caches" +msgstr "" + +#: cas_server/models.py:271 +msgid "User" +msgstr "" + +#: cas_server/models.py:272 +msgid "Users" +msgstr "" + +#: cas_server/models.py:364 +#, python-format +msgid "Error during service logout %s" +msgstr "" + +#: cas_server/models.py:484 +msgid "Service pattern" +msgstr "" + +#: cas_server/models.py:485 +msgid "Services patterns" +msgstr "" + +#: cas_server/models.py:491 +msgid "service patterns are sorted using the position attribute" +msgstr "" + +#: cas_server/models.py:499 cas_server/models.py:664 +msgid "name" +msgstr "" + +#: cas_server/models.py:500 +msgid "A name for the service" +msgstr "" + +#: cas_server/models.py:508 cas_server/models.py:707 cas_server/models.py:737 +msgid "pattern" +msgstr "" + +#: cas_server/models.py:510 +msgid "" +"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 " +"'\\'." +msgstr "" + +#: cas_server/models.py:521 +msgid "user field" +msgstr "" + +#: cas_server/models.py:522 +msgid "Name of the attribute to transmit as username, empty = login" +msgstr "" + +#: cas_server/models.py:527 +msgid "restrict username" +msgstr "" + +#: cas_server/models.py:528 +msgid "Limit username allowed to connect to the list provided bellow" +msgstr "" + +#: cas_server/models.py:533 +msgid "proxy" +msgstr "" + +#: cas_server/models.py:534 +msgid "Proxy tickets can be delivered to the service" +msgstr "" + +#: cas_server/models.py:540 +msgid "proxy callback" +msgstr "" + +#: cas_server/models.py:541 +msgid "can be used as a proxy callback to deliver PGT" +msgstr "" + +#: cas_server/models.py:548 +msgid "single log out" +msgstr "" + +#: cas_server/models.py:549 +msgid "Enable SLO for the service" +msgstr "" + +#: cas_server/models.py:558 +msgid "" +"URL where the SLO request will be POST. empty = service url\n" +"This is usefull for non HTTP proxied services." +msgstr "" + +#: cas_server/models.py:639 +msgid "username allowed to connect to the service" +msgstr "" + +#: cas_server/models.py:665 +msgid "name of an attribute to send to the service, use * for all attributes" +msgstr "" + +#: cas_server/models.py:672 cas_server/models.py:745 +msgid "replace" +msgstr "" + +#: cas_server/models.py:673 +msgid "" +"name under which the attribute will be show to the service. empty = default name of the " +"attribut" +msgstr "" + +#: cas_server/models.py:700 cas_server/models.py:731 +msgid "attribute" +msgstr "" + +#: cas_server/models.py:701 +msgid "Name of the attribute which must verify pattern" +msgstr "" + +#: cas_server/models.py:708 +msgid "a regular expression" +msgstr "" + +#: cas_server/models.py:732 +msgid "Name of the attribute for which the value must be replace" +msgstr "" + +#: cas_server/models.py:738 +msgid "An regular expression maching whats need to be replaced" +msgstr "" + +#: cas_server/models.py:746 +msgid "replace expression, groups are capture by \\1, \\2 …" +msgstr "" + +#: cas_server/templates/cas_server/base.html:43 +#, python-format +msgid "" +"A new version of the application is available. This instance runs %(VERSION)s and the " +"last version is %(LAST_VERSION)s. Please consider upgrading." +msgstr "" +"Uma nova versão da aplicação está disponível. Está instância usa a versão %(VERSION)s e " +"a última versão é %(LAST_VERSION)s. Por favor, considere a atualização." + +#: cas_server/templates/cas_server/logged.html:4 +msgid "" +"

Log In Successful

You have successfully logged into the Central Authentication " +"Service.
For security reasons, please Log Out and Exit your web browser when you are " +"done accessing services that require authentication!" +msgstr "" +"

Log In realizado com sucesso

Você foi conectado com sucesso a Central de " +"Autenticação de Serviços.
Por razões de segurança, faça o Log Out e saia do seu " +"navegador quando você terminar de acessar os serviços que exigem auntenticação!" + +#: cas_server/templates/cas_server/logged.html:8 +msgid "Log me out from all my sessions" +msgstr "Desconecte-me de todas as sessões" + +#: cas_server/templates/cas_server/logged.html:14 +msgid "Forget the identity provider" +msgstr "Esquecer o provedor de identidade" + +#: cas_server/templates/cas_server/logged.html:18 +msgid "Logout" +msgstr "" + +#: cas_server/templates/cas_server/login.html:6 +msgid "Please log in" +msgstr "Por favor, faça log in" + +#: cas_server/templates/cas_server/login.html:14 +msgid "Login" +msgstr "" + +#: cas_server/templates/cas_server/warn.html:9 +msgid "Connect to the service" +msgstr "" + +#: cas_server/utils.py:744 +#, python-format +msgid "\"%(value)s\" is not a valid regular expression" +msgstr "" + +#: cas_server/views.py:185 +msgid "" +"

Logout successful

You have successfully logged out from the Central " +"Authentication Service. For security reasons, close your web browser." +msgstr "" +"

Logout realizado com sucesso

Você foi desconectado com sucesso da Central de " +"Autenticação de Serviços. Por razões de segurança, feche seu navegador." + +#: cas_server/views.py:191 +#, python-format +msgid "" +"

Logout successful

You have successfully logged out from %s sessions of the " +"Central Authentication Service. For security reasons, close your web browser." +msgstr "" +"

Logout realizado com sucesso

Você foi desconectado com sucesso da %s sessão da " +"Centralde Autenticação de Serviços. Por razões de segurança, feche seu navegador." + +#: cas_server/views.py:198 +msgid "" +"

Logout successful

You were already logged out from the Central Authentication " +"Service. For security reasons, close your web browser." +msgstr "" +"

Logout realizado com sucesso

Você já está desconectado da Central de " +"Autenticação de Serviços. Por razões de segurança, feche seu navegador." + +#: cas_server/views.py:378 +#, python-format +msgid "" +"Invalid response from your identity provider CAS upon ticket %(ticket)s validation: " +"%(error)r" +msgstr "" +"Resposta inválida do provedor de identidade CAS sobre o ticket %(ticket)svalidação: " +"%(error)r" + +#: cas_server/views.py:500 +msgid "Invalid login ticket, please try to log in again" +msgstr "Ticket de login inválido, por favor tente novamente" + +#: cas_server/views.py:693 +#, python-format +msgid "Authentication has been required by service %(name)s (%(url)s)" +msgstr "Autenticação requerida pelo serviço %(name)s (%(url)s)" + +#: cas_server/views.py:731 +#, python-format +msgid "Service %(url)s not allowed." +msgstr "Serviço %(url)s não permitido" + +#: cas_server/views.py:738 +msgid "Username not allowed" +msgstr "Usuário não permitido" + +#: cas_server/views.py:745 +msgid "User characteristics not allowed" +msgstr "Características de usuário não permitida" + +#: cas_server/views.py:752 +#, python-format +msgid "The attribute %(field)s is needed to use that service" +msgstr "O atributo %(field)s é necessário para usar o serviço" + +#: cas_server/views.py:842 +#, python-format +msgid "Authentication renewal required by service %(name)s (%(url)s)." +msgstr "Renovação da autenticação requerida pelo serviço %(name)s (%(url)s)." + +#: cas_server/views.py:849 +#, python-format +msgid "Authentication required by service %(name)s (%(url)s)." +msgstr "Autenticação requerida pelo serviço %(name)s (%(url)s)." + +#: cas_server/views.py:856 +#, python-format +msgid "Service %s not allowed" +msgstr "Serviço %s não permitido" From 971cde093ce5af5aac9ced93c85b92c40e6e5665 Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Fri, 17 Nov 2017 15:23:25 +0100 Subject: [PATCH 11/12] Fix XSS js injection --- CHANGELOG.rst | 1 + cas_server/templates/cas_server/base.html | 2 +- cas_server/templates/cas_server/logout.html | 2 +- cas_server/views.py | 15 ++++++++------- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cfe1791..ff7acae 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,7 @@ Fixed if the user dn was not found. This was causing the exception ``'NoneType' object has no attribute 'getitem'`` describe in #21 * Increase the max size of usernames (30 chars to 250) +* Fix XSS js injection diff --git a/cas_server/templates/cas_server/base.html b/cas_server/templates/cas_server/base.html index a3dd3a7..8b16b5f 100644 --- a/cas_server/templates/cas_server/base.html +++ b/cas_server/templates/cas_server/base.html @@ -58,7 +58,7 @@ class="alert alert-danger" {% endif %} {% endspaceless %}> -

{{message|safe}}

+

{{message}}

{% endfor %} {% if auto_submit %}{% endif %} diff --git a/cas_server/templates/cas_server/logout.html b/cas_server/templates/cas_server/logout.html index 5c69dfc..d8ab1dc 100644 --- a/cas_server/templates/cas_server/logout.html +++ b/cas_server/templates/cas_server/logout.html @@ -2,6 +2,6 @@ {% load staticfiles %} {% load i18n %} {% block content %} - + {% endblock %} diff --git a/cas_server/views.py b/cas_server/views.py index 70eb618..3db45c1 100644 --- a/cas_server/views.py +++ b/cas_server/views.py @@ -23,6 +23,7 @@ from django.views.decorators.csrf import csrf_exempt from django.middleware.csrf import CsrfViewMiddleware from django.views.generic import View from django.utils.encoding import python_2_unicode_compatible +from django.utils.safestring import mark_safe import re import logging @@ -181,24 +182,24 @@ class LogoutView(View, LogoutMixin): else: # build logout message depending of the number of sessions the user logs out if session_nb == 1: - logout_msg = _( + logout_msg = mark_safe(_( "

Logout successful

" "You have successfully logged out from the Central Authentication Service. " "For security reasons, close your web browser." - ) + )) elif session_nb > 1: - logout_msg = _( + logout_msg = mark_safe(_( "

Logout successful

" - "You have successfully logged out from %s sessions of the Central " + "You have successfully logged out from %d sessions of the Central " "Authentication Service. " "For security reasons, close your web browser." - ) % session_nb + ) % session_nb) else: - logout_msg = _( + logout_msg = mark_safe(_( "

Logout successful

" "You were already logged out from the Central Authentication Service. " "For security reasons, close your web browser." - ) + )) # depending of settings, redirect to the login page with a logout message or display # the logout page. The default is to display tge logout page. From 5811d6435c4af32d99edbfb917494665161c6a96 Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Fri, 17 Nov 2017 15:29:19 +0100 Subject: [PATCH 12/12] Update version to 0.9.0 --- CHANGELOG.rst | 4 ++-- cas_server/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ff7acae..9e60767 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,8 +7,8 @@ All notable changes to this project will be documented in this file. :depth: 2 -Unreleased -========== +v0.9.0 - 2017-11-17 +=================== Added ----- diff --git a/cas_server/__init__.py b/cas_server/__init__.py index 07db413..da8813c 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 = '0.8.0' +VERSION = '0.9.0' #: path the the application configuration class default_app_config = 'cas_server.apps.CasAppConfig'