Add app home Spaces shell and session diagnostics profile menu

Post-login lands on Spaces empty state instead of a principal dump.
Profile menu exposes Session details with identity, tenant, roles/groups,
and authz diagnostics for operator refinement (CSOC-WP-0004 T01/T07).
This commit is contained in:
tegwick 2026-08-11 02:31:55 +02:00
parent 8169102866
commit 422cd613f6
10 changed files with 404 additions and 88 deletions

View file

@ -1,61 +1,51 @@
from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse, HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.shortcuts import redirect, render
from coulomb_social.apps.identity import flex_auth
from .principal import build_principal
def landing(request: HttpRequest) -> HttpResponse:
if request.user.is_authenticated:
from django.shortcuts import redirect
return redirect("core:app_home")
return render(request, "core/landing.html")
@login_required
def app_home(request: HttpRequest) -> HttpResponse:
member = getattr(request.user, "member", None)
subject = member.subject if member else request.user.get_username()
tenant = member.tenant_id if member else ""
decision = flex_auth.check(
"shell:view",
resource="shell",
resource_id="app_home",
subject=subject,
tenant=tenant,
attributes={
"issuer": member.issuer if member else "",
"user_engine_user_id": str(member.user_engine_user_id) if member else "",
},
)
if not decision.allow:
principal = build_principal(request, authz_resource_id="app_home")
if not principal["authz_allow"]:
return HttpResponseForbidden(
f"Not authorized to view shell ({decision.reason})."
f"Not authorized to view shell ({principal['authz_reason']})."
)
# Spaces list is empty until CSOC-WP-0004-T02; keep the product empty-state.
spaces: list[dict] = []
return render(
request,
"core/app_home.html",
{
"member": member,
"principal": {
"username": request.user.get_username(),
"display_name": (
member.display_name
if member and member.display_name
else request.user.get_full_name() or request.user.get_username()
),
"issuer": member.issuer if member else "",
"subject": member.subject if member else "",
"user_engine_user_id": (
str(member.user_engine_user_id) if member else ""
),
"tenant_id": member.tenant_id if member else "",
"user_engine_source": request.session.get("user_engine_source", ""),
"authz_decision_id": decision.decision_id,
"authz_reason": decision.reason,
},
"principal": principal,
"display_name": principal["display_name"],
"spaces": spaces,
},
)
@login_required
def account_session(request: HttpRequest) -> HttpResponse:
"""Principal / session diagnostics (profile menu → T07)."""
principal = build_principal(request, authz_resource_id="account_session")
if not principal["authz_allow"]:
return HttpResponseForbidden(
f"Not authorized to view session details ({principal['authz_reason']})."
)
return render(
request,
"core/account_session.html",
{
"principal": principal,
"display_name": principal["display_name"],
},
)