snapshot: extract remaining workflow view helper clusters
This commit is contained in:
145
backend/workflows/admin_user_helpers.py
Normal file
145
backend/workflows/admin_user_helpers.py
Normal file
@@ -0,0 +1,145 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.shortcuts import render
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from django.utils.translation import gettext as _
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
|
||||
from .branding import get_branding_email_copy
|
||||
from .forms import UserManagementCreateForm
|
||||
from .models import AdminAuditLog
|
||||
from .emailing import send_system_email
|
||||
from .roles import ROLE_GROUP_NAMES, ROLE_LABELS, ROLE_PLATFORM_OWNER, ROLE_SUPER_ADMIN, get_user_role_key
|
||||
|
||||
|
||||
def user_management_rows(*, display_user_name_fn):
|
||||
user_model = get_user_model()
|
||||
role_order = {
|
||||
ROLE_PLATFORM_OWNER: 0,
|
||||
ROLE_SUPER_ADMIN: 0,
|
||||
'admin': 1,
|
||||
'it_staff': 2,
|
||||
'staff': 3,
|
||||
}
|
||||
rows = []
|
||||
for user in user_model.objects.all().order_by('-is_active', 'username'):
|
||||
role_key = get_user_role_key(user)
|
||||
rows.append(
|
||||
{
|
||||
'user': user,
|
||||
'role_key': role_key,
|
||||
'role_label': str(ROLE_LABELS[role_key]),
|
||||
'role_sort': role_order.get(role_key, 99),
|
||||
'display_name': display_user_name_fn(user),
|
||||
}
|
||||
)
|
||||
rows.sort(key=lambda item: (not item['user'].is_active, item['role_sort'], item['user'].username.lower()))
|
||||
return rows
|
||||
|
||||
|
||||
def render_user_management(request, *, create_form=None, status_code: int = 200, audit_action_label_fn, display_user_name_fn):
|
||||
recent_user_events = list(
|
||||
AdminAuditLog.objects.select_related('actor')
|
||||
.filter(action__in=['user_created', 'user_updated', 'user_password_reset_sent', 'user_deleted'])
|
||||
.order_by('-created_at', '-id')[:12]
|
||||
)
|
||||
for row in recent_user_events:
|
||||
row.action_label = audit_action_label_fn(row.action)
|
||||
role_key = (row.details or {}).get('role')
|
||||
row.role_label = str(ROLE_LABELS[role_key]) if role_key in ROLE_LABELS else role_key
|
||||
include_product_owner = get_user_role_key(request.user) == ROLE_PLATFORM_OWNER
|
||||
return render(
|
||||
request,
|
||||
'workflows/user_management.html',
|
||||
{
|
||||
'create_form': create_form or UserManagementCreateForm(include_product_owner=include_product_owner),
|
||||
'rows': user_management_rows(display_user_name_fn=display_user_name_fn),
|
||||
'role_choices': [
|
||||
(key, str(ROLE_LABELS[key]))
|
||||
for key in ROLE_GROUP_NAMES
|
||||
if include_product_owner or key != ROLE_PLATFORM_OWNER
|
||||
],
|
||||
'include_product_owner': include_product_owner,
|
||||
'recent_user_events': recent_user_events,
|
||||
},
|
||||
status=status_code,
|
||||
)
|
||||
|
||||
|
||||
def platform_owner_user_count() -> int:
|
||||
user_model = get_user_model()
|
||||
return sum(1 for user in user_model.objects.all() if get_user_role_key(user) == ROLE_PLATFORM_OWNER and user.is_active)
|
||||
|
||||
|
||||
def super_admin_user_count() -> int:
|
||||
user_model = get_user_model()
|
||||
return sum(1 for user in user_model.objects.all() if get_user_role_key(user) == ROLE_SUPER_ADMIN and user.is_active)
|
||||
|
||||
|
||||
def would_remove_last_super_admin(user, new_role_key: str | None = None, new_is_active: bool | None = None, deleting: bool = False) -> bool:
|
||||
if get_user_role_key(user) != ROLE_SUPER_ADMIN or not user.is_active:
|
||||
return False
|
||||
if super_admin_user_count() > 1:
|
||||
return False
|
||||
if deleting:
|
||||
return True
|
||||
if new_role_key is not None and new_role_key != ROLE_SUPER_ADMIN:
|
||||
return True
|
||||
if new_is_active is not None and not new_is_active:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def would_remove_last_platform_owner(user, new_role_key: str | None = None, new_is_active: bool | None = None, deleting: bool = False) -> bool:
|
||||
if get_user_role_key(user) != ROLE_PLATFORM_OWNER or not user.is_active:
|
||||
return False
|
||||
if platform_owner_user_count() > 1:
|
||||
return False
|
||||
if deleting:
|
||||
return True
|
||||
if new_role_key is not None and new_role_key != ROLE_PLATFORM_OWNER:
|
||||
return True
|
||||
if new_is_active is not None and not new_is_active:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def send_user_access_email(request, target_user, *, invitation: bool, display_user_name_fn) -> None:
|
||||
email = (target_user.email or '').strip()
|
||||
if not email:
|
||||
raise ValueError(_('Für diesen Benutzer ist keine E-Mail-Adresse hinterlegt.'))
|
||||
|
||||
uid = urlsafe_base64_encode(force_bytes(target_user.pk))
|
||||
token = default_token_generator.make_token(target_user)
|
||||
reset_path = reverse('password_reset_confirm', kwargs={'uidb64': uid, 'token': token})
|
||||
reset_url = request.build_absolute_uri(reset_path)
|
||||
branding_copy = get_branding_email_copy()
|
||||
|
||||
if invitation:
|
||||
subject = _('Zugangseinladung für %(username)s') % {'username': target_user.username}
|
||||
body = _(
|
||||
'Hallo %(name)s,\n\n'
|
||||
'für Sie wurde ein Benutzerkonto im %(portal_title)s angelegt.\n'
|
||||
'Bitte öffnen Sie den folgenden Link, um Ihr Passwort zu setzen:\n'
|
||||
'%(url)s\n\n'
|
||||
'Wenn Sie diese Einladung nicht erwartet haben, melden Sie sich bitte bei Ihrem Administrator.'
|
||||
) % {
|
||||
'name': display_user_name_fn(target_user),
|
||||
'portal_title': branding_copy['portal_title'],
|
||||
'url': reset_url,
|
||||
}
|
||||
else:
|
||||
subject = _('Passwort zurücksetzen für %(username)s') % {'username': target_user.username}
|
||||
body = _(
|
||||
'Hallo %(name)s,\n\n'
|
||||
'für Ihr Konto wurde ein Link zum Zurücksetzen des Passworts erstellt.\n'
|
||||
'Bitte öffnen Sie den folgenden Link:\n'
|
||||
'%(url)s\n\n'
|
||||
'Wenn Sie diese Anfrage nicht erwartet haben, können Sie diese E-Mail ignorieren.'
|
||||
) % {
|
||||
'name': display_user_name_fn(target_user),
|
||||
'url': reset_url,
|
||||
}
|
||||
|
||||
send_system_email(subject=subject, body=body, to=[email])
|
||||
Reference in New Issue
Block a user