Skip to content

Instantly share code, notes, and snippets.

Last active September 4, 2023 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jurrian/9c41c936929d9d0ec869f33960d67149 to your computer and use it in GitHub Desktop.
Save jurrian/9c41c936929d9d0ec869f33960d67149 to your computer and use it in GitHub Desktop.
Mixin to apply over the Django `User` or `AbstractUser` model, this will change the superuser checkbox to a datetime field that will expire.
from datetime import timedelta
from django.db import models
from django.utils.timezone import now
class ExpiringSuperuserMixin:
_is_superuser = models.DateTimeField(
_('superuser until'),
help_text=_('Until when the user has special top-level permissions. Use with extra caution, '
'this includes most destructive permissions. Only specify a very limited timeframe.'),
def save(self, *args, **kwargs):
"""Clear superuser field if expired.
if self._is_superuser < now():
self._is_superuser = None
except TypeError:
return super().save(*args, **kwargs)
def is_superuser(self):
"""Evaluate if superuser datetime is not due or None.
If the datetime is due then reset the field to None.
is_within_window = self._is_superuser > now()
except TypeError:
return False
if not is_within_window:
self._is_superuser = None['_is_superuser'])
return False
return True
def is_superuser(self, value):
"""Backwards compatibility: set a default time for superuser.
When using ` createsuperuser`, this method will be called with `value=True`.
In that case we need to set a default time starting now.
if isinstance(value, datetime):
self._is_superuser = value
elif value is True:
self._is_superuser = now() + timedelta(minutes=30)
self._is_superuser = None
class Meta(AbstractUser.Meta):
permissions = [('can_assign_superuser', 'Can assign superuser')] # Creates permission on model creation
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
class UserAdmin(AuthUserAdmin):
fieldsets = (
(None, {"fields": ("username", "password")}),
(_("Personal info"), {"fields": ("first_name", "last_name", "email")}),
"fields": (
"_is_superuser", # <--
(_("Important dates"), {"fields": ("last_login", "date_joined")}),
list_filter = ("is_staff", "_is_superuser", "is_active", "groups")
def get_readonly_fields(self, request, obj=None):
"""Only allow editing superuser status when has can_assign_superuser perm.
The has_perm() check also triggers is_superuser() to reset it if needed.
readonly_fields = super().get_readonly_fields(request, obj)
if not request.user.has_perm('profiles.can_assign_superuser'):
readonly_fields += ('_is_superuser',)
return readonly_fields
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment