From 34e42dacb103eb799a7fe679d982350f76df40c5 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 8 Jul 2021 09:19:52 +0300 Subject: [PATCH] misc: update import statements (#55602) --- debian/debian_config.py | 2 +- debian/multitenant/debian_config.py | 2 +- src/authentic2/a2_rbac/management.py | 2 +- .../a2_rbac/migrations/0001_initial.py | 12 +- src/authentic2/a2_rbac/signal_handlers.py | 3 +- src/authentic2/admin.py | 7 +- src/authentic2/api_views.py | 19 ++- src/authentic2/attributes_ng/engine.py | 7 +- src/authentic2/authenticators.py | 11 +- src/authentic2/backends/ldap_backend.py | 2 +- src/authentic2/cbv.py | 5 +- src/authentic2/context_processors.py | 5 +- src/authentic2/csv_import.py | 2 +- .../custom_user/migrations/0001_initial.py | 4 +- src/authentic2/custom_user/models.py | 7 +- src/authentic2/decorators.py | 2 +- src/authentic2/forms/authentication.py | 7 +- src/authentic2/forms/passwords.py | 13 +- src/authentic2/idp/saml/backend.py | 2 +- src/authentic2/idp/saml/saml2_endpoints.py | 13 +- .../commands/clean-unused-accounts.py | 2 +- .../management/commands/resetpassword.py | 2 +- src/authentic2/manager/forms.py | 2 +- src/authentic2/manager/role_views.py | 2 +- src/authentic2/manager/urls.py | 4 +- src/authentic2/manager/user_export.py | 2 +- src/authentic2/manager/user_import.py | 2 +- src/authentic2/manager/user_views.py | 10 +- src/authentic2/manager/views.py | 2 +- src/authentic2/middleware.py | 11 +- src/authentic2/models.py | 2 +- src/authentic2/saml/utils.py | 2 +- src/authentic2/settings.py | 2 +- src/authentic2/utils/switch_user.py | 2 +- src/authentic2/views.py | 161 ++++++++++-------- src/authentic2_auth_fc/apps.py | 4 +- src/authentic2_auth_fc/authenticators.py | 10 +- src/authentic2_auth_fc/views.py | 24 +-- src/authentic2_auth_oidc/apps.py | 2 +- src/authentic2_auth_oidc/authenticators.py | 2 +- src/authentic2_auth_oidc/views.py | 2 +- src/authentic2_auth_saml/adapters.py | 4 +- src/authentic2_auth_saml/authenticators.py | 2 +- src/authentic2_idp_cas/models.py | 2 +- src/authentic2_idp_cas/views.py | 2 +- src/authentic2_idp_oidc/utils.py | 2 +- src/authentic2_idp_oidc/views.py | 2 +- src/django_rbac/migrations/0001_initial.py | 2 - tests/auth_fc/conftest.py | 2 +- tests/idp_oidc/test_misc.py | 2 +- tests/test_a2_rbac.py | 2 +- tests/test_all.py | 20 +-- tests/test_api.py | 2 +- tests/test_auth_oidc.py | 2 +- tests/test_backends.py | 2 +- tests/test_data_transfer.py | 2 +- tests/test_idp_saml2.py | 2 +- tests/test_ldap.py | 3 +- tests/test_password_reset.py | 4 +- tests/test_registration.py | 37 ++-- tests/test_user_manager.py | 4 +- tests/test_utils.py | 8 +- tests/utils.py | 7 +- 63 files changed, 255 insertions(+), 239 deletions(-) diff --git a/debian/debian_config.py b/debian/debian_config.py index 64a459624..d3181f430 100644 --- a/debian/debian_config.py +++ b/debian/debian_config.py @@ -28,7 +28,7 @@ LOGGING = { 'disable_existing_loggers': True, 'filters': { 'cleaning': { - '()': 'authentic2.utils.CleanLogMessage', + '()': 'authentic2.utils.misc.CleanLogMessage', }, 'request_context': { '()': 'authentic2.log_filters.RequestContextFilter', diff --git a/debian/multitenant/debian_config.py b/debian/multitenant/debian_config.py index 53e3a2d48..42394c1fb 100644 --- a/debian/multitenant/debian_config.py +++ b/debian/multitenant/debian_config.py @@ -25,7 +25,7 @@ INSTALLED_APPS = ('hobo.agent.authentic2',) + INSTALLED_APPS LOGGING['filters'].update( { 'cleaning': { - '()': 'authentic2.utils.CleanLogMessage', + '()': 'authentic2.utils.misc.CleanLogMessage', }, } ) diff --git a/src/authentic2/a2_rbac/management.py b/src/authentic2/a2_rbac/management.py index 51ae6b773..eaf8ccd1e 100644 --- a/src/authentic2/a2_rbac/management.py +++ b/src/authentic2/a2_rbac/management.py @@ -19,9 +19,9 @@ from django.utils.text import slugify from django.utils.translation import ugettext from django.utils.translation import ugettext_lazy as _ +from authentic2.utils.misc import get_fk_model from django_rbac.utils import get_ou_model, get_role_model -from ..utils import get_fk_model from . import app_settings, utils diff --git a/src/authentic2/a2_rbac/migrations/0001_initial.py b/src/authentic2/a2_rbac/migrations/0001_initial.py index d94b6e658..14f490d1b 100644 --- a/src/authentic2/a2_rbac/migrations/0001_initial.py +++ b/src/authentic2/a2_rbac/migrations/0001_initial.py @@ -2,7 +2,7 @@ from django.conf import settings from django.db import migrations, models import authentic2.a2_rbac.fields -import authentic2.utils +import authentic2.utils.misc class Migration(migrations.Migration): @@ -25,7 +25,10 @@ class Migration(migrations.Migration): ( 'uuid', models.CharField( - default=authentic2.utils.get_hex_uuid, unique=True, max_length=32, verbose_name='uuid' + default=authentic2.utils.misc.get_hex_uuid, + unique=True, + max_length=32, + verbose_name='uuid', ), ), ('name', models.CharField(max_length=256, verbose_name='name')), @@ -89,7 +92,10 @@ class Migration(migrations.Migration): ( 'uuid', models.CharField( - default=authentic2.utils.get_hex_uuid, unique=True, max_length=32, verbose_name='uuid' + default=authentic2.utils.misc.get_hex_uuid, + unique=True, + max_length=32, + verbose_name='uuid', ), ), ('name', models.CharField(max_length=256, verbose_name='name')), diff --git a/src/authentic2/a2_rbac/signal_handlers.py b/src/authentic2/a2_rbac/signal_handlers.py index 6447f7f87..fa4c02d06 100644 --- a/src/authentic2/a2_rbac/signal_handlers.py +++ b/src/authentic2/a2_rbac/signal_handlers.py @@ -20,11 +20,10 @@ from django.db import DEFAULT_DB_ALIAS, router, transaction from django.utils.translation import override from django.utils.translation import ugettext as _ +from authentic2.utils.misc import get_fk_model from django_rbac.managers import defer_update_transitive_closure from django_rbac.utils import get_operation, get_ou_model, get_role_model -from ..utils import get_fk_model - def create_default_ou(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): if not router.allow_migrate(using, get_ou_model()): diff --git a/src/authentic2/admin.py b/src/authentic2/admin.py index 4d4a3bb30..a70849cc7 100644 --- a/src/authentic2/admin.py +++ b/src/authentic2/admin.py @@ -29,10 +29,11 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django.views.decorators.cache import never_cache -from . import app_settings, attribute_kinds, decorators, models, utils +from . import app_settings, attribute_kinds, decorators, models from .custom_user.models import DeletedUser, User from .forms.profile import BaseUserForm, modelform_factory from .nonce.models import Nonce +from .utils import misc as utils_misc def cleanup_action(modeladmin, request, queryset): @@ -408,7 +409,7 @@ admin.site.register(DeletedUser, DeletedUserAdmin) @never_cache def login(request, extra_context=None): - return utils.redirect_to_login(request, login_url=utils.get_manager_login_url()) + return utils_misc.redirect_to_login(request, login_url=utils_misc.get_manager_login_url()) admin.site.login = login @@ -416,7 +417,7 @@ admin.site.login = login @never_cache def logout(request, extra_context=None): - return utils.redirect_to_login(request, login_url='auth_logout') + return utils_misc.redirect_to_login(request, login_url='auth_logout') admin.site.logout = logout diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py index b576fddb8..d26c403fe 100644 --- a/src/authentic2/api_views.py +++ b/src/authentic2/api_views.py @@ -56,12 +56,13 @@ from rest_framework.viewsets import ModelViewSet, ViewSet from authentic2.compat.drf import action from django_rbac.utils import get_ou_model, get_role_model -from . import api_mixins, app_settings, decorators, hooks, utils +from . import api_mixins, app_settings, decorators, hooks from .a2_rbac.utils import get_default_ou from .custom_user.models import User from .journal_event_types import UserLogin, UserRegistration from .models import Attribute, PasswordReset, Service from .passwords import get_password_checker +from .utils import misc as utils_misc from .utils.lookups import Unaccent # Retro-compatibility with older Django versions @@ -72,7 +73,7 @@ if django.VERSION < (2,): rest_framework.fields.ProhibitNullCharactersValidator = validators.ProhibitNullCharactersValidator if django.VERSION < (1, 11): - authentication.authenticate = utils.authenticate + authentication.authenticate = utils_misc.authenticate User = get_user_model() @@ -236,8 +237,8 @@ class Register(BaseRpcView): token = None final_return_url = None if validated_data.get('return_url'): - token = utils.get_hex_uuid()[:16] - final_return_url = utils.make_url(validated_data['return_url'], params={'token': token}) + token = utils_misc.get_hex_uuid()[:16] + final_return_url = utils_misc.make_url(validated_data['return_url'], params={'token': token}) if email and not validated_data.get('no_email_validation'): registration_template = ['authentic2/activation_email'] @@ -245,7 +246,7 @@ class Register(BaseRpcView): registration_template.insert(0, 'authentic2/activation_email_%s' % validated_data['ou'].slug) try: - utils.send_registration_mail( + utils_misc.send_registration_mail( self.request, email, template_names=registration_template, @@ -298,7 +299,7 @@ class Register(BaseRpcView): 'token': token, } if email: - response['validation_url'] = utils.build_activation_url( + response['validation_url'] = utils_misc.build_activation_url( request, email, next_url=final_return_url, ou=ou, **registration_data ) if token: @@ -433,7 +434,7 @@ class BaseUserSerializer(serializers.ModelSerializer): instance.save() if send_registration_email and validated_data.get('email'): try: - utils.send_password_reset_mail( + utils_misc.send_password_reset_mail( instance, template_names=[ 'authentic2/api_user_create_registration_email', @@ -836,7 +837,7 @@ class UsersAPI(api_mixins.GetOrCreateMixinView, HookMixin, ExceptionHandlerMixin {'result': 0, 'reason': 'User has no mail'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) - utils.send_password_reset_mail(user, request=request) + utils_misc.send_password_reset_mail(user, request=request) request.journal.record('manager.user.password.reset.request', target_user=user, api=True) return Response(status=status.HTTP_204_NO_CONTENT) @@ -849,7 +850,7 @@ class UsersAPI(api_mixins.GetOrCreateMixinView, HookMixin, ExceptionHandlerMixin return Response(response, status.HTTP_400_BAD_REQUEST) user.email_verified = False user.save() - utils.send_email_change_email(user, serializer.validated_data['email'], request=request) + utils_misc.send_email_change_email(user, serializer.validated_data['email'], request=request) return Response({'result': 1}) @action(detail=False, methods=['get'], permission_classes=(DjangoPermission('custom_user.search_user'),)) diff --git a/src/authentic2/attributes_ng/engine.py b/src/authentic2/attributes_ng/engine.py index 96983ceb4..fd3d67e21 100644 --- a/src/authentic2/attributes_ng/engine.py +++ b/src/authentic2/attributes_ng/engine.py @@ -18,8 +18,9 @@ import logging from django.utils.translation import ugettext as _ -from .. import app_settings, plugins, utils +from .. import app_settings, plugins from ..decorators import to_iter, to_list +from ..utils import misc as utils_misc __ALL__ = ['get_attribute_names', 'get_attributes', 'get_service_attributes'] @@ -83,11 +84,11 @@ def get_sources(): List all known sources """ for path in app_settings.ATTRIBUTE_BACKENDS: - yield utils.import_module_or_class(path) + yield utils_misc.import_module_or_class(path) for plugin in plugins.get_plugins(): if hasattr(plugin, 'get_attribute_backends'): for path in plugin.get_attribute_backends(): - yield utils.import_module_or_class(path) + yield utils_misc.import_module_or_class(path) @to_list diff --git a/src/authentic2/authenticators.py b/src/authentic2/authenticators.py index aa6f19c95..bb61d091b 100644 --- a/src/authentic2/authenticators.py +++ b/src/authentic2/authenticators.py @@ -25,8 +25,9 @@ from authentic2.a2_rbac.models import OrganizationalUnit as OU from authentic2.a2_rbac.models import Role from authentic2.custom_user.models import User -from . import app_settings, utils, views +from . import app_settings, views from .forms import authentication as authentication_forms +from .utils import misc as utils_misc from .utils.evaluate import evaluate_condition from .utils.service import get_service_from_request from .utils.views import csrf_token_check @@ -88,7 +89,7 @@ class LoginPasswordAuthenticator(BaseAuthenticator): return OU.objects.filter(pk__in=service_ou_ids) def get_preferred_ous(self, request, service): - preferred_ous_cookie = utils.get_remember_cookie(request, 'preferred-ous') + preferred_ous_cookie = utils_misc.get_remember_cookie(request, 'preferred-ous') preferred_ous = [] if preferred_ous_cookie: preferred_ous.extend(OU.objects.filter(pk__in=preferred_ous_cookie)) @@ -134,15 +135,15 @@ class LoginPasswordAuthenticator(BaseAuthenticator): if form.cleaned_data.get('remember_me'): request.session['remember_me'] = True request.session.set_expiry(app_settings.A2_USER_REMEMBER_ME) - response = utils.login(request, form.get_user(), how, service=service) + response = utils_misc.login(request, form.get_user(), how, service=service) if 'ou' in form.fields: - utils.prepend_remember_cookie( + utils_misc.prepend_remember_cookie( request, response, 'preferred-ous', form.cleaned_data['ou'].pk ) if hasattr(request, 'needs_password_change'): del request.needs_password_change - return utils.redirect( + return utils_misc.redirect( request, 'password_change', params={'next': response.url}, resolve=True ) diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index c447e6112..4f5f310de 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -57,7 +57,7 @@ from authentic2.ldap_utils import FilterFormatter from authentic2.middleware import StoreRequestMiddleware from authentic2.models import UserExternalId from authentic2.user_login_failure import user_login_failure, user_login_success -from authentic2.utils import to_list +from authentic2.utils.misc import to_list from django_rbac.utils import get_ou_model # code originaly copied from by now merely inspired by diff --git a/src/authentic2/cbv.py b/src/authentic2/cbv.py index 9bbbd0f45..6b25197fa 100644 --- a/src/authentic2/cbv.py +++ b/src/authentic2/cbv.py @@ -20,7 +20,8 @@ from django.forms import Form from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie -from . import hooks, utils +from . import hooks +from .utils import misc as utils_misc from .utils.views import csrf_token_check @@ -69,7 +70,7 @@ class NextURLViewMixin(RedirectToNextURLViewMixin): pass else: next_url = request.META.get('HTTP_REFERER') or self.next_url_default - return utils.redirect( + return utils_misc.redirect( request, request.path, keep_params=True, diff --git a/src/authentic2/context_processors.py b/src/authentic2/context_processors.py index 56a482298..08ef82af2 100644 --- a/src/authentic2/context_processors.py +++ b/src/authentic2/context_processors.py @@ -17,8 +17,9 @@ from django.conf import settings from pkg_resources import get_distribution -from . import app_settings, constants, utils +from . import app_settings, constants from .models import Service +from .utils import misc as utils_misc class UserFederations: @@ -35,7 +36,7 @@ class UserFederations: except ValueError: pass else: - links = utils.accumulate_from_backends(self.request, 'links') + links = utils_misc.accumulate_from_backends(self.request, 'links') for provider, link in links: if provider.id != provider_id: continue diff --git a/src/authentic2/csv_import.py b/src/authentic2/csv_import.py index 75dca0e69..ea1f2fce7 100644 --- a/src/authentic2/csv_import.py +++ b/src/authentic2/csv_import.py @@ -34,7 +34,7 @@ from authentic2.a2_rbac.utils import get_default_ou from authentic2.custom_user.models import User from authentic2.forms.profile import BaseUserForm, modelform_factory from authentic2.models import Attribute, AttributeValue, UserExternalId -from authentic2.utils import send_password_reset_mail +from authentic2.utils.misc import send_password_reset_mail from django_rbac.utils import get_role_model Role = get_role_model() diff --git a/src/authentic2/custom_user/migrations/0001_initial.py b/src/authentic2/custom_user/migrations/0001_initial.py index a45fdbf1d..e4d96852e 100644 --- a/src/authentic2/custom_user/migrations/0001_initial.py +++ b/src/authentic2/custom_user/migrations/0001_initial.py @@ -1,7 +1,7 @@ import django.utils.timezone from django.db import migrations, models -import authentic2.utils +import authentic2.utils.misc import authentic2.validators @@ -103,7 +103,7 @@ class Migration(migrations.Migration): ( 'uuid', models.CharField( - default=authentic2.utils.get_hex_uuid, + default=authentic2.utils.misc.get_hex_uuid, verbose_name='uuid', unique=True, max_length=32, diff --git a/src/authentic2/custom_user/models.py b/src/authentic2/custom_user/models.py index b2f8e6781..c3f60f2ea 100644 --- a/src/authentic2/custom_user/models.py +++ b/src/authentic2/custom_user/models.py @@ -33,9 +33,10 @@ except ImportError: from django.contrib.auth.models import AbstractBaseUser from django.contrib.postgres.fields import JSONField -from authentic2 import app_settings, utils +from authentic2 import app_settings from authentic2.decorators import RequestCache, errorcollector from authentic2.models import Attribute, AttributeValue, Service +from authentic2.utils import misc as utils_misc from authentic2.validators import email_validator from django_rbac.models import PermissionMixin from django_rbac.utils import get_role_parenting_model @@ -140,7 +141,9 @@ class User(AbstractBaseUser, PermissionMixin): Username, password and email are required. Other fields are optional. """ - uuid = models.CharField(_('uuid'), max_length=32, default=utils.get_hex_uuid, editable=False, unique=True) + uuid = models.CharField( + _('uuid'), max_length=32, default=utils_misc.get_hex_uuid, editable=False, unique=True + ) username = models.CharField(_('username'), max_length=256, null=True, blank=True) first_name = models.CharField(_('first name'), max_length=128, blank=True) last_name = models.CharField(_('last name'), max_length=128, blank=True) diff --git a/src/authentic2/decorators.py b/src/authentic2/decorators.py index c10640c4c..edbc6eabc 100644 --- a/src/authentic2/decorators.py +++ b/src/authentic2/decorators.py @@ -30,7 +30,7 @@ from django.views.debug import technical_404_response from . import app_settings, middleware # XXX: import to_list for retrocompaibility -from .utils import to_iter, to_list # noqa: F401 +from .utils.misc import to_iter, to_list # noqa: F401 class CacheUnusable(RuntimeError): diff --git a/src/authentic2/forms/authentication.py b/src/authentic2/forms/authentication.py index 19138a030..5a35b0ae4 100644 --- a/src/authentic2/forms/authentication.py +++ b/src/authentic2/forms/authentication.py @@ -29,9 +29,10 @@ from django.utils.translation import ugettext_lazy as _ from authentic2.forms.fields import PasswordField from authentic2.utils.lazy import lazy_label -from .. import app_settings, utils +from .. import app_settings from ..a2_rbac.models import OrganizationalUnit as OU from ..exponential_retry_timeout import ExponentialRetryTimeout +from ..utils import misc as utils_misc class AuthenticationForm(auth_forms.AuthenticationForm): @@ -118,7 +119,9 @@ class AuthenticationForm(auth_forms.AuthenticationForm): ou = self.cleaned_data.get('ou') if username is not None and password: - self.user_cache = utils.authenticate(self.request, username=username, password=password, ou=ou) + self.user_cache = utils_misc.authenticate( + self.request, username=username, password=password, ou=ou + ) if self.user_cache is None: raise forms.ValidationError( self.error_messages['invalid_login'], diff --git a/src/authentic2/forms/passwords.py b/src/authentic2/forms/passwords.py index 74d7b8025..9eeee844c 100644 --- a/src/authentic2/forms/passwords.py +++ b/src/authentic2/forms/passwords.py @@ -26,8 +26,9 @@ from django.utils.translation import ugettext_lazy as _ from authentic2.journal import journal -from .. import app_settings, hooks, models, utils, validators +from .. import app_settings, hooks, models, validators from ..backends import get_user_queryset +from ..utils import misc as utils_misc from .fields import CheckPasswordField, NewPasswordField, PasswordField, ValidatedEmailField from .honeypot import HoneypotForm from .utils import NextUrlFormMixin @@ -79,22 +80,22 @@ class PasswordResetForm(HoneypotForm): # we don't set the password to a random string, as some users should not have # a password set_random_password = user.has_usable_password() and app_settings.A2_SET_RANDOM_PASSWORD_ON_RESET - utils.send_password_reset_mail( + utils_misc.send_password_reset_mail( user, set_random_password=set_random_password, next_url=self.cleaned_data.get('next_url') ) journal.record('user.password.reset.request', email=user.email, user=user) for user in self.users.filter(is_active=False): logger.info('password reset failed for user "%r": account is disabled', user) - utils.send_templated_mail(user, ['authentic2/password_reset_refused']) + utils_misc.send_templated_mail(user, ['authentic2/password_reset_refused']) if not self.users.exists() and email: logger.info('password reset request for "%s", no user found', email) if getattr(settings, 'REGISTRATION_OPEN', True): ctx = { - 'registration_url': utils.make_url('registration_register', absolute=True), + 'registration_url': utils_misc.make_url('registration_register', absolute=True), } else: ctx = {} - utils.send_templated_mail(email, ['authentic2/password_reset_no_account'], context=ctx) + utils_misc.send_templated_mail(email, ['authentic2/password_reset_no_account'], context=ctx) hooks.call_hooks('event', name='password-reset', email=email or email_or_username, users=active_users) @@ -126,7 +127,7 @@ class NotifyOfPasswordChange: 'user': user, 'password': self.cleaned_data['new_password1'], } - utils.send_templated_mail(user, "authentic2/password_change", ctx) + utils_misc.send_templated_mail(user, "authentic2/password_change", ctx) return user diff --git a/src/authentic2/idp/saml/backend.py b/src/authentic2/idp/saml/backend.py index 281ac71ba..ebfe67a9c 100644 --- a/src/authentic2/idp/saml/backend.py +++ b/src/authentic2/idp/saml/backend.py @@ -29,7 +29,7 @@ import authentic2.idp.saml.saml2_endpoints as saml2_endpoints import authentic2.saml.common as common import authentic2.saml.models as models from authentic2.decorators import to_list -from authentic2.utils import Service +from authentic2.utils.misc import Service class SamlBackend: diff --git a/src/authentic2/idp/saml/saml2_endpoints.py b/src/authentic2/idp/saml/saml2_endpoints.py index 7f989f2f5..2c4fd3931 100644 --- a/src/authentic2/idp/saml/saml2_endpoints.py +++ b/src/authentic2/idp/saml/saml2_endpoints.py @@ -59,7 +59,7 @@ from django.views.decorators.http import require_POST import authentic2.saml.saml2utils as saml2utils import authentic2.views as a2_views -from authentic2 import hooks, utils +from authentic2 import hooks from authentic2.attributes_ng.engine import get_attributes from authentic2.compat_lasso import lasso from authentic2.constants import NONCE_FIELD_NAME @@ -108,9 +108,10 @@ from authentic2.saml.models import ( saml2_urn_to_nidformat, save_key_values, ) -from authentic2.utils import datetime_to_xs_datetime, find_authentication_event -from authentic2.utils import get_backends as get_idp_backends -from authentic2.utils import login_require, make_url +from authentic2.utils import misc as utils_misc +from authentic2.utils.misc import datetime_to_xs_datetime, find_authentication_event +from authentic2.utils.misc import get_backends as get_idp_backends +from authentic2.utils.misc import login_require, make_url from . import app_settings @@ -681,7 +682,7 @@ def continue_sso(request): login_dump, consent_obtained, nid_format = get_and_delete_key_values(nonce) except KeyError: messages.warning(request, _('request has expired')) - return utils.redirect(request, 'auth_homepage') + return utils_misc.redirect(request, 'auth_homepage') server = create_server(request) # Work Around for lasso < 2.3.6 login_dump = login_dump.replace('', '') @@ -1101,7 +1102,7 @@ def finish_slo(request): logout_dump, session_key = get_and_delete_key_values(id) except KeyError: messages.warning(request, _('request has expired')) - return utils.redirect(request, 'auth_homepage') + return utils_misc.redirect(request, 'auth_homepage') server = create_server(request) logout = lasso.Logout.newFromDump(server, force_str(logout_dump)) load_provider(request, logout.remoteProviderId, server=logout.server) diff --git a/src/authentic2/management/commands/clean-unused-accounts.py b/src/authentic2/management/commands/clean-unused-accounts.py index 1d7fbe669..60456e580 100644 --- a/src/authentic2/management/commands/clean-unused-accounts.py +++ b/src/authentic2/management/commands/clean-unused-accounts.py @@ -29,7 +29,7 @@ from django.utils import timezone, translation from authentic2 import app_settings from authentic2.backends import get_user_queryset from authentic2.backends.ldap_backend import LDAPBackend -from authentic2.utils import send_templated_mail +from authentic2.utils.misc import send_templated_mail from django_rbac.utils import get_ou_model logger = logging.getLogger(__name__) diff --git a/src/authentic2/management/commands/resetpassword.py b/src/authentic2/management/commands/resetpassword.py index 2a5d7a62c..c7ab96479 100644 --- a/src/authentic2/management/commands/resetpassword.py +++ b/src/authentic2/management/commands/resetpassword.py @@ -21,7 +21,7 @@ from django.core.management.base import BaseCommand, CommandError from django.db import DEFAULT_DB_ALIAS from authentic2.models import PasswordReset -from authentic2.utils import generate_password +from authentic2.utils.misc import generate_password User = get_user_model() diff --git a/src/authentic2/manager/forms.py b/src/authentic2/manager/forms.py index b2b3a5e1f..996b58460 100644 --- a/src/authentic2/manager/forms.py +++ b/src/authentic2/manager/forms.py @@ -35,7 +35,7 @@ from authentic2.forms.fields import CheckPasswordField, NewPasswordField, Valida from authentic2.forms.profile import BaseUserForm from authentic2.models import PasswordReset from authentic2.passwords import generate_password -from authentic2.utils import ( +from authentic2.utils.misc import ( import_module_or_class, send_email_change_email, send_password_reset_mail, diff --git a/src/authentic2/manager/role_views.py b/src/authentic2/manager/role_views.py index 576f5f450..286b7d0d9 100644 --- a/src/authentic2/manager/role_views.py +++ b/src/authentic2/manager/role_views.py @@ -33,7 +33,7 @@ from django.views.generic.detail import SingleObjectMixin from authentic2 import data_transfer, hooks from authentic2.apps.journal.views import JournalViewWithContext from authentic2.forms.profile import modelform_factory -from authentic2.utils import redirect +from authentic2.utils.misc import redirect from django_rbac.utils import get_ou_model, get_permission_model, get_role_model from . import app_settings, forms, resources, tables, views diff --git a/src/authentic2/manager/urls.py b/src/authentic2/manager/urls.py index d41b28b8d..4e5483bc3 100644 --- a/src/authentic2/manager/urls.py +++ b/src/authentic2/manager/urls.py @@ -19,14 +19,14 @@ from django.contrib.auth.decorators import login_required from django.utils.functional import lazy from django.views.i18n import JavaScriptCatalog -from authentic2 import utils +from authentic2.utils import misc as utils_misc from ..decorators import required from . import journal_views, ou_views, role_views, service_views, user_views, views def manager_login_required(func): - return login_required(func, login_url=lazy(utils.get_manager_login_url, str)()) + return login_required(func, login_url=lazy(utils_misc.get_manager_login_url, str)()) urlpatterns = required( diff --git a/src/authentic2/manager/user_export.py b/src/authentic2/manager/user_export.py index 80a5fa6a9..7043c1a37 100644 --- a/src/authentic2/manager/user_export.py +++ b/src/authentic2/manager/user_export.py @@ -27,7 +27,7 @@ from django.core.files.storage import default_storage from authentic2.manager.resources import UserResource from authentic2.models import Attribute, AttributeValue -from authentic2.utils import batch_queryset +from authentic2.utils.misc import batch_queryset def get_user_dataset(qs): diff --git a/src/authentic2/manager/user_import.py b/src/authentic2/manager/user_import.py index 613aa9908..6edbc2259 100644 --- a/src/authentic2/manager/user_import.py +++ b/src/authentic2/manager/user_import.py @@ -33,7 +33,7 @@ from django.utils.functional import cached_property from django.utils.timezone import utc from django.utils.translation import ugettext_lazy as _ -from authentic2.utils import gettid +from authentic2.utils.misc import gettid logger = logging.getLogger(__name__) diff --git a/src/authentic2/manager/user_views.py b/src/authentic2/manager/user_views.py index 0ddda91d2..c5f3a03f4 100644 --- a/src/authentic2/manager/user_views.py +++ b/src/authentic2/manager/user_views.py @@ -42,14 +42,8 @@ from authentic2 import hooks from authentic2.a2_rbac.utils import get_default_ou from authentic2.apps.journal.views import JournalViewWithContext from authentic2.models import Attribute, PasswordReset -from authentic2.utils import ( - make_url, - redirect, - select_next_url, - send_password_reset_mail, - spooler, - switch_user, -) +from authentic2.utils import spooler, switch_user +from authentic2.utils.misc import make_url, redirect, select_next_url, send_password_reset_mail from authentic2_idp_oidc.models import OIDCAuthorization, OIDCClient from django_rbac.utils import get_ou_model, get_role_model, get_role_parenting_model diff --git a/src/authentic2/manager/views.py b/src/authentic2/manager/views.py index 807183142..dc8e34509 100644 --- a/src/authentic2/manager/views.py +++ b/src/authentic2/manager/views.py @@ -43,7 +43,7 @@ from authentic2.a2_rbac.models import OrganizationalUnit as OU from authentic2.data_transfer import ImportContext, export_site, import_site from authentic2.decorators import json as json_view from authentic2.forms.profile import modelform_factory -from authentic2.utils import batch_queryset, redirect +from authentic2.utils.misc import batch_queryset, redirect from django_rbac.utils import get_ou_model from . import app_settings, forms, utils, widgets diff --git a/src/authentic2/middleware.py b/src/authentic2/middleware.py index b03d8a2a6..1a2a56535 100644 --- a/src/authentic2/middleware.py +++ b/src/authentic2/middleware.py @@ -30,7 +30,8 @@ from django.utils.deprecation import MiddlewareMixin from django.utils.functional import SimpleLazyObject from django.utils.translation import ugettext as _ -from . import app_settings, plugins, utils +from . import app_settings, plugins +from .utils import misc as utils_misc from .utils.service import get_service_from_request, get_service_from_session @@ -133,7 +134,7 @@ class ViewRestrictionMiddleware(MiddlewareMixin): return if view == 'password_change': messages.warning(request, _('You must change your password to continue')) - return utils.redirect_and_come_back(request, view) + return utils_misc.redirect_and_come_back(request, view) class XForwardedForMiddleware(MiddlewareMixin): @@ -175,14 +176,14 @@ class DisplayMessageBeforeRedirectMiddleware(MiddlewareMixin): storage = messages.get_messages(request) if not len(storage): return response - return utils.redirect(request, 'continue', resolve=True, params={'next': url}) + return utils_misc.redirect(request, 'continue', resolve=True, params={'next': url}) class ServiceAccessControlMiddleware(MiddlewareMixin): def process_exception(self, request, exception): - if not isinstance(exception, (utils.ServiceAccessDenied,)): + if not isinstance(exception, (utils_misc.ServiceAccessDenied,)): return None - return utils.unauthorized_view(request, exception.service) + return utils_misc.unauthorized_view(request, exception.service) class CookieTestMiddleware(MiddlewareMixin): diff --git a/src/authentic2/models.py b/src/authentic2/models.py index ceb2a7864..497a2d834 100644 --- a/src/authentic2/models.py +++ b/src/authentic2/models.py @@ -45,7 +45,7 @@ except ImportError: # install our natural_key implementation from . import managers from . import natural_key as unused_natural_key # noqa: F401 -from .utils import ServiceAccessDenied +from .utils.misc import ServiceAccessDenied class UserExternalId(models.Model): diff --git a/src/authentic2/saml/utils.py b/src/authentic2/saml/utils.py index dd9deecab..5f6728ebf 100644 --- a/src/authentic2/saml/utils.py +++ b/src/authentic2/saml/utils.py @@ -26,7 +26,7 @@ def get_entity_ids(): @GlobalCache(timeout=60) def saml_good_next_url(next_url): - from authentic2.utils import same_origin + from authentic2.utils.misc import same_origin entity_ids = get_entity_ids() for entity_id in entity_ids: diff --git a/src/authentic2/settings.py b/src/authentic2/settings.py index 732a72381..bac2386c5 100644 --- a/src/authentic2/settings.py +++ b/src/authentic2/settings.py @@ -233,7 +233,7 @@ LOGGING = { 'disable_existing_loggers': True, 'filters': { 'cleaning': { - '()': 'authentic2.utils.CleanLogMessage', + '()': 'authentic2.utils.misc.CleanLogMessage', }, 'request_context': { '()': 'authentic2.log_filters.RequestContextFilter', diff --git a/src/authentic2/utils/switch_user.py b/src/authentic2/utils/switch_user.py index ad735dab3..710d8af89 100644 --- a/src/authentic2/utils/switch_user.py +++ b/src/authentic2/utils/switch_user.py @@ -16,7 +16,7 @@ from authentic2.custom_user.models import User from authentic2.models import Token -from authentic2.utils import make_url +from authentic2.utils.misc import make_url def build_url(user, duration=30): diff --git a/src/authentic2/views.py b/src/authentic2/views.py index 35eab76fa..c049ec992 100644 --- a/src/authentic2/views.py +++ b/src/authentic2/views.py @@ -53,13 +53,14 @@ from ratelimit.utils import is_ratelimited from authentic2.custom_user.models import iter_attributes -from . import app_settings, attribute_kinds, cbv, constants, decorators, hooks, models, utils, validators +from . import app_settings, attribute_kinds, cbv, constants, decorators, hooks, models, validators from .a2_rbac.models import OrganizationalUnit as OU from .a2_rbac.utils import get_default_ou from .forms import passwords as passwords_forms from .forms import profile as profile_forms from .forms import registration as registration_forms -from .utils import switch_user +from .utils import misc as utils_misc +from .utils import switch_user as utils_switch_user from .utils.evaluate import HTTPHeaders from .utils.service import get_service_from_request, get_service_from_token, set_service_ref @@ -108,7 +109,7 @@ class EditProfile(cbv.HookMixin, cbv.TemplateNamesMixin, UpdateView): ] else: default_fields = list(attributes.values_list('name', flat=True)) - fields, labels = utils.get_fields_and_labels(editable_profile_fields, default_fields) + fields, labels = utils_misc.get_fields_and_labels(editable_profile_fields, default_fields) if scopes: # restrict fields to those in the scopes fields = [field for field in fields if field in default_fields] @@ -131,17 +132,17 @@ class EditProfile(cbv.HookMixin, cbv.TemplateNamesMixin, UpdateView): def get_form_kwargs(self, **kwargs): kwargs = super().get_form_kwargs(**kwargs) - kwargs['next_url'] = utils.select_next_url(self.request, reverse('account_management')) + kwargs['next_url'] = utils_misc.select_next_url(self.request, reverse('account_management')) return kwargs def get_success_url(self): - return utils.select_next_url( + return utils_misc.select_next_url( self.request, default=reverse('account_management'), field_name='next_url', include_post=True ) def post(self, request, *args, **kwargs): if 'cancel' in request.POST: - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) return super().post(request, *args, **kwargs) def form_valid(self, form): @@ -173,12 +174,12 @@ class EmailChangeView(cbv.TemplateNamesMixin, FormView): def post(self, request, *args, **kwargs): if 'cancel' in request.POST: - return utils.redirect(request, 'account_management') + return utils_misc.redirect(request, 'account_management') return super().post(request, *args, **kwargs) def form_valid(self, form): email = form.cleaned_data['email'] - utils.send_email_change_email(self.request.user, email, request=self.request) + utils_misc.send_email_change_email(self.request.user, email, request=self.request) hooks.call_hooks('event', name='change-email', user=self.request.user, email=email) messages.info( self.request, @@ -265,7 +266,7 @@ def login(request, template_name='authentic2/login.html', redirect_field_name=RE # redirect user to homepage if already connected, if setting # A2_LOGIN_REDIRECT_AUTHENTICATED_USERS_TO_HOMEPAGE is True if request.user.is_authenticated and app_settings.A2_LOGIN_REDIRECT_AUTHENTICATED_USERS_TO_HOMEPAGE: - return utils.redirect(request, 'auth_homepage') + return utils_misc.redirect(request, 'auth_homepage') redirect_to = request.GET.get(redirect_field_name) @@ -281,11 +282,11 @@ def login(request, template_name='authentic2/login.html', redirect_field_name=RE redirect_to = settings.LOGIN_REDIRECT_URL nonce = request.GET.get(constants.NONCE_FIELD_NAME) - authenticators = utils.get_backends('AUTH_FRONTENDS') + authenticators = utils_misc.get_backends('AUTH_FRONTENDS') blocks = [] - registration_url = utils.get_registration_url(request, service=service) + registration_url = utils_misc.get_registration_url(request, service=service) context = { 'cancel': app_settings.A2_LOGIN_DISPLAY_A_CANCEL_BUTTON and nonce is not None, @@ -296,7 +297,7 @@ def login(request, template_name='authentic2/login.html', redirect_field_name=RE # Cancel button if request.method == "POST" and constants.CANCEL_FIELD_NAME in request.POST: - return utils.continue_to_next_url(request, params={'cancel': 1}) + return utils_misc.continue_to_next_url(request, params={'cancel': 1}) # Create blocks for authenticator in authenticators: @@ -332,13 +333,15 @@ def login(request, template_name='authentic2/login.html', redirect_field_name=RE parameters['instance_id'] = instance_id if not authenticator.shown(instance_id=instance_id, ctx=show_ctx): continue - block = utils.get_authenticator_method(authenticator, 'login', parameters) + block = utils_misc.get_authenticator_method(authenticator, 'login', parameters) # update block id in order to separate instances block['id'] = '%s_%s' % (block['id'], instance_id) auth_blocks.append(block) else: if authenticator.shown(ctx=show_ctx): - auth_blocks.append(utils.get_authenticator_method(authenticator, 'login', parameters)) + auth_blocks.append( + utils_misc.get_authenticator_method(authenticator, 'login', parameters) + ) # If a login frontend method returns an HttpResponse with a status code != 200 # this response is returned. for block in auth_blocks: @@ -383,7 +386,7 @@ def login(request, template_name='authentic2/login.html', redirect_field_name=RE def service_list(request): '''Compute the service list to show on user homepage''' - return utils.accumulate_from_backends(request, 'service_list') + return utils_misc.accumulate_from_backends(request, 'service_list') class Homepage(cbv.TemplateNamesMixin, TemplateView): @@ -391,7 +394,7 @@ class Homepage(cbv.TemplateNamesMixin, TemplateView): def dispatch(self, request, *args, **kwargs): if app_settings.A2_HOMEPAGE_URL: - return utils.redirect(request, app_settings.A2_HOMEPAGE_URL) + return utils_misc.redirect(request, app_settings.A2_HOMEPAGE_URL) return login_required(super().dispatch)(request, *args, **kwargs) def get_context_data(self, **kwargs): @@ -410,12 +413,12 @@ class ProfileView(cbv.TemplateNamesMixin, TemplateView): def dispatch(self, request, *args, **kwargs): if app_settings.A2_ACCOUNTS_URL: - return utils.redirect(request, app_settings.A2_ACCOUNTS_URL) + return utils_misc.redirect(request, app_settings.A2_ACCOUNTS_URL) return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - frontends = utils.get_backends('AUTH_FRONTENDS') + frontends = utils_misc.get_backends('AUTH_FRONTENDS') request = self.request @@ -488,13 +491,15 @@ class ProfileView(cbv.TemplateNamesMixin, TemplateView): # Credentials management parameters = {'request': request, 'context': context} - profiles = [utils.get_authenticator_method(frontend, 'profile', parameters) for frontend in frontends] + profiles = [ + utils_misc.get_authenticator_method(frontend, 'profile', parameters) for frontend in frontends + ] # Old frontends data structure for templates blocks = [block['content'] for block in profiles if block] # New frontends data structure for templates blocks_by_id = collections.OrderedDict((block['id'], block) for block in profiles if block) - idp_backends = utils.get_backends() + idp_backends = utils_misc.get_backends() # Get actions for federation management federation_management = [] if app_settings.A2_PROFILE_CAN_MANAGE_FEDERATION: @@ -512,7 +517,7 @@ class ProfileView(cbv.TemplateNamesMixin, TemplateView): 'allow_email_change': app_settings.A2_PROFILE_CAN_CHANGE_EMAIL, 'allow_authorization_management': False, # TODO: deprecated should be removed when publik-base-theme is updated - 'allow_password_change': utils.user_can_change_password(request=request), + 'allow_password_change': utils_misc.user_can_change_password(request=request), 'federation_management': federation_management, } ) @@ -536,12 +541,12 @@ profile = login_required(ProfileView.as_view()) def logout_list(request): '''Return logout links from idp backends''' - return utils.accumulate_from_backends(request, 'logout_list') + return utils_misc.accumulate_from_backends(request, 'logout_list') def redirect_logout_list(request): '''Return redirect logout links from idp backends''' - return utils.accumulate_from_backends(request, 'redirect_logout_list') + return utils_misc.accumulate_from_backends(request, 'redirect_logout_list') def logout(request, next_url=None, do_local=True, check_referer=True): @@ -552,7 +557,7 @@ def logout(request, next_url=None, do_local=True, check_referer=True): Logout endpoints of IdP module must re-user the view by setting check_referer and do_local to False. """ - next_url = next_url or utils.select_next_url(request, settings.LOGIN_REDIRECT_URL) + next_url = next_url or utils_misc.select_next_url(request, settings.LOGIN_REDIRECT_URL) ctx = {} ctx['next_url'] = next_url @@ -560,14 +565,14 @@ def logout(request, next_url=None, do_local=True, check_referer=True): local_logout_done = False if request.user.is_authenticated: - if check_referer and not utils.check_referer(request): + if check_referer and not utils_misc.check_referer(request): return render(request, 'authentic2/logout_confirm.html', ctx) do_local = do_local and 'local' in request.GET if not do_local: fragments = logout_list(request) if fragments: # Full logout with iframes - next_url = utils.make_url( + next_url = utils_misc.make_url( 'auth_logout', params={'local': 'ok'}, next_url=next_url, sign_next_url=True ) ctx['next_url'] = next_url @@ -604,7 +609,7 @@ def logout(request, next_url=None, do_local=True, check_referer=True): def login_password_profile(request, *args, **kwargs): context = kwargs.pop('context', {}) - can_change_password = utils.user_can_change_password(request=request) + can_change_password = utils_misc.user_can_change_password(request=request) has_usable_password = request.user.has_usable_password() context.update( { @@ -666,7 +671,7 @@ class PasswordResetView(FormView): def get_form_kwargs(self, **kwargs): kwargs = super().get_form_kwargs(**kwargs) initial = kwargs.setdefault('initial', {}) - initial['next_url'] = utils.select_next_url(self.request, '') + initial['next_url'] = utils_misc.select_next_url(self.request, '') return kwargs def get_context_data(self, **kwargs): @@ -678,7 +683,7 @@ class PasswordResetView(FormView): def form_valid(self, form): if form.is_robot(): - return utils.redirect( + return utils_misc.redirect( self.request, self.get_success_url(), params={ @@ -778,20 +783,20 @@ class PasswordResetConfirmView(cbv.RedirectToNextURLViewMixin, FormView): self.token = models.Token.use('pw-reset', token, delete=False) except models.Token.DoesNotExist: messages.warning(request, _('Password reset token is unknown or expired')) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) except (TypeError, ValueError): messages.warning(request, _('Password reset token is invalid')) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) uid = self.token.content['user'] try: # use authenticate to eventually get an LDAPUser - self.user = utils.authenticate(request, user=User._default_manager.get(pk=uid)) + self.user = utils_misc.authenticate(request, user=User._default_manager.get(pk=uid)) except (TypeError, ValueError, OverflowError, User.DoesNotExist): messages.warning(request, _('User not found')) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) - can_reset_password = utils.get_user_flag( + can_reset_password = utils_misc.get_user_flag( user=self.user, name='can_reset_password', default=self.user.has_usable_password() ) if ( @@ -802,7 +807,7 @@ class PasswordResetConfirmView(cbv.RedirectToNextURLViewMixin, FormView): messages.warning( request, _('It\'s not possible to reset your password. Please contact an administrator.') ) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): @@ -827,7 +832,7 @@ class PasswordResetConfirmView(cbv.RedirectToNextURLViewMixin, FormView): return self.finish() def finish(self): - response = utils.simulate_authentication(self.request, self.user, 'email') + response = utils_misc.simulate_authentication(self.request, self.user, 'email') self.request.journal.record('user.password.reset') return response @@ -857,12 +862,12 @@ class BaseRegistrationView(FormView): return HttpResponseBadRequest('invalid token', content_type='text/plain') if 'ou' in self.token: self.ou = OU.objects.get(pk=self.token['ou']) - self.next_url = self.token.pop(REDIRECT_FIELD_NAME, utils.select_next_url(request, None)) + self.next_url = self.token.pop(REDIRECT_FIELD_NAME, utils_misc.select_next_url(request, None)) return super().dispatch(request, *args, **kwargs) def form_valid(self, form): if form.is_robot(): - return utils.redirect( + return utils_misc.redirect( self.request, 'registration_complete', params={ @@ -932,9 +937,11 @@ class BaseRegistrationView(FormView): self.token.pop(REDIRECT_FIELD_NAME, None) self.token.pop('email', None) - utils.send_registration_mail(self.request, email, next_url=self.next_url, ou=self.ou, **self.token) + utils_misc.send_registration_mail( + self.request, email, next_url=self.next_url, ou=self.ou, **self.token + ) self.request.session['registered_email'] = email - return utils.redirect( + return utils_misc.redirect( self.request, 'registration_complete', params={REDIRECT_FIELD_NAME: self.next_url} ) @@ -942,8 +949,8 @@ class BaseRegistrationView(FormView): context = super().get_context_data(**kwargs) parameters = {'request': self.request, 'context': context} blocks = [ - utils.get_authenticator_method(authenticator, 'registration', parameters) - for authenticator in utils.get_backends('AUTH_FRONTENDS') + utils_misc.get_authenticator_method(authenticator, 'registration', parameters) + for authenticator in utils_misc.get_backends('AUTH_FRONTENDS') ] context['frontends'] = collections.OrderedDict((block['id'], block) for block in blocks if block) return context @@ -973,12 +980,12 @@ class RegistrationCompletionView(CreateView): if self.token and self.token.get(REDIRECT_FIELD_NAME): url = self.token[REDIRECT_FIELD_NAME] if redirect_url: - url = utils.make_url(redirect_url, params={next_field: url}) + url = utils_misc.make_url(redirect_url, params={next_field: url}) else: if redirect_url: url = redirect_url else: - url = utils.make_url(self.success_url) + url = utils_misc.make_url(self.success_url) return url def dispatch(self, request, *args, **kwargs): @@ -987,10 +994,10 @@ class RegistrationCompletionView(CreateView): token = models.Token.use('registration', registration_token, delete=False) except models.Token.DoesNotExist: messages.warning(request, _('Your activation key is unknown or expired')) - return utils.redirect(request, 'registration_register') + return utils_misc.redirect(request, 'registration_register') except (TypeError, ValueError): messages.warning(request, _('Activation failed')) - return utils.redirect(request, 'registration_register') + return utils_misc.redirect(request, 'registration_register') self.token_obj = token self.token = token.content @@ -1018,7 +1025,7 @@ class RegistrationCompletionView(CreateView): attributes = models.Attribute.objects.filter(asked_on_registration=True) default_fields = attributes.values_list('name', flat=True) required_fields = models.Attribute.objects.filter(required=True).values_list('name', flat=True) - fields, labels = utils.get_fields_and_labels( + fields, labels = utils_misc.get_fields_and_labels( app_settings.A2_REGISTRATION_FIELDS, default_fields, app_settings.A2_REGISTRATION_REQUIRED_FIELDS, @@ -1082,7 +1089,7 @@ class RegistrationCompletionView(CreateView): attributes[key] = self.token[key] logger.debug('attributes %s', attributes) - prefilling_list = utils.accumulate_from_backends(self.request, 'registration_form_prefill') + prefilling_list = utils_misc.accumulate_from_backends(self.request, 'registration_form_prefill') logger.debug('prefilling_list %s', prefilling_list) # Build a single meaningful prefilling with sets of values prefilling = {} @@ -1124,10 +1131,10 @@ class RegistrationCompletionView(CreateView): def get(self, request, *args, **kwargs): if len(self.users) == 1 and self.email_is_unique: # Found one user, EMAIL is unique, log her in - utils.simulate_authentication( + utils_misc.simulate_authentication( request, self.users[0], method=self.authentication_method, service=self.service ) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) confirm_data = self.token.get('confirm_data', False) if confirm_data == 'required': @@ -1156,17 +1163,17 @@ class RegistrationCompletionView(CreateView): def post(self, request, *args, **kwargs): if self.users and self.email_is_unique: # email is unique, users already exist, creating a new one is forbidden ! - return utils.redirect( + return utils_misc.redirect( request, request.resolver_match.view_name, args=self.args, kwargs=self.kwargs ) if 'uid' in request.POST: uid = request.POST['uid'] for user in self.users: if str(user.id) == uid: - utils.simulate_authentication( + utils_misc.simulate_authentication( request, user, method=self.authentication_method, service=self.service ) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) return super().post(request, *args, **kwargs) def form_valid(self, form): @@ -1195,10 +1202,12 @@ class RegistrationCompletionView(CreateView): data[attribute.name] = kind['serialize'](data[attribute.name]) data['no_password'] = self.token.get('no_password', False) - utils.send_registration_mail(self.request, ou=self.ou, next_url=self.get_success_url(), **data) + utils_misc.send_registration_mail( + self.request, ou=self.ou, next_url=self.get_success_url(), **data + ) self.token_obj.delete() self.request.session['registered_email'] = form.cleaned_data['email'] - return utils.redirect(self.request, 'registration_complete') + return utils_misc.redirect(self.request, 'registration_complete') super().form_valid(form) return self.registration_success(self.request, form.instance, form) @@ -1215,11 +1224,13 @@ class RegistrationCompletionView(CreateView): service=self.service and self.service.slug, ) self.token_obj.delete() - utils.simulate_authentication(request, user, method=self.authentication_method, service=self.service) + utils_misc.simulate_authentication( + request, user, method=self.authentication_method, service=self.service + ) message_template = loader.get_template('authentic2/registration_success_message.html') messages.info(self.request, message_template.render(request=request)) self.send_registration_success_email(user) - return utils.redirect(request, self.get_success_url()) + return utils_misc.redirect(request, self.get_success_url()) def send_registration_success_email(self, user): if not user.email: @@ -1227,7 +1238,7 @@ class RegistrationCompletionView(CreateView): template_names = ['authentic2/registration_success'] login_url = self.request.build_absolute_uri(settings.LOGIN_URL) - utils.send_templated_mail( + utils_misc.send_templated_mail( user, template_names=template_names, context={ @@ -1250,15 +1261,15 @@ class DeleteView(TemplateView): def dispatch(self, request, *args, **kwargs): if not app_settings.A2_REGISTRATION_CAN_DELETE_ACCOUNT: - return utils.redirect(request, '..') + return utils_misc.redirect(request, '..') return super().dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): if 'cancel' in request.POST: - return utils.redirect(request, 'account_management') - utils.send_account_deletion_code(self.request, self.request.user) + return utils_misc.redirect(request, 'account_management') + utils_misc.send_account_deletion_code(self.request, self.request.user) messages.info(request, _("An account deletion validation email has been sent to your email address.")) - return utils.redirect(request, 'account_management') + return utils_misc.redirect(request, 'account_management') def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -1295,11 +1306,11 @@ class ValidateDeletionView(TemplateView): else: return super().dispatch(request, *args, **kwargs) messages.error(request, error) - return utils.redirect(request, 'auth_homepage') + return utils_misc.redirect(request, 'auth_homepage') def post(self, request, *args, **kwargs): if 'cancel' not in request.POST: - utils.send_account_deletion_mail(self.request, self.user) + utils_misc.send_account_deletion_mail(self.request, self.user) logger.info('deletion of account %s performed', self.user) hooks.call_hooks('event', name='delete-account', user=self.user) request.journal.record('user.deletion', user=self.user) @@ -1311,7 +1322,7 @@ class ValidateDeletionView(TemplateView): # homepage. if is_deleted_user_logged: return logout(request, check_referer=False) - return utils.redirect(request, 'auth_homepage') + return utils_misc.redirect(request, 'auth_homepage') def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -1323,7 +1334,7 @@ class RegistrationCompleteView(TemplateView): template_name = 'registration/registration_complete.html' def get_context_data(self, **kwargs): - kwargs['next_url'] = utils.select_next_url(self.request, settings.LOGIN_REDIRECT_URL) + kwargs['next_url'] = utils_misc.select_next_url(self.request, settings.LOGIN_REDIRECT_URL) kwargs['from_email'] = settings.DEFAULT_FROM_EMAIL kwargs['from_email_address'] = parseaddr(settings.DEFAULT_FROM_EMAIL)[1] return super().get_context_data(account_activation_days=settings.ACCOUNT_ACTIVATION_DAYS, **kwargs) @@ -1343,14 +1354,14 @@ class PasswordChangeView(DjPasswordChangeView): self.post_change_redirect = request.GET[REDIRECT_FIELD_NAME] else: self.post_change_redirect = reverse('account_management') - if not utils.user_can_change_password(request=request): + if not utils_misc.user_can_change_password(request=request): messages.warning(request, _('Password change is forbidden')) - return utils.redirect(request, self.post_change_redirect) + return utils_misc.redirect(request, self.post_change_redirect) return super().dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): if 'cancel' in request.POST: - return utils.redirect(request, self.post_change_redirect) + return utils_misc.redirect(request, self.post_change_redirect) return super().post(request, *args, **kwargs) def form_valid(self, form): @@ -1380,13 +1391,13 @@ password_change = decorators.setting_enabled('A2_REGISTRATION_CAN_CHANGE_PASSWOR class SuView(View): def get(self, request, uuid): - user = switch_user.resolve_token(uuid) + user = utils_switch_user.resolve_token(uuid) if not user: raise Http404 # LDAP ad-hoc behaviour if user.userexternalid_set.exists(): - user = utils.authenticate(request, user=user) - return utils.simulate_authentication(request, user, 'su') + user = utils_misc.authenticate(request, user=user) + return utils_misc.simulate_authentication(request, user, 'su') su = SuView.as_view() @@ -1423,19 +1434,19 @@ def old_view_redirect(request, to, message=None): '''Redirect old URL to new URL, eventually showing a message.''' if message: messages.info(request, message) - return utils.redirect(request, to=to) + return utils_misc.redirect(request, to=to) class DisplayMessageAndContinueView(TemplateView): template_name = 'authentic2/display_message_and_continue.html' def get(self, request, *args, **kwargs): - self.url = utils.select_next_url(self.request, reverse('account_management')) + self.url = utils_misc.select_next_url(self.request, reverse('account_management')) self.only_info = True storage = messages.get_messages(request) if not len(storage): - return utils.redirect(request, self.url, resolve=False) + return utils_misc.redirect(request, self.url, resolve=False) for message in storage: if message.level not in (messages.INFO, messages.SUCCESS): diff --git a/src/authentic2_auth_fc/apps.py b/src/authentic2_auth_fc/apps.py index 98f5c34ae..05dcad7b3 100644 --- a/src/authentic2_auth_fc/apps.py +++ b/src/authentic2_auth_fc/apps.py @@ -42,7 +42,7 @@ class AppConfig(django.apps.AppConfig): def a2_hook_api_modify_serializer(self, view, serializer): from rest_framework import serializers - from authentic2.utils import make_url + from authentic2.utils.misc import make_url from . import app_settings @@ -77,7 +77,7 @@ class AppConfig(django.apps.AppConfig): return None def a2_hook_user_can_change_password(self, user, request, **kwargs): - from authentic2.utils import get_authentication_events + from authentic2.utils.misc import get_authentication_events if not request: return True diff --git a/src/authentic2_auth_fc/authenticators.py b/src/authentic2_auth_fc/authenticators.py index c88bfca29..2eb9d7094 100644 --- a/src/authentic2_auth_fc/authenticators.py +++ b/src/authentic2_auth_fc/authenticators.py @@ -19,9 +19,9 @@ from django.template.response import TemplateResponse from django.utils.translation import gettext_noop from authentic2 import app_settings as a2_app_settings -from authentic2 import utils as a2_utils from authentic2.authenticators import BaseAuthenticator -from authentic2.utils import redirect_to_login +from authentic2.utils import misc as utils_misc +from authentic2.utils.misc import redirect_to_login from . import app_settings @@ -53,7 +53,7 @@ class FcAuthenticator(BaseAuthenticator): 'fc_user_info': fc_user_info, } ) - context['login_url'] = a2_utils.make_url('fc-login-or-link', keep_params=True, request=request) + context['login_url'] = utils_misc.make_url('fc-login-or-link', keep_params=True, request=request) context['block-extra-css-class'] = 'fc-login' template = 'authentic2_auth_fc/login.html' return TemplateResponse(request, template, context) @@ -64,11 +64,11 @@ class FcAuthenticator(BaseAuthenticator): # and unlinking would make the account unreachable. unlink = request.user.has_usable_password() or a2_app_settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD - account_path = a2_utils.reverse('account_management') + account_path = utils_misc.reverse('account_management') params = { 'next': account_path, } - link_url = a2_utils.make_url('fc-login-or-link', params=params) + link_url = utils_misc.make_url('fc-login-or-link', params=params) context = kwargs.pop('context', {}).copy() context.update( diff --git a/src/authentic2_auth_fc/views.py b/src/authentic2_auth_fc/views.py index 4d7d2b37a..f7c65c55f 100644 --- a/src/authentic2_auth_fc/views.py +++ b/src/authentic2_auth_fc/views.py @@ -36,12 +36,12 @@ from requests_oauthlib import OAuth2Session from authentic2 import app_settings as a2_app_settings from authentic2 import constants, hooks from authentic2 import models as a2_models -from authentic2 import utils as a2_utils from authentic2.a2_rbac.utils import get_default_ou from authentic2.compat.cookies import set_cookie from authentic2.crypto import check_hmac_url, hash_chain, hmac_url from authentic2.forms.passwords import SetPasswordForm -from authentic2.utils import views as views_utils +from authentic2.utils import misc as utils_misc +from authentic2.utils import views as utils_views from authentic2.utils.models import safe_get_or_create from authentic2.utils.service import get_service_from_ref, get_service_from_request, service_ref @@ -74,14 +74,14 @@ class LoginOrLinkView(View): @property def next_url(self): - return self._next_url or a2_utils.select_next_url(self.request, default=settings.LOGIN_REDIRECT_URL) + return self._next_url or utils_misc.select_next_url(self.request, default=settings.LOGIN_REDIRECT_URL) @property def redirect_uri(self): return self.request.build_absolute_uri(reverse('fc-login-or-link')) def redirect(self): - return a2_utils.redirect(self.request, self.next_url) + return utils_misc.redirect(self.request, self.next_url) @property def fc_display_name(self): @@ -117,7 +117,7 @@ class LoginOrLinkView(View): try: state, self._next_url, self.service = self.decode_state(state) except ValueError: - return a2_utils.redirect(request, settings.LOGIN_REDIRECT_URL) + return utils_misc.redirect(request, settings.LOGIN_REDIRECT_URL) # regenerte the chain of hash from the stored nonce_seed try: @@ -325,7 +325,7 @@ class LoginOrLinkView(View): return self.redirect() def login(self, request): - user = a2_utils.authenticate(request, sub=self.sub, user_info=self.user_info, token=self.token) + user = utils_misc.authenticate(request, sub=self.sub, user_info=self.user_info, token=self.token) if not user: user = self.create_account(request, sub=self.sub, token=self.token, user_info=self.user_info) @@ -337,8 +337,8 @@ class LoginOrLinkView(View): def finish_login(self, request, user, user_info): self.update_user_info(user, user_info) - views_utils.check_cookie_works(request) - a2_utils.login(request, user, 'france-connect', service=self.service) + utils_views.check_cookie_works(request) + utils_misc.login(request, user, 'france-connect', service=self.service) # keep id_token around for logout request.session['fc_id_token'] = self.id_token @@ -360,7 +360,7 @@ class LoginOrLinkView(View): request, _('The following fields are mandatory for account creation: %s') % ', '.join(missing), ) - return a2_utils.redirect(request, 'profile_edit', params={'next': self.next_url}) + return utils_misc.redirect(request, 'profile_edit', params={'next': self.next_url}) return self.redirect() def create_account(self, request, sub, token, user_info): @@ -423,7 +423,7 @@ class LoginOrLinkView(View): # let's try again if created: user.delete() - return a2_utils.authenticate(request, sub=sub, token=token, user_info=user_info) + return utils_misc.authenticate(request, sub=sub, token=token, user_info=user_info) except Exception: # if anything unexpected happen and user was created, delete it and re-raise if created: @@ -437,7 +437,7 @@ class LoginOrLinkView(View): logger.info('auth_fc: existing account "%s" linked to FranceConnect sub "%s"', user, sub) hooks.call_hooks('event', name='fc-link', user=user, sub=sub, request=request) - return a2_utils.authenticate(request, sub=sub, user_info=user_info, token=token) + return utils_misc.authenticate(request, sub=sub, user_info=user_info, token=token) def uniqueness_check_failed(self, request): # currently logged : @@ -551,7 +551,7 @@ class UnlinkView(FormView): def post(self, request, *args, **kwargs): if 'cancel' in request.POST: - return a2_utils.redirect(request, 'account_management') + return utils_misc.redirect(request, 'account_management') return super().post(request, *args, **kwargs) diff --git a/src/authentic2_auth_oidc/apps.py b/src/authentic2_auth_oidc/apps.py index c74bca2ab..aada5d6e1 100644 --- a/src/authentic2_auth_oidc/apps.py +++ b/src/authentic2_auth_oidc/apps.py @@ -53,7 +53,7 @@ class Plugin: def redirect_logout_list(self, request, next=None): from django.urls import reverse - from authentic2.utils import make_url + from authentic2.utils.misc import make_url from .models import OIDCProvider diff --git a/src/authentic2_auth_oidc/authenticators.py b/src/authentic2_auth_oidc/authenticators.py index b9676b4e9..9296fd007 100644 --- a/src/authentic2_auth_oidc/authenticators.py +++ b/src/authentic2_auth_oidc/authenticators.py @@ -18,7 +18,7 @@ from django.shortcuts import render from django.utils.translation import gettext_noop from authentic2.authenticators import BaseAuthenticator -from authentic2.utils import make_url, redirect_to_login +from authentic2.utils.misc import make_url, redirect_to_login from . import app_settings, utils from .models import OIDCProvider diff --git a/src/authentic2_auth_oidc/views.py b/src/authentic2_auth_oidc/views.py index df3068a88..8d5d767fb 100644 --- a/src/authentic2_auth_oidc/views.py +++ b/src/authentic2_auth_oidc/views.py @@ -32,7 +32,7 @@ from django.views.generic.base import View from authentic2.compat.cookies import set_cookie from authentic2.decorators import setting_enabled -from authentic2.utils import authenticate, good_next_url, login, redirect +from authentic2.utils.misc import authenticate, good_next_url, login, redirect from . import app_settings, models from .utils import get_provider, get_provider_by_issuer diff --git a/src/authentic2_auth_saml/adapters.py b/src/authentic2_auth_saml/adapters.py index 5f615612a..a7e3e12a9 100644 --- a/src/authentic2_auth_saml/adapters.py +++ b/src/authentic2_auth_saml/adapters.py @@ -24,11 +24,11 @@ from django.utils.translation import ugettext as _ from mellon.adapters import DefaultAdapter, UserCreationError from mellon.utils import get_setting -from authentic2 import utils from authentic2.a2_rbac.models import OrganizationalUnit as OU from authentic2.a2_rbac.models import Role from authentic2.a2_rbac.utils import get_default_ou from authentic2.backends import get_user_queryset +from authentic2.utils import misc as utils_misc from authentic2.utils.evaluate import evaluate_condition logger = logging.getLogger('authentic2.auth_saml') @@ -273,7 +273,7 @@ class AuthenticAdapter(DefaultAdapter): return self.action_add_role(*args, **kwargs) def auth_login(self, request, user): - utils.login(request, user, 'saml') + utils_misc.login(request, user, 'saml') def get_users_queryset(self, idp, saml_attributes): return get_user_queryset() diff --git a/src/authentic2_auth_saml/authenticators.py b/src/authentic2_auth_saml/authenticators.py index 072bd384f..9c28d9ab7 100644 --- a/src/authentic2_auth_saml/authenticators.py +++ b/src/authentic2_auth_saml/authenticators.py @@ -20,7 +20,7 @@ from django.utils.translation import gettext_noop from mellon.utils import get_idp, get_idps from authentic2.authenticators import BaseAuthenticator -from authentic2.utils import redirect_to_login +from authentic2.utils.misc import redirect_to_login from . import app_settings diff --git a/src/authentic2_idp_cas/models.py b/src/authentic2_idp_cas/models.py index 0e7318f4d..f91bc7089 100644 --- a/src/authentic2_idp_cas/models.py +++ b/src/authentic2_idp_cas/models.py @@ -21,7 +21,7 @@ from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from authentic2.models import LogoutUrlAbstract, Service -from authentic2.utils import check_session_key +from authentic2.utils.misc import check_session_key from . import constants, managers, utils diff --git a/src/authentic2_idp_cas/views.py b/src/authentic2_idp_cas/views.py index 4ed35d1c2..7190f708a 100644 --- a/src/authentic2_idp_cas/views.py +++ b/src/authentic2_idp_cas/views.py @@ -27,7 +27,7 @@ from django.views.generic.base import View from authentic2 import hooks from authentic2.attributes_ng.engine import get_attributes from authentic2.constants import NONCE_FIELD_NAME -from authentic2.utils import ( +from authentic2.utils.misc import ( attribute_values_to_identifier, find_authentication_event, get_user_from_session_key, diff --git a/src/authentic2_idp_oidc/utils.py b/src/authentic2_idp_oidc/utils.py index b19e165e0..28d5408ed 100644 --- a/src/authentic2_idp_oidc/utils.py +++ b/src/authentic2_idp_oidc/utils.py @@ -271,7 +271,7 @@ def add_oidc_session(request, client): @GlobalCache(timeout=60) def good_next_url(next_url): - from authentic2.utils import same_origin + from authentic2.utils.misc import same_origin from .models import OIDCClient diff --git a/src/authentic2_idp_oidc/views.py b/src/authentic2_idp_oidc/views.py index 768da98bd..0b0cd1fda 100644 --- a/src/authentic2_idp_oidc/views.py +++ b/src/authentic2_idp_oidc/views.py @@ -47,7 +47,7 @@ from authentic2 import app_settings as a2_app_settings from authentic2 import hooks from authentic2.decorators import setting_enabled from authentic2.exponential_retry_timeout import ExponentialRetryTimeout -from authentic2.utils import last_authentication_event, login_require, make_url, redirect +from authentic2.utils.misc import last_authentication_event, login_require, make_url, redirect from authentic2.views import logout as a2_logout from django_rbac.utils import get_ou_model diff --git a/src/django_rbac/migrations/0001_initial.py b/src/django_rbac/migrations/0001_initial.py index 32cb31c87..1fe5ec6ec 100644 --- a/src/django_rbac/migrations/0001_initial.py +++ b/src/django_rbac/migrations/0001_initial.py @@ -1,8 +1,6 @@ from django.conf import settings from django.db import migrations, models -import authentic2.utils - class Migration(migrations.Migration): diff --git a/tests/auth_fc/conftest.py b/tests/auth_fc/conftest.py index a2d395973..131caf31f 100644 --- a/tests/auth_fc/conftest.py +++ b/tests/auth_fc/conftest.py @@ -31,7 +31,7 @@ from jwcrypto import jwk, jwt from authentic2.a2_rbac.utils import get_default_ou from authentic2.models import Service -from authentic2.utils import make_url +from authentic2.utils.misc import make_url from ..utils import assert_equals_url diff --git a/tests/idp_oidc/test_misc.py b/tests/idp_oidc/test_misc.py index 404fb2bde..e4660b2f8 100644 --- a/tests/idp_oidc/test_misc.py +++ b/tests/idp_oidc/test_misc.py @@ -34,7 +34,7 @@ from jwcrypto.jwt import JWT from authentic2.a2_rbac.utils import get_default_ou from authentic2.models import Attribute, AuthorizedRole -from authentic2.utils import good_next_url, make_url +from authentic2.utils.misc import good_next_url, make_url from authentic2_auth_oidc.utils import parse_timestamp from authentic2_idp_oidc.models import OIDCAccessToken, OIDCAuthorization, OIDCClaim, OIDCClient, OIDCCode from authentic2_idp_oidc.utils import base64url, get_first_ec_sig_key, get_first_rsa_sig_key, make_sub diff --git a/tests/test_a2_rbac.py b/tests/test_a2_rbac.py index e6450f075..07bc0e07e 100644 --- a/tests/test_a2_rbac.py +++ b/tests/test_a2_rbac.py @@ -25,7 +25,7 @@ from authentic2.a2_rbac.models import Permission, Role, RoleAttribute from authentic2.a2_rbac.utils import get_default_ou from authentic2.custom_user.models import User from authentic2.models import Service -from authentic2.utils import get_hex_uuid +from authentic2.utils.misc import get_hex_uuid from django_rbac.models import CHANGE_OP, Operation from django_rbac.utils import get_permission_model diff --git a/tests/test_all.py b/tests/test_all.py index cb9cbbe64..4d0e1e76d 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -32,7 +32,9 @@ from django.utils.encoding import force_text from django.utils.translation import ugettext as _ from rest_framework import status, test -from authentic2 import attribute_kinds, models, utils +from authentic2 import attribute_kinds, models +from authentic2.utils import misc as utils_misc +from authentic2.utils.misc import continue_to_next_url, login_require, make_url, redirect, redirect_to_login from django_rbac.utils import get_ou_model, get_role_model from .utils import Authentic2TestCase, assert_event, get_link_from_mail, get_response_form @@ -134,8 +136,6 @@ class UtilsTests(Authentic2TestCase): self.assertEqualsURL('/test?coin=1&bob=2&coin=3', '/test?bob=2&coin=1&coin=3') def test_make_url(self): - from authentic2.utils import make_url - self.assertEqualsURL(make_url('../coin'), '../coin') self.assertEqualsURL(make_url('../boob', params={'next': '..'}), '../boob?next=..') self.assertEqualsURL( @@ -153,8 +153,6 @@ class UtilsTests(Authentic2TestCase): def test_redirect(self): from django.test.client import RequestFactory - from authentic2.utils import redirect - rf = RequestFactory() request = rf.get('/coin', data={'next': '..'}) request2 = rf.get('/coin', data={'next': '..', 'token': 'xxx'}) @@ -174,8 +172,6 @@ class UtilsTests(Authentic2TestCase): def test_redirect_to_login(self): from django.test.client import RequestFactory - from authentic2.utils import redirect_to_login - rf = RequestFactory() request = rf.get('/coin', data={'next': '..'}) response = redirect_to_login(request) @@ -184,8 +180,6 @@ class UtilsTests(Authentic2TestCase): def test_continue_to_next_url(self): from django.test.client import RequestFactory - from authentic2.utils import continue_to_next_url - rf = RequestFactory() request = rf.get('/coin', data={'next': '/zob/', 'nonce': 'xxx'}) response = continue_to_next_url(request) @@ -194,8 +188,6 @@ class UtilsTests(Authentic2TestCase): def test_login_require(self): from django.test.client import RequestFactory - from authentic2.utils import login_require - rf = RequestFactory() request = rf.get('/coin', data={'next': '/zob/', 'nonce': 'xxx'}) request.session = SessionStore() @@ -474,7 +466,7 @@ class APITest(TestCase): activation_url = get_link_from_mail(mail.outbox[-1]) response = client.get(activation_url, follow=True) self.assertEqual(response.status_code, status.HTTP_200_OK) - assert utils.make_url(return_url, params={'token': token}) in force_text(response.content) + assert utils_misc.make_url(return_url, params={'token': token}) in force_text(response.content) self.assertEqual(User.objects.count(), user_count + 1) response = client.get(reverse('auth_homepage')) self.assertContains(response, username) @@ -584,7 +576,7 @@ class APITest(TestCase): activation_url = get_link_from_mail(mail.outbox[0]) response = client.get(activation_url, follow=True) self.assertEqual(response.status_code, status.HTTP_200_OK) - assert utils.make_url(return_url, params={'token': token}) in force_text(response.content) + assert utils_misc.make_url(return_url, params={'token': token}) in force_text(response.content) self.assertEqual(User.objects.count(), user_count + 1) response = client.get(reverse('auth_homepage')) self.assertContains(response, username) @@ -686,7 +678,7 @@ class APITest(TestCase): activation_url = get_link_from_mail(activation_mail1) response = client.get(activation_url, follow=True) self.assertEqual(response.status_code, status.HTTP_200_OK) - assert utils.make_url(return_url, params={'token': token}) in force_text(response.content) + assert utils_misc.make_url(return_url, params={'token': token}) in force_text(response.content) self.assertEqual(User.objects.count(), user_count + 1) response = client.get(reverse('auth_homepage')) self.assertContains(response, username) diff --git a/tests/test_api.py b/tests/test_api.py index c6a75a211..82440a275 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -37,7 +37,7 @@ from authentic2.a2_rbac.models import Role from authentic2.a2_rbac.utils import get_default_ou from authentic2.apps.journal.models import Event, EventType from authentic2.models import Attribute, AttributeValue, AuthorizedRole, Service -from authentic2.utils import good_next_url +from authentic2.utils.misc import good_next_url from django_rbac.models import SEARCH_OP from django_rbac.utils import get_ou_model, get_role_model diff --git a/tests/test_auth_oidc.py b/tests/test_auth_oidc.py index 845ebf119..0b0854b77 100644 --- a/tests/test_auth_oidc.py +++ b/tests/test_auth_oidc.py @@ -38,7 +38,7 @@ from jwcrypto.jwt import JWT from authentic2.a2_rbac.utils import get_default_ou from authentic2.custom_user.models import DeletedUser from authentic2.models import Attribute, AttributeValue -from authentic2.utils import last_authentication_event +from authentic2.utils.misc import last_authentication_event from authentic2_auth_oidc.models import OIDCAccount, OIDCClaimMapping, OIDCProvider from authentic2_auth_oidc.utils import ( IDToken, diff --git a/tests/test_backends.py b/tests/test_backends.py index 6d94412d0..b3e1593d4 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -15,7 +15,7 @@ # along with this program. If not, see . from authentic2.backends import is_user_authenticable -from authentic2.utils import authenticate +from authentic2.utils.misc import authenticate def test_user_filters(settings, db, simple_user, user_ou1, ou1): diff --git a/tests/test_data_transfer.py b/tests/test_data_transfer.py index 9eb1edfc2..82ac40aab 100644 --- a/tests/test_data_transfer.py +++ b/tests/test_data_transfer.py @@ -29,7 +29,7 @@ from authentic2.data_transfer import ( import_site, search_role, ) -from authentic2.utils import get_hex_uuid +from authentic2.utils.misc import get_hex_uuid from django_rbac.utils import get_ou_model, get_role_model Role = get_role_model() diff --git a/tests/test_idp_saml2.py b/tests/test_idp_saml2.py index b69bf79fb..b26b736b6 100644 --- a/tests/test_idp_saml2.py +++ b/tests/test_idp_saml2.py @@ -40,7 +40,7 @@ from authentic2.idp.saml.saml2_endpoints import get_extensions, get_login_hints_ from authentic2.models import Attribute, Service from authentic2.saml import models as saml_models from authentic2.saml.models import SAMLAttribute -from authentic2.utils import make_url +from authentic2.utils.misc import make_url from . import utils diff --git a/tests/test_ldap.py b/tests/test_ldap.py index b0cd812a8..05ca39092 100644 --- a/tests/test_ldap.py +++ b/tests/test_ldap.py @@ -35,7 +35,8 @@ from authentic2.a2_rbac.models import Role from authentic2.a2_rbac.utils import get_default_ou from authentic2.backends import ldap_backend from authentic2.models import Service -from authentic2.utils import authenticate, switch_user +from authentic2.utils import switch_user +from authentic2.utils.misc import authenticate from django_rbac.utils import get_ou_model from . import utils diff --git a/tests/test_password_reset.py b/tests/test_password_reset.py index f29c145b4..bdfb329cb 100644 --- a/tests/test_password_reset.py +++ b/tests/test_password_reset.py @@ -17,12 +17,12 @@ import pytest from django.test.utils import override_settings from django.urls import reverse +from authentic2.utils.misc import send_password_reset_mail + from . import utils def test_send_password_reset_email(app, simple_user, mailoutbox): - from authentic2.utils import send_password_reset_mail - assert len(mailoutbox) == 0 with utils.run_on_commit_hooks(): send_password_reset_mail( diff --git a/tests/test_registration.py b/tests/test_registration.py index f714365de..c89d0a10c 100644 --- a/tests/test_registration.py +++ b/tests/test_registration.py @@ -21,8 +21,9 @@ from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model from django.urls import reverse from django.utils.http import urlquote -from authentic2 import models, utils +from authentic2 import models from authentic2.apps.journal.models import Event +from authentic2.utils import misc as utils_misc from authentic2.validators import EmailValidator from .utils import assert_event, get_link_from_mail @@ -39,7 +40,7 @@ def test_registration_success(app, db, settings, mailoutbox, external_redirect): # disable existing attributes models.Attribute.objects.update(disabled=True) - url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) + url = utils_misc.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) response = app.get(url) response.form.set('email', 'testbot@entrouvert.com') response = response.form.submit() @@ -114,7 +115,7 @@ def test_registration_realm(app, db, settings, mailoutbox): models.Attribute.objects.update(disabled=True) next_url = 'http://relying-party.org/' - url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) + url = utils_misc.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) response = app.get(url) response.form.set('email', 'testbot@entrouvert.com') @@ -424,7 +425,7 @@ def test_registration_confirm_data(app, settings, db, rf): # make first name not required models.Attribute.objects.filter(name='first_name').update(required=False) - activation_url = utils.build_activation_url( + activation_url = utils_misc.build_activation_url( rf.post('/accounts/register/'), email='john.doe@example.com', next_url='/', @@ -436,7 +437,7 @@ def test_registration_confirm_data(app, settings, db, rf): response = app.get(activation_url, status=302) - activation_url = utils.build_activation_url( + activation_url = utils_misc.build_activation_url( rf.post('/accounts/register/'), email='john.doe@example.com', next_url='/', @@ -449,7 +450,7 @@ def test_registration_confirm_data(app, settings, db, rf): assert 'form' in response.context assert set(response.context['form'].fields.keys()) == {'first_name', 'last_name'} - activation_url = utils.build_activation_url( + activation_url = utils_misc.build_activation_url( rf.post('/accounts/register/'), email='john.doe@example.com', next_url='/', @@ -465,7 +466,7 @@ def test_revalidate_email(app, rf, db, settings, mailoutbox): # disable existing attributes models.Attribute.objects.update(disabled=True) - url = utils.build_activation_url( + url = utils_misc.build_activation_url( rf.get('/'), 'testbot@entrouvert.com', next_url=None, valid_email=False, franceconnect=True ) @@ -491,7 +492,7 @@ def test_email_is_unique_multiple_objects_returned(app, db, settings, mailoutbox User.objects.create(email='testbot@entrouvert.com') User.objects.create(email='testbot@entrouvert.com') - url = utils.build_activation_url( + url = utils_misc.build_activation_url( rf.get('/'), 'testbot@entrouvert.com', first_name='Test', @@ -515,7 +516,7 @@ def test_username_is_unique_multiple_objects_returned(app, db, settings, mailout User.objects.create(username='testbot', email='testbot1@entrouvert.com') User.objects.create(username='testbot', email='testbot2@entrouvert.com') - url = utils.build_activation_url( + url = utils_misc.build_activation_url( rf.get('/'), 'testbot@entrouvert.com', username='testbot', @@ -544,7 +545,7 @@ def test_registration_redirect(app, db, settings, mailoutbox, external_redirect) # disable existing attributes models.Attribute.objects.update(disabled=True) - url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) + url = utils_misc.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) response = app.get(url) response.form.set('email', 'testbot@entrouvert.com') response = response.form.submit() @@ -597,7 +598,7 @@ def test_registration_redirect_tuple(app, db, settings, mailoutbox, external_red # disable existing attributes models.Attribute.objects.update(disabled=True) - url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) + url = utils_misc.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url}) response = app.get(url) response.form.set('email', 'testbot@entrouvert.com') response = response.form.submit() @@ -627,7 +628,7 @@ def test_registration_activate_passwords_not_equal(app, db, settings, mailoutbox def test_authentication_method(app, db, rf, hooks): - activation_url = utils.build_activation_url( + activation_url = utils_misc.build_activation_url( rf.post('/accounts/register/'), email='john.doe@example.com', next_url='/', @@ -644,7 +645,7 @@ def test_authentication_method(app, db, rf, hooks): assert hooks.calls['event'][-1]['kwargs']['name'] == 'login' assert hooks.calls['event'][-1]['kwargs']['how'] == 'email' - activation_url = utils.build_activation_url( + activation_url = utils_misc.build_activation_url( rf.post('/accounts/register/'), email='jane.doe@example.com', next_url='/', @@ -664,7 +665,7 @@ def test_authentication_method(app, db, rf, hooks): def test_registration_with_email_suggestions(app, db, settings): - url = utils.make_url('registration_register') + url = utils_misc.make_url('registration_register') response = app.get(url) assert "email_domains_suggestions.js" in response.text assert "field-live-hint" in response.text @@ -689,7 +690,7 @@ def test_registration_no_email_full_profile_no_password(app, db, rf, mailoutbox) 'authentication_method': 'france-connect', } - activation_url = utils.build_activation_url(rf.post('/accounts/register/'), next_url='/', **data) + activation_url = utils_misc.build_activation_url(rf.post('/accounts/register/'), next_url='/', **data) response = app.get(activation_url) response.form.set('first_name', data['first_name']) @@ -776,7 +777,7 @@ def test_registration_email_not_verified_required_and_unrequired_attributes(app, 'authentication_method': 'france-connect', } - activation_url = utils.build_activation_url(rf.post('/accounts/register/'), next_url='/', **data) + activation_url = utils_misc.build_activation_url(rf.post('/accounts/register/'), next_url='/', **data) response = app.get(activation_url) response.form.set('first_name', data['first_name']) @@ -800,9 +801,9 @@ def test_registration_email_not_verified_required_and_unrequired_attributes(app, def test_honeypot(app, db, settings, mailoutbox): settings.DEFAULT_FROM_EMAIL = 'show only addr ' - response = app.get(utils.make_url('registration_register')) + response = app.get(utils_misc.make_url('registration_register')) response = app.post( - utils.make_url('registration_register'), + utils_misc.make_url('registration_register'), params={ 'email': 'testbot@entrouvert.com', 'csrfmiddlewaretoken': response.context['csrf_token'], diff --git a/tests/test_user_manager.py b/tests/test_user_manager.py index dccd4bfad..3dd9f98cf 100644 --- a/tests/test_user_manager.py +++ b/tests/test_user_manager.py @@ -593,9 +593,7 @@ def test_user_import_legacy_encoding(transactional_db, app, admin, ou1, admin_ou tnoel@entrouvert.com,Thomas,Noël,1234 fpeters@entrouvert.com,Frédéric,Péters,5678 john.doe@entrouvert.com,John,Doe,9101112 -x,x,x,x'''.encode( - 'utf-8' - ), +x,x,x,x'''.encode(), 'application/octet-stream', ), ) diff --git a/tests/test_utils.py b/tests/test_utils.py index cc4d21264..02f75ba24 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -22,17 +22,19 @@ from django.core import mail from django.utils.functional import lazy from authentic2.journal import Journal -from authentic2.utils import ( +from authentic2.utils.lazy import lazy_join +from authentic2.utils.misc import ( authenticate, get_authentication_events, + get_remember_cookie, good_next_url, login, + prepend_remember_cookie, same_origin, select_next_url, send_templated_mail, user_can_change_password, ) -from authentic2.utils.lazy import lazy_join from django_rbac.utils import get_ou_model @@ -106,8 +108,6 @@ def test_get_authentication_events_hows(rf, simple_user): def test_remember_cookie(rf): from django.http import HttpResponse - from authentic2.utils import get_remember_cookie, prepend_remember_cookie - request = rf.get('/') request.COOKIES['preferrence'] = '1 2' assert get_remember_cookie(request, 'preferrence') == [1, 2] diff --git a/tests/utils.py b/tests/utils.py index 53656464b..e2b39f668 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -29,8 +29,9 @@ from django.urls import reverse from django.utils.encoding import force_text, iri_to_uri from lxml import etree -from authentic2 import models, utils +from authentic2 import models from authentic2.apps.journal.models import Event +from authentic2.utils import misc as utils_misc def login(app, user, path=None, password=None, remember_me=None, args=None, kwargs=None, fail=False): @@ -96,9 +97,9 @@ def assert_equals_url(url1, url2, **kwargs): given parameter exist in the first url, it does not check the exact value. """ - url1 = iri_to_uri(utils.make_url(url1, params=None)) + url1 = iri_to_uri(utils_misc.make_url(url1, params=None)) splitted1 = urllib.parse.urlsplit(url1) - url2 = iri_to_uri(utils.make_url(url2, params=kwargs)) + url2 = iri_to_uri(utils_misc.make_url(url2, params=kwargs)) splitted2 = urllib.parse.urlsplit(url2) for i, (elt1, elt2) in enumerate(zip(splitted1, splitted2)): if i == 3: