1
0
forked from baron/baron-sso

fix: stabilize tests and refine RBAC model for privileged roles

- Updated devfront to recognize 'rp_admin' and 'tenant_admin' as privileged developer roles.
- Added specific forbidden messages for privileged roles in devfront.
- Improved adminfront Worksmobile test reliability across browsers.
- Updated Makefile to skip userfront tests in environments without Flutter SDK.
- Applied lint and format fixes across adminfront and devfront.
This commit is contained in:
2026-06-04 09:56:02 +09:00
parent 719f408e7e
commit fcb246ea9e
22 changed files with 65 additions and 47 deletions

View File

@@ -1,5 +1,5 @@
import { act } from "react-dom/test-utils";
import { createRoot } from "react-dom/client";
import { act } from "react-dom/test-utils";
import { afterEach, describe, expect, it, vi } from "vitest";
import { DeveloperAccessRequestCard } from "./DeveloperAccessRequestCard";

View File

@@ -34,6 +34,16 @@ export function ForbiddenMessage({ resourceToken }: Props) {
"Standard user accounts can use this feature only when an operational or administrative relationship is granted for the target application. Request access from an administrator if needed.",
);
}
} else if (role === "rp_admin") {
explanation = t(
"msg.dev.forbidden.rp_admin",
"RP administrators can only access resources for their assigned applications.",
);
} else if (role === "tenant_admin") {
explanation = t(
"msg.dev.forbidden.tenant_admin",
"Tenant administrator permissions are not configured correctly or have expired.",
);
}
const resourceLabel =

View File

@@ -1,6 +1,6 @@
import { act } from "react-dom/test-utils";
import { createRoot, type Root } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createRoot, type Root } from "react-dom/client";
import { act } from "react-dom/test-utils";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import AuditLogsPage from "./AuditLogsPage";

View File

@@ -8,9 +8,8 @@ import { parseAuditDetails } from "../../../../common/core/audit";
import { AuditLogTable } from "../../../../common/core/components/audit";
import { PageHeader } from "../../../../common/core/components/page";
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
import { useDeveloperAccessGate } from "../developer-access/developerAccessGate";
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
@@ -26,6 +25,7 @@ import { fetchDevAuditLogs } from "../../lib/devApi";
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import { fetchMe } from "../auth/authApi";
import { useDeveloperAccessGate } from "../developer-access/developerAccessGate";
function toCsv(logs: DevAuditLog[]) {
const header = [

View File

@@ -1,6 +1,6 @@
import { act } from "react-dom/test-utils";
import { createRoot, type Root } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createRoot, type Root } from "react-dom/client";
import { act } from "react-dom/test-utils";
import { MemoryRouter } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import ClientsPage from "./ClientsPage";

View File

@@ -1,6 +1,6 @@
import { act } from "react-dom/test-utils";
import type { ComponentProps, ReactNode } from "react";
import { createRoot, type Root } from "react-dom/client";
import type { ReactNode, ComponentProps } from "react";
import { act } from "react-dom/test-utils";
import { afterEach, describe, expect, it, vi } from "vitest";
import { ClientLogo } from "./ClientLogo";

View File

@@ -1,6 +1,6 @@
import { act } from "react-dom/test-utils";
import { createRoot, type Root } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createRoot, type Root } from "react-dom/client";
import { act } from "react-dom/test-utils";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { ClientFederationPage } from "./ClientFederationPage";

View File

@@ -1,7 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import {
fetchDeveloperRequestStatus,
type DeveloperRequestStatus,
fetchDeveloperRequestStatus,
} from "../../lib/devApi";
export type DeveloperAccessGateState = {
@@ -12,7 +12,11 @@ export type DeveloperAccessGateState = {
};
function isPrivilegedDeveloperRole(profileRole: string) {
return profileRole === "super_admin";
return (
profileRole === "super_admin" ||
profileRole === "rp_admin" ||
profileRole === "tenant_admin"
);
}
export function resolveDeveloperAccessGate(

View File

@@ -1,6 +1,6 @@
import { act } from "react-dom/test-utils";
import { createRoot, type Root } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createRoot, type Root } from "react-dom/client";
import { act } from "react-dom/test-utils";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import DeveloperRequestPage from "./DeveloperRequestPage";

View File

@@ -4,8 +4,8 @@ import {
Activity,
AlertTriangle,
CheckCircle2,
Clock3,
ChevronDown,
Clock3,
Layers3,
LayoutDashboard,
ShieldCheck,
@@ -21,7 +21,6 @@ import {
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import { useDeveloperAccessGate } from "../developer-access/developerAccessGate";
import {
type ClientSummary,
fetchClients,
@@ -35,6 +34,7 @@ import {
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import { fetchMe } from "../auth/authApi";
import { useDeveloperAccessGate } from "../developer-access/developerAccessGate";
import {
buildRecentClientChanges,
type RecentClientChange,

View File

@@ -1,12 +1,12 @@
import {
type AuditDetails,
type CommonAuditLog,
formatAuditValue,
parseAuditDetails,
resolveAuditActor,
type AuditDetails,
type CommonAuditLog,
} from "../../../../common/core/audit";
import { t } from "../../lib/i18n";
import type { ClientSummary, DevAuditLog } from "../../lib/devApi";
import { t } from "../../lib/i18n";
export type RecentClientChange = {
eventId: string;

View File

@@ -7,6 +7,14 @@ export function normalizeRole(rawRole: unknown): string {
case "superadmin":
case "super-admin":
return "super_admin";
case "rp_admin":
case "rpadmin":
case "rp-admin":
return "rp_admin";
case "tenant_admin":
case "tenantadmin":
case "tenant-admin":
return "tenant_admin";
default:
return "user";
}

View File

@@ -1,8 +1,8 @@
import { expect, test } from "@playwright/test";
import {
type DevAssignableUser,
type AuditLog,
type Consent,
type DevAssignableUser,
installDevApiMock,
makeClient,
seedAuth,