Password page with the AD policy listed first, ordered service (throttle limit below the lockout threshold, verification, local hints, directory change, ended sessions, audit and confirmation mail in one transaction), plain-language errors, German text and tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
62 lines
1.7 KiB
Python
62 lines
1.7 KiB
Python
"""The left menu, declared once. An entry is shown only to users who may open its page."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from django.urls import reverse
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Entry:
|
|
label: object # lazy translated string
|
|
url_name: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Group:
|
|
title: object | None
|
|
role: str | None # None: everyone; otherwise "publisher" or "admin"
|
|
entries: tuple[Entry, ...]
|
|
|
|
|
|
MENU = (
|
|
Group(None, None, (Entry(_("Home"), "home"), Entry(_("Change password"), "password"))),
|
|
Group(
|
|
_("Publishing"),
|
|
"publisher",
|
|
(Entry(_("Manage announcements"), "publish-announcements"),),
|
|
),
|
|
Group(
|
|
_("Administration"),
|
|
"admin",
|
|
(
|
|
Entry(_("Appearance"), "admin-appearance"),
|
|
Entry(_("Settings"), "admin-settings"),
|
|
Entry(_("Audit log"), "admin-audit"),
|
|
Entry(_("Status"), "admin-status"),
|
|
),
|
|
),
|
|
)
|
|
|
|
|
|
def _allowed(group: Group, portal_user) -> bool:
|
|
if group.role is None:
|
|
return True
|
|
return bool(getattr(portal_user, f"is_{group.role}", False))
|
|
|
|
|
|
def for_user(portal_user, current_path: str) -> list[dict]:
|
|
"""The groups this user sees, each entry with its address and whether it is current."""
|
|
groups = []
|
|
for group in MENU:
|
|
if not _allowed(group, portal_user):
|
|
continue
|
|
entries = []
|
|
for entry in group.entries:
|
|
url = reverse(entry.url_name)
|
|
entries.append({"label": entry.label, "url": url, "current": url == current_path})
|
|
groups.append({"title": group.title, "entries": entries})
|
|
return groups
|