Skip to content
Snippets Groups Projects
Commit 8ec9f3fd authored by Art's avatar Art :lizard:
Browse files

Make the staff permission/flag work in realistic situations

parent caa382dd
Branches
No related tags found
No related merge requests found
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
......
......@@ -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():
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
except Group.DoesNotExist:
logger.error("No compat groups. Migrate or run management command create_compat_groups.")
# done
user.save()
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
......@@ -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 %}
......
......@@ -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:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment