misc: remove six module usage (#52503)
This commit is contained in:
parent
8b506d4281
commit
4751846fed
|
@ -29,7 +29,6 @@ Depends: ${misc:Depends}, ${python3:Depends},
|
||||||
python3-djangorestframework (<< 3.10),
|
python3-djangorestframework (<< 3.10),
|
||||||
python3-markdown (>= 2.1),
|
python3-markdown (>= 2.1),
|
||||||
python3-ldap (>= 2.4),
|
python3-ldap (>= 2.4),
|
||||||
python3-six (>= 1.0),
|
|
||||||
python3-jwcrypto (>= 0.3.1),
|
python3-jwcrypto (>= 0.3.1),
|
||||||
python3-cryptography (>= 1.3.4),
|
python3-cryptography (>= 1.3.4),
|
||||||
python3-django-filters (>= 1),
|
python3-django-filters (>= 1),
|
||||||
|
|
|
@ -9,7 +9,6 @@ XStatic_jQuery python3-xstatic-jquery
|
||||||
XStatic_jquery_ui python3-xstatic-jquery-ui
|
XStatic_jquery_ui python3-xstatic-jquery-ui
|
||||||
django-import-export python3-django-import-export
|
django-import-export python3-django-import-export
|
||||||
django-sekizai python3-django-sekizai
|
django-sekizai python3-django-sekizai
|
||||||
six python3-six
|
|
||||||
pycryptodome python3-pycryptodome
|
pycryptodome python3-pycryptodome
|
||||||
ldaptools python3-ldaptools
|
ldaptools python3-ldaptools
|
||||||
django-mellon python3-django-mellon
|
django-mellon python3-django-mellon
|
||||||
|
|
|
@ -23,7 +23,6 @@ The other Authentic 2 dependencies are:
|
||||||
- gadjo>=0.6
|
- gadjo>=0.6
|
||||||
- django-import-export>=0.2.7,<=0.4.5
|
- django-import-export>=0.2.7,<=0.4.5
|
||||||
- djangorestframework>=3.3
|
- djangorestframework>=3.3
|
||||||
- six>=1.9
|
|
||||||
- Markdown>=2.5
|
- Markdown>=2.5
|
||||||
- python-ldap
|
- python-ldap
|
||||||
|
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -129,7 +129,6 @@ setup(
|
||||||
'gadjo>=0.53',
|
'gadjo>=0.53',
|
||||||
'django-import-export>=1,<2',
|
'django-import-export>=1,<2',
|
||||||
'djangorestframework>=3.3,<3.10',
|
'djangorestframework>=3.3,<3.10',
|
||||||
'six>=1',
|
|
||||||
'Markdown>=2.1',
|
'Markdown>=2.1',
|
||||||
'python-ldap',
|
'python-ldap',
|
||||||
'django-filter>1,<2.3',
|
'django-filter>1,<2.3',
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
@ -90,7 +89,7 @@ class PermissionAdmin(admin.ModelAdmin):
|
||||||
list_select_related = True
|
list_select_related = True
|
||||||
|
|
||||||
def name(self, obj):
|
def name(self, obj):
|
||||||
return six.text_type(obj)
|
return str(obj)
|
||||||
|
|
||||||
name.short_description = _('name')
|
name.short_description = _('name')
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.utils import six
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -41,9 +40,9 @@ def update_ou_admin_roles(ou):
|
||||||
# do not create scoped admin roles if the model is not scopable
|
# do not create scoped admin roles if the model is not scopable
|
||||||
if not ou_model:
|
if not ou_model:
|
||||||
continue
|
continue
|
||||||
name = six.text_type(MANAGED_CT[key]['name'])
|
name = str(MANAGED_CT[key]['name'])
|
||||||
slug = '_a2-' + slugify(name)
|
slug = '_a2-' + slugify(name)
|
||||||
scoped_name = six.text_type(MANAGED_CT[key]['scoped_name'])
|
scoped_name = str(MANAGED_CT[key]['scoped_name'])
|
||||||
name = scoped_name.format(ou=ou)
|
name = scoped_name.format(ou=ou)
|
||||||
ou_slug = slug + '-' + ou.slug
|
ou_slug = slug + '-' + ou.slug
|
||||||
if app_settings.MANAGED_CONTENT_TYPES == ():
|
if app_settings.MANAGED_CONTENT_TYPES == ():
|
||||||
|
@ -123,7 +122,7 @@ def update_content_types_roles():
|
||||||
if ct_tuple not in MANAGED_CT:
|
if ct_tuple not in MANAGED_CT:
|
||||||
continue
|
continue
|
||||||
# General admin role
|
# General admin role
|
||||||
name = six.text_type(MANAGED_CT[ct_tuple]['name'])
|
name = str(MANAGED_CT[ct_tuple]['name'])
|
||||||
slug = '_a2-' + slugify(name)
|
slug = '_a2-' + slugify(name)
|
||||||
if (
|
if (
|
||||||
app_settings.MANAGED_CONTENT_TYPES is not None
|
app_settings.MANAGED_CONTENT_TYPES is not None
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
from django.utils.six import text_type
|
|
||||||
|
|
||||||
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP
|
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP
|
||||||
from django_rbac.models import CHANGE_OP
|
from django_rbac.models import CHANGE_OP
|
||||||
|
@ -14,8 +13,8 @@ def update_self_administration_perm(apps, schema_editor):
|
||||||
Permission = apps.get_model('a2_rbac', 'Permission')
|
Permission = apps.get_model('a2_rbac', 'Permission')
|
||||||
Operation = apps.get_model('django_rbac', 'Operation')
|
Operation = apps.get_model('django_rbac', 'Operation')
|
||||||
ContentType = apps.get_model('contenttypes', 'ContentType')
|
ContentType = apps.get_model('contenttypes', 'ContentType')
|
||||||
change_op, _ = Operation.objects.get_or_create(slug=text_type(CHANGE_OP.slug))
|
change_op, _ = Operation.objects.get_or_create(slug=str(CHANGE_OP.slug))
|
||||||
manage_members_op, _ = Operation.objects.get_or_create(slug=text_type(MANAGE_MEMBERS_OP.slug))
|
manage_members_op, _ = Operation.objects.get_or_create(slug=str(MANAGE_MEMBERS_OP.slug))
|
||||||
ct = ContentType.objects.get_for_model(Role)
|
ct = ContentType.objects.get_for_model(Role)
|
||||||
perms_to_delete = []
|
perms_to_delete = []
|
||||||
for role in Role.objects.all():
|
for role in Role.objects.all():
|
||||||
|
|
|
@ -20,7 +20,6 @@ from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import pgettext_lazy
|
from django.utils.translation import pgettext_lazy
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -248,8 +247,8 @@ class Role(RoleAbstractBase):
|
||||||
|
|
||||||
admin_role = self.__class__.objects.get_admin_role(
|
admin_role = self.__class__.objects.get_admin_role(
|
||||||
self,
|
self,
|
||||||
name=_('Managers of role "{role}"').format(role=six.text_type(self)),
|
name=_('Managers of role "{role}"').format(role=str(self)),
|
||||||
slug='_a2-managers-of-role-{role}'.format(role=slugify(six.text_type(self))),
|
slug='_a2-managers-of-role-{role}'.format(role=slugify(str(self))),
|
||||||
permissions=(view_user_perm,),
|
permissions=(view_user_perm,),
|
||||||
self_administered=True,
|
self_administered=True,
|
||||||
update_name=True,
|
update_name=True,
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import six
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ class Setting(object):
|
||||||
|
|
||||||
def __init__(self, default=SENTINEL, definition='', names=None):
|
def __init__(self, default=SENTINEL, definition='', names=None):
|
||||||
self.names = names or []
|
self.names = names or []
|
||||||
if isinstance(self.names, six.string_types):
|
if isinstance(self.names, str):
|
||||||
self.names = [self.names]
|
self.names = [self.names]
|
||||||
self.names = set(self.names)
|
self.names = set(self.names)
|
||||||
self.default = default
|
self.default = default
|
||||||
|
|
|
@ -28,7 +28,7 @@ from django.core.files.storage import default_storage
|
||||||
from django.core.validators import RegexValidator
|
from django.core.validators import RegexValidator
|
||||||
from django.db.models import query
|
from django.db.models import query
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import formats, html, six
|
from django.utils import formats, html
|
||||||
from django.utils.functional import keep_lazy
|
from django.utils.functional import keep_lazy
|
||||||
from django.utils.translation import pgettext_lazy
|
from django.utils.translation import pgettext_lazy
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -42,7 +42,7 @@ from .forms import fields, widgets
|
||||||
from .plugins import collect_from_plugins
|
from .plugins import collect_from_plugins
|
||||||
|
|
||||||
|
|
||||||
@keep_lazy(six.text_type)
|
@keep_lazy(str)
|
||||||
def capfirst(value):
|
def capfirst(value):
|
||||||
return value and value[0].upper() + value[1:]
|
return value and value[0].upper() + value[1:]
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class DateRestField(serializers.DateField):
|
||||||
# Test for the empty string here so that it does not get validated,
|
# Test for the empty string here so that it does not get validated,
|
||||||
# and so that subclasses do not need to handle it explicitly
|
# and so that subclasses do not need to handle it explicitly
|
||||||
# inside the `to_internal_value()` method.
|
# inside the `to_internal_value()` method.
|
||||||
if data == '' or (self.trim_whitespace and six.text_type(data).strip() == ''):
|
if data == '' or (self.trim_whitespace and str(data).strip() == ''):
|
||||||
if not self.allow_blank:
|
if not self.allow_blank:
|
||||||
self.fail('blank')
|
self.fail('blank')
|
||||||
return ''
|
return ''
|
||||||
|
|
|
@ -16,11 +16,8 @@
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
|
class BaseAttributeSource(object, metaclass=abc.ABCMeta):
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class BaseAttributeSource(object):
|
|
||||||
"""
|
"""
|
||||||
Base class for attribute sources
|
Base class for attribute sources
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django_rbac.utils import get_role_model
|
from django_rbac.utils import get_role_model
|
||||||
|
@ -91,7 +90,7 @@ def get_attributes(instance, ctx):
|
||||||
ctx['django_user_' + str(av.attribute.name)] = serialized
|
ctx['django_user_' + str(av.attribute.name)] = serialized
|
||||||
ctx['django_user_' + str(av.attribute.name) + ':verified'] = av.verified
|
ctx['django_user_' + str(av.attribute.name) + ':verified'] = av.verified
|
||||||
ctx['django_user_groups'] = [group for group in user.groups.all()]
|
ctx['django_user_groups'] = [group for group in user.groups.all()]
|
||||||
ctx['django_user_group_names'] = [six.text_type(group) for group in user.groups.all()]
|
ctx['django_user_group_names'] = [str(group) for group in user.groups.all()]
|
||||||
if user.username:
|
if user.username:
|
||||||
splitted = user.username.rsplit('@', 1)
|
splitted = user.username.rsplit('@', 1)
|
||||||
ctx['django_user_domain'] = splitted[1] if '@' in user.username else ''
|
ctx['django_user_domain'] = splitted[1] if '@' in user.username else ''
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import six
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from ...decorators import to_list
|
from ...decorators import to_list
|
||||||
|
@ -62,7 +61,7 @@ def get_instances(ctx):
|
||||||
config_error(UNEXPECTED_KEYS_ERROR, unexpected)
|
config_error(UNEXPECTED_KEYS_ERROR, unexpected)
|
||||||
if 'name' not in keys or 'template' not in keys:
|
if 'name' not in keys or 'template' not in keys:
|
||||||
config_error(BAD_CONFIG_ERROR)
|
config_error(BAD_CONFIG_ERROR)
|
||||||
if not isinstance(d['template'], six.string_types):
|
if not isinstance(d['template'], str):
|
||||||
config_error(TYPE_ERROR)
|
config_error(TYPE_ERROR)
|
||||||
yield d
|
yield d
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from django.utils.deprecation import CallableTrue
|
from django.utils.deprecation import CallableTrue
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -71,8 +69,7 @@ class Authentic2Authentication(BasicAuthentication):
|
||||||
pass
|
pass
|
||||||
# try BasicAuthentication
|
# try BasicAuthentication
|
||||||
if (
|
if (
|
||||||
six.PY3
|
'request'
|
||||||
and 'request'
|
|
||||||
in inspect.signature(super(Authentic2Authentication, self).authenticate_credentials).parameters
|
in inspect.signature(super(Authentic2Authentication, self).authenticate_credentials).parameters
|
||||||
):
|
):
|
||||||
# compatibility with DRF 3.4
|
# compatibility with DRF 3.4
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ldap
|
import ldap
|
||||||
|
@ -36,6 +37,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
@ -43,9 +45,7 @@ from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ngettext
|
from django.utils.translation import ngettext
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ elif PYTHON_LDAP3 is False:
|
||||||
def map_text(d):
|
def map_text(d):
|
||||||
if d is None:
|
if d is None:
|
||||||
return d
|
return d
|
||||||
elif isinstance(d, six.string_types):
|
elif isinstance(d, str):
|
||||||
return force_text(d)
|
return force_text(d)
|
||||||
elif isinstance(d, (list, tuple)):
|
elif isinstance(d, (list, tuple)):
|
||||||
return d.__class__(map_text(x) for x in d)
|
return d.__class__(map_text(x) for x in d)
|
||||||
|
@ -1031,7 +1031,7 @@ class LDAPBackend(object):
|
||||||
'''Obtain a Django role'''
|
'''Obtain a Django role'''
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
slug = None
|
slug = None
|
||||||
if isinstance(role_id, six.string_types):
|
if isinstance(role_id, str):
|
||||||
slug = role_id
|
slug = role_id
|
||||||
elif isinstance(role_id, (tuple, list)):
|
elif isinstance(role_id, (tuple, list)):
|
||||||
try:
|
try:
|
||||||
|
@ -1302,7 +1302,7 @@ class LDAPBackend(object):
|
||||||
attribute, param = attribute.split(':')
|
attribute, param = attribute.split(':')
|
||||||
quote = 'noquote' not in param.split(',')
|
quote = 'noquote' not in param.split(',')
|
||||||
if quote:
|
if quote:
|
||||||
decoded.append((attribute, urlparse.unquote(value)))
|
decoded.append((attribute, urllib.parse.unquote(value)))
|
||||||
else:
|
else:
|
||||||
decoded.append((attribute, force_text(value)))
|
decoded.append((attribute, force_text(value)))
|
||||||
filters = [filter_format(u'(%s=%s)', (a, b)) for a, b in decoded]
|
filters = [filter_format(u'(%s=%s)', (a, b)) for a, b in decoded]
|
||||||
|
@ -1322,7 +1322,7 @@ class LDAPBackend(object):
|
||||||
if isinstance(part, list):
|
if isinstance(part, list):
|
||||||
part = part[0]
|
part = part[0]
|
||||||
if quote:
|
if quote:
|
||||||
part = urlparse.quote(part.encode('utf-8'))
|
part = urllib.parse.quote(part.encode('utf-8'))
|
||||||
parts.append(part)
|
parts.append(part)
|
||||||
return ' '.join(part for part in parts)
|
return ' '.join(part for part in parts)
|
||||||
|
|
||||||
|
@ -1676,7 +1676,7 @@ class LDAPBackend(object):
|
||||||
|
|
||||||
# convert string to list of strings for settings accepting it
|
# convert string to list of strings for settings accepting it
|
||||||
for i in cls._TO_ITERABLE:
|
for i in cls._TO_ITERABLE:
|
||||||
if i in block and isinstance(block[i], six.string_types):
|
if i in block and isinstance(block[i], str):
|
||||||
block[i] = (block[i],)
|
block[i] = (block[i],)
|
||||||
|
|
||||||
for d in cls._DEFAULTS:
|
for d in cls._DEFAULTS:
|
||||||
|
@ -1685,8 +1685,8 @@ class LDAPBackend(object):
|
||||||
if d == 'user_filter' and app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
|
if d == 'user_filter' and app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
|
||||||
block[d] = '(|(mail=%s)(uid=%s))'
|
block[d] = '(|(mail=%s)(uid=%s))'
|
||||||
else:
|
else:
|
||||||
if isinstance(cls._DEFAULTS[d], six.string_types):
|
if isinstance(cls._DEFAULTS[d], str):
|
||||||
if not isinstance(block[d], six.string_types):
|
if not isinstance(block[d], str):
|
||||||
raise ImproperlyConfigured('LDAP_AUTH_SETTINGS: attribute %r must be a string' % d)
|
raise ImproperlyConfigured('LDAP_AUTH_SETTINGS: attribute %r must be a string' % d)
|
||||||
try:
|
try:
|
||||||
block[d] = force_text(block[d])
|
block[d] = force_text(block[d])
|
||||||
|
@ -1710,7 +1710,7 @@ class LDAPBackend(object):
|
||||||
for key in cls._TO_LOWERCASE:
|
for key in cls._TO_LOWERCASE:
|
||||||
# we handle strings, list of strings and list of list or tuple whose first element is a
|
# we handle strings, list of strings and list of list or tuple whose first element is a
|
||||||
# string
|
# string
|
||||||
if isinstance(block[key], six.string_types):
|
if isinstance(block[key], str):
|
||||||
block[key] = force_text(block[key]).lower()
|
block[key] = force_text(block[key]).lower()
|
||||||
elif isinstance(block[key], (list, tuple)):
|
elif isinstance(block[key], (list, tuple)):
|
||||||
new_seq = []
|
new_seq = []
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import functools
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
from authentic2.backends import get_user_queryset
|
from authentic2.backends import get_user_queryset
|
||||||
from authentic2.user_login_failure import user_login_failure, user_login_success
|
from authentic2.user_login_failure import user_login_failure, user_login_success
|
||||||
|
@ -58,7 +59,7 @@ class ModelBackend(ModelBackend):
|
||||||
queries.append(models.Q(**{username_field: upn(username, realm)}))
|
queries.append(models.Q(**{username_field: upn(username, realm)}))
|
||||||
else:
|
else:
|
||||||
queries.append(models.Q(**{username_field: upn(username, realm)}))
|
queries.append(models.Q(**{username_field: upn(username, realm)}))
|
||||||
queries = six.moves.reduce(models.Q.__or__, queries)
|
queries = functools.reduce(models.Q.__or__, queries)
|
||||||
if ou:
|
if ou:
|
||||||
queries &= models.Q(ou=ou)
|
queries &= models.Q(ou=ou)
|
||||||
return queries
|
return queries
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
|
|
||||||
from . import app_settings, plugins
|
from . import app_settings, plugins
|
||||||
from .decorators import SessionCache
|
from .decorators import SessionCache
|
||||||
|
@ -24,7 +25,7 @@ from .decorators import SessionCache
|
||||||
|
|
||||||
def make_origin(url):
|
def make_origin(url):
|
||||||
'''Build origin of an URL'''
|
'''Build origin of an URL'''
|
||||||
parsed = urlparse.urlparse(url)
|
parsed = urllib.parse.urlparse(url)
|
||||||
if ':' in parsed.netloc:
|
if ':' in parsed.netloc:
|
||||||
host, port = parsed.netloc.split(':', 1)
|
host, port = parsed.netloc.split(':', 1)
|
||||||
if parsed.scheme == 'http' and port == 80:
|
if parsed.scheme == 'http' and port == 80:
|
||||||
|
|
|
@ -26,7 +26,6 @@ from Cryptodome.Hash import HMAC, SHA256
|
||||||
from Cryptodome.Protocol.KDF import PBKDF2
|
from Cryptodome.Protocol.KDF import PBKDF2
|
||||||
from django.utils.crypto import constant_time_compare
|
from django.utils.crypto import constant_time_compare
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
from django.utils.six import text_type
|
|
||||||
|
|
||||||
|
|
||||||
class DecryptionError(Exception):
|
class DecryptionError(Exception):
|
||||||
|
@ -123,7 +122,7 @@ def aes_base64url_deterministic_encrypt(key, data, salt, hash_name='sha256', cou
|
||||||
key_size = 16
|
key_size = 16
|
||||||
hmac_size = key_size
|
hmac_size = key_size
|
||||||
|
|
||||||
if isinstance(salt, text_type):
|
if isinstance(salt, str):
|
||||||
salt = force_bytes(salt)
|
salt = force_bytes(salt)
|
||||||
iv = hashmod.new(salt).digest()
|
iv = hashmod.new(salt).digest()
|
||||||
|
|
||||||
|
@ -174,7 +173,7 @@ def aes_base64url_deterministic_decrypt(key, urlencoded, salt, raise_on_error=Tr
|
||||||
if not crypted or not hmac or prf(key, crypted)[:hmac_size] != hmac:
|
if not crypted or not hmac or prf(key, crypted)[:hmac_size] != hmac:
|
||||||
raise DecryptionError('invalid HMAC')
|
raise DecryptionError('invalid HMAC')
|
||||||
|
|
||||||
if isinstance(salt, text_type):
|
if isinstance(salt, str):
|
||||||
salt = force_bytes(salt)
|
salt = force_bytes(salt)
|
||||||
iv = hashmod.new(salt).digest()
|
iv = hashmod.new(salt).digest()
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ from django.core.exceptions import FieldDoesNotExist, ValidationError
|
||||||
from django.core.validators import RegexValidator
|
from django.core.validators import RegexValidator
|
||||||
from django.db import IntegrityError, models
|
from django.db import IntegrityError, models
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
@ -109,9 +108,9 @@ class CsvImporter(object):
|
||||||
encoding = None
|
encoding = None
|
||||||
|
|
||||||
def run(self, fd_or_str, encoding):
|
def run(self, fd_or_str, encoding):
|
||||||
if isinstance(fd_or_str, six.binary_type):
|
if isinstance(fd_or_str, bytes):
|
||||||
input_fd = io.BytesIO(fd_or_str)
|
input_fd = io.BytesIO(fd_or_str)
|
||||||
elif isinstance(fd_or_str, six.text_type):
|
elif isinstance(fd_or_str, str):
|
||||||
input_fd = io.StringIO(fd_or_str)
|
input_fd = io.StringIO(fd_or_str)
|
||||||
elif not hasattr(fd_or_str, 'read1'):
|
elif not hasattr(fd_or_str, 'read1'):
|
||||||
try:
|
try:
|
||||||
|
@ -122,7 +121,7 @@ class CsvImporter(object):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
content = fd_or_str.read()
|
content = fd_or_str.read()
|
||||||
if isinstance(content, six.text_type):
|
if isinstance(content, str):
|
||||||
input_fd = io.StringIO(content)
|
input_fd = io.StringIO(content)
|
||||||
else:
|
else:
|
||||||
input_fd = io.BytesIO(content)
|
input_fd = io.BytesIO(content)
|
||||||
|
@ -539,7 +538,7 @@ class UserCsvImporter(object):
|
||||||
form.is_valid()
|
form.is_valid()
|
||||||
|
|
||||||
def get_form_errors(form, name):
|
def get_form_errors(form, name):
|
||||||
return [Error('data-error', six.text_type(value)) for value in form.errors.get(name, [])]
|
return [Error('data-error', str(value)) for value in form.errors.get(name, [])]
|
||||||
|
|
||||||
cells = [
|
cells = [
|
||||||
CsvCell(
|
CsvCell(
|
||||||
|
|
|
@ -24,7 +24,7 @@ import os
|
||||||
from django.core.exceptions import MultipleObjectsReturned, ValidationError
|
from django.core.exceptions import MultipleObjectsReturned, ValidationError
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.utils import six, timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -233,7 +233,7 @@ class User(AbstractBaseUser, PermissionMixin):
|
||||||
return '%s (%s)' % (human_name, short_id)
|
return '%s (%s)' % (human_name, short_id)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<User: %r>' % six.text_type(self)
|
return '<User: %r>' % str(self)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if not (self.username or self.email or (self.first_name and self.last_name)):
|
if not (self.username or self.email or (self.first_name and self.last_name)):
|
||||||
|
|
|
@ -25,7 +25,6 @@ from json import dumps as json_dumps
|
||||||
from django.core.cache import cache as django_cache
|
from django.core.cache import cache as django_cache
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
||||||
from django.utils import six
|
|
||||||
from django.views.debug import technical_404_response
|
from django.views.debug import technical_404_response
|
||||||
|
|
||||||
from . import app_settings, middleware
|
from . import app_settings, middleware
|
||||||
|
@ -195,12 +194,12 @@ class CacheDecoratorBase(object):
|
||||||
for i, arg in enumerate(args):
|
for i, arg in enumerate(args):
|
||||||
if self.args and i not in self.args:
|
if self.args and i not in self.args:
|
||||||
continue
|
continue
|
||||||
parts.append(six.text_type(arg))
|
parts.append(str(arg))
|
||||||
|
|
||||||
for kw, arg in sorted(kwargs.items(), key=lambda x: x[0]):
|
for kw, arg in sorted(kwargs.items(), key=lambda x: x[0]):
|
||||||
if kw not in self.kwargs:
|
if kw not in self.kwargs:
|
||||||
continue
|
continue
|
||||||
parts.append(u'%s-%s' % (six.text_type(kw), six.text_type(arg)))
|
parts.append(u'%s-%s' % (str(kw), str(arg)))
|
||||||
return u'|'.join(parts)
|
return u'|'.join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,13 @@
|
||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import urllib.parse
|
||||||
from xml.dom.minidom import parseString
|
from xml.dom.minidom import parseString
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from authentic2 import settings
|
from authentic2 import settings
|
||||||
|
@ -117,21 +117,21 @@ def get_disco_return_url_from_metadata(entity_id):
|
||||||
|
|
||||||
|
|
||||||
def is_param_id_in_return_url(return_url, returnIDParam):
|
def is_param_id_in_return_url(return_url, returnIDParam):
|
||||||
url = urlparse.urlparse(return_url)
|
url = urllib.parse.urlparse(return_url)
|
||||||
if url.query and returnIDParam in urlparse.parse_qs(url.query):
|
if url.query and returnIDParam in urllib.parse.parse_qs(url.query):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def add_param_to_url(url, param_name, value):
|
def add_param_to_url(url, param_name, value):
|
||||||
scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
|
scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url)
|
||||||
if query:
|
if query:
|
||||||
qs = urlparse.parse_qs(query)
|
qs = urllib.parse.parse_qs(query)
|
||||||
qs[param_name] = [value]
|
qs[param_name] = [value]
|
||||||
query = urlparse.urlencode(qs)
|
query = urlparse.urlencode(qs)
|
||||||
else:
|
else:
|
||||||
query = '%s=%s' % (param_name, value)
|
query = '%s=%s' % (param_name, value)
|
||||||
return urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
|
return urllib.parse.urlunparse((scheme, netloc, path, params, query, fragment))
|
||||||
|
|
||||||
|
|
||||||
def disco(request):
|
def disco(request):
|
||||||
|
|
|
@ -19,7 +19,6 @@ import logging
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class ExponentialRetryTimeout(object):
|
class ExponentialRetryTimeout(object):
|
||||||
|
@ -45,7 +44,7 @@ class ExponentialRetryTimeout(object):
|
||||||
self.key_prefix = key_prefix
|
self.key_prefix = key_prefix
|
||||||
|
|
||||||
def key(self, keys):
|
def key(self, keys):
|
||||||
key = u'-'.join(six.text_type(key) for key in keys)
|
key = u'-'.join(str(key) for key in keys)
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
return '%s%s' % (self.key_prefix or self.KEY_PREFIX, hashlib.md5(key).hexdigest())
|
return '%s%s' % (self.key_prefix or self.KEY_PREFIX, hashlib.md5(key).hexdigest())
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,15 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import functools
|
||||||
import logging
|
import logging
|
||||||
import operator
|
import operator
|
||||||
import random
|
import random
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six
|
|
||||||
from django.utils.six.moves.urllib.parse import quote
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
import authentic2.idp.saml.saml2_endpoints as saml2_endpoints
|
import authentic2.idp.saml.saml2_endpoints as saml2_endpoints
|
||||||
|
@ -68,7 +68,7 @@ class SamlBackend(object):
|
||||||
queries.append(
|
queries.append(
|
||||||
q.filter(sp_options_policy__isnull=True, liberty_provider__entity_id__in=sessions_eids)
|
q.filter(sp_options_policy__isnull=True, liberty_provider__entity_id__in=sessions_eids)
|
||||||
)
|
)
|
||||||
qs = six.moves.reduce(operator.__or__, queries)
|
qs = functools.reduce(operator.__or__, queries)
|
||||||
# do some prefetching
|
# do some prefetching
|
||||||
qs = qs.prefetch_related('liberty_provider')
|
qs = qs.prefetch_related('liberty_provider')
|
||||||
qs = qs.select_related('sp_options_policy')
|
qs = qs.select_related('sp_options_policy')
|
||||||
|
|
|
@ -41,6 +41,7 @@ import random
|
||||||
import string
|
import string
|
||||||
import xml.etree.cElementTree as ctree
|
import xml.etree.cElementTree as ctree
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from urllib.parse import quote, urlencode
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
@ -50,9 +51,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseRedirect
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_bytes, force_str, force_text
|
from django.utils.encoding import force_bytes, force_str, force_text
|
||||||
from django.utils.six.moves.urllib.parse import quote, urlencode
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.translation import ugettext_noop as N_
|
from django.utils.translation import ugettext_noop as N_
|
||||||
from django.views.decorators.cache import never_cache
|
from django.views.decorators.cache import never_cache
|
||||||
|
@ -821,7 +820,7 @@ def sso_after_process_request(
|
||||||
if not access_granted:
|
if not access_granted:
|
||||||
logger.debug('access denied, return answer to the requester')
|
logger.debug('access denied, return answer to the requester')
|
||||||
set_saml2_response_responder_status_code(
|
set_saml2_response_responder_status_code(
|
||||||
login.response, lasso.SAML2_STATUS_CODE_REQUEST_DENIED, msg=six.text_type(dic['message'])
|
login.response, lasso.SAML2_STATUS_CODE_REQUEST_DENIED, msg=str(dic['message'])
|
||||||
)
|
)
|
||||||
return finish_sso(request, login)
|
return finish_sso(request, login)
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class RequestContextFilter(logging.Filter):
|
class RequestContextFilter(logging.Filter):
|
||||||
DEFAULT_USERNAME = '-'
|
DEFAULT_USERNAME = '-'
|
||||||
|
@ -45,7 +43,7 @@ class RequestContextFilter(logging.Filter):
|
||||||
|
|
||||||
if not hasattr(record, 'user'):
|
if not hasattr(record, 'user'):
|
||||||
if hasattr(request, 'user') and request.user.is_authenticated:
|
if hasattr(request, 'user') and request.user.is_authenticated:
|
||||||
record.user = six.text_type(request.user)
|
record.user = str(request.user)
|
||||||
else:
|
else:
|
||||||
record.user = self.DEFAULT_USERNAME
|
record.user = self.DEFAULT_USERNAME
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ from django.db import connection
|
||||||
from django.db.models import Count, Q
|
from django.db.models import Count, Q
|
||||||
from django.db.models.functions import Lower
|
from django.db.models.functions import Lower
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
from django.utils.six.moves import input
|
|
||||||
from django.utils.timezone import localtime
|
from django.utils.timezone import localtime
|
||||||
|
|
||||||
from authentic2 import app_settings
|
from authentic2 import app_settings
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import urllib.parse
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -25,7 +26,6 @@ from django.core.management.base import BaseCommand
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
from django.utils import timezone, translation
|
from django.utils import timezone, translation
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
|
|
||||||
from authentic2.backends.ldap_backend import LDAPBackend
|
from authentic2.backends.ldap_backend import LDAPBackend
|
||||||
from authentic2.utils import send_templated_mail
|
from authentic2.utils import send_templated_mail
|
||||||
|
@ -110,7 +110,7 @@ class Command(BaseCommand):
|
||||||
ctx = {
|
ctx = {
|
||||||
'user': user,
|
'user': user,
|
||||||
'days_to_deletion': days_to_deletion,
|
'days_to_deletion': days_to_deletion,
|
||||||
'login_url': urlparse.urljoin(settings.SITE_BASE_URL, settings.LOGIN_URL),
|
'login_url': urllib.parse.urljoin(settings.SITE_BASE_URL, settings.LOGIN_URL),
|
||||||
}
|
}
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
if not self.fake:
|
if not self.fake:
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import io
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.utils import six
|
|
||||||
from ldap.dn import escape_dn_chars
|
from ldap.dn import escape_dn_chars
|
||||||
from ldif import LDIFWriter
|
from ldif import LDIFWriter
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class Command(BaseCommand):
|
||||||
def ldap(self, command, attrs):
|
def ldap(self, command, attrs):
|
||||||
self.logger.debug('received command %s %s', command, attrs)
|
self.logger.debug('received command %s %s', command, attrs)
|
||||||
if command == 'SEARCH':
|
if command == 'SEARCH':
|
||||||
out = six.BytesIO()
|
out = io.BytesIO()
|
||||||
ldif_writer = LDIFWriter(out)
|
ldif_writer = LDIFWriter(out)
|
||||||
qs = get_user_model().objects.all()
|
qs = get_user_model().objects.all()
|
||||||
if attrs['filter'] != '(objectClass=*)':
|
if attrs['filter'] != '(objectClass=*)':
|
||||||
|
@ -85,7 +85,7 @@ class Command(BaseCommand):
|
||||||
for user in qs:
|
for user in qs:
|
||||||
o = {}
|
o = {}
|
||||||
for user_attribute, ldap_attribute in MAPPING.items():
|
for user_attribute, ldap_attribute in MAPPING.items():
|
||||||
o[ldap_attribute] = [six.text_type(getattr(user, user_attribute)).encode('utf-8')]
|
o[ldap_attribute] = [str(getattr(user, user_attribute)).encode('utf-8')]
|
||||||
o['objectClass'] = ['inetOrgPerson']
|
o['objectClass'] = ['inetOrgPerson']
|
||||||
dn = 'uid=%s,%s' % (escape_dn_chars(o['uid'][0]), attrs['suffix'])
|
dn = 'uid=%s,%s' % (escape_dn_chars(o['uid'][0]), attrs['suffix'])
|
||||||
self.logger.debug(u'sending entry %s %s', dn, o)
|
self.logger.debug(u'sending entry %s %s', dn, o)
|
||||||
|
|
|
@ -23,7 +23,6 @@ from django import forms
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils import six
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import pgettext, ugettext
|
from django.utils.translation import pgettext, ugettext
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -67,7 +66,7 @@ class SlugMixin(forms.ModelForm):
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
instance = self.instance
|
instance = self.instance
|
||||||
if not instance.slug:
|
if not instance.slug:
|
||||||
instance.slug = slugify(six.text_type(instance.name)).lstrip('_')
|
instance.slug = slugify(str(instance.name)).lstrip('_')
|
||||||
qs = instance.__class__.objects.all()
|
qs = instance.__class__.objects.all()
|
||||||
if instance.pk:
|
if instance.pk:
|
||||||
qs = qs.exclude(pk=instance.pk)
|
qs = qs.exclude(pk=instance.pk)
|
||||||
|
@ -441,7 +440,7 @@ class OUSearchForm(FormWithRequest):
|
||||||
if self.show_all_ou and (len(self.ou_qs) > 1 or self.search_all_ous):
|
if self.show_all_ou and (len(self.ou_qs) > 1 or self.search_all_ous):
|
||||||
choices.append(('all', all_ou_label))
|
choices.append(('all', all_ou_label))
|
||||||
for ou in self.ou_qs:
|
for ou in self.ou_qs:
|
||||||
choices.append((str(ou.pk), six.text_type(ou)))
|
choices.append((str(ou.pk), str(ou)))
|
||||||
if self.show_none_ou and self.search_all_ous:
|
if self.show_none_ou and self.search_all_ous:
|
||||||
choices.append(('none', pgettext('organizational unit', 'None')))
|
choices.append(('none', pgettext('organizational unit', 'None')))
|
||||||
|
|
||||||
|
@ -703,7 +702,7 @@ class UserImportForm(forms.Form):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def raise_validation_error(error_message):
|
def raise_validation_error(error_message):
|
||||||
message_prefix = ugettext('Invalid import file')
|
message_prefix = ugettext('Invalid import file')
|
||||||
raise forms.ValidationError('%s : %s' % (message_prefix, six.text_type(error_message)))
|
raise forms.ValidationError('%s : %s' % (message_prefix, str(error_message)))
|
||||||
|
|
||||||
|
|
||||||
class UserNewImportForm(UserImportForm):
|
class UserNewImportForm(UserImportForm):
|
||||||
|
|
|
@ -21,7 +21,6 @@ from django.core.exceptions import PermissionDenied, ValidationError
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.generic import FormView
|
from django.views.generic import FormView
|
||||||
|
|
||||||
|
@ -68,7 +67,7 @@ class OrganizationalUnitDetailView(views.BaseDetailView):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
return six.text_type(self.object)
|
return str(self.object)
|
||||||
|
|
||||||
def authorize(self, request, *args, **kwargs):
|
def authorize(self, request, *args, **kwargs):
|
||||||
super(OrganizationalUnitDetailView, self).authorize(request, *args, **kwargs)
|
super(OrganizationalUnitDetailView, self).authorize(request, *args, **kwargs)
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils import six
|
|
||||||
from import_export.fields import Field
|
from import_export.fields import Field
|
||||||
from import_export.resources import ModelResource
|
from import_export.resources import ModelResource
|
||||||
from import_export.widgets import Widget
|
from import_export.widgets import Widget
|
||||||
|
@ -30,7 +29,7 @@ class ListWidget(Widget):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def render(self, value, object):
|
def render(self, value, object):
|
||||||
return u', '.join(six.text_type(v) for v in value.all())
|
return u', '.join(str(v) for v in value.all())
|
||||||
|
|
||||||
|
|
||||||
class UserResource(ModelResource):
|
class UserResource(ModelResource):
|
||||||
|
@ -42,7 +41,7 @@ class UserResource(ModelResource):
|
||||||
result.add(role)
|
result.add(role)
|
||||||
for pr in role.parent_relation.all():
|
for pr in role.parent_relation.all():
|
||||||
result.add(pr.parent)
|
result.add(pr.parent)
|
||||||
return ', '.join(six.text_type(x) for x in result)
|
return ', '.join(str(x) for x in result)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from authentic2.models import Service
|
from authentic2.models import Service
|
||||||
|
@ -53,7 +52,7 @@ class ServiceView(
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
return six.text_type(self.object)
|
return str(self.object)
|
||||||
|
|
||||||
def get_table_queryset(self):
|
def get_table_queryset(self):
|
||||||
return self.object.authorized_roles.all()
|
return self.object.authorized_roles.all()
|
||||||
|
|
|
@ -30,7 +30,6 @@ from atomicwrites import AtomicWriter
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.storage import default_storage
|
from django.core.files.storage import default_storage
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.utils import six
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.timezone import utc
|
from django.utils.timezone import utc
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -225,7 +224,7 @@ class Report(object):
|
||||||
logger.exception('error during report %s:%s run', self.user_import.uuid, self.uuid)
|
logger.exception('error during report %s:%s run', self.user_import.uuid, self.uuid)
|
||||||
state = self.STATE_ERROR
|
state = self.STATE_ERROR
|
||||||
try:
|
try:
|
||||||
exception = six.text_type(e)
|
exception = str(e)
|
||||||
except Exception:
|
except Exception:
|
||||||
exception = repr(repr(e))
|
exception = repr(repr(e))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -26,7 +26,6 @@ from django.db import transaction
|
||||||
from django.forms import MediaDefiningClass
|
from django.forms import MediaDefiningClass
|
||||||
from django.http import Http404, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
@ -62,8 +61,7 @@ class MultipleOUMixin(object):
|
||||||
return super(MultipleOUMixin, self).get_context_data(**kwargs)
|
return super(MultipleOUMixin, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(MediaMixinBase)
|
class MediaMixin(object, metaclass=MediaMixinBase):
|
||||||
class MediaMixin(object):
|
|
||||||
'''Expose needed CSS and JS files as a media object'''
|
'''Expose needed CSS and JS files as a media object'''
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
|
@ -401,7 +399,7 @@ class ModelNameMixin(MediaMixin):
|
||||||
|
|
||||||
def get_instance_name(self):
|
def get_instance_name(self):
|
||||||
if hasattr(self, 'get_object'):
|
if hasattr(self, 'get_object'):
|
||||||
return six.text_type(self.get_object())
|
return str(self.get_object())
|
||||||
return u''
|
return u''
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
@ -674,9 +672,9 @@ class MenuJson(HomepageView):
|
||||||
continue
|
continue
|
||||||
menu_entries.append(
|
menu_entries.append(
|
||||||
{
|
{
|
||||||
'label': six.text_type(entry['label']),
|
'label': str(entry['label']),
|
||||||
'slug': entry.get('slug', ''),
|
'slug': entry.get('slug', ''),
|
||||||
'url': request.build_absolute_uri(six.text_type(entry['href'])),
|
'url': request.build_absolute_uri(str(entry['href'])),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return menu_entries
|
return menu_entries
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import functools
|
||||||
import operator
|
import operator
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django_select2.forms import ModelSelect2MultipleWidget, ModelSelect2Widget
|
from django_select2.forms import ModelSelect2MultipleWidget, ModelSelect2Widget
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class SplitTermMixin(object):
|
||||||
queries = []
|
queries = []
|
||||||
for term in term.split():
|
for term in term.split():
|
||||||
queries.append(super(SplitTermMixin, self).filter_queryset(term, queryset=qs))
|
queries.append(super(SplitTermMixin, self).filter_queryset(term, queryset=qs))
|
||||||
qs = six.moves.reduce(self.split_term_operator, queries)
|
qs = functools.reduce(self.split_term_operator, queries)
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class SearchRoleWidgetMixin(SplitTermMixin):
|
||||||
]
|
]
|
||||||
|
|
||||||
def label_from_instance(self, obj):
|
def label_from_instance(self, obj):
|
||||||
label = six.text_type(obj)
|
label = str(obj)
|
||||||
if obj.ou and utils.get_ou_count() > 1:
|
if obj.ou and utils.get_ou_count() > 1:
|
||||||
label = u'{ou} - {obj}'.format(ou=obj.ou, obj=obj)
|
label = u'{ou} - {obj}'.format(ou=obj.ou, obj=obj)
|
||||||
return label
|
return label
|
||||||
|
|
|
@ -21,12 +21,13 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
threading = None
|
threading = None
|
||||||
|
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from django import http
|
from django import http
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
from django.utils.functional import SimpleLazyObject
|
from django.utils.functional import SimpleLazyObject
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from . import app_settings, plugins, utils
|
from . import app_settings, plugins, utils
|
||||||
|
@ -162,10 +163,10 @@ class DisplayMessageBeforeRedirectMiddleware(MiddlewareMixin):
|
||||||
return response
|
return response
|
||||||
if not getattr(response, 'display_message', True):
|
if not getattr(response, 'display_message', True):
|
||||||
return response
|
return response
|
||||||
parsed_url = urlparse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
if not parsed_url.scheme and not parsed_url.netloc:
|
if not parsed_url.scheme and not parsed_url.netloc:
|
||||||
return response
|
return response
|
||||||
parsed_request_url = urlparse.urlparse(request.build_absolute_uri())
|
parsed_request_url = urllib.parse.urlparse(request.build_absolute_uri())
|
||||||
if (parsed_request_url.scheme == parsed_url.scheme or not parsed_url.scheme) and (
|
if (parsed_request_url.scheme == parsed_url.scheme or not parsed_url.scheme) and (
|
||||||
parsed_request_url.netloc == parsed_url.netloc
|
parsed_request_url.netloc == parsed_url.netloc
|
||||||
):
|
):
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from django.db.migrations.operations.base import Operation
|
from django.db.migrations.operations.base import Operation
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class CreatePartialIndexes(Operation):
|
class CreatePartialIndexes(Operation):
|
||||||
|
@ -64,10 +63,10 @@ class CreatePartialIndexes(Operation):
|
||||||
for clause in where:
|
for clause in where:
|
||||||
if isinstance(clause, tuple):
|
if isinstance(clause, tuple):
|
||||||
clause, params = clause
|
clause, params = clause
|
||||||
assert isinstance(clause, six.string_types)
|
assert isinstance(clause, str)
|
||||||
assert isinstance(params, tuple)
|
assert isinstance(params, tuple)
|
||||||
clause = clause % tuple(schema_editor.quote_value(param) for param in params)
|
clause = clause % tuple(schema_editor.quote_value(param) for param in params)
|
||||||
assert isinstance(clause, six.string_types)
|
assert isinstance(clause, str)
|
||||||
clauses.append(clause)
|
clauses.append(clause)
|
||||||
where_clause = ' AND '.join(clauses)
|
where_clause = ' AND '.join(clauses)
|
||||||
# SQLite does not accept parameters in partial index creations, don't ask why :/
|
# SQLite does not accept parameters in partial index creations, don't ask why :/
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import django
|
import django
|
||||||
|
@ -27,9 +28,8 @@ from django.contrib.postgres.search import SearchVectorField
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models.query import Q
|
from django.db.models.query import Q
|
||||||
from django.utils import six, timezone
|
from django.utils import timezone
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from model_utils.managers import QueryManager
|
from model_utils.managers import QueryManager
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ class LogoutUrlAbstract(models.Model):
|
||||||
|
|
||||||
def get_logout_url(self, request):
|
def get_logout_url(self, request):
|
||||||
ok_icon_url = (
|
ok_icon_url = (
|
||||||
request.build_absolute_uri(urlparse.urljoin(settings.STATIC_URL, 'authentic2/images/ok.png'))
|
request.build_absolute_uri(urllib.parse.urljoin(settings.STATIC_URL, 'authentic2/images/ok.png'))
|
||||||
+ '?nonce=%s' % time.time()
|
+ '?nonce=%s' % time.time()
|
||||||
)
|
)
|
||||||
return self.logout_url.format(urlquote(ok_icon_url))
|
return self.logout_url.format(urlquote(ok_icon_url))
|
||||||
|
@ -363,7 +363,7 @@ class PasswordReset(models.Model):
|
||||||
verbose_name_plural = _('password reset')
|
verbose_name_plural = _('password reset')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return six.text_type(self.user)
|
return str(self.user)
|
||||||
|
|
||||||
|
|
||||||
class Service(models.Model):
|
class Service(models.Model):
|
||||||
|
@ -418,7 +418,7 @@ class Service(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %r>' % (self.__class__.__name__, six.text_type(self))
|
return '<%s %r>' % (self.__class__.__name__, str(self))
|
||||||
|
|
||||||
def authorize(self, user):
|
def authorize(self, user):
|
||||||
if not self.authorized_roles.exists():
|
if not self.authorized_roles.exists():
|
||||||
|
@ -492,7 +492,7 @@ class Token(models.Model):
|
||||||
else:
|
else:
|
||||||
return _uuid
|
return _uuid
|
||||||
|
|
||||||
if isinstance(_uuid, six.text_type):
|
if isinstance(_uuid, str):
|
||||||
_uuid = _uuid.encode('ascii')
|
_uuid = _uuid.encode('ascii')
|
||||||
_uuid = base64url_decode(_uuid)
|
_uuid = base64url_decode(_uuid)
|
||||||
return uuid.UUID(bytes=_uuid)
|
return uuid.UUID(bytes=_uuid)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import re
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils import six
|
|
||||||
from django.utils.functional import lazy
|
from django.utils.functional import lazy
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -50,8 +49,7 @@ def generate_password():
|
||||||
return ''.join(new_password)
|
return ''.join(new_password)
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
class PasswordChecker(object, metaclass=abc.ABCMeta):
|
||||||
class PasswordChecker(object):
|
|
||||||
class Check(object):
|
class Check(object):
|
||||||
def __init__(self, label, result):
|
def __init__(self, label, result):
|
||||||
self.label = label
|
self.label = label
|
||||||
|
@ -134,4 +132,4 @@ def password_help_text(password='', only_errors=False):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
password_help_text = lazy(password_help_text, six.text_type)
|
password_help_text = lazy(password_help_text, str)
|
||||||
|
|
|
@ -22,7 +22,6 @@ from django.conf.urls import url
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -72,7 +71,7 @@ class TextAndFileWidget(forms.widgets.MultiWidget):
|
||||||
def render(self, name, value, attrs=None, **kwargs):
|
def render(self, name, value, attrs=None, **kwargs):
|
||||||
if attrs is None:
|
if attrs is None:
|
||||||
attrs = {}
|
attrs = {}
|
||||||
if isinstance(value, (str, six.text_type)):
|
if isinstance(value, (str, str)):
|
||||||
attrs['rows'] = value.count('\n') + 5
|
attrs['rows'] = value.count('\n') + 5
|
||||||
attrs['cols'] = min(max((len(x) for x in value.split('\n'))), 150)
|
attrs['cols'] = min(max((len(x) for x in value.split('\n'))), 150)
|
||||||
return super(TextAndFileWidget, self).render(name, value, attrs, **kwargs)
|
return super(TextAndFileWidget, self).render(name, value, attrs, **kwargs)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import functools
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
@ -25,7 +26,6 @@ from django.core.exceptions import ValidationError
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from authentic2.compat_lasso import lasso
|
from authentic2.compat_lasso import lasso
|
||||||
|
@ -337,7 +337,7 @@ def retrieve_metadata_and_create(request, provider_id, sp_or_idp):
|
||||||
return None
|
return None
|
||||||
logger.debug('loaded %d bytes', len(metadata))
|
logger.debug('loaded %d bytes', len(metadata))
|
||||||
try:
|
try:
|
||||||
metadata = six.text_type(metadata, 'utf-8')
|
metadata = str(metadata, 'utf-8')
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
logging.error('SAML metadata autoload: retrieved metadata for entity id %s is not UTF-8', provider_id)
|
logging.error('SAML metadata autoload: retrieved metadata for entity id %s is not UTF-8', provider_id)
|
||||||
return None
|
return None
|
||||||
|
@ -586,5 +586,5 @@ def get_session_not_on_or_after(assertion):
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
if session_not_on_or_afters:
|
if session_not_on_or_afters:
|
||||||
return six.moves.reduce(min, session_not_on_or_afters)
|
return functools.reduce(min, session_not_on_or_afters)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -27,7 +27,6 @@ from django.contrib.humanize.templatetags.humanize import apnumber
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.template.defaultfilters import pluralize
|
from django.template.defaultfilters import pluralize
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ def dumps(value):
|
||||||
# Initial author: Oliver Beattie
|
# Initial author: Oliver Beattie
|
||||||
|
|
||||||
|
|
||||||
class PickledObject(six.text_type):
|
class PickledObject(str):
|
||||||
"""A subclass of string so it can be told whether a string is
|
"""A subclass of string so it can be told whether a string is
|
||||||
a pickled object or not (if the object is an instance of this class
|
a pickled object or not (if the object is an instance of this class
|
||||||
then it must [well, should] be a pickled one)."""
|
then it must [well, should] be a pickled one)."""
|
||||||
|
@ -161,7 +160,7 @@ class MultiSelectField(models.Field):
|
||||||
return MultiSelectFormField(**defaults)
|
return MultiSelectFormField(**defaults)
|
||||||
|
|
||||||
def get_db_prep_value(self, value, connection, prepared=False):
|
def get_db_prep_value(self, value, connection, prepared=False):
|
||||||
if isinstance(value, six.string_types):
|
if isinstance(value, str):
|
||||||
return value
|
return value
|
||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
return ",".join(value)
|
return ",".join(value)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -26,7 +27,6 @@ from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
from django.template.defaultfilters import slugify
|
from django.template.defaultfilters import slugify
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from authentic2.compat_lasso import lasso
|
from authentic2.compat_lasso import lasso
|
||||||
|
@ -340,11 +340,11 @@ Any other kind of attribute filter policy is unsupported.
|
||||||
response = requests.get(metadata_file_path)
|
response = requests.get(metadata_file_path)
|
||||||
if not response.ok:
|
if not response.ok:
|
||||||
raise CommandError('Unable to open url %s' % metadata_file_path)
|
raise CommandError('Unable to open url %s' % metadata_file_path)
|
||||||
metadata_file = six.BytesIO(response.content)
|
metadata_file = io.BytesIO(response.content)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
with open(metadata_file_path, 'rb') as fd:
|
with open(metadata_file_path, 'rb') as fd:
|
||||||
metadata_file = six.BytesIO(fd.read())
|
metadata_file = io.BytesIO(fd.read())
|
||||||
except IOError:
|
except IOError:
|
||||||
raise CommandError('Unable to open file %s' % metadata_file_path)
|
raise CommandError('Unable to open file %s' % metadata_file_path)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_str, force_text
|
from django.utils.encoding import force_str, force_text
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -484,7 +483,7 @@ class LibertyServiceProvider(models.Model):
|
||||||
return (self.liberty_provider.slug,)
|
return (self.liberty_provider.slug,)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return six.text_type(self.liberty_provider)
|
return str(self.liberty_provider)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('SAML service provider')
|
verbose_name = _('SAML service provider')
|
||||||
|
|
|
@ -22,7 +22,6 @@ import re
|
||||||
import time
|
import time
|
||||||
import xml.etree.ElementTree as etree
|
import xml.etree.ElementTree as etree
|
||||||
|
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from authentic2.compat_lasso import lasso
|
from authentic2.compat_lasso import lasso
|
||||||
|
@ -30,14 +29,14 @@ from authentic2.saml import x509utils
|
||||||
|
|
||||||
|
|
||||||
def filter_attribute_private_key(message):
|
def filter_attribute_private_key(message):
|
||||||
if isinstance(message, six.string_types):
|
if isinstance(message, str):
|
||||||
return re.sub(r' (\w+:)?(PrivateKey=")([&#;\w/ +-=])+(")', '', message)
|
return re.sub(r' (\w+:)?(PrivateKey=")([&#;\w/ +-=])+(")', '', message)
|
||||||
else:
|
else:
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
def filter_element_private_key(message):
|
def filter_element_private_key(message):
|
||||||
if isinstance(message, six.string_types):
|
if isinstance(message, str):
|
||||||
return re.sub(
|
return re.sub(
|
||||||
r'(<saml)(p)?(:PrivateKeyFile>-----BEGIN RSA PRIVATE KEY-----)'
|
r'(<saml)(p)?(:PrivateKeyFile>-----BEGIN RSA PRIVATE KEY-----)'
|
||||||
r'([&#;\w/+=\s])+'
|
r'([&#;\w/+=\s])+'
|
||||||
|
|
|
@ -19,14 +19,12 @@ import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
_openssl = 'openssl'
|
_openssl = 'openssl'
|
||||||
|
|
||||||
|
|
||||||
def decapsulate_pem_file(file_or_string):
|
def decapsulate_pem_file(file_or_string):
|
||||||
'''Remove PEM header lines'''
|
'''Remove PEM header lines'''
|
||||||
if not isinstance(file_or_string, six.string_types):
|
if not isinstance(file_or_string, str):
|
||||||
content = file_or_string.read()
|
content = file_or_string.read()
|
||||||
else:
|
else:
|
||||||
content = file_or_string
|
content = file_or_string
|
||||||
|
|
|
@ -23,7 +23,6 @@ from django.core.serializers.base import DeserializationError
|
||||||
from django.core.serializers.json import Serializer as JSONSerializer
|
from django.core.serializers.json import Serializer as JSONSerializer
|
||||||
from django.core.serializers.python import _get_model
|
from django.core.serializers.python import _get_model
|
||||||
from django.db import DEFAULT_DB_ALIAS
|
from django.db import DEFAULT_DB_ALIAS
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class Serializer(JSONSerializer):
|
class Serializer(JSONSerializer):
|
||||||
|
@ -73,7 +72,7 @@ def Deserializer(stream_or_string, **options):
|
||||||
"""
|
"""
|
||||||
from django.core.serializers.python import Deserializer as PythonDeserializer
|
from django.core.serializers.python import Deserializer as PythonDeserializer
|
||||||
|
|
||||||
if not isinstance(stream_or_string, (bytes, six.string_types)):
|
if not isinstance(stream_or_string, (bytes, str)):
|
||||||
stream_or_string = stream_or_string.read()
|
stream_or_string = stream_or_string.read()
|
||||||
if isinstance(stream_or_string, bytes):
|
if isinstance(stream_or_string, bytes):
|
||||||
stream_or_string = stream_or_string.decode('utf-8')
|
stream_or_string = stream_or_string.decode('utf-8')
|
||||||
|
@ -85,5 +84,4 @@ def Deserializer(stream_or_string, **options):
|
||||||
except GeneratorExit:
|
except GeneratorExit:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Map to deserializer error
|
raise DeserializationError(e)
|
||||||
six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import ctypes
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
@ -40,10 +41,9 @@ from django.shortcuts import render, resolve_url
|
||||||
from django.template.context import make_context
|
from django.template.context import make_context
|
||||||
from django.template.loader import TemplateDoesNotExist, render_to_string, select_template
|
from django.template.loader import TemplateDoesNotExist, render_to_string, select_template
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import html, six, timezone
|
from django.utils import html, timezone
|
||||||
from django.utils.encoding import iri_to_uri, uri_to_iri
|
from django.utils.encoding import iri_to_uri, uri_to_iri
|
||||||
from django.utils.formats import localize
|
from django.utils.formats import localize
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ungettext
|
from django.utils.translation import ungettext
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -171,7 +171,7 @@ def get_backends(setting_name='IDP_BACKENDS'):
|
||||||
backends = []
|
backends = []
|
||||||
for backend_path in getattr(app_settings, setting_name):
|
for backend_path in getattr(app_settings, setting_name):
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if not isinstance(backend_path, six.string_types):
|
if not isinstance(backend_path, str):
|
||||||
backend_path, kwargs = backend_path
|
backend_path, kwargs = backend_path
|
||||||
kwargs_settings = getattr(app_settings, setting_name + '_KWARGS', {})
|
kwargs_settings = getattr(app_settings, setting_name + '_KWARGS', {})
|
||||||
backend = load_backend(backend_path, kwargs_settings)
|
backend = load_backend(backend_path, kwargs_settings)
|
||||||
|
@ -232,9 +232,9 @@ def get_authenticator_method(authenticator, method, parameters):
|
||||||
|
|
||||||
def add_arg(url, key, value=None):
|
def add_arg(url, key, value=None):
|
||||||
'''Add a parameter to an URL'''
|
'''Add a parameter to an URL'''
|
||||||
key = urlparse.quote(key)
|
key = urllib.parse.quote(key)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
add = '%s=%s' % (key, urlparse.quote(value))
|
add = '%s=%s' % (key, urllib.parse.quote(value))
|
||||||
else:
|
else:
|
||||||
add = key
|
add = key
|
||||||
if '?' in url:
|
if '?' in url:
|
||||||
|
@ -262,7 +262,7 @@ class Service(object):
|
||||||
|
|
||||||
def field_names(list_of_field_name_and_titles):
|
def field_names(list_of_field_name_and_titles):
|
||||||
for t in list_of_field_name_and_titles:
|
for t in list_of_field_name_and_titles:
|
||||||
if isinstance(t, six.string_types):
|
if isinstance(t, str):
|
||||||
yield t
|
yield t
|
||||||
else:
|
else:
|
||||||
yield t[0]
|
yield t[0]
|
||||||
|
@ -270,7 +270,7 @@ def field_names(list_of_field_name_and_titles):
|
||||||
|
|
||||||
def is_valid_url(url):
|
def is_valid_url(url):
|
||||||
try:
|
try:
|
||||||
parsed = urlparse.urlparse(url)
|
parsed = urllib.parse.urlparse(url)
|
||||||
if parsed.scheme in ('http', 'https', ''):
|
if parsed.scheme in ('http', 'https', ''):
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -307,8 +307,8 @@ def make_url(
|
||||||
else:
|
else:
|
||||||
url = to
|
url = to
|
||||||
url = iri_to_uri(url)
|
url = iri_to_uri(url)
|
||||||
scheme, netloc, path, query_string, o_fragment = urlparse.urlsplit(url)
|
scheme, netloc, path, query_string, o_fragment = urllib.parse.urlsplit(url)
|
||||||
url = uri_to_iri(urlparse.urlunsplit((scheme, netloc, path, '', '')))
|
url = uri_to_iri(urllib.parse.urlunsplit((scheme, netloc, path, '', '')))
|
||||||
fragment = fragment or o_fragment
|
fragment = fragment or o_fragment
|
||||||
# Django < 1.6 compat, query_string is not optional
|
# Django < 1.6 compat, query_string is not optional
|
||||||
url_params = QueryDict(query_string=query_string, mutable=True)
|
url_params = QueryDict(query_string=query_string, mutable=True)
|
||||||
|
@ -348,7 +348,7 @@ def make_url(
|
||||||
if request:
|
if request:
|
||||||
url = request.build_absolute_uri(url)
|
url = request.build_absolute_uri(url)
|
||||||
elif hasattr(settings, 'SITE_BASE_URL'):
|
elif hasattr(settings, 'SITE_BASE_URL'):
|
||||||
url = urlparse.urljoin(settings.SITE_BASE_URL, url)
|
url = urllib.parse.urljoin(settings.SITE_BASE_URL, url)
|
||||||
else:
|
else:
|
||||||
raise TypeError('make_url() absolute cannot be used without request')
|
raise TypeError('make_url() absolute cannot be used without request')
|
||||||
# keep using unicode
|
# keep using unicode
|
||||||
|
@ -426,13 +426,13 @@ def record_authentication_event(request, how, nonce=None):
|
||||||
# explicitly state that the session has been modified
|
# explicitly state that the session has been modified
|
||||||
request.session.modified = True
|
request.session.modified = True
|
||||||
event = {
|
event = {
|
||||||
'who': six.text_type(request.user),
|
'who': str(request.user),
|
||||||
'who_id': getattr(request.user, 'pk', None),
|
'who_id': getattr(request.user, 'pk', None),
|
||||||
'how': how,
|
'how': how,
|
||||||
'when': int(time.time()),
|
'when': int(time.time()),
|
||||||
}
|
}
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'who': six.text_type(request.user)[:80],
|
'who': str(request.user)[:80],
|
||||||
'how': how,
|
'how': how,
|
||||||
}
|
}
|
||||||
nonce = nonce or get_nonce(request)
|
nonce = nonce or get_nonce(request)
|
||||||
|
@ -621,12 +621,12 @@ def to_iter(func):
|
||||||
def normalize_attribute_values(values):
|
def normalize_attribute_values(values):
|
||||||
'''Take a list of values or a single one and normalize it'''
|
'''Take a list of values or a single one and normalize it'''
|
||||||
values_set = set()
|
values_set = set()
|
||||||
if isinstance(values, six.string_types) or not hasattr(values, '__iter__'):
|
if isinstance(values, str) or not hasattr(values, '__iter__'):
|
||||||
values = [values]
|
values = [values]
|
||||||
for value in values:
|
for value in values:
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
value = str(value).lower()
|
value = str(value).lower()
|
||||||
values_set.add(six.text_type(value))
|
values_set.add(str(value))
|
||||||
return values_set
|
return values_set
|
||||||
|
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ def send_templated_mail(
|
||||||
"""
|
"""
|
||||||
from .. import middleware
|
from .. import middleware
|
||||||
|
|
||||||
if isinstance(template_names, six.string_types):
|
if isinstance(template_names, str):
|
||||||
template_names = [template_names]
|
template_names = [template_names]
|
||||||
if per_ou_templates and getattr(user_or_email, 'ou', None):
|
if per_ou_templates and getattr(user_or_email, 'ou', None):
|
||||||
new_template_names = []
|
new_template_names = []
|
||||||
|
@ -1055,7 +1055,7 @@ def select_next_url(request, default, field_name=None, include_post=False, repla
|
||||||
if good_next_url(request, next_url):
|
if good_next_url(request, next_url):
|
||||||
if replace:
|
if replace:
|
||||||
for key, value in replace.items():
|
for key, value in replace.items():
|
||||||
next_url = next_url.replace(key, urlparse.quote(value))
|
next_url = next_url.replace(key, urllib.parse.quote(value))
|
||||||
return next_url
|
return next_url
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
@ -1127,7 +1127,7 @@ def same_origin(url1, url2):
|
||||||
If not scheme and not port are given, port compare is skipped.
|
If not scheme and not port are given, port compare is skipped.
|
||||||
The last two rules allow authorizing complete domains easily.
|
The last two rules allow authorizing complete domains easily.
|
||||||
"""
|
"""
|
||||||
p1, p2 = urlparse.urlparse(url1), urlparse.urlparse(url2)
|
p1, p2 = urllib.parse.urlparse(url1), urllib.parse.urlparse(url2)
|
||||||
p1_host, p1_port = netloc_to_host_port(p1.netloc)
|
p1_host, p1_port = netloc_to_host_port(p1.netloc)
|
||||||
p2_host, p2_port = netloc_to_host_port(p2.netloc)
|
p2_host, p2_port = netloc_to_host_port(p2.netloc)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ except ImportError:
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
|
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +109,7 @@ class BaseExpressionValidator(ast.NodeVisitor):
|
||||||
# set the nearer expr node as the node of the error
|
# set the nearer expr node as the node of the error
|
||||||
if e.node is None and hasattr(node, 'col_offset'):
|
if e.node is None and hasattr(node, 'col_offset'):
|
||||||
e.set_node(node)
|
e.set_node(node)
|
||||||
six.reraise(*sys.exc_info())
|
raise e
|
||||||
|
|
||||||
@lru_cache(maxsize=1024)
|
@lru_cache(maxsize=1024)
|
||||||
def __call__(self, expression):
|
def __call__(self, expression):
|
||||||
|
@ -126,7 +125,7 @@ class BaseExpressionValidator(ast.NodeVisitor):
|
||||||
if e.text is None:
|
if e.text is None:
|
||||||
e.text = expression
|
e.text = expression
|
||||||
e.params = {'expression': expression}
|
e.params = {'expression': expression}
|
||||||
six.reraise(*sys.exc_info())
|
raise e
|
||||||
return compile(tree, expression, mode='eval')
|
return compile(tree, expression, mode='eval')
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,8 +178,7 @@ class ConditionValidator(BaseExpressionValidator):
|
||||||
super(ConditionValidator, self).__init__(
|
super(ConditionValidator, self).__init__(
|
||||||
authorized_nodes=authorized_nodes, forbidden_nodes=forbidden_nodes
|
authorized_nodes=authorized_nodes, forbidden_nodes=forbidden_nodes
|
||||||
)
|
)
|
||||||
if six.PY3:
|
self.authorized_nodes.append(ast.NameConstant)
|
||||||
self.authorized_nodes.append(ast.NameConstant)
|
|
||||||
|
|
||||||
def check_Name(self, node):
|
def check_Name(self, node):
|
||||||
if node.id.startswith('_'):
|
if node.id.startswith('_'):
|
||||||
|
@ -225,7 +223,7 @@ def evaluate_condition(expression, ctx=None, validator=None, on_raise=None):
|
||||||
raise ExpressionError(
|
raise ExpressionError(
|
||||||
_('variable is not defined: %s') % e, code='undefined-variable', text=expression, column=0
|
_('variable is not defined: %s') % e, code='undefined-variable', text=expression, column=0
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
if on_raise is not None:
|
if on_raise is not None:
|
||||||
return on_raise
|
return on_raise
|
||||||
six.reraise(*sys.exc_info())
|
raise e
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import keep_lazy
|
from django.utils.functional import keep_lazy
|
||||||
from django.utils.text import format_lazy
|
from django.utils.text import format_lazy
|
||||||
|
@ -30,7 +29,7 @@ def lazy_join(join, args):
|
||||||
return format_lazy(fstring, *args)
|
return format_lazy(fstring, *args)
|
||||||
|
|
||||||
|
|
||||||
@keep_lazy(six.text_type)
|
@keep_lazy(str)
|
||||||
def lazy_label(default, func):
|
def lazy_label(default, func):
|
||||||
"""Allow using a getter for a label, with late binding.
|
"""Allow using a getter for a label, with late binding.
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ from django.shortcuts import get_object_or_404, render
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six, timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.decorators.cache import never_cache
|
from django.views.decorators.cache import never_cache
|
||||||
from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
|
from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
|
||||||
|
@ -452,7 +452,7 @@ class ProfileView(cbv.TemplateNamesMixin, TemplateView):
|
||||||
value = filter(None, value)
|
value = filter(None, value)
|
||||||
value = [html_value(attribute, at_value) for at_value in value]
|
value = [html_value(attribute, at_value) for at_value in value]
|
||||||
if not title:
|
if not title:
|
||||||
title = six.text_type(attribute)
|
title = str(attribute)
|
||||||
else:
|
else:
|
||||||
# fallback to model attributes
|
# fallback to model attributes
|
||||||
try:
|
try:
|
||||||
|
@ -471,7 +471,7 @@ class ProfileView(cbv.TemplateNamesMixin, TemplateView):
|
||||||
if not isinstance(value, (list, tuple)):
|
if not isinstance(value, (list, tuple)):
|
||||||
value = (value,)
|
value = (value,)
|
||||||
raw_value = value
|
raw_value = value
|
||||||
value = [six.text_type(v) for v in value]
|
value = [str(v) for v in value]
|
||||||
if value or app_settings.A2_PROFILE_DISPLAY_EMPTY_FIELDS:
|
if value or app_settings.A2_PROFILE_DISPLAY_EMPTY_FIELDS:
|
||||||
profile.append((title, value))
|
profile.append((title, value))
|
||||||
attributes.append({'attribute': attribute, 'values': raw_value})
|
attributes.append({'attribute': attribute, 'values': raw_value})
|
||||||
|
|
|
@ -18,11 +18,11 @@ import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
import json
|
import json
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -66,11 +66,11 @@ def parse_id_token(id_token, client_id=None, client_secret=None):
|
||||||
return None, 'id_token is expired'
|
return None, 'id_token is expired'
|
||||||
|
|
||||||
def check_issuer():
|
def check_issuer():
|
||||||
parsed = urlparse.urlparse(app_settings.authorize_url)
|
parsed = urllib.parse.urlparse(app_settings.authorize_url)
|
||||||
if 'iss' not in payload:
|
if 'iss' not in payload:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
parsed_issuer = urlparse.urlparse(payload['iss'])
|
parsed_issuer = urllib.parse.urlparse(payload['iss'])
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
return parsed_issuer.scheme == parsed.scheme and parsed_issuer.netloc == parsed.netloc
|
return parsed_issuer.scheme == parsed.scheme and parsed_issuer.netloc == parsed.netloc
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
@ -31,7 +32,6 @@ from django.http import Http404, HttpResponseRedirect
|
||||||
from django.shortcuts import render, resolve_url
|
from django.shortcuts import render, resolve_url
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import is_safe_url, urlencode
|
from django.utils.http import is_safe_url, urlencode
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.generic import FormView, View
|
from django.views.generic import FormView, View
|
||||||
from requests_oauthlib import OAuth2Session
|
from requests_oauthlib import OAuth2Session
|
||||||
|
@ -509,9 +509,9 @@ class RegistrationView(PopupViewMixin, LoggerMixin, View):
|
||||||
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
|
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
|
||||||
|
|
||||||
# Prevent errors when redirect_to does not contain fc-login-or-link view
|
# Prevent errors when redirect_to does not contain fc-login-or-link view
|
||||||
parsed_redirect_to = urlparse.urlparse(redirect_to)
|
parsed_redirect_to = urllib.parse.urlparse(redirect_to)
|
||||||
if parsed_redirect_to.path == reverse('fc-login-or-link'):
|
if parsed_redirect_to.path == reverse('fc-login-or-link'):
|
||||||
redirect_to = urlparse.parse_qs(parsed_redirect_to.query).get(
|
redirect_to = urllib.parse.parse_qs(parsed_redirect_to.query).get(
|
||||||
REDIRECT_FIELD_NAME, [a2_utils.make_url('auth_homepage')]
|
REDIRECT_FIELD_NAME, [a2_utils.make_url('auth_homepage')]
|
||||||
)[0]
|
)[0]
|
||||||
params = {
|
params = {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import logging
|
||||||
import requests
|
import requests
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
from django.utils import six
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from jwcrypto.jwk import JWK
|
from jwcrypto.jwk import JWK
|
||||||
from jwcrypto.jwt import JWT
|
from jwcrypto.jwt import JWT
|
||||||
|
@ -88,7 +87,7 @@ class OIDCBackend(ModelBackend):
|
||||||
jwt = JWT(jwt=original_id_token, key=key_or_keyset, check_claims={}, algs=algs)
|
jwt = JWT(jwt=original_id_token, key=key_or_keyset, check_claims={}, algs=algs)
|
||||||
jwt.claims
|
jwt.claims
|
||||||
|
|
||||||
if isinstance(id_token.aud, six.text_type) and provider.client_id != id_token.aud:
|
if isinstance(id_token.aud, str) and provider.client_id != id_token.aud:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'auth_oidc: invalid id_token audience %s != provider client_id %s',
|
'auth_oidc: invalid id_token audience %s != provider client_id %s',
|
||||||
id_token.aud,
|
id_token.aud,
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.utils import six
|
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import utc
|
from django.utils.timezone import utc
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from jwcrypto.common import JWException, base64url_encode, json_decode
|
from jwcrypto.common import JWException, base64url_encode, json_decode
|
||||||
|
@ -93,14 +92,14 @@ def parse_id_token(encoded, provider):
|
||||||
|
|
||||||
REQUIRED_ID_TOKEN_KEYS = set(['iss', 'sub', 'aud', 'exp', 'iat'])
|
REQUIRED_ID_TOKEN_KEYS = set(['iss', 'sub', 'aud', 'exp', 'iat'])
|
||||||
KEY_TYPES = {
|
KEY_TYPES = {
|
||||||
'iss': six.text_type,
|
'iss': str,
|
||||||
'sub': six.text_type,
|
'sub': str,
|
||||||
'exp': int,
|
'exp': int,
|
||||||
'iat': int,
|
'iat': int,
|
||||||
'auth_time': int,
|
'auth_time': int,
|
||||||
'nonce': six.text_type,
|
'nonce': str,
|
||||||
'acr': six.text_type,
|
'acr': str,
|
||||||
'azp': six.text_type,
|
'azp': str,
|
||||||
# aud and amr havec specific checks
|
# aud and amr havec specific checks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +119,7 @@ class IDToken(object):
|
||||||
nonce = None
|
nonce = None
|
||||||
|
|
||||||
def __init__(self, encoded):
|
def __init__(self, encoded):
|
||||||
if not isinstance(encoded, (six.binary_type, six.string_types)):
|
if not isinstance(encoded, (bytes, str)):
|
||||||
raise IDTokenError(_('Encoded ID Token must be either binary or string data'))
|
raise IDTokenError(_('Encoded ID Token must be either binary or string data'))
|
||||||
self._encoded = encoded
|
self._encoded = encoded
|
||||||
|
|
||||||
|
@ -139,7 +138,7 @@ class IDToken(object):
|
||||||
if key == 'amr':
|
if key == 'amr':
|
||||||
if not isinstance(decoded['amr'], list):
|
if not isinstance(decoded['amr'], list):
|
||||||
raise IDTokenError(_('invalid amr value: %s') % decoded['amr'])
|
raise IDTokenError(_('invalid amr value: %s') % decoded['amr'])
|
||||||
if not all(isinstance(v, six.text_type) for v in decoded['amr']):
|
if not all(isinstance(v, str) for v in decoded['amr']):
|
||||||
raise IDTokenError(_('invalid amr value: %s') % decoded['amr'])
|
raise IDTokenError(_('invalid amr value: %s') % decoded['amr'])
|
||||||
elif key in KEY_TYPES:
|
elif key in KEY_TYPES:
|
||||||
if not isinstance(decoded[key], KEY_TYPES[key]):
|
if not isinstance(decoded[key], KEY_TYPES[key]):
|
||||||
|
@ -197,7 +196,7 @@ OPENID_CONFIGURATION_REQUIRED = set(
|
||||||
|
|
||||||
|
|
||||||
def check_https(url):
|
def check_https(url):
|
||||||
return urlparse.urlparse(url).scheme == 'https'
|
return urllib.parse.urlparse(url).scheme == 'https'
|
||||||
|
|
||||||
|
|
||||||
def register_issuer(name, issuer=None, openid_configuration=None, verify=True, timeout=None, ou=None):
|
def register_issuer(name, issuer=None, openid_configuration=None, verify=True, timeout=None, ou=None):
|
||||||
|
@ -293,10 +292,12 @@ def register_issuer(name, issuer=None, openid_configuration=None, verify=True, t
|
||||||
|
|
||||||
|
|
||||||
def get_openid_configuration_url(issuer):
|
def get_openid_configuration_url(issuer):
|
||||||
parsed = urlparse.urlparse(issuer)
|
parsed = urllib.parse.urlparse(issuer)
|
||||||
if parsed.query or parsed.fragment or parsed.scheme != 'https':
|
if parsed.query or parsed.fragment or parsed.scheme != 'https':
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_('invalid issuer URL, it must use the https:// scheme and not have a ' 'query or fragment')
|
_('invalid issuer URL, it must use the https:// scheme and not have a ' 'query or fragment')
|
||||||
)
|
)
|
||||||
issuer = urlparse.urlunparse((parsed.scheme, parsed.netloc, parsed.path.rstrip('/'), None, None, None))
|
issuer = urllib.parse.urlunparse(
|
||||||
|
(parsed.scheme, parsed.netloc, parsed.path.rstrip('/'), None, None, None)
|
||||||
|
)
|
||||||
return issuer + '/.well-known/openid-configuration'
|
return issuer + '/.well-known/openid-configuration'
|
||||||
|
|
|
@ -21,7 +21,6 @@ import logging
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.exceptions import MultipleObjectsReturned
|
from django.core.exceptions import MultipleObjectsReturned
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from mellon.adapters import DefaultAdapter, UserCreationError
|
from mellon.adapters import DefaultAdapter, UserCreationError
|
||||||
from mellon.utils import get_setting
|
from mellon.utils import get_setting
|
||||||
|
@ -44,7 +43,7 @@ class MappingError(Exception):
|
||||||
super(MappingError, self).__init__(message)
|
super(MappingError, self).__init__(message)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = six.text_type(self.args[0])
|
s = str(self.args[0])
|
||||||
if self.details:
|
if self.details:
|
||||||
s += ' ' + repr(self.details)
|
s += ' ' + repr(self.details)
|
||||||
return s
|
return s
|
||||||
|
@ -127,7 +126,7 @@ class AuthenticAdapter(DefaultAdapter):
|
||||||
action = mapping.get('action', 'set-attribute')
|
action = mapping.get('action', 'set-attribute')
|
||||||
mandatory = mapping.get('mandatory', False) is True
|
mandatory = mapping.get('mandatory', False) is True
|
||||||
method = None
|
method = None
|
||||||
if isinstance(action, six.string_types):
|
if isinstance(action, str):
|
||||||
try:
|
try:
|
||||||
method = getattr(self, 'action_' + action.replace('-', '_'))
|
method = getattr(self, 'action_' + action.replace('-', '_'))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -149,21 +148,21 @@ class AuthenticAdapter(DefaultAdapter):
|
||||||
|
|
||||||
def action_rename(self, user, idp, saml_attributes, mapping):
|
def action_rename(self, user, idp, saml_attributes, mapping):
|
||||||
from_name = mapping.get('from')
|
from_name = mapping.get('from')
|
||||||
if not from_name or not isinstance(from_name, six.string_types):
|
if not from_name or not isinstance(from_name, str):
|
||||||
raise MappingError('missing from in rename')
|
raise MappingError('missing from in rename')
|
||||||
to_name = mapping.get('to')
|
to_name = mapping.get('to')
|
||||||
if not to_name or not isinstance(to_name, six.string_types):
|
if not to_name or not isinstance(to_name, str):
|
||||||
raise MappingError('missing to in rename')
|
raise MappingError('missing to in rename')
|
||||||
if from_name in saml_attributes:
|
if from_name in saml_attributes:
|
||||||
saml_attributes[to_name] = saml_attributes[from_name]
|
saml_attributes[to_name] = saml_attributes[from_name]
|
||||||
|
|
||||||
def action_set_attribute(self, user, idp, saml_attributes, mapping):
|
def action_set_attribute(self, user, idp, saml_attributes, mapping):
|
||||||
attribute = mapping.get('attribute')
|
attribute = mapping.get('attribute')
|
||||||
if not attribute or not isinstance(attribute, six.string_types):
|
if not attribute or not isinstance(attribute, str):
|
||||||
raise MappingError('missing attribute key')
|
raise MappingError('missing attribute key')
|
||||||
|
|
||||||
saml_attribute = mapping.get('saml_attribute')
|
saml_attribute = mapping.get('saml_attribute')
|
||||||
if not saml_attribute or not isinstance(saml_attribute, six.string_types):
|
if not saml_attribute or not isinstance(saml_attribute, str):
|
||||||
raise MappingError('missing saml_attribute key')
|
raise MappingError('missing saml_attribute key')
|
||||||
|
|
||||||
if saml_attribute not in saml_attributes:
|
if saml_attribute not in saml_attributes:
|
||||||
|
@ -199,14 +198,14 @@ class AuthenticAdapter(DefaultAdapter):
|
||||||
slug = ou_desc.get('slug')
|
slug = ou_desc.get('slug')
|
||||||
name = ou_desc.get('name')
|
name = ou_desc.get('name')
|
||||||
if slug:
|
if slug:
|
||||||
if not isinstance(slug, six.string_types):
|
if not isinstance(slug, str):
|
||||||
raise MappingError('invalid ou.slug in ou description')
|
raise MappingError('invalid ou.slug in ou description')
|
||||||
try:
|
try:
|
||||||
return OU.objects.get(slug=slug)
|
return OU.objects.get(slug=slug)
|
||||||
except OU.DoesNotExist:
|
except OU.DoesNotExist:
|
||||||
raise MappingError('unknown ou', details={'slug': slug})
|
raise MappingError('unknown ou', details={'slug': slug})
|
||||||
elif name:
|
elif name:
|
||||||
if not isinstance(name, six.string_types):
|
if not isinstance(name, str):
|
||||||
raise MappingError('invalid ou.slug in ou description')
|
raise MappingError('invalid ou.slug in ou description')
|
||||||
try:
|
try:
|
||||||
return OU.objects.get(name=name)
|
return OU.objects.get(name=name)
|
||||||
|
@ -228,11 +227,11 @@ class AuthenticAdapter(DefaultAdapter):
|
||||||
kwargs['ou'] = ou
|
kwargs['ou'] = ou
|
||||||
|
|
||||||
if slug:
|
if slug:
|
||||||
if not isinstance(slug, six.string_types):
|
if not isinstance(slug, str):
|
||||||
raise MappingError('invalid role slug', details={'slug': slug})
|
raise MappingError('invalid role slug', details={'slug': slug})
|
||||||
kwargs['slug'] = slug
|
kwargs['slug'] = slug
|
||||||
elif name:
|
elif name:
|
||||||
if not isinstance(name, six.string_types):
|
if not isinstance(name, str):
|
||||||
raise MappingError('invalid role name', details={'name': name})
|
raise MappingError('invalid role name', details={'name': name})
|
||||||
kwargs['name'] = name
|
kwargs['name'] = name
|
||||||
else:
|
else:
|
||||||
|
@ -249,7 +248,7 @@ class AuthenticAdapter(DefaultAdapter):
|
||||||
condition = mapping.get('condition')
|
condition = mapping.get('condition')
|
||||||
if condition is None:
|
if condition is None:
|
||||||
return True
|
return True
|
||||||
if not isinstance(condition, six.string_types):
|
if not isinstance(condition, str):
|
||||||
raise MappingError('invalid condition')
|
raise MappingError('invalid condition')
|
||||||
try:
|
try:
|
||||||
# use a proxy to simplify condition expressions as subscript is forbidden
|
# use a proxy to simplify condition expressions as subscript is forbidden
|
||||||
|
@ -258,7 +257,7 @@ class AuthenticAdapter(DefaultAdapter):
|
||||||
logger.debug('auth_saml: condition %r is %s', condition, value, extra={'user': user})
|
logger.debug('auth_saml: condition %r is %s', condition, value, extra={'user': user})
|
||||||
return value
|
return value
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise MappingError('condition evaluation failed', details={'error': six.text_type(e)})
|
raise MappingError('condition evaluation failed', details={'error': str(e)})
|
||||||
|
|
||||||
def action_add_role(self, user, idp, saml_attributes, mapping):
|
def action_add_role(self, user, idp, saml_attributes, mapping):
|
||||||
role = self.get_role(mapping)
|
role = self.get_role(mapping)
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import urllib.parse
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import query
|
from django.db.models import query
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class TicketQuerySet(query.QuerySet):
|
||||||
class ServiceQuerySet(query.QuerySet):
|
class ServiceQuerySet(query.QuerySet):
|
||||||
def for_service(self, service):
|
def for_service(self, service):
|
||||||
'''Find service with the longest match'''
|
'''Find service with the longest match'''
|
||||||
parsed = urlparse.urlparse(service)
|
parsed = urllib.parse.urlparse(service)
|
||||||
matches = []
|
matches = []
|
||||||
for match in self.filter(urls__contains=parsed.netloc):
|
for match in self.filter(urls__contains=parsed.netloc):
|
||||||
urls = match.get_urls()
|
urls = match.get_urls()
|
||||||
|
|
|
@ -21,7 +21,6 @@ from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
from django.utils import six
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.views.generic.base import View
|
from django.views.generic.base import View
|
||||||
|
|
||||||
|
@ -262,7 +261,7 @@ class ValidateBaseView(CasMixin, View):
|
||||||
if st.service.identifier_attribute not in attributes:
|
if st.service.identifier_attribute not in attributes:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
'unable to compute an identifier for user %r and service %s',
|
'unable to compute an identifier for user %r and service %s',
|
||||||
six.text_type(st.user),
|
str(st.user),
|
||||||
st.service_url,
|
st.service_url,
|
||||||
)
|
)
|
||||||
return self.validation_failure(request, service, INTERNAL_ERROR)
|
return self.validation_failure(request, service, INTERNAL_ERROR)
|
||||||
|
@ -299,7 +298,7 @@ class ValidateBaseView(CasMixin, View):
|
||||||
'validation success service: %r ticket: %s user: %r identifier: %r',
|
'validation success service: %r ticket: %s user: %r identifier: %r',
|
||||||
st.service_url,
|
st.service_url,
|
||||||
st.ticket_id,
|
st.ticket_id,
|
||||||
six.text_type(st.user),
|
str(st.user),
|
||||||
identifier,
|
identifier,
|
||||||
)
|
)
|
||||||
return self.real_validation_success(request, st, identifier)
|
return self.real_validation_success(request, st, identifier)
|
||||||
|
@ -327,7 +326,7 @@ class ServiceValidateView(ValidateBaseView):
|
||||||
root = ET.Element(SERVICE_RESPONSE_ELT)
|
root = ET.Element(SERVICE_RESPONSE_ELT)
|
||||||
success = ET.SubElement(root, AUTHENTICATION_SUCCESS_ELT)
|
success = ET.SubElement(root, AUTHENTICATION_SUCCESS_ELT)
|
||||||
user = ET.SubElement(success, USER_ELT)
|
user = ET.SubElement(success, USER_ELT)
|
||||||
user.text = six.text_type(identifier)
|
user.text = str(identifier)
|
||||||
self.provision_pgt(request, st, success)
|
self.provision_pgt(request, st, success)
|
||||||
self.provision_attributes(request, st, success)
|
self.provision_attributes(request, st, success)
|
||||||
return HttpResponse(ET.tostring(root, encoding='utf-8'), content_type='text/xml')
|
return HttpResponse(ET.tostring(root, encoding='utf-8'), content_type='text/xml')
|
||||||
|
@ -349,7 +348,7 @@ class ServiceValidateView(ValidateBaseView):
|
||||||
for key, values in values.items():
|
for key, values in values.items():
|
||||||
for value in values:
|
for value in values:
|
||||||
attribute_elt = ET.SubElement(attributes_elt, '{%s}%s' % (CAS_NAMESPACE, key))
|
attribute_elt = ET.SubElement(attributes_elt, '{%s}%s' % (CAS_NAMESPACE, key))
|
||||||
attribute_elt.text = six.text_type(value)
|
attribute_elt.text = str(value)
|
||||||
|
|
||||||
def provision_pgt(self, request, st, success):
|
def provision_pgt(self, request, st, success):
|
||||||
"""Provision a PGT ticket if requested"""
|
"""Provision a PGT ticket if requested"""
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
|
@ -22,8 +23,6 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelatio
|
||||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||||
from django.core.validators import URLValidator
|
from django.core.validators import URLValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ from . import app_settings, managers, utils
|
||||||
|
|
||||||
|
|
||||||
def generate_uuid():
|
def generate_uuid():
|
||||||
return six.text_type(uuid.uuid4())
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
|
|
||||||
def validate_https_url(data):
|
def validate_https_url(data):
|
||||||
|
@ -173,9 +172,9 @@ class OIDCClient(Service):
|
||||||
if len(redirect_uri) > app_settings.REDIRECT_URI_MAX_LENGTH:
|
if len(redirect_uri) > app_settings.REDIRECT_URI_MAX_LENGTH:
|
||||||
raise ValueError('redirect_uri length > %s' % app_settings.REDIRECT_URI_MAX_LENGTH)
|
raise ValueError('redirect_uri length > %s' % app_settings.REDIRECT_URI_MAX_LENGTH)
|
||||||
|
|
||||||
parsed_uri = urlparse.urlparse(redirect_uri)
|
parsed_uri = urllib.parse.urlparse(redirect_uri)
|
||||||
for valid_redirect_uri in self.redirect_uris.split():
|
for valid_redirect_uri in self.redirect_uris.split():
|
||||||
parsed_valid_uri = urlparse.urlparse(valid_redirect_uri)
|
parsed_valid_uri = urllib.parse.urlparse(valid_redirect_uri)
|
||||||
if parsed_uri.scheme != parsed_valid_uri.scheme:
|
if parsed_uri.scheme != parsed_valid_uri.scheme:
|
||||||
continue
|
continue
|
||||||
if parsed_valid_uri.netloc.startswith('*'):
|
if parsed_valid_uri.netloc.startswith('*'):
|
||||||
|
@ -257,8 +256,8 @@ class OIDCAuthorization(models.Model):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<OIDCAuthorization client:%r user:%r scopes:%r>' % (
|
return '<OIDCAuthorization client:%r user:%r scopes:%r>' % (
|
||||||
self.client_id and six.text_type(self.client),
|
self.client_id and str(self.client),
|
||||||
self.user_id and six.text_type(self.user),
|
self.user_id and str(self.user),
|
||||||
self.scopes,
|
self.scopes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -324,8 +323,8 @@ class OIDCCode(SessionMixin, models.Model):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<OIDCCode uuid:%s client:%s user:%s expired:%s scopes:%s>' % (
|
return '<OIDCCode uuid:%s client:%s user:%s expired:%s scopes:%s>' % (
|
||||||
self.uuid,
|
self.uuid,
|
||||||
self.client_id and six.text_type(self.client),
|
self.client_id and str(self.client),
|
||||||
self.user_id and six.text_type(self.user),
|
self.user_id and str(self.user),
|
||||||
self.expired,
|
self.expired,
|
||||||
self.scopes,
|
self.scopes,
|
||||||
)
|
)
|
||||||
|
@ -362,8 +361,8 @@ class OIDCAccessToken(SessionMixin, models.Model):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<OIDCAccessToken uuid:%s client:%s user:%s expired:%s scopes:%s>' % (
|
return '<OIDCAccessToken uuid:%s client:%s user:%s expired:%s scopes:%s>' % (
|
||||||
self.uuid,
|
self.uuid,
|
||||||
self.client_id and six.text_type(self.client),
|
self.client_id and str(self.client),
|
||||||
self.user_id and six.text_type(self.user),
|
self.user_id and str(self.user),
|
||||||
self.expired,
|
self.expired,
|
||||||
self.scopes,
|
self.scopes,
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,13 +17,12 @@
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from jwcrypto.jwk import JWK, InvalidJWKValue, JWKSet
|
from jwcrypto.jwk import JWK, InvalidJWKValue, JWKSet
|
||||||
from jwcrypto.jwt import JWT
|
from jwcrypto.jwt import JWT
|
||||||
|
|
||||||
|
@ -107,7 +106,7 @@ def clean_words(data):
|
||||||
|
|
||||||
|
|
||||||
def url_domain(url):
|
def url_domain(url):
|
||||||
return urlparse.urlparse(url).netloc.split(':')[0]
|
return urllib.parse.urlparse(url).netloc.split(':')[0]
|
||||||
|
|
||||||
|
|
||||||
def make_sub(client, user):
|
def make_sub(client, user):
|
||||||
|
@ -165,7 +164,7 @@ def reverse_pairwise_sub(client, sub):
|
||||||
|
|
||||||
def normalize_claim_values(values):
|
def normalize_claim_values(values):
|
||||||
values_list = []
|
values_list = []
|
||||||
if isinstance(values, six.string_types) or not hasattr(values, '__iter__'):
|
if isinstance(values, str) or not hasattr(values, '__iter__'):
|
||||||
return values
|
return values
|
||||||
for value in values:
|
for value in values:
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
|
|
|
@ -36,7 +36,6 @@ from django.contrib.auth import authenticate
|
||||||
from django.http import HttpResponse, HttpResponseNotAllowed, JsonResponse
|
from django.http import HttpResponse, HttpResponseNotAllowed, JsonResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.utils.timezone import now, utc
|
from django.utils.timezone import now, utc
|
||||||
|
@ -423,7 +422,7 @@ def authorize_for_client(request, client, redirect_uri):
|
||||||
'idp_oidc: sending code %s for scopes %s for service %s', code.uuid, ' '.join(scopes), client
|
'idp_oidc: sending code %s for scopes %s for service %s', code.uuid, ' '.join(scopes), client
|
||||||
)
|
)
|
||||||
params = {
|
params = {
|
||||||
'code': six.text_type(code.uuid),
|
'code': str(code.uuid),
|
||||||
}
|
}
|
||||||
if state is not None:
|
if state is not None:
|
||||||
params['state'] = state
|
params['state'] = state
|
||||||
|
@ -664,7 +663,7 @@ def idtoken_from_user_credential(request):
|
||||||
)
|
)
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
{
|
{
|
||||||
'access_token': six.text_type(access_token.uuid),
|
'access_token': str(access_token.uuid),
|
||||||
'token_type': 'Bearer',
|
'token_type': 'Bearer',
|
||||||
'expires_in': int(expires_in.total_seconds()),
|
'expires_in': int(expires_in.total_seconds()),
|
||||||
'id_token': utils.make_idtoken(client, id_token),
|
'id_token': utils.make_idtoken(client, id_token),
|
||||||
|
@ -726,7 +725,7 @@ def tokens_from_authz_code(request):
|
||||||
id_token['nonce'] = oidc_code.nonce
|
id_token['nonce'] = oidc_code.nonce
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
{
|
{
|
||||||
'access_token': six.text_type(access_token.uuid),
|
'access_token': str(access_token.uuid),
|
||||||
'token_type': 'Bearer',
|
'token_type': 'Bearer',
|
||||||
'expires_in': int(expires_in.total_seconds()),
|
'expires_in': int(expires_in.total_seconds()),
|
||||||
'id_token': utils.make_idtoken(client, id_token),
|
'id_token': utils.make_idtoken(client, id_token),
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import copy
|
import copy
|
||||||
|
import functools
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db.models.query import Q
|
from django.db.models.query import Q
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from django.core.exceptions import FieldDoesNotExist
|
from django.core.exceptions import FieldDoesNotExist
|
||||||
|
@ -145,7 +145,7 @@ class DjangoRBACBackend(object):
|
||||||
return False
|
return False
|
||||||
if user_obj.is_superuser:
|
if user_obj.is_superuser:
|
||||||
return True
|
return True
|
||||||
if isinstance(perm_or_perms, six.string_types):
|
if isinstance(perm_or_perms, str):
|
||||||
perm_or_perms = [perm_or_perms]
|
perm_or_perms = [perm_or_perms]
|
||||||
perm_or_perms = set(perm_or_perms)
|
perm_or_perms = set(perm_or_perms)
|
||||||
cache = self.get_permission_cache(user_obj)
|
cache = self.get_permission_cache(user_obj)
|
||||||
|
@ -174,7 +174,7 @@ class DjangoRBACBackend(object):
|
||||||
return False
|
return False
|
||||||
if user_obj.is_superuser:
|
if user_obj.is_superuser:
|
||||||
return True
|
return True
|
||||||
if isinstance(perm_or_perms, six.string_types):
|
if isinstance(perm_or_perms, str):
|
||||||
perm_or_perms = [perm_or_perms]
|
perm_or_perms = [perm_or_perms]
|
||||||
perm_or_perms = set(perm_or_perms)
|
perm_or_perms = set(perm_or_perms)
|
||||||
cache = self.get_permission_cache(user_obj)
|
cache = self.get_permission_cache(user_obj)
|
||||||
|
@ -197,7 +197,7 @@ class DjangoRBACBackend(object):
|
||||||
ct_id, fk = key.split('.')
|
ct_id, fk = key.split('.')
|
||||||
q.append(Q(pk=int(fk)))
|
q.append(Q(pk=int(fk)))
|
||||||
if q:
|
if q:
|
||||||
return six.moves.reduce(Q.__or__, q)
|
return functools.reduce(Q.__or__, q)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def filter_by_perm(self, user_obj, perm_or_perms, qs):
|
def filter_by_perm(self, user_obj, perm_or_perms, qs):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import functools
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
@ -6,7 +7,6 @@ from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import query
|
from django.db.models import query
|
||||||
from django.db.models.query import Prefetch, Q
|
from django.db.models.query import Prefetch, Q
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ class RoleParentingManager(models.Manager):
|
||||||
obsolete = old - add
|
obsolete = old - add
|
||||||
if obsolete:
|
if obsolete:
|
||||||
queries = (query.Q(parent_id=a, child_id=b, direct=False) for a, b in obsolete)
|
queries = (query.Q(parent_id=a, child_id=b, direct=False) for a, b in obsolete)
|
||||||
self.model.objects.filter(six.moves.reduce(query.Q.__or__, queries)).delete()
|
self.model.objects.filter(functools.reduce(query.Q.__or__, queries)).delete()
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.query import Prefetch, Q
|
from django.db.models.query import Prefetch, Q
|
||||||
from django.utils import six
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class AbstractBase(models.Model):
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
# truncate slug and add a hash if it's too long
|
# truncate slug and add a hash if it's too long
|
||||||
if not self.slug:
|
if not self.slug:
|
||||||
self.slug = slugify(six.text_type(self.name)).lstrip('_')
|
self.slug = slugify(str(self.name)).lstrip('_')
|
||||||
if len(self.slug) > 256:
|
if len(self.slug) > 256:
|
||||||
self.slug = self.slug[:252] + hashlib.md5(self.slug).hexdigest()[:4]
|
self.slug = self.slug[:252] + hashlib.md5(self.slug).hexdigest()[:4]
|
||||||
if not self.uuid:
|
if not self.uuid:
|
||||||
|
@ -373,7 +373,7 @@ class PermissionMixin(models.Model):
|
||||||
if hasattr(backend, "filter_by_perm"):
|
if hasattr(backend, "filter_by_perm"):
|
||||||
results.append(backend.filter_by_perm(self, perm_or_perms, qs))
|
results.append(backend.filter_by_perm(self, perm_or_perms, qs))
|
||||||
if results:
|
if results:
|
||||||
return six.moves.reduce(operator.__or__, results)
|
return functools.reduce(operator.__or__, results)
|
||||||
else:
|
else:
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import base64
|
||||||
import contextlib
|
import contextlib
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import urllib.parse as urlparse
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import httmock
|
import httmock
|
||||||
|
@ -60,7 +60,7 @@ class FranceConnectMock:
|
||||||
|
|
||||||
def handle_authorization(self, app, url, **kwargs):
|
def handle_authorization(self, app, url, **kwargs):
|
||||||
assert url.startswith('https://fcp.integ01')
|
assert url.startswith('https://fcp.integ01')
|
||||||
parsed_url = urlparse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
query = QueryDict(parsed_url.query)
|
query = QueryDict(parsed_url.query)
|
||||||
assert_equals_url(query['redirect_uri'], self.callback_url)
|
assert_equals_url(query['redirect_uri'], self.callback_url)
|
||||||
assert query['client_id'] == self.client_id
|
assert query['client_id'] == self.client_id
|
||||||
|
@ -90,7 +90,7 @@ class FranceConnectMock:
|
||||||
app.session.flush()
|
app.session.flush()
|
||||||
response = app.get(path)
|
response = app.get(path)
|
||||||
self.callback_params = {
|
self.callback_params = {
|
||||||
k: v for k, v in QueryDict(urlparse.urlparse(response.location).query).items()
|
k: v for k, v in QueryDict(urllib.parse.urlparse(response.location).query).items()
|
||||||
}
|
}
|
||||||
response = response.follow()
|
response = response.follow()
|
||||||
response = response.click(href='callback')
|
response = response.click(href='callback')
|
||||||
|
@ -142,7 +142,7 @@ class FranceConnectMock:
|
||||||
|
|
||||||
def handle_logout(self, app, url):
|
def handle_logout(self, app, url):
|
||||||
assert url.startswith('https://fcp.integ01.dev-franceconnect.fr/api/v1/logout')
|
assert url.startswith('https://fcp.integ01.dev-franceconnect.fr/api/v1/logout')
|
||||||
parsed_url = urlparse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
query = QueryDict(parsed_url.query)
|
query = QueryDict(parsed_url.query)
|
||||||
assert_equals_url(query['post_logout_redirect_uri'], 'http://testserver' + reverse('fc-logout'))
|
assert_equals_url(query['post_logout_redirect_uri'], 'http://testserver' + reverse('fc-logout'))
|
||||||
assert query['state']
|
assert query['state']
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
from authentic2.custom_user.models import DeletedUser
|
from authentic2.custom_user.models import DeletedUser
|
||||||
|
@ -34,7 +34,7 @@ User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
def path(url):
|
def path(url):
|
||||||
return urlparse.urlparse(url).path
|
return urllib.parse.urlparse(url).path
|
||||||
|
|
||||||
|
|
||||||
def test_login_redirect(app, franceconnect):
|
def test_login_redirect(app, franceconnect):
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import django
|
import django
|
||||||
import django_webtest
|
import django_webtest
|
||||||
import mock
|
import mock
|
||||||
|
@ -25,7 +27,6 @@ from django.core.cache import cache
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.db.migrations.executor import MigrationExecutor
|
from django.db.migrations.executor import MigrationExecutor
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from pytest_django.migrations import DisableMigrations
|
from pytest_django.migrations import DisableMigrations
|
||||||
|
|
||||||
from authentic2 import hooks as a2_hooks
|
from authentic2 import hooks as a2_hooks
|
||||||
|
@ -458,7 +459,7 @@ def assert_external_redirect(external_redirect):
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def check_location(response, default_return):
|
def check_location(response, default_return):
|
||||||
assert urlparse.urljoin('http://testserver/', default_return).endswith(response['Location'])
|
assert urllib.parse.urljoin('http://testserver/', default_return).endswith(response['Location'])
|
||||||
|
|
||||||
return check_location
|
return check_location
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from authentic2.custom_user.models import User
|
from authentic2.custom_user.models import User
|
||||||
from authentic2.models import Attribute
|
from authentic2.models import Attribute
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
@ -29,8 +30,6 @@ from django.test.client import Client
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six import text_type
|
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from rest_framework import status, test
|
from rest_framework import status, test
|
||||||
|
|
||||||
|
@ -203,7 +202,8 @@ class UtilsTests(Authentic2TestCase):
|
||||||
response = login_require(request, login_hint=['backoffice'])
|
response = login_require(request, login_hint=['backoffice'])
|
||||||
self.assertEqualsURL(response['Location'].split('?', 1)[0], '/login/')
|
self.assertEqualsURL(response['Location'].split('?', 1)[0], '/login/')
|
||||||
self.assertEqualsURL(
|
self.assertEqualsURL(
|
||||||
urlparse.parse_qs(response['Location'].split('?', 1)[1])['next'][0], '/coin?nonce=xxx&next=/zob/'
|
urllib.parse.parse_qs(response['Location'].split('?', 1)[1])['next'][0],
|
||||||
|
'/coin?nonce=xxx&next=/zob/',
|
||||||
)
|
)
|
||||||
self.assertEqual(request.session['login-hint'], ['backoffice'])
|
self.assertEqual(request.session['login-hint'], ['backoffice'])
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ class AttributeKindsTest(TestCase):
|
||||||
for i, name in enumerate(attribute_kinds.get_attribute_kinds()):
|
for i, name in enumerate(attribute_kinds.get_attribute_kinds()):
|
||||||
fields['field_%d' % i] = attribute_kinds.get_form_field(name)
|
fields['field_%d' % i] = attribute_kinds.get_form_field(name)
|
||||||
AttributeKindForm = type('AttributeKindForm', (forms.Form,), fields)
|
AttributeKindForm = type('AttributeKindForm', (forms.Form,), fields)
|
||||||
text_type(AttributeKindForm().as_p())
|
str(AttributeKindForm().as_p())
|
||||||
|
|
||||||
|
|
||||||
class APITest(TestCase):
|
class APITest(TestCase):
|
||||||
|
|
|
@ -21,6 +21,7 @@ import os
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
@ -28,7 +29,6 @@ from django.db import IntegrityError, transaction
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_str, force_text
|
from django.utils.encoding import force_str, force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import now, utc
|
from django.utils.timezone import now, utc
|
||||||
from httmock import HTTMock, urlmatch
|
from httmock import HTTMock, urlmatch
|
||||||
from jwcrypto.common import base64url_decode, base64url_encode, json_encode
|
from jwcrypto.common import base64url_decode, base64url_encode, json_encode
|
||||||
|
@ -248,13 +248,13 @@ def oidc_provider_mock(
|
||||||
provides_kid_header=False,
|
provides_kid_header=False,
|
||||||
kid=None,
|
kid=None,
|
||||||
):
|
):
|
||||||
token_endpoint = urlparse.urlparse(oidc_provider.token_endpoint)
|
token_endpoint = urllib.parse.urlparse(oidc_provider.token_endpoint)
|
||||||
userinfo_endpoint = urlparse.urlparse(oidc_provider.userinfo_endpoint)
|
userinfo_endpoint = urllib.parse.urlparse(oidc_provider.userinfo_endpoint)
|
||||||
token_revocation_endpoint = urlparse.urlparse(oidc_provider.token_revocation_endpoint)
|
token_revocation_endpoint = urllib.parse.urlparse(oidc_provider.token_revocation_endpoint)
|
||||||
|
|
||||||
@urlmatch(netloc=token_endpoint.netloc, path=token_endpoint.path)
|
@urlmatch(netloc=token_endpoint.netloc, path=token_endpoint.path)
|
||||||
def token_endpoint_mock(url, request):
|
def token_endpoint_mock(url, request):
|
||||||
if urlparse.parse_qs(request.body).get('code') == [code]:
|
if urllib.parse.parse_qs(request.body).get('code') == [code]:
|
||||||
exp = now() + datetime.timedelta(seconds=10)
|
exp = now() + datetime.timedelta(seconds=10)
|
||||||
id_token = {
|
id_token = {
|
||||||
'iss': oidc_provider.issuer,
|
'iss': oidc_provider.issuer,
|
||||||
|
@ -341,7 +341,7 @@ def oidc_provider_mock(
|
||||||
|
|
||||||
@urlmatch(netloc=token_revocation_endpoint.netloc, path=token_revocation_endpoint.path)
|
@urlmatch(netloc=token_revocation_endpoint.netloc, path=token_revocation_endpoint.path)
|
||||||
def token_revocation_endpoint_mock(url, request):
|
def token_revocation_endpoint_mock(url, request):
|
||||||
query = urlparse.parse_qs(request.body)
|
query = urllib.parse.parse_qs(request.body)
|
||||||
assert 'token' in query
|
assert 'token' in query
|
||||||
return {
|
return {
|
||||||
'status_code': 200,
|
'status_code': 200,
|
||||||
|
@ -458,8 +458,8 @@ def test_sso(app, caplog, code, oidc_provider, oidc_provider_jwkset, hooks):
|
||||||
response = app.get('/admin/').maybe_follow()
|
response = app.get('/admin/').maybe_follow()
|
||||||
assert oidc_provider.name in response.text
|
assert oidc_provider.name in response.text
|
||||||
response = response.click(oidc_provider.name)
|
response = response.click(oidc_provider.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
endpoint = urlparse.urlparse(oidc_provider.authorization_endpoint)
|
endpoint = urllib.parse.urlparse(oidc_provider.authorization_endpoint)
|
||||||
assert location.scheme == endpoint.scheme
|
assert location.scheme == endpoint.scheme
|
||||||
assert location.netloc == endpoint.netloc
|
assert location.netloc == endpoint.netloc
|
||||||
assert location.path == endpoint.path
|
assert location.path == endpoint.path
|
||||||
|
@ -510,7 +510,7 @@ def test_sso(app, caplog, code, oidc_provider, oidc_provider_jwkset, hooks):
|
||||||
assert set(hooks.auth_oidc_backend_modify_user[0]['kwargs']) >= set(
|
assert set(hooks.auth_oidc_backend_modify_user[0]['kwargs']) >= set(
|
||||||
['user', 'provider', 'user_info', 'id_token', 'access_token']
|
['user', 'provider', 'user_info', 'id_token', 'access_token']
|
||||||
)
|
)
|
||||||
assert urlparse.urlparse(response['Location']).path == '/admin/'
|
assert urllib.parse.urlparse(response['Location']).path == '/admin/'
|
||||||
assert User.objects.count() == 1
|
assert User.objects.count() == 1
|
||||||
user = User.objects.get()
|
user = User.objects.get()
|
||||||
assert user.ou == get_default_ou()
|
assert user.ou == get_default_ou()
|
||||||
|
@ -588,7 +588,7 @@ def test_strategy_find_uuid(app, caplog, code, oidc_provider, oidc_provider_jwks
|
||||||
response = app.get('/').maybe_follow()
|
response = app.get('/').maybe_follow()
|
||||||
assert oidc_provider.name in response.text
|
assert oidc_provider.name in response.text
|
||||||
response = response.click(oidc_provider.name)
|
response = response.click(oidc_provider.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
query = QueryDict(location.query)
|
query = QueryDict(location.query)
|
||||||
state = query['state']
|
state = query['state']
|
||||||
nonce = query['nonce']
|
nonce = query['nonce']
|
||||||
|
@ -603,7 +603,7 @@ def test_strategy_find_uuid(app, caplog, code, oidc_provider, oidc_provider_jwks
|
||||||
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, sub=simple_user.uuid, nonce=nonce):
|
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, sub=simple_user.uuid, nonce=nonce):
|
||||||
response = app.get(login_callback_url(oidc_provider), params={'code': code, 'state': state})
|
response = app.get(login_callback_url(oidc_provider), params={'code': code, 'state': state})
|
||||||
|
|
||||||
assert urlparse.urlparse(response['Location']).path == '/'
|
assert urllib.parse.urlparse(response['Location']).path == '/'
|
||||||
assert User.objects.count() == 1
|
assert User.objects.count() == 1
|
||||||
user = User.objects.get()
|
user = User.objects.get()
|
||||||
# verify user was not modified
|
# verify user was not modified
|
||||||
|
@ -630,7 +630,7 @@ def test_strategy_create(app, caplog, code, oidc_provider, oidc_provider_jwkset)
|
||||||
response = app.get('/').maybe_follow()
|
response = app.get('/').maybe_follow()
|
||||||
assert oidc_provider.name in response.text
|
assert oidc_provider.name in response.text
|
||||||
response = response.click(oidc_provider.name)
|
response = response.click(oidc_provider.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
query = QueryDict(location.query)
|
query = QueryDict(location.query)
|
||||||
state = query['state']
|
state = query['state']
|
||||||
nonce = query['nonce']
|
nonce = query['nonce']
|
||||||
|
@ -658,7 +658,7 @@ def test_register_issuer(db, app, caplog, oidc_provider_jwkset):
|
||||||
config_file = os.path.join(config_dir, 'openid_configuration.json')
|
config_file = os.path.join(config_dir, 'openid_configuration.json')
|
||||||
with open(config_file) as f:
|
with open(config_file) as f:
|
||||||
oidc_conf = json.load(f)
|
oidc_conf = json.load(f)
|
||||||
jwks_uri = urlparse.urlparse(oidc_conf['jwks_uri'])
|
jwks_uri = urllib.parse.urlparse(oidc_conf['jwks_uri'])
|
||||||
|
|
||||||
@urlmatch(netloc=jwks_uri.netloc, path=jwks_uri.path)
|
@urlmatch(netloc=jwks_uri.netloc, path=jwks_uri.path)
|
||||||
def jwks_mock(url, request):
|
def jwks_mock(url, request):
|
||||||
|
@ -705,7 +705,7 @@ def test_invalid_kid(app, caplog, code, oidc_provider_rsa, oidc_provider_jwkset,
|
||||||
response = app.get('/').maybe_follow()
|
response = app.get('/').maybe_follow()
|
||||||
assert oidc_provider_rsa.name in response.text
|
assert oidc_provider_rsa.name in response.text
|
||||||
response = response.click(oidc_provider_rsa.name)
|
response = response.click(oidc_provider_rsa.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
query = QueryDict(location.query)
|
query = QueryDict(location.query)
|
||||||
state = query['state']
|
state = query['state']
|
||||||
nonce = query['nonce']
|
nonce = query['nonce']
|
||||||
|
@ -771,7 +771,7 @@ def test_templated_claim_mapping(app, caplog, code, oidc_provider, oidc_provider
|
||||||
|
|
||||||
response = app.get('/').maybe_follow()
|
response = app.get('/').maybe_follow()
|
||||||
response = response.click(oidc_provider.name)
|
response = response.click(oidc_provider.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
query = QueryDict(location.query)
|
query = QueryDict(location.query)
|
||||||
state = query['state']
|
state = query['state']
|
||||||
nonce = query['nonce']
|
nonce = query['nonce']
|
||||||
|
@ -799,7 +799,7 @@ def test_lost_state(app, caplog, code, oidc_provider, oidc_provider_jwkset, hook
|
||||||
# As the oidc-state is used during a redirect from a third-party, we need
|
# As the oidc-state is used during a redirect from a third-party, we need
|
||||||
# it to be lax.
|
# it to be lax.
|
||||||
assert re.search('Set-Cookie.* oidc-state=.*SameSite=Lax', str(response))
|
assert re.search('Set-Cookie.* oidc-state=.*SameSite=Lax', str(response))
|
||||||
qs = urlparse.parse_qs(urlparse.urlparse(response.location).query)
|
qs = urllib.parse.parse_qs(urllib.parse.urlparse(response.location).query)
|
||||||
state = qs['state']
|
state = qs['state']
|
||||||
|
|
||||||
# reset the session to forget the state
|
# reset the session to forget the state
|
||||||
|
@ -858,7 +858,7 @@ def test_multiple_users_with_same_email(app, caplog, code, oidc_provider_jwkset,
|
||||||
response = app.get('/').maybe_follow()
|
response = app.get('/').maybe_follow()
|
||||||
assert oidc_provider.name in response.text
|
assert oidc_provider.name in response.text
|
||||||
response = response.click(oidc_provider.name)
|
response = response.click(oidc_provider.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
query = QueryDict(location.query)
|
query = QueryDict(location.query)
|
||||||
state = query['state']
|
state = query['state']
|
||||||
nonce = query['nonce']
|
nonce = query['nonce']
|
||||||
|
@ -877,7 +877,7 @@ def test_multiple_users_with_same_email(app, caplog, code, oidc_provider_jwkset,
|
||||||
response = app.get('/').maybe_follow()
|
response = app.get('/').maybe_follow()
|
||||||
assert oidc_provider.name in response.text
|
assert oidc_provider.name in response.text
|
||||||
response = response.click(oidc_provider.name)
|
response = response.click(oidc_provider.name)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
query = QueryDict(location.query)
|
query = QueryDict(location.query)
|
||||||
state = query['state']
|
state = query['state']
|
||||||
nonce = query['nonce']
|
nonce = query['nonce']
|
||||||
|
|
|
@ -14,11 +14,12 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.test.client import Client, RequestFactory
|
from django.test.client import Client, RequestFactory
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
|
|
||||||
from authentic2.a2_rbac.utils import get_default_ou
|
from authentic2.a2_rbac.utils import get_default_ou
|
||||||
from authentic2.constants import AUTHENTICATION_EVENTS_SESSION_KEY, NONCE_FIELD_NAME
|
from authentic2.constants import AUTHENTICATION_EVENTS_SESSION_KEY, NONCE_FIELD_NAME
|
||||||
|
@ -132,9 +133,9 @@ class CasTests(Authentic2TestCase):
|
||||||
assert service.authorized_roles.exists() is True
|
assert service.authorized_roles.exists() is True
|
||||||
response = client.get('/idp/cas/login', {constants.SERVICE_PARAM: self.URL})
|
response = client.get('/idp/cas/login', {constants.SERVICE_PARAM: self.URL})
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
response = client.get(location)
|
response = client.get(location)
|
||||||
response = client.post(
|
response = client.post(
|
||||||
location,
|
location,
|
||||||
|
@ -152,9 +153,9 @@ class CasTests(Authentic2TestCase):
|
||||||
assert service.authorized_roles.exists() is True
|
assert service.authorized_roles.exists() is True
|
||||||
response = client.get('/idp/cas/login', {constants.SERVICE_PARAM: self.URL})
|
response = client.get('/idp/cas/login', {constants.SERVICE_PARAM: self.URL})
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
response = client.get(location)
|
response = client.get(location)
|
||||||
response = client.post(
|
response = client.post(
|
||||||
location,
|
location,
|
||||||
|
@ -163,7 +164,7 @@ class CasTests(Authentic2TestCase):
|
||||||
)
|
)
|
||||||
response = client.get(response.url)
|
response = client.get(response.url)
|
||||||
client = Client()
|
client = Client()
|
||||||
ticket_id = urlparse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
ticket_id = urllib.parse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/idp/cas/validate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
'/idp/cas/validate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
||||||
)
|
)
|
||||||
|
@ -174,13 +175,13 @@ class CasTests(Authentic2TestCase):
|
||||||
ticket = Ticket.objects.get()
|
ticket = Ticket.objects.get()
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
url = location.split('?')[0]
|
url = location.split('?')[0]
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
self.assertTrue(url.endswith('/login/'))
|
self.assertTrue(url.endswith('/login/'))
|
||||||
self.assertIn('nonce', query)
|
self.assertIn('nonce', query)
|
||||||
self.assertIn('next', query)
|
self.assertIn('next', query)
|
||||||
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
self.assertEqual(next_url, '/idp/cas/continue/')
|
self.assertEqual(next_url, '/idp/cas/continue/')
|
||||||
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
||||||
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
||||||
|
@ -214,7 +215,7 @@ class CasTests(Authentic2TestCase):
|
||||||
# Do not the same client for direct calls from the CAS service provider
|
# Do not the same client for direct calls from the CAS service provider
|
||||||
# to prevent use of the user session
|
# to prevent use of the user session
|
||||||
client = Client()
|
client = Client()
|
||||||
ticket_id = urlparse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
ticket_id = urllib.parse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/idp/cas/validate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
'/idp/cas/validate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
||||||
)
|
)
|
||||||
|
@ -231,13 +232,13 @@ class CasTests(Authentic2TestCase):
|
||||||
ticket = Ticket.objects.get()
|
ticket = Ticket.objects.get()
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
url = location.split('?')[0]
|
url = location.split('?')[0]
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
self.assertTrue(url.endswith('/login/'))
|
self.assertTrue(url.endswith('/login/'))
|
||||||
self.assertIn('nonce', query)
|
self.assertIn('nonce', query)
|
||||||
self.assertIn('next', query)
|
self.assertIn('next', query)
|
||||||
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
self.assertEqual(next_url, '/idp/cas/continue/')
|
self.assertEqual(next_url, '/idp/cas/continue/')
|
||||||
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
||||||
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
||||||
|
@ -271,7 +272,7 @@ class CasTests(Authentic2TestCase):
|
||||||
# Do not the same client for direct calls from the CAS service provider
|
# Do not the same client for direct calls from the CAS service provider
|
||||||
# to prevent use of the user session
|
# to prevent use of the user session
|
||||||
client = Client()
|
client = Client()
|
||||||
ticket_id = urlparse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
ticket_id = urllib.parse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/idp/cas/serviceValidate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
'/idp/cas/serviceValidate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
||||||
)
|
)
|
||||||
|
@ -292,13 +293,13 @@ class CasTests(Authentic2TestCase):
|
||||||
ticket = Ticket.objects.get()
|
ticket = Ticket.objects.get()
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
url = location.split('?')[0]
|
url = location.split('?')[0]
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
self.assertTrue(url.endswith('/login/'))
|
self.assertTrue(url.endswith('/login/'))
|
||||||
self.assertIn('nonce', query)
|
self.assertIn('nonce', query)
|
||||||
self.assertIn('next', query)
|
self.assertIn('next', query)
|
||||||
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
self.assertEqual(next_url, '/idp/cas/continue/')
|
self.assertEqual(next_url, '/idp/cas/continue/')
|
||||||
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
||||||
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
||||||
|
@ -332,7 +333,7 @@ class CasTests(Authentic2TestCase):
|
||||||
# Do not the same client for direct calls from the CAS service provider
|
# Do not the same client for direct calls from the CAS service provider
|
||||||
# to prevent use of the user session
|
# to prevent use of the user session
|
||||||
client = Client()
|
client = Client()
|
||||||
ticket_id = urlparse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
ticket_id = urllib.parse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/idp/cas/serviceValidate',
|
'/idp/cas/serviceValidate',
|
||||||
{constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL, constants.RENEW_PARAM: ''},
|
{constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL, constants.RENEW_PARAM: ''},
|
||||||
|
@ -351,13 +352,13 @@ class CasTests(Authentic2TestCase):
|
||||||
ticket = Ticket.objects.get()
|
ticket = Ticket.objects.get()
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
url = location.split('?')[0]
|
url = location.split('?')[0]
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
self.assertTrue(url.endswith('/login/'))
|
self.assertTrue(url.endswith('/login/'))
|
||||||
self.assertIn('nonce', query)
|
self.assertIn('nonce', query)
|
||||||
self.assertIn('next', query)
|
self.assertIn('next', query)
|
||||||
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
self.assertEqual(next_url, '/idp/cas/continue/')
|
self.assertEqual(next_url, '/idp/cas/continue/')
|
||||||
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
||||||
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
||||||
|
@ -391,7 +392,7 @@ class CasTests(Authentic2TestCase):
|
||||||
# Do not the same client for direct calls from the CAS service provider
|
# Do not the same client for direct calls from the CAS service provider
|
||||||
# to prevent use of the user session
|
# to prevent use of the user session
|
||||||
client = Client()
|
client = Client()
|
||||||
ticket_id = urlparse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
ticket_id = urllib.parse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/idp/cas/proxyValidate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
'/idp/cas/proxyValidate', {constants.TICKET_PARAM: ticket_id, constants.SERVICE_PARAM: self.URL}
|
||||||
)
|
)
|
||||||
|
@ -413,13 +414,13 @@ class CasTests(Authentic2TestCase):
|
||||||
ticket = Ticket.objects.get()
|
ticket = Ticket.objects.get()
|
||||||
location = response['Location']
|
location = response['Location']
|
||||||
url = location.split('?')[0]
|
url = location.split('?')[0]
|
||||||
query = urlparse.parse_qs(location.split('?')[1])
|
query = urllib.parse.parse_qs(location.split('?')[1])
|
||||||
self.assertTrue(url.endswith('/login/'))
|
self.assertTrue(url.endswith('/login/'))
|
||||||
self.assertIn('nonce', query)
|
self.assertIn('nonce', query)
|
||||||
self.assertIn('next', query)
|
self.assertIn('next', query)
|
||||||
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
self.assertEqual(query['nonce'], [ticket.ticket_id])
|
||||||
next_url, next_url_query = query['next'][0].split('?')
|
next_url, next_url_query = query['next'][0].split('?')
|
||||||
next_url_query = urlparse.parse_qs(next_url_query)
|
next_url_query = urllib.parse.parse_qs(next_url_query)
|
||||||
self.assertEqual(next_url, '/idp/cas/continue/')
|
self.assertEqual(next_url, '/idp/cas/continue/')
|
||||||
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
self.assertEqual(set(next_url_query.keys()), set([constants.SERVICE_PARAM, NONCE_FIELD_NAME]))
|
||||||
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
self.assertEqual(next_url_query[constants.SERVICE_PARAM], [self.URL])
|
||||||
|
@ -453,7 +454,7 @@ class CasTests(Authentic2TestCase):
|
||||||
# Do not the same client for direct calls from the CAS service provider
|
# Do not the same client for direct calls from the CAS service provider
|
||||||
# to prevent use of the user session
|
# to prevent use of the user session
|
||||||
client = Client()
|
client = Client()
|
||||||
ticket_id = urlparse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
ticket_id = urllib.parse.parse_qs(response.url.split('?')[1])[constants.TICKET_PARAM][0]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'/idp/cas/serviceValidate',
|
'/idp/cas/serviceValidate',
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ import base64
|
||||||
import datetime
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
|
import urllib.parse
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -28,7 +29,6 @@ from django.http import QueryDict
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from jwcrypto.jwk import JWK, JWKSet
|
from jwcrypto.jwk import JWK, JWKSet
|
||||||
from jwcrypto.jwt import JWT
|
from jwcrypto.jwt import JWT
|
||||||
|
@ -301,9 +301,9 @@ def test_authorization_code_sso(
|
||||||
assert code.auth_time <= now()
|
assert code.auth_time <= now()
|
||||||
assert code.expired >= now()
|
assert code.expired >= now()
|
||||||
assert response['Location'].startswith(redirect_uri)
|
assert response['Location'].startswith(redirect_uri)
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
|
if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
assert set(query.keys()) == set(['code', 'state'])
|
assert set(query.keys()) == set(['code', 'state'])
|
||||||
assert query['code'] == [code.uuid]
|
assert query['code'] == [code.uuid]
|
||||||
code = query['code'][0]
|
code = query['code'][0]
|
||||||
|
@ -328,7 +328,7 @@ def test_authorization_code_sso(
|
||||||
id_token = response.json['id_token']
|
id_token = response.json['id_token']
|
||||||
elif oidc_client.authorization_flow == oidc_client.FLOW_IMPLICIT:
|
elif oidc_client.authorization_flow == oidc_client.FLOW_IMPLICIT:
|
||||||
assert location.fragment
|
assert location.fragment
|
||||||
query = urlparse.parse_qs(location.fragment)
|
query = urllib.parse.parse_qs(location.fragment)
|
||||||
assert OIDCAccessToken.objects.count() == 1
|
assert OIDCAccessToken.objects.count() == 1
|
||||||
access_token = OIDCAccessToken.objects.get()
|
access_token = OIDCAccessToken.objects.get()
|
||||||
assert set(query.keys()) == set(['access_token', 'token_type', 'expires_in', 'id_token', 'state'])
|
assert set(query.keys()) == set(['access_token', 'token_type', 'expires_in', 'id_token', 'state'])
|
||||||
|
@ -434,13 +434,13 @@ def check_authorize_error(
|
||||||
):
|
):
|
||||||
# check next_url qs
|
# check next_url qs
|
||||||
if message:
|
if message:
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
assert location.path == '/continue/'
|
assert location.path == '/continue/'
|
||||||
if check_next:
|
if check_next:
|
||||||
location_qs = QueryDict(location.query or '')
|
location_qs = QueryDict(location.query or '')
|
||||||
assert 'next' in location_qs
|
assert 'next' in location_qs
|
||||||
assert location_qs['next'].startswith(redirect_uri)
|
assert location_qs['next'].startswith(redirect_uri)
|
||||||
next_url = urlparse.urlparse(location_qs['next'])
|
next_url = urllib.parse.urlparse(location_qs['next'])
|
||||||
next_url_qs = QueryDict(next_url.fragment if fragment else next_url.query)
|
next_url_qs = QueryDict(next_url.fragment if fragment else next_url.query)
|
||||||
assert next_url_qs['error'] == error
|
assert next_url_qs['error'] == error
|
||||||
assert next_url_qs['error_description'] == error_description
|
assert next_url_qs['error_description'] == error_description
|
||||||
|
@ -449,7 +449,7 @@ def check_authorize_error(
|
||||||
assert error_description in continue_response.pyquery('.error').text()
|
assert error_description in continue_response.pyquery('.error').text()
|
||||||
elif check_next:
|
elif check_next:
|
||||||
assert response.location.startswith(redirect_uri)
|
assert response.location.startswith(redirect_uri)
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
location_qs = QueryDict(location.fragment if fragment else location.query)
|
location_qs = QueryDict(location.fragment if fragment else location.query)
|
||||||
assert location_qs['error'] == error
|
assert location_qs['error'] == error
|
||||||
assert location_qs['error_description'] == error_description
|
assert location_qs['error_description'] == error_description
|
||||||
|
@ -466,7 +466,7 @@ def check_authorize_error(
|
||||||
|
|
||||||
|
|
||||||
def assert_authorization_response(response, fragment=False, **kwargs):
|
def assert_authorization_response(response, fragment=False, **kwargs):
|
||||||
location = urlparse.urlparse(response.location)
|
location = urllib.parse.urlparse(response.location)
|
||||||
location_qs = QueryDict(location.fragment if fragment else location.query)
|
location_qs = QueryDict(location.fragment if fragment else location.query)
|
||||||
assert set(location_qs) == set(kwargs)
|
assert set(location_qs) == set(kwargs)
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
|
@ -769,7 +769,7 @@ def test_invalid_request(oidc_client, caplog, oidc_settings, simple_user, app):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
response = app.get(authorize_url)
|
response = app.get(authorize_url)
|
||||||
assert urlparse.urlparse(response['Location']).path == reverse('auth_login')
|
assert urllib.parse.urlparse(response['Location']).path == reverse('auth_login')
|
||||||
|
|
||||||
if oidc_client.authorization_mode != oidc_client.AUTHORIZATION_MODE_NONE:
|
if oidc_client.authorization_mode != oidc_client.AUTHORIZATION_MODE_NONE:
|
||||||
# prompt is none, but consent is required
|
# prompt is none, but consent is required
|
||||||
|
@ -873,8 +873,8 @@ def test_invalid_request(oidc_client, caplog, oidc_settings, simple_user, app):
|
||||||
code.expired = now() - datetime.timedelta(seconds=120)
|
code.expired = now() - datetime.timedelta(seconds=120)
|
||||||
assert not code.is_valid()
|
assert not code.is_valid()
|
||||||
code.save()
|
code.save()
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
assert set(query.keys()) == set(['code'])
|
assert set(query.keys()) == set(['code'])
|
||||||
assert query['code'] == [code.uuid]
|
assert query['code'] == [code.uuid]
|
||||||
code = query['code'][0]
|
code = query['code'][0]
|
||||||
|
@ -1000,8 +1000,8 @@ def test_client_secret_post_authentication(oidc_settings, app, simple_oidc_clien
|
||||||
authorize_url = make_url('oidc-authorize', params=params)
|
authorize_url = make_url('oidc-authorize', params=params)
|
||||||
response = app.get(authorize_url)
|
response = app.get(authorize_url)
|
||||||
response = response.form.submit('accept')
|
response = response.form.submit('accept')
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
code = query['code'][0]
|
code = query['code'][0]
|
||||||
token_url = make_url('oidc-token')
|
token_url = make_url('oidc-token')
|
||||||
response = app.post(
|
response = app.post(
|
||||||
|
@ -1067,9 +1067,9 @@ def test_role_control_access(login_first, oidc_settings, oidc_client, simple_use
|
||||||
assert OIDCAuthorization.objects.get()
|
assert OIDCAuthorization.objects.get()
|
||||||
if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
|
if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
|
||||||
code = OIDCCode.objects.get()
|
code = OIDCCode.objects.get()
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
|
if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
code = query['code'][0]
|
code = query['code'][0]
|
||||||
token_url = make_url('oidc-token')
|
token_url = make_url('oidc-token')
|
||||||
response = app.post(
|
response = app.post(
|
||||||
|
@ -1083,7 +1083,7 @@ def test_role_control_access(login_first, oidc_settings, oidc_client, simple_use
|
||||||
)
|
)
|
||||||
id_token = response.json['id_token']
|
id_token = response.json['id_token']
|
||||||
elif oidc_client.authorization_flow == oidc_client.FLOW_IMPLICIT:
|
elif oidc_client.authorization_flow == oidc_client.FLOW_IMPLICIT:
|
||||||
query = urlparse.parse_qs(location.fragment)
|
query = urllib.parse.parse_qs(location.fragment)
|
||||||
id_token = query['id_token'][0]
|
id_token = query['id_token'][0]
|
||||||
|
|
||||||
if oidc_client.idtoken_algo in (oidc_client.ALGO_RSA, oidc_client.ALGO_EC):
|
if oidc_client.idtoken_algo in (oidc_client.ALGO_RSA, oidc_client.ALGO_EC):
|
||||||
|
@ -1118,12 +1118,12 @@ def test_registration_service_slug(oidc_settings, app, simple_oidc_client, simpl
|
||||||
authorize_url = make_url('oidc-authorize', params=params)
|
authorize_url = make_url('oidc-authorize', params=params)
|
||||||
response = app.get(authorize_url)
|
response = app.get(authorize_url)
|
||||||
|
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
assert query['service'] == ['default client']
|
assert query['service'] == ['default client']
|
||||||
response = response.follow().click('Register')
|
response = response.follow().click('Register')
|
||||||
location = urlparse.urlparse(response.request.url)
|
location = urllib.parse.urlparse(response.request.url)
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
assert query['service'] == ['default client']
|
assert query['service'] == ['default client']
|
||||||
|
|
||||||
response.form.set('email', 'john.doe@example.com')
|
response.form.set('email', 'john.doe@example.com')
|
||||||
|
@ -1317,8 +1317,8 @@ def test_claim_default_value(oidc_settings, normal_oidc_client, simple_user, app
|
||||||
authorize_url = make_url('oidc-authorize', params=params)
|
authorize_url = make_url('oidc-authorize', params=params)
|
||||||
|
|
||||||
response = app.get(authorize_url)
|
response = app.get(authorize_url)
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
code = query['code'][0]
|
code = query['code'][0]
|
||||||
|
|
||||||
token_url = make_url('oidc-token')
|
token_url = make_url('oidc-token')
|
||||||
|
@ -1420,8 +1420,8 @@ def test_claim_templated(oidc_settings, normal_oidc_client, simple_user, app):
|
||||||
authorize_url = make_url('oidc-authorize', params=params)
|
authorize_url = make_url('oidc-authorize', params=params)
|
||||||
|
|
||||||
response = app.get(authorize_url)
|
response = app.get(authorize_url)
|
||||||
location = urlparse.urlparse(response['Location'])
|
location = urllib.parse.urlparse(response['Location'])
|
||||||
query = urlparse.parse_qs(location.query)
|
query = urllib.parse.parse_qs(location.query)
|
||||||
code = query['code'][0]
|
code = query['code'][0]
|
||||||
|
|
||||||
token_url = make_url('oidc-token')
|
token_url = make_url('oidc-token')
|
||||||
|
|
|
@ -21,6 +21,7 @@ import base64
|
||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import re
|
import re
|
||||||
|
import urllib.parse
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
import lasso
|
import lasso
|
||||||
|
@ -31,7 +32,6 @@ from django.core.files import File
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_bytes, force_str, force_text
|
from django.utils.encoding import force_bytes, force_str, force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
||||||
|
@ -272,7 +272,7 @@ class SamlSP(object):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
login.buildAuthnRequestMsg()
|
login.buildAuthnRequestMsg()
|
||||||
url_parsed = urlparse.urlparse(login.msgUrl)
|
url_parsed = urllib.parse.urlparse(login.msgUrl)
|
||||||
assert url_parsed.path == reverse('a2-idp-saml-sso'), 'msgUrl should target the sso endpoint'
|
assert url_parsed.path == reverse('a2-idp-saml-sso'), 'msgUrl should target the sso endpoint'
|
||||||
if self.keys:
|
if self.keys:
|
||||||
assert 'rsa-sha256' in login.msgUrl
|
assert 'rsa-sha256' in login.msgUrl
|
||||||
|
@ -288,7 +288,7 @@ class SamlSP(object):
|
||||||
if response.location:
|
if response.location:
|
||||||
method = lasso.HTTP_METHOD_ARTIFACT_GET
|
method = lasso.HTTP_METHOD_ARTIFACT_GET
|
||||||
query_string = response.location.split('?', 1)[1]
|
query_string = response.location.split('?', 1)[1]
|
||||||
parsed_query_string = urlparse.parse_qs(query_string)
|
parsed_query_string = urllib.parse.parse_qs(query_string)
|
||||||
self.relay_state = parsed_query_string.get('RelayState')
|
self.relay_state = parsed_query_string.get('RelayState')
|
||||||
login.msgRelayState = force_str(self.relay_state)
|
login.msgRelayState = force_str(self.relay_state)
|
||||||
else: # lasso.HTTP_METHOD_ARTIFACT_POST, never happens
|
else: # lasso.HTTP_METHOD_ARTIFACT_POST, never happens
|
||||||
|
@ -334,7 +334,7 @@ class Scenario(object):
|
||||||
REDIRECT_FIELD_NAME: make_url('a2-idp-saml-continue', params={NONCE_FIELD_NAME: request_id}),
|
REDIRECT_FIELD_NAME: make_url('a2-idp-saml-continue', params={NONCE_FIELD_NAME: request_id}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.nonce = urlparse.parse_qs(urlparse.urlparse(response['Location']).query)['nonce'][0]
|
self.nonce = urllib.parse.parse_qs(urllib.parse.urlparse(response['Location']).query)['nonce'][0]
|
||||||
url = response['Location']
|
url = response['Location']
|
||||||
response = self.app.get(url)
|
response = self.app.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import builtins as __builtin__
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
@ -21,7 +22,6 @@ import pytest
|
||||||
from django import VERSION
|
from django import VERSION
|
||||||
from django.core import management
|
from django.core import management
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.six.moves import builtins as __builtin__
|
|
||||||
|
|
||||||
from django_rbac.utils import get_role_model
|
from django_rbac.utils import get_role_model
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import ldap
|
import ldap
|
||||||
import mock
|
import mock
|
||||||
|
@ -27,7 +28,6 @@ from django.core import mail, management
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from ldap.dn import escape_dn_chars
|
from ldap.dn import escape_dn_chars
|
||||||
from ldaptools.slapd import Slapd, has_slapd
|
from ldaptools.slapd import Slapd, has_slapd
|
||||||
|
|
||||||
|
@ -1479,7 +1479,7 @@ def test_sync_ldap_users(slapd, settings, app, db, capsys):
|
||||||
assert all(
|
assert all(
|
||||||
[
|
[
|
||||||
user.userexternalid_set.first().external_id
|
user.userexternalid_set.first().external_id
|
||||||
== urlparse.quote(user.username.split('@')[0].encode('utf-8'))
|
== urllib.parse.quote(user.username.split('@')[0].encode('utf-8'))
|
||||||
for user in User.objects.all()
|
for user in User.objects.all()
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.six.moves.urllib.parse import quote
|
|
||||||
|
|
||||||
from authentic2 import models
|
from authentic2 import models
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
@ -25,7 +26,6 @@ from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_bytes, force_str
|
from django.utils.encoding import force_bytes, force_str
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
|
||||||
from webtest import Upload
|
from webtest import Upload
|
||||||
|
|
||||||
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP
|
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
|
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
from authentic2 import models, utils
|
from authentic2 import models, utils
|
||||||
from authentic2.apps.journal.models import Event
|
from authentic2.apps.journal.models import Event
|
||||||
|
|
|
@ -27,7 +27,6 @@ import pytest
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.six import text_type
|
|
||||||
from webtest import Upload
|
from webtest import Upload
|
||||||
|
|
||||||
from authentic2.a2_rbac.utils import get_default_ou, get_view_user_perm
|
from authentic2.a2_rbac.utils import get_default_ou, get_view_user_perm
|
||||||
|
@ -230,12 +229,12 @@ def test_manager_user_change_email(app, superuser_or_admin, simple_user, mailout
|
||||||
response = login(
|
response = login(
|
||||||
app,
|
app,
|
||||||
superuser_or_admin,
|
superuser_or_admin,
|
||||||
reverse('a2-manager-user-by-uuid-detail', kwargs={'slug': text_type(simple_user.uuid)}),
|
reverse('a2-manager-user-by-uuid-detail', kwargs={'slug': str(simple_user.uuid)}),
|
||||||
)
|
)
|
||||||
assert 'Change user email' in response.text
|
assert 'Change user email' in response.text
|
||||||
# cannot click it's a submit button :/
|
# cannot click it's a submit button :/
|
||||||
response = app.get(
|
response = app.get(
|
||||||
reverse('a2-manager-user-by-uuid-change-email', kwargs={'slug': text_type(simple_user.uuid)})
|
reverse('a2-manager-user-by-uuid-change-email', kwargs={'slug': str(simple_user.uuid)})
|
||||||
)
|
)
|
||||||
assert response.form['new_email'].value == simple_user.email
|
assert response.form['new_email'].value == simple_user.email
|
||||||
response.form.set('new_email', NEW_EMAIL)
|
response.form.set('new_email', NEW_EMAIL)
|
||||||
|
@ -270,12 +269,12 @@ def test_manager_user_change_email_no_change(app, superuser_or_admin, simple_use
|
||||||
response = login(
|
response = login(
|
||||||
app,
|
app,
|
||||||
superuser_or_admin,
|
superuser_or_admin,
|
||||||
reverse('a2-manager-user-by-uuid-detail', kwargs={'slug': text_type(simple_user.uuid)}),
|
reverse('a2-manager-user-by-uuid-detail', kwargs={'slug': str(simple_user.uuid)}),
|
||||||
)
|
)
|
||||||
assert 'Change user email' in response.text
|
assert 'Change user email' in response.text
|
||||||
# cannot click it's a submit button :/
|
# cannot click it's a submit button :/
|
||||||
response = app.get(
|
response = app.get(
|
||||||
reverse('a2-manager-user-by-uuid-change-email', kwargs={'slug': text_type(simple_user.uuid)})
|
reverse('a2-manager-user-by-uuid-change-email', kwargs={'slug': str(simple_user.uuid)})
|
||||||
)
|
)
|
||||||
assert response.form['new_email'].value == simple_user.email
|
assert response.form['new_email'].value == simple_user.email
|
||||||
assert len(mailoutbox) == 0
|
assert len(mailoutbox) == 0
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
# authentic2
|
# authentic2
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
from authentic2.custom_user.models import DeletedUser, User
|
from authentic2.custom_user.models import DeletedUser, User
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
import base64
|
import base64
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
import urllib.parse
|
||||||
from contextlib import closing, contextmanager
|
from contextlib import closing, contextmanager
|
||||||
|
|
||||||
import httmock
|
import httmock
|
||||||
|
@ -25,9 +26,7 @@ from django.core.management import call_command as django_call_command
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_text, iri_to_uri
|
from django.utils.encoding import force_text, iri_to_uri
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from authentic2 import models, utils
|
from authentic2 import models, utils
|
||||||
|
@ -98,13 +97,13 @@ def assert_equals_url(url1, url2, **kwargs):
|
||||||
value.
|
value.
|
||||||
"""
|
"""
|
||||||
url1 = iri_to_uri(utils.make_url(url1, params=None))
|
url1 = iri_to_uri(utils.make_url(url1, params=None))
|
||||||
splitted1 = urlparse.urlsplit(url1)
|
splitted1 = urllib.parse.urlsplit(url1)
|
||||||
url2 = iri_to_uri(utils.make_url(url2, params=kwargs))
|
url2 = iri_to_uri(utils.make_url(url2, params=kwargs))
|
||||||
splitted2 = urlparse.urlsplit(url2)
|
splitted2 = urllib.parse.urlsplit(url2)
|
||||||
for i, (elt1, elt2) in enumerate(zip(splitted1, splitted2)):
|
for i, (elt1, elt2) in enumerate(zip(splitted1, splitted2)):
|
||||||
if i == 3:
|
if i == 3:
|
||||||
elt1 = urlparse.parse_qs(elt1, True)
|
elt1 = urllib.parse.parse_qs(elt1, True)
|
||||||
elt2 = urlparse.parse_qs(elt2, True)
|
elt2 = urllib.parse.parse_qs(elt2, True)
|
||||||
for k, v in elt1.items():
|
for k, v in elt1.items():
|
||||||
elt1[k] = set(v)
|
elt1[k] = set(v)
|
||||||
for k, v in elt2.items():
|
for k, v in elt2.items():
|
||||||
|
@ -117,11 +116,11 @@ def assert_equals_url(url1, url2, **kwargs):
|
||||||
|
|
||||||
def assert_redirects_complex(response, expected_url, **kwargs):
|
def assert_redirects_complex(response, expected_url, **kwargs):
|
||||||
assert response.status_code == 302, 'code should be 302'
|
assert response.status_code == 302, 'code should be 302'
|
||||||
scheme, netloc, path, query, fragment = urlparse.urlsplit(response.url)
|
scheme, netloc, path, query, fragment = urllib.parse.urlsplit(response.url)
|
||||||
e_scheme, e_netloc, e_path, e_query, e_fragment = urlparse.urlsplit(expected_url)
|
e_scheme, e_netloc, e_path, e_query, e_fragment = urllib.parse.urlsplit(expected_url)
|
||||||
e_scheme = e_scheme if e_scheme else scheme
|
e_scheme = e_scheme if e_scheme else scheme
|
||||||
e_netloc = e_netloc if e_netloc else netloc
|
e_netloc = e_netloc if e_netloc else netloc
|
||||||
expected_url = urlparse.urlunsplit((e_scheme, e_netloc, e_path, e_query, e_fragment))
|
expected_url = urllib.parse.urlunsplit((e_scheme, e_netloc, e_path, e_query, e_fragment))
|
||||||
assert_equals_url(response['Location'], expected_url, **kwargs)
|
assert_equals_url(response['Location'], expected_url, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,7 +131,7 @@ def assert_xpath_constraints(xml, constraints, namespaces):
|
||||||
for xpath, content in constraints:
|
for xpath, content in constraints:
|
||||||
nodes = doc.xpath(xpath, namespaces=namespaces)
|
nodes = doc.xpath(xpath, namespaces=namespaces)
|
||||||
assert len(nodes) > 0, 'xpath %s not found' % xpath
|
assert len(nodes) > 0, 'xpath %s not found' % xpath
|
||||||
if isinstance(content, six.string_types):
|
if isinstance(content, str):
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
if hasattr(node, 'text'):
|
if hasattr(node, 'text'):
|
||||||
assert node.text == content, 'xpath %s does not contain %s but %s' % (
|
assert node.text == content, 'xpath %s does not contain %s but %s' % (
|
||||||
|
|
Loading…
Reference in New Issue