Compare commits

...
Author SHA1 Message Date
Emil 7c1d0dc568 Tell non-admins why the console is off-limits instead of bouncing them to the dashboard
coordinator / test (push) Canceled after 0s
python / test (push) Canceled after 0s
release / binaries (amd64, darwin) (push) Canceled after 0s
release / binaries (amd64, linux) (push) Canceled after 0s
release / binaries (amd64, windows) (push) Canceled after 0s
release / binaries (arm64, darwin) (push) Canceled after 0s
release / binaries (arm64, linux) (push) Canceled after 0s
release / binaries (arm64, windows) (push) Canceled after 0s
release / image (push) Canceled after 0s
users / test (push) Canceled after 0s
release / release (push) Canceled after 0s
2026-08-03 01:34:22 +03:00
4 changed files with 10 additions and 8 deletions
@@ -26,12 +26,14 @@ var adminUserActions = map[string]bool{
} }
// requireAdmin gates a route on the session caller being an admin. It runs // requireAdmin gates a route on the session caller being an admin. It runs
// inside withUISession, which has already stamped the requester. A non-admin is // inside withUISession, which has already stamped the requester. A signed-in
// sent back to the dashboard rather than shown the panel. // non-admin is told why (and bounced to the login with the message); an
// unauthenticated caller never gets here — the gate has already sent them to
// the login page with the intended destination.
func requireAdmin(next http.Handler) http.Handler { func requireAdmin(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if req, ok := authctx.From(r.Context()); !ok || !req.IsAdmin() { if req, ok := authctx.From(r.Context()); !ok || !req.IsAdmin() {
http.Redirect(w, r, "/ui", http.StatusSeeOther) http.Redirect(w, r, "/ui/login?error=admin+role+required", http.StatusSeeOther)
return return
} }
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
@@ -30,15 +30,15 @@ func TestRequireAdminAllowsAdminOnly(t *testing.T) {
t.Error("admin must reach the handler") t.Error("admin must reach the handler")
} }
// Plain user is redirected to the dashboard. // Plain user is redirected to the login with the reason.
reached = false reached = false
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
h.ServeHTTP(rec, adminReq(t, "user")) h.ServeHTTP(rec, adminReq(t, "user"))
if reached { if reached {
t.Error("non-admin must not reach the handler") t.Error("non-admin must not reach the handler")
} }
if rec.Code != http.StatusSeeOther || rec.Header().Get("Location") != "/ui" { if rec.Code != http.StatusSeeOther || rec.Header().Get("Location") != "/ui/login?error=admin+role+required" {
t.Errorf("non-admin got %d -> %q, want 303 -> /ui", rec.Code, rec.Header().Get("Location")) t.Errorf("non-admin got %d -> %q, want 303 -> login with the admin-required error", rec.Code, rec.Header().Get("Location"))
} }
} }
+1 -1
View File
@@ -65,7 +65,7 @@ Write-Host "SciMesh $Component installed: $Target"
Write-Host "" Write-Host ""
if ($Component -eq "coordinator") { if ($Component -eq "coordinator") {
if ($AutoStart -eq "1") { if ($AutoStart -eq "1") {
Write-Host "Starting the platform and opening the control room in your browser..." Write-Host "Starting the platform and opening the admin console in your browser..."
Write-Host "(stop it with Ctrl-C; it keeps your data in ~\.scimesh)" Write-Host "(stop it with Ctrl-C; it keeps your data in ~\.scimesh)"
Write-Host "" Write-Host ""
& $Target serve --open & $Target serve --open
+1 -1
View File
@@ -78,7 +78,7 @@ fi
if [ "$COMPONENT" = "coordinator" ]; then if [ "$COMPONENT" = "coordinator" ]; then
if [ "$AUTO_START" = "1" ]; then if [ "$AUTO_START" = "1" ]; then
echo echo
echo "Starting the platform and opening the control room in your browser..." echo "Starting the platform and opening the admin console in your browser..."
echo "(stop it with Ctrl-C; it keeps your data in ~/.scimesh)" echo "(stop it with Ctrl-C; it keeps your data in ~/.scimesh)"
echo echo
exec "$TARGET" serve --open exec "$TARGET" serve --open