From e1290397a9ad3247c957e7e3bee0d73ef7e1c2c0 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 15 Mar 2023 16:02:17 +0100 Subject: [PATCH] misc: change django-upgrade target version to 3.2 (#75442) --- .pre-commit-config.yaml | 4 +- README | 2 +- src/authentic2/__init__.py | 2 - src/authentic2/a2_rbac/__init__.py | 2 - src/authentic2/a2_rbac/admin.py | 3 +- src/authentic2/admin.py | 42 ++++++------------- src/authentic2/apps/journal/__init__.py | 2 - src/authentic2/apps/journal/admin.py | 8 +--- .../apps/journal/migrations/0001_initial.py | 6 +-- src/authentic2/apps/journal/models.py | 9 +--- src/authentic2/backends/__init__.py | 2 - src/authentic2/custom_user/__init__.py | 2 - .../management/commands/changepassword.py | 2 +- .../management/commands/fix-attributes.py | 2 +- .../migrations/0020_deleteduser.py | 7 +--- .../migrations/0029_profile_profiletype.py | 6 +-- src/authentic2/custom_user/models.py | 8 +--- .../disco_service/disco_responder.py | 4 +- src/authentic2/idp/saml/__init__.py | 3 -- .../management/commands/load-ldif.py | 2 +- src/authentic2/manager/__init__.py | 2 - src/authentic2/middleware.py | 2 +- src/authentic2/migrations/0026_token.py | 7 +--- src/authentic2/models.py | 11 ++--- src/authentic2/plugins.py | 6 +-- src/authentic2/saml/__init__.py | 2 - src/authentic2/saml/admin.py | 5 +-- src/authentic2/saml/common.py | 9 ++-- .../saml/management/commands/sync-metadata.py | 2 +- src/authentic2/settings.py | 11 ++--- src/authentic2/urls.py | 14 +++---- src/authentic2_auth_fc/urls.py | 4 +- src/authentic2_auth_oidc/__init__.py | 2 - .../commands/oidc-register-issuer.py | 2 +- .../migrations/0001_initial.py | 7 +--- src/authentic2_auth_oidc/models.py | 7 +--- .../migrations/0001_initial.py | 6 +-- src/authentic2_auth_saml/models.py | 7 +--- src/authentic2_auth_saml/urls.py | 6 +-- src/authentic2_idp_cas/__init__.py | 2 - src/authentic2_idp_oidc/__init__.py | 2 - src/authentic2_idp_oidc/views.py | 6 +-- src/django_rbac/__init__.py | 1 - tests/test_registration.py | 7 ++-- 44 files changed, 73 insertions(+), 175 deletions(-) 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)