diff --git a/ssoauth/app_settings/defaults.py b/ssoauth/app_settings/defaults.py index 4629eecababf22426fb8f62f0bdf2b261598fa83..99723867374423445e65ba2f909d6d076b670671 100644 --- a/ssoauth/app_settings/defaults.py +++ b/ssoauth/app_settings/defaults.py @@ -1,5 +1,4 @@ import os -from django import urls from django.conf import settings as django_settings @@ -54,7 +53,7 @@ GROUPS = getattr(django_settings, "LOCAL_GROUPS", { Settings you might want to change on development (don't change them for production): """ -SP_FORCE_ENTITY_ID = None # do NOT set for production, set to some unique string on development +SP_FORCE_ENTITY_ID = None # do NOT set for production, set to some unique string on development if SSO is enabled """ @@ -68,8 +67,11 @@ SP_METADATA_LIFETIME_DAYS = 365 * 20 PROJECT_NAME = os.environ.get('DJANGO_SETTINGS_MODULE').split('.')[0] -SU_GROUP_NAME = "{0}_superusers".format(PROJECT_NAME) -STAFF_GROUP_NAME = "{0}_staff".format(PROJECT_NAME) +# superusers is a group to have the best possible overview of them +SUPERUSER_GROUP_NAME = "{0}_superusers".format(PROJECT_NAME) + +# staff is a permission because a group would normally combine staff and permissions over some models +STAFF_PERM_CODENAME = "staff" PRETEND_AUTH_BACKEND = django_settings.AUTHENTICATION_BACKENDS[0] # pretend to be this backend; django does not expect that it is possible to log in without an authentication backend diff --git a/ssoauth/auth_utils.py b/ssoauth/auth_utils.py index 3e6a9c4751dc5e2cafe2d92a76f981f249341918..735461551259699f3211276d25ad45ecf2cd30f0 100644 --- a/ssoauth/auth_utils.py +++ b/ssoauth/auth_utils.py @@ -137,20 +137,26 @@ def cleanup_direct_permissions(user): def set_user_compat_flags(user, user_is_active=True): - user.is_active = user_is_active + user.is_active = user_is_active # cannot do much with it, by default activates all users that came from SSO + # defaults are restrictive user.is_staff = False user.is_superuser = False + # superuser try: - group_su = Group.objects.get(name=app_settings.SU_GROUP_NAME) - group_staff = Group.objects.get(name=app_settings.STAFF_GROUP_NAME) + group_su = Group.objects.get(name=app_settings.SUPERUSER_GROUP_NAME) if group_su in user.groups.all(): logger.info("User {user} is superuser".format(**locals())) - user.is_staff = True user.is_superuser = True - if group_staff in user.groups.all(): - logger.info("User {user} is staff (has admin access)".format(**locals())) - user.is_staff = True - except Group.DoesNotExist: - logger.error("No compat groups. Migrate or run management command create_compat_groups.") + except Group.DoesNotExist as e: + logger.error("Could not fetch the superuser group. Forgot to migrate?") + # staff + full_staff_perm_name = "{app}.{codename}".format( + app=get_user_model()._meta.app_label, + codename=app_settings.STAFF_PERM_CODENAME, + ) + if user.has_perm(full_staff_perm_name): + logger.info("User {user} is staff (has admin access)".format(**locals())) + user.is_staff = True + # done user.save() diff --git a/ssoauth/management/commands/create_compat_groups.py b/ssoauth/management/commands/create_compat_groups.py index 19e5975ee0c62b832e73245ed493224ece69af01..65d3d0facbc738790bc41e66ca52db5574309a48 100644 --- a/ssoauth/management/commands/create_compat_groups.py +++ b/ssoauth/management/commands/create_compat_groups.py @@ -1,26 +1,27 @@ from django.core.management.base import BaseCommand, CommandError from django.contrib.auth.models import Group, Permission -from django.contrib.contenttypes.models import ContentType from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType from ... import app_settings from ... import logger class Command(BaseCommand): - help = "Creates groups required for django.contrib.auth compatibility." + help = "Creates groups and permissions for django.contrib.auth compatibility." requires_migrations_checks = True requires_system_checks = True def handle(self, *args, **options): try: - self.ensure_group_exists(app_settings.SU_GROUP_NAME) - self.ensure_group_exists(app_settings.STAFF_GROUP_NAME) + self.ensure_group_exists(app_settings.SUPERUSER_GROUP_NAME) + self.ensure_permission_exists(app_settings.STAFF_PERM_CODENAME) except Exception as e: raise CommandError("Could not ensure that compatibility groups and permissions exist. {0}".format(str(e))) - @staticmethod - def ensure_group_exists(group_name, permission_names=list()): + @classmethod + def ensure_group_exists(cls, group_name, permission_names=list()): """ + :return: group object Ensures the group with the given permissions exists. Creates the group and/or permissions if needed. Adds permissions to the group if needed (but never removes any). @@ -29,12 +30,26 @@ class Command(BaseCommand): if created: logger.info("Created group '{}'".format(group)) for permission_name in permission_names: - permission, created = Permission.objects.get_or_create( - codename=permission_name, - content_type_id=ContentType.objects.get_for_model(get_user_model()).id, - ) - if created: - logger.info("Created permission '{}'".format(permission.codename)) + permission = cls.ensure_permission_exists(permission_name) if permission not in group.permissions.all(): group.permissions.add(permission) logger.info("Added permission '{1}' to group '{0}'".format(group, permission.codename)) + return group + + @staticmethod + def ensure_permission_exists(codename): + """ + :return: permission object + Ensures the permissions exists. Creates it if needed. + """ + user_content_type = ContentType.objects.get_for_model(get_user_model()) + permission, created = Permission.objects.get_or_create( + codename=codename, + content_type_id=user_content_type.pk, + ) + if created: + permission.name = "{0} (ssoauth)".format(codename) + permission.save() + logger.info("Created permission '{}'".format(permission)) + return permission + diff --git a/ssoauth/templates/ssoauth/dev.html b/ssoauth/templates/ssoauth/dev.html index 3d3ddb80fa17d11b87343d8e258d210c0e6f706b..2602c2db088fc82c03b95754228c2f85b1eb086a 100644 --- a/ssoauth/templates/ssoauth/dev.html +++ b/ssoauth/templates/ssoauth/dev.html @@ -52,7 +52,11 @@ </div> </form> {% if next_url %}<p class="message">You will be redirected to: <strong>{{ next_url }}</strong></p>{% endif %} - {% if user.is_superuser %}<p class="message">You are a superuser</p>{% endif %} + {% if user.is_superuser %} + <p class="message">You are a superuser</p> + {% elif user.is_staff %} + <p class="message">You are a staff member</p> + {% endif %} </section> {% for table_name, table_contents in tables %} diff --git a/ssoauth/views.py b/ssoauth/views.py index 48f22f5f7e22d274bfaf61f653c154b1b24e4ff6..58df4eb11f74ee5e767f9f55515508dab7bc46c9 100644 --- a/ssoauth/views.py +++ b/ssoauth/views.py @@ -338,7 +338,7 @@ class DevView(FormView): else: logger.warning("Too anonymous to join groups.") elif local_logout: - logger.info("Logging out") + logger.info("Logging out {u}".format(u=self.request.user)) contrib_auth.logout(self.request) # update the compat flags, might be needed when user or their groups change if self.request.user.is_authenticated: