diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index bbf59cb11..8872da095 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,10 +7,10 @@ repos:
- id: pyupgrade
args: ['--keep-percent-format', '--py37-plus']
- repo: https://github.com/adamchainz/django-upgrade
- rev: 1.10.0
+ rev: 1.13.0
hooks:
- id: django-upgrade
- args: ['--target-version', '2.2']
+ args: ['--target-version', '3.2']
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
diff --git a/README b/README
index 408845856..9376cc3aa 100644
--- a/README
+++ b/README
@@ -93,7 +93,7 @@ djhtml is used to automatically indent html files, using those parameters:
django-upgrade is used to automatically upgrade Django syntax, using those parameters:
- django-upgrade --target-version 2.2
+ django-upgrade --target-version 3.2
There is .pre-commit-config.yaml to use pre-commit to automatically run these tools
before commits. (execute `pre-commit install` to install the git hook.)
diff --git a/src/authentic2/__init__.py b/src/authentic2/__init__.py
index b5f7c7f9c..3d8db7294 100644
--- a/src/authentic2/__init__.py
+++ b/src/authentic2/__init__.py
@@ -16,8 +16,6 @@
import django
-default_app_config = 'authentic2.app.Authentic2Config'
-
if django.VERSION < (2,):
from django.forms import fields
diff --git a/src/authentic2/a2_rbac/__init__.py b/src/authentic2/a2_rbac/__init__.py
index fffc9b093..0121e3144 100644
--- a/src/authentic2/a2_rbac/__init__.py
+++ b/src/authentic2/a2_rbac/__init__.py
@@ -13,5 +13,3 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-default_app_config = 'authentic2.a2_rbac.apps.Authentic2RBACConfig'
diff --git a/src/authentic2/a2_rbac/admin.py b/src/authentic2/a2_rbac/admin.py
index 41a54957d..eacf520cb 100644
--- a/src/authentic2/a2_rbac/admin.py
+++ b/src/authentic2/a2_rbac/admin.py
@@ -86,11 +86,10 @@ class PermissionAdmin(admin.ModelAdmin):
list_display = ('name', 'operation', 'ou', 'target')
list_select_related = True
+ @admin.display(description=_('name'))
def name(self, obj):
return str(obj)
- name.short_description = _('name')
-
admin.site.register(models.Role, RoleAdmin)
admin.site.register(models.OrganizationalUnit, OrganizationalUnitAdmin)
diff --git a/src/authentic2/admin.py b/src/authentic2/admin.py
index 9e3a9eb4a..26059bb05 100644
--- a/src/authentic2/admin.py
+++ b/src/authentic2/admin.py
@@ -36,13 +36,11 @@ from .nonce.models import Nonce
from .utils import misc as utils_misc
+@admin.action(description=_('Cleanup expired objects'))
def cleanup_action(modeladmin, request, queryset):
queryset.cleanup()
-cleanup_action.short_description = _('Cleanup expired objects')
-
-
class CleanupAdminMixin(admin.ModelAdmin):
def get_actions(self, request):
actions = super().get_actions(request)
@@ -51,13 +49,11 @@ class CleanupAdminMixin(admin.ModelAdmin):
return actions
+@admin.register(Nonce)
class NonceModelAdmin(admin.ModelAdmin):
list_display = ("value", "context", "not_on_or_after")
-admin.site.register(Nonce, NonceModelAdmin)
-
-
class AttributeValueAdmin(admin.ModelAdmin):
list_display = ('content_type', 'owner', 'attribute', 'content')
@@ -100,25 +96,25 @@ DB_SESSION_ENGINES = (
if settings.SESSION_ENGINE in DB_SESSION_ENGINES:
+ @admin.register(Session)
class SessionAdmin(admin.ModelAdmin):
+ @admin.display(description=_('session data'))
def _session_data(self, obj):
return pprint.pformat(obj.get_decoded()).replace('\n', '
\n')
- _session_data.allow_tags = True
- _session_data.short_description = _('session data')
list_display = ['session_key', 'ips', 'user', '_session_data', 'expire_date']
fields = ['session_key', 'ips', 'user', '_session_data', 'expire_date']
readonly_fields = ['ips', 'user', '_session_data']
date_hierarchy = 'expire_date'
actions = ['clear_expired']
+ @admin.display(description=_('IP adresses'))
def ips(self, session):
content = session.get_decoded()
ips = content.get('ips', set())
return ', '.join(ips)
- ips.short_description = _('IP adresses')
-
+ @admin.display(description=_('user'))
def user(self, session):
from django.contrib import auth
from django.contrib.auth import models as auth_models
@@ -137,15 +133,10 @@ if settings.SESSION_ENGINE in DB_SESSION_ENGINES:
user = _('deleted user %r') % user_id
return user
- user.short_description = _('user')
-
+ @admin.action(description=_('clear expired sessions'))
def clear_expired(self, request, queryset):
queryset.filter(expire_date__lt=timezone.now()).delete()
- clear_expired.short_description = _('clear expired sessions')
-
- admin.site.register(Session, SessionAdmin)
-
class ExternalUserListFilter(admin.SimpleListFilter):
title = _('external')
@@ -283,6 +274,7 @@ class UserCreationForm(BaseUserForm):
return user
+@admin.register(User)
class AuthenticUserAdmin(UserAdmin):
fieldsets = (
(None, {'fields': ('uuid', 'ou', 'password')}),
@@ -371,17 +363,13 @@ class AuthenticUserAdmin(UserAdmin):
kwargs['fields'] = fields
return super().get_form(request, obj=obj, **kwargs)
+ @admin.action(description=_('Mark as inactive'))
@transaction.atomic
def mark_as_inactive(self, request, queryset):
timestamp = timezone.now()
for user in queryset:
user.mark_as_inactive(timestamp=timestamp)
- mark_as_inactive.short_description = _('Mark as inactive')
-
-
-admin.site.register(User, AuthenticUserAdmin)
-
class AttributeForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
@@ -421,30 +409,24 @@ class AttributeAdmin(admin.ModelAdmin):
admin.site.register(models.Attribute, AttributeAdmin)
+@admin.register(DeletedUser)
class DeletedUserAdmin(admin.ModelAdmin):
list_display = ['deleted', 'old_user_id', 'old_uuid', 'old_email']
date_hierarchy = 'deleted'
search_fields = ['=old_user_id', '^old_uuid', 'old_email']
-admin.site.register(DeletedUser, DeletedUserAdmin)
-
-
+@admin.register(ProfileType)
class ProfileTypeAdmin(admin.ModelAdmin):
list_display = ['uuid', 'name', 'slug']
readonly_fields = ['uuid']
-admin.site.register(ProfileType, ProfileTypeAdmin)
-
-
+@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
list_display = ['profile_type', 'user', 'identifier', 'email']
-admin.site.register(Profile, ProfileAdmin)
-
-
@never_cache
def login(request, extra_context=None):
return utils_misc.redirect_to_login(request, login_url=utils_misc.get_manager_login_url())
diff --git a/src/authentic2/apps/journal/__init__.py b/src/authentic2/apps/journal/__init__.py
index 09ae0fc8b..b938cf52f 100644
--- a/src/authentic2/apps/journal/__init__.py
+++ b/src/authentic2/apps/journal/__init__.py
@@ -14,5 +14,3 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-default_app_config = 'authentic2.apps.journal.app.JournalAppConfig'
diff --git a/src/authentic2/apps/journal/admin.py b/src/authentic2/apps/journal/admin.py
index ca88f178b..95a6ba297 100644
--- a/src/authentic2/apps/journal/admin.py
+++ b/src/authentic2/apps/journal/admin.py
@@ -22,6 +22,7 @@ from django.utils.html import format_html
from .models import Event, EventType
+@admin.register(EventType)
class EventTypeAdmin(admin.ModelAdmin):
list_display = [
'__str__',
@@ -29,9 +30,7 @@ class EventTypeAdmin(admin.ModelAdmin):
]
-admin.site.register(EventType, EventTypeAdmin)
-
-
+@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
date_hierarchy = 'timestamp'
list_filter = ['type']
@@ -65,6 +64,3 @@ class EventAdmin(admin.ModelAdmin):
def raw_json(self, event):
return format_html('
{}
', json.dumps(event.data or {}, indent=4))
-
-
-admin.site.register(Event, EventAdmin)
diff --git a/src/authentic2/apps/journal/migrations/0001_initial.py b/src/authentic2/apps/journal/migrations/0001_initial.py
index d9fa8244f..d5cf67c97 100644
--- a/src/authentic2/apps/journal/migrations/0001_initial.py
+++ b/src/authentic2/apps/journal/migrations/0001_initial.py
@@ -5,13 +5,9 @@ import django.contrib.postgres.fields
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
+from django.db.models import JSONField
from django.utils import timezone
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
class Migration(migrations.Migration):
diff --git a/src/authentic2/apps/journal/models.py b/src/authentic2/apps/journal/models.py
index 77e27d13c..bf3550c00 100644
--- a/src/authentic2/apps/journal/models.py
+++ b/src/authentic2/apps/journal/models.py
@@ -27,10 +27,10 @@ from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import ArrayField
-from django.contrib.postgres.fields.jsonb import KeyTextTransform
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
-from django.db.models import Count, F, Q, QuerySet, Value
+from django.db.models import Count, F, JSONField, Q, QuerySet, Value
+from django.db.models.fields.json import KeyTextTransform
from django.db.models.functions import Trunc
from django.utils.timezone import now, utc
from django.utils.translation import gettext_lazy as _
@@ -40,11 +40,6 @@ from authentic2.utils.cache import GlobalCache
from . import sql
from .utils import Statistics
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
logger = logging.getLogger(__name__)
User = get_user_model()
diff --git a/src/authentic2/backends/__init__.py b/src/authentic2/backends/__init__.py
index 06f50d6e1..bc9278226 100644
--- a/src/authentic2/backends/__init__.py
+++ b/src/authentic2/backends/__init__.py
@@ -18,8 +18,6 @@ from django.contrib.auth import get_user_model
from authentic2 import app_settings
-default_app_config = 'authentic2.backends.apps.AppConfig'
-
def get_user_queryset():
User = get_user_model()
diff --git a/src/authentic2/custom_user/__init__.py b/src/authentic2/custom_user/__init__.py
index a45d758e1..0121e3144 100644
--- a/src/authentic2/custom_user/__init__.py
+++ b/src/authentic2/custom_user/__init__.py
@@ -13,5 +13,3 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-default_app_config = 'authentic2.custom_user.apps.CustomUserConfig'
diff --git a/src/authentic2/custom_user/management/commands/changepassword.py b/src/authentic2/custom_user/management/commands/changepassword.py
index 83cfece32..38662f25b 100644
--- a/src/authentic2/custom_user/management/commands/changepassword.py
+++ b/src/authentic2/custom_user/management/commands/changepassword.py
@@ -28,7 +28,7 @@ from django.utils.encoding import force_str
class Command(BaseCommand):
help = "Change a user's password for django.contrib.auth."
- requires_system_checks = False
+ requires_system_checks = []
def add_arguments(self, parser):
parser.add_argument('username', nargs='?', type=str)
diff --git a/src/authentic2/custom_user/management/commands/fix-attributes.py b/src/authentic2/custom_user/management/commands/fix-attributes.py
index 92a7ce9e4..879247816 100644
--- a/src/authentic2/custom_user/management/commands/fix-attributes.py
+++ b/src/authentic2/custom_user/management/commands/fix-attributes.py
@@ -23,7 +23,7 @@ from authentic2.custom_user.models import User
class Command(BaseCommand):
help = "Fix user attributes"
- requires_system_checks = False
+ requires_system_checks = []
def handle(self, *args, **options):
user_ids = User.objects.values_list('id', flat=True)
diff --git a/src/authentic2/custom_user/migrations/0020_deleteduser.py b/src/authentic2/custom_user/migrations/0020_deleteduser.py
index 5fd92d91c..506ad7226 100644
--- a/src/authentic2/custom_user/migrations/0020_deleteduser.py
+++ b/src/authentic2/custom_user/migrations/0020_deleteduser.py
@@ -1,12 +1,7 @@
# Generated by Django 2.2.12 on 2020-05-05 14:16
-import django
from django.db import migrations, models
-
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
+from django.db.models import JSONField
class Migration(migrations.Migration):
diff --git a/src/authentic2/custom_user/migrations/0029_profile_profiletype.py b/src/authentic2/custom_user/migrations/0029_profile_profiletype.py
index b58a46d1f..3646ae7c4 100644
--- a/src/authentic2/custom_user/migrations/0029_profile_profiletype.py
+++ b/src/authentic2/custom_user/migrations/0029_profile_profiletype.py
@@ -6,11 +6,7 @@ import django
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
-
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
+from django.db.models import JSONField
class Migration(migrations.Migration):
diff --git a/src/authentic2/custom_user/models.py b/src/authentic2/custom_user/models.py
index 7c1de8ff1..c87508e04 100644
--- a/src/authentic2/custom_user/models.py
+++ b/src/authentic2/custom_user/models.py
@@ -22,7 +22,6 @@ import operator
import os
import uuid
-import django
from django.contrib import auth
from django.contrib.auth.models import AbstractBaseUser, Group
from django.contrib.auth.models import Permission as AuthPermission
@@ -46,6 +45,8 @@ except ImportError:
return _user_get_permissions(user, obj, 'all')
+from django.db.models import JSONField
+
from authentic2 import app_settings
from authentic2.a2_rbac.models import RoleParenting
from authentic2.decorators import errorcollector
@@ -58,11 +59,6 @@ from authentic2.validators import PhoneNumberValidator, email_validator
from .backends import DjangoRBACBackend
from .managers import UserManager, UserQuerySet
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
@RequestCache
def get_attributes_map():
diff --git a/src/authentic2/disco_service/disco_responder.py b/src/authentic2/disco_service/disco_responder.py
index 67a836412..5ff5149da 100644
--- a/src/authentic2/disco_service/disco_responder.py
+++ b/src/authentic2/disco_service/disco_responder.py
@@ -24,11 +24,11 @@
import logging
import urllib.parse
+from urllib.parse import quote
from xml.dom.minidom import parseString
from django.http import HttpResponseRedirect
from django.urls import path, reverse
-from django.utils.http import urlquote
from django.utils.translation import gettext as _
from authentic2 import settings
@@ -220,7 +220,7 @@ def disco(request):
def idp_selection(request):
# XXX: Code here the IdP selection
- idp_selected = urlquote('http://www.identity-hub.com/idp/saml2/metadata')
+ idp_selected = quote('http://www.identity-hub.com/idp/saml2/metadata')
return HttpResponseRedirect('%s?idp_selected=%s' % (reverse(disco), idp_selected))
diff --git a/src/authentic2/idp/saml/__init__.py b/src/authentic2/idp/saml/__init__.py
index 3a137099c..1f7e4f1ff 100644
--- a/src/authentic2/idp/saml/__init__.py
+++ b/src/authentic2/idp/saml/__init__.py
@@ -38,9 +38,6 @@ class SAML2IdPConfig(AppConfig):
return Plugin()
-default_app_config = 'authentic2.idp.saml.SAML2IdPConfig'
-
-
def check_authentic2_config(app_configs, **kwargs):
from . import app_settings
diff --git a/src/authentic2/management/commands/load-ldif.py b/src/authentic2/management/commands/load-ldif.py
index 7c199e4ce..6977b3885 100644
--- a/src/authentic2/management/commands/load-ldif.py
+++ b/src/authentic2/management/commands/load-ldif.py
@@ -111,7 +111,7 @@ class Command(BaseCommand):
'''Load LDAP ldif file'''
can_import_django_settings = True
- requires_system_checks = True
+ requires_system_checks = "__all__"
help = 'Load/update LDIF files as users'
def add_arguments(self, parser):
diff --git a/src/authentic2/manager/__init__.py b/src/authentic2/manager/__init__.py
index b7f79856c..937a969f6 100644
--- a/src/authentic2/manager/__init__.py
+++ b/src/authentic2/manager/__init__.py
@@ -16,5 +16,3 @@
# django_select2.conf must be loaded early to modify django.conf.settings before everybody
import django_select2.conf # noqa: F401
-
-default_app_config = 'authentic2.manager.apps.AppConfig'
diff --git a/src/authentic2/middleware.py b/src/authentic2/middleware.py
index f5eeeb226..63f696995 100644
--- a/src/authentic2/middleware.py
+++ b/src/authentic2/middleware.py
@@ -207,7 +207,7 @@ class XForwardedForMiddleware(MiddlewareMixin):
forged (behind a reverse proxy for example)."""
def process_request(self, request):
- if 'HTTP_X_FORWARDED_FOR' in request.META:
+ if 'x-forwarded-for' in request.headers:
request.META['REMOTE_ADDR'] = request.headers['X-Forwarded-For'].split(",")[0].strip()
return None
diff --git a/src/authentic2/migrations/0026_token.py b/src/authentic2/migrations/0026_token.py
index bfa190eb7..bcdb62247 100644
--- a/src/authentic2/migrations/0026_token.py
+++ b/src/authentic2/migrations/0026_token.py
@@ -2,13 +2,8 @@
import uuid
-import django
from django.db import migrations, models
-
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
+from django.db.models import JSONField
class Migration(migrations.Migration):
diff --git a/src/authentic2/models.py b/src/authentic2/models.py
index 5a952201e..fb0d28b9a 100644
--- a/src/authentic2/models.py
+++ b/src/authentic2/models.py
@@ -21,8 +21,8 @@ import os
import time
import urllib.parse
import uuid
+from urllib.parse import quote
-import django
from django.conf import settings
from django.contrib import auth
from django.contrib.contenttypes.fields import GenericForeignKey
@@ -32,10 +32,10 @@ from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import SearchVectorField
from django.core.exceptions import PermissionDenied, ValidationError
from django.db import DatabaseError, models, transaction
+from django.db.models import JSONField
from django.db.models.query import Q
from django.urls import reverse
from django.utils import timezone
-from django.utils.http import urlquote
from django.utils.translation import gettext_lazy as _
from model_utils.managers import QueryManager
@@ -51,11 +51,6 @@ from . import natural_key as unused_natural_key # pylint: disable=unused-import
from .utils.misc import ServiceAccessDenied
from .utils.sms import create_sms_code
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
class UserExternalId(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
@@ -135,7 +130,7 @@ class LogoutUrlAbstract(models.Model):
request.build_absolute_uri(urllib.parse.urljoin(settings.STATIC_URL, 'authentic2/images/ok.png'))
+ '?nonce=%s' % time.time()
)
- return self.logout_url.format(urlquote(ok_icon_url))
+ return self.logout_url.format(quote(ok_icon_url))
class Meta:
abstract = True
diff --git a/src/authentic2/plugins.py b/src/authentic2/plugins.py
index 5ca623e10..4db1f93dd 100644
--- a/src/authentic2/plugins.py
+++ b/src/authentic2/plugins.py
@@ -23,7 +23,7 @@ import logging
import pkg_resources
from django.apps import apps
-from django.urls import include, re_path
+from django.urls import include, path
logger = logging.getLogger(__name__)
@@ -80,10 +80,10 @@ def register_plugins_urls(urlpatterns, group_name=DEFAULT_GROUP_NAME):
for plugin in plugins:
if hasattr(plugin, 'get_before_urls'):
urls = plugin.get_before_urls()
- before_urls.append(re_path('^', include(urls)))
+ before_urls.append(path('', include(urls)))
if hasattr(plugin, 'get_after_urls'):
urls = plugin.get_after_urls()
- after_urls.append(re_path('^', include(urls)))
+ after_urls.append(path('', include(urls)))
return before_urls + urlpatterns + after_urls
diff --git a/src/authentic2/saml/__init__.py b/src/authentic2/saml/__init__.py
index e18d764c3..b52d8bd76 100644
--- a/src/authentic2/saml/__init__.py
+++ b/src/authentic2/saml/__init__.py
@@ -16,8 +16,6 @@
from django.apps import AppConfig
-default_app_config = 'authentic2.saml.A2SAMLAppConfig'
-
class A2SAMLAppConfig(AppConfig):
name = 'authentic2.saml'
diff --git a/src/authentic2/saml/admin.py b/src/authentic2/saml/admin.py
index 9964a7ef6..f98b00cd0 100644
--- a/src/authentic2/saml/admin.py
+++ b/src/authentic2/saml/admin.py
@@ -148,6 +148,7 @@ class SAMLAttributeInlineAdmin(GenericTabularInline):
return super().get_formset(request, obj=obj, **kwargs)
+@admin.register(LibertyProvider)
class LibertyProviderAdmin(admin.ModelAdmin):
form = LibertyProviderForm
list_display = ('name', 'ou', 'slug', 'entity_id')
@@ -194,6 +195,7 @@ class LibertyFederationAdmin(admin.ModelAdmin):
return name_id_format
+@admin.register(SPOptionsIdPPolicy)
class SPOptionsIdPPolicyAdmin(admin.ModelAdmin):
inlines = [SAMLAttributeInlineAdmin]
fields = (
@@ -215,9 +217,6 @@ class SPOptionsIdPPolicyAdmin(admin.ModelAdmin):
)
-admin.site.register(SPOptionsIdPPolicy, SPOptionsIdPPolicyAdmin)
-admin.site.register(LibertyProvider, LibertyProviderAdmin)
-
if settings.DEBUG:
admin.site.register(LibertyFederation, LibertyFederationAdmin)
admin.site.register(LibertySession)
diff --git a/src/authentic2/saml/common.py b/src/authentic2/saml/common.py
index 03b3015e4..a3c109693 100644
--- a/src/authentic2/saml/common.py
+++ b/src/authentic2/saml/common.py
@@ -64,8 +64,8 @@ def get_soap_message(request):
'''Verify that POST content looks like a SOAP message and returns it'''
assert (
request.method == 'POST'
- and 'CONTENT_TYPE' in request.META
- and 'text/xml' in request.META['CONTENT_TYPE']
+ and 'content-type' in request.headers
+ and 'text/xml' in request.headers['content-type']
), 'not a SOAP message'
return request.body
@@ -75,7 +75,10 @@ def get_http_binding(request):
return 'GET'
elif request.method == 'POST':
# disambiguate SOAP and form POST
- if request.META.get('CONTENT_TYPE') in ['application/x-www-form-urlencoded', 'multipart/form-data']:
+ if request.headers.get('content-type') in [
+ 'application/x-www-form-urlencoded',
+ 'multipart/form-data',
+ ]:
return 'POST'
else:
return 'SOAP'
diff --git a/src/authentic2/saml/management/commands/sync-metadata.py b/src/authentic2/saml/management/commands/sync-metadata.py
index 9a9a00bd5..8f4ac6f2a 100644
--- a/src/authentic2/saml/management/commands/sync-metadata.py
+++ b/src/authentic2/saml/management/commands/sync-metadata.py
@@ -255,7 +255,7 @@ class Command(BaseCommand):
can_import_django_settings = True
output_transaction = True
- requires_system_checks = True
+ requires_system_checks = "__all__"
help = 'Load the specified SAMLv2 metadata file'
diff --git a/src/authentic2/settings.py b/src/authentic2/settings.py
index fd39bb7ab..aae166b39 100644
--- a/src/authentic2/settings.py
+++ b/src/authentic2/settings.py
@@ -19,7 +19,6 @@ import logging.config
import os
# Load default from Django
-import django
from django.conf import global_settings
from django.utils.translation import gettext_lazy as _
@@ -51,7 +50,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
+ 'ENGINE': 'django.db.backends.postgresql',
'NAME': 'authentic2',
}
}
@@ -61,12 +60,8 @@ SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
LANGUAGE_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Lax'
-if django.VERSION < (3, 1):
- SESSION_COOKIE_SAMESITE = 'Lax'
- LANGUAGE_COOKIE_SAMESITE = 'Lax'
-else:
- SESSION_COOKIE_SAMESITE = 'None'
- LANGUAGE_COOKIE_SAMESITE = 'None'
+SESSION_COOKIE_SAMESITE = 'None'
+LANGUAGE_COOKIE_SAMESITE = 'None'
# Hey Entr'ouvert is in France !!
TIME_ZONE = 'Europe/Paris'
diff --git a/src/authentic2/urls.py b/src/authentic2/urls.py
index 94d08ea03..8baa2669d 100644
--- a/src/authentic2/urls.py
+++ b/src/authentic2/urls.py
@@ -99,11 +99,11 @@ urlpatterns = [
re_path(r'^login/token/(?P[A-Za-z0-9_ -]+)/$', views.token_login, name='token_login'),
path('logout/', views.logout, name='auth_logout'),
re_path(r'^su/(?P[A-Za-z0-9_-]+)/$', views.su, name='su'),
- re_path(r'^accounts/', include(accounts_urlpatterns)),
+ path('accounts/', include(accounts_urlpatterns)),
re_path(r'^admin/', admin.site.urls),
- re_path(r'^idp/', include('authentic2.idp.urls')),
- re_path(r'^manage/', include('authentic2.manager.urls')),
- re_path(r'^api/', include('authentic2.api_urls')),
+ path('idp/', include('authentic2.idp.urls')),
+ path('manage/', include('authentic2.manager.urls')),
+ path('api/', include('authentic2.api_urls')),
path('continue/', views.display_message_and_continue, name='continue'),
re_path(r'^\.well-known/change-password$', RedirectView.as_view(pattern_name='password_change')),
# Registration
@@ -158,7 +158,7 @@ if settings.DEBUG and 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar # pylint: disable=import-error
urlpatterns = [
- re_path(r'^__debug__/', include(debug_toolbar.urls)),
+ path('__debug__/', include(debug_toolbar.urls)),
] + urlpatterns
# prevent click-jacking on authentic views
@@ -168,12 +168,12 @@ urlpatterns = plugins.register_plugins_urls(urlpatterns)
authentic2_idp_saml_urls = required(
(setting_enabled('ENABLE', settings=authentic2.idp.saml.app_settings), lasso_required()),
- [re_path(r'^idp/saml2/', include('authentic2.idp.saml.urls'))],
+ [path('idp/saml2/', include('authentic2.idp.saml.urls'))],
)
authentic2_idp_cas_urls = required(
(setting_enabled('ENABLE', settings=authentic2_idp_cas.app_settings),),
- [re_path(r'^idp/cas/', include('authentic2_idp_cas.urls'))],
+ [path('idp/cas/', include('authentic2_idp_cas.urls'))],
)
urlpatterns = (
diff --git a/src/authentic2_auth_fc/urls.py b/src/authentic2_auth_fc/urls.py
index 746989270..9f9865c5d 100644
--- a/src/authentic2_auth_fc/urls.py
+++ b/src/authentic2_auth_fc/urls.py
@@ -14,7 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-from django.urls import include, path, re_path
+from django.urls import include, path
from . import views
@@ -24,6 +24,6 @@ fcpatterns = [
]
urlpatterns = [
- re_path(r'^fc/', include(fcpatterns)),
+ path('fc/', include(fcpatterns)),
path('accounts/fc/unlink/', views.unlink, name='fc-unlink'),
]
diff --git a/src/authentic2_auth_oidc/__init__.py b/src/authentic2_auth_oidc/__init__.py
index ebb552754..0121e3144 100644
--- a/src/authentic2_auth_oidc/__init__.py
+++ b/src/authentic2_auth_oidc/__init__.py
@@ -13,5 +13,3 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-default_app_config = 'authentic2_auth_oidc.apps.AppConfig'
diff --git a/src/authentic2_auth_oidc/management/commands/oidc-register-issuer.py b/src/authentic2_auth_oidc/management/commands/oidc-register-issuer.py
index daef5c9e8..8be72fda1 100644
--- a/src/authentic2_auth_oidc/management/commands/oidc-register-issuer.py
+++ b/src/authentic2_auth_oidc/management/commands/oidc-register-issuer.py
@@ -31,7 +31,7 @@ class Command(BaseCommand):
'''Load LDAP ldif file'''
can_import_django_settings = True
- requires_system_checks = True
+ requires_system_checks = "__all__"
help = 'Register an OpenID Connect OP'
def add_arguments(self, parser):
diff --git a/src/authentic2_auth_oidc/migrations/0001_initial.py b/src/authentic2_auth_oidc/migrations/0001_initial.py
index 78de81ae1..7435a35fe 100644
--- a/src/authentic2_auth_oidc/migrations/0001_initial.py
+++ b/src/authentic2_auth_oidc/migrations/0001_initial.py
@@ -1,14 +1,9 @@
-import django
from django.conf import settings
from django.db import migrations, models
+from django.db.models import JSONField
import authentic2_auth_oidc.models
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
class Migration(migrations.Migration):
diff --git a/src/authentic2_auth_oidc/models.py b/src/authentic2_auth_oidc/models.py
index 804c44296..2feb4c058 100644
--- a/src/authentic2_auth_oidc/models.py
+++ b/src/authentic2_auth_oidc/models.py
@@ -18,11 +18,11 @@ import json
import logging
from datetime import datetime, timedelta
-import django
import requests
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
+from django.db.models import JSONField
from django.shortcuts import render
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
@@ -40,11 +40,6 @@ from authentic2.utils.template import validate_template
from . import managers, utils
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
def validate_jwkset(data):
data = json.dumps(data)
diff --git a/src/authentic2_auth_saml/migrations/0001_initial.py b/src/authentic2_auth_saml/migrations/0001_initial.py
index 9bc14724f..5b971e169 100644
--- a/src/authentic2_auth_saml/migrations/0001_initial.py
+++ b/src/authentic2_auth_saml/migrations/0001_initial.py
@@ -3,15 +3,11 @@
import django
import django.db.models.deletion
from django.db import migrations, models
+from django.db.models import JSONField
import authentic2_auth_saml.models
from authentic2_auth_saml.models import NAME_ID_FORMAT_CHOICES
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
class Migration(migrations.Migration):
diff --git a/src/authentic2_auth_saml/models.py b/src/authentic2_auth_saml/models.py
index 0c951ab04..46894d4f8 100644
--- a/src/authentic2_auth_saml/models.py
+++ b/src/authentic2_auth_saml/models.py
@@ -16,11 +16,11 @@
import xml.etree.ElementTree as ET
-import django
import lasso
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
+from django.db.models import JSONField
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
@@ -32,11 +32,6 @@ from authentic2.apps.authenticators.models import (
)
from authentic2.utils.misc import redirect_to_login
-if django.VERSION < (3, 1):
- from django.contrib.postgres.fields.jsonb import JSONField # noqa pylint: disable=ungrouped-imports
-else:
- from django.db.models import JSONField
-
NAME_ID_FORMAT_CHOICES = (
('', _('None')),
(
diff --git a/src/authentic2_auth_saml/urls.py b/src/authentic2_auth_saml/urls.py
index ffd0579a1..a3882bd7e 100644
--- a/src/authentic2_auth_saml/urls.py
+++ b/src/authentic2_auth_saml/urls.py
@@ -14,13 +14,13 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-from django.urls import include, path, re_path
+from django.urls import include, path
from . import views
urlpatterns = [
- re_path(
- r'^accounts/saml/',
+ path(
+ 'accounts/saml/',
include('mellon.urls'),
kwargs={'template_base': 'authentic2/base.html', 'logout_next_url': '/logout/'},
),
diff --git a/src/authentic2_idp_cas/__init__.py b/src/authentic2_idp_cas/__init__.py
index 311d07e56..0121e3144 100644
--- a/src/authentic2_idp_cas/__init__.py
+++ b/src/authentic2_idp_cas/__init__.py
@@ -13,5 +13,3 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-default_app_config = 'authentic2_idp_cas.apps.AppConfig'
diff --git a/src/authentic2_idp_oidc/__init__.py b/src/authentic2_idp_oidc/__init__.py
index 03296937d..0121e3144 100644
--- a/src/authentic2_idp_oidc/__init__.py
+++ b/src/authentic2_idp_oidc/__init__.py
@@ -13,5 +13,3 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-default_app_config = 'authentic2_idp_oidc.apps.AppConfig'
diff --git a/src/authentic2_idp_oidc/views.py b/src/authentic2_idp_oidc/views.py
index 8fffd4995..d4d25fd3c 100644
--- a/src/authentic2_idp_oidc/views.py
+++ b/src/authentic2_idp_oidc/views.py
@@ -587,7 +587,7 @@ def is_ro_cred_grant_ratelimited(request, key='ip', increment=True):
def authenticate_client(request, ratelimit=False, client=None):
'''Authenticate client on the token endpoint'''
- if 'HTTP_AUTHORIZATION' in request.META:
+ if 'authorization' in request.headers:
client_id, client_secret = parse_http_basic(request)
elif 'client_id' in request.POST:
client_id = request.POST.get('client_id', '')
@@ -631,7 +631,7 @@ def idtoken_from_user_credential(request):
client=client,
)
- if request.META.get('CONTENT_TYPE') != 'application/x-www-form-urlencoded':
+ if request.headers.get('content-type') != 'application/x-www-form-urlencoded':
raise InvalidRequest(
_('Wrong content type. request content type must be \'application/x-www-form-urlencoded\''),
client=client,
@@ -841,7 +841,7 @@ def token(request, *args, **kwargs):
def authenticate_access_token(request):
- if 'HTTP_AUTHORIZATION' not in request.META:
+ if 'authorization' not in request.headers:
raise InvalidRequest(_('Bearer authentication is mandatory'), status=401)
authorization = request.headers['Authorization'].split()
if authorization[0] != 'Bearer' or len(authorization) != 2:
diff --git a/src/django_rbac/__init__.py b/src/django_rbac/__init__.py
index d0107eda9..e69de29bb 100644
--- a/src/django_rbac/__init__.py
+++ b/src/django_rbac/__init__.py
@@ -1 +0,0 @@
-default_app_config = 'django_rbac.apps.DjangoRBACConfig'
diff --git a/tests/test_registration.py b/tests/test_registration.py
index e52789d0d..aa460bdd2 100644
--- a/tests/test_registration.py
+++ b/tests/test_registration.py
@@ -17,12 +17,11 @@
import json
from datetime import date, timedelta
from unittest import mock
-from urllib.parse import urlparse
+from urllib.parse import quote, urlparse
import requests
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
from django.urls import reverse
-from django.utils.http import urlquote
from httmock import HTTMock, remember_called, urlmatch
from authentic2 import models
@@ -552,7 +551,7 @@ def test_registration_redirect(app, db, settings, mailoutbox, external_redirect)
new_next_url = settings.A2_REGISTRATION_REDIRECT
if good_next_url:
- new_next_url += '?next=' + urlquote(next_url)
+ new_next_url += '?next=' + quote(next_url)
# disable existing attributes
models.Attribute.objects.update(disabled=True)
@@ -605,7 +604,7 @@ def test_registration_redirect_tuple(app, db, settings, mailoutbox, external_red
new_next_url = settings.A2_REGISTRATION_REDIRECT[0]
if good_next_url:
- new_next_url += '?target=' + urlquote(next_url)
+ new_next_url += '?target=' + quote(next_url)
# disable existing attributes
models.Attribute.objects.update(disabled=True)