diff --git a/adminfront/src/components/layout/AppLayout.tsx b/adminfront/src/components/layout/AppLayout.tsx index 77494dc9..b1ffb8bf 100644 --- a/adminfront/src/components/layout/AppLayout.tsx +++ b/adminfront/src/components/layout/AppLayout.tsx @@ -270,8 +270,7 @@ function AppLayout() { if (item.to === "/permissions-direct") return false; if (item.to === "/tenants") return permissions.tenants; if (item.to === orgfrontUrl) return permissions.org_chart; - if (item.to === "/worksmobile") - return permissions.worksmobile && showWorksmobile; + if (item.to === "/worksmobile") return permissions.worksmobile; if (item.to === "/system/ory-ssot") return permissions.ory_ssot; if (item.to === "/system/data-integrity") return permissions.data_integrity; diff --git a/adminfront/src/features/coverage/adminTenantTabs.test.tsx b/adminfront/src/features/coverage/adminTenantTabs.test.tsx index 2ec4b09f..efa5ea33 100644 --- a/adminfront/src/features/coverage/adminTenantTabs.test.tsx +++ b/adminfront/src/features/coverage/adminTenantTabs.test.tsx @@ -61,7 +61,7 @@ const users = [ id: "user-owner", name: "Owner User", email: "owner@example.com", - role: "tenant_admin", + role: "super_admin", status: "active", }, { diff --git a/adminfront/src/features/tenants/hooks/useTenantPermission.ts b/adminfront/src/features/tenants/hooks/useTenantPermission.ts index b7c3c5e8..19241fd7 100644 --- a/adminfront/src/features/tenants/hooks/useTenantPermission.ts +++ b/adminfront/src/features/tenants/hooks/useTenantPermission.ts @@ -13,7 +13,9 @@ export type TenantPermissionKey = | "view_organization" | "manage_organization" | "view_schema" - | "manage_schema"; + | "manage_schema" + | "view_worksmobile" + | "manage_worksmobile"; export function useTenantPermission(tenantId: string) { const { data: profile } = useQuery({ diff --git a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx index 96a85a5f..01840b15 100644 --- a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx +++ b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx @@ -645,7 +645,9 @@ export function TenantFineGrainedPermissionsPage() { {menu.label} {(menu.relation === "ory_ssot" || - menu.relation === "data_integrity") && ( + menu.relation === "data_integrity" || + menu.relation === + "permissions_direct") && ( { const nextVal = e.target.value as diff --git a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx index 779237b1..b5f3335e 100644 --- a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx +++ b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx @@ -31,13 +31,13 @@ import { import { toast } from "../../../components/ui/use-toast"; import { addTenantRelation, + fetchMe, fetchTenantRelations, fetchUsers, removeTenantRelation, type TenantRelation, } from "../../../lib/adminApi"; import { t } from "../../../lib/i18n"; -import { useTenantPermission } from "../hooks/useTenantPermission"; interface TenantFineGrainedPermissionsTabProps { tenantIdProp?: string; @@ -48,8 +48,11 @@ export function TenantFineGrainedPermissionsTab({ }: TenantFineGrainedPermissionsTabProps = {}) { const { tenantId: tenantIdParam } = useParams<{ tenantId: string }>(); const tenantId = tenantIdProp || tenantIdParam || ""; - const { hasPermission } = useTenantPermission(tenantId); - const isWritable = hasPermission("manage_admins"); + const { data: profile } = useQuery({ + queryKey: ["me"], + queryFn: fetchMe, + }); + const isWritable = profile?.role === "super_admin"; const queryClient = useQueryClient(); const [searchTerm, setSearchTerm] = useState(""); const [isDialogOpen, setIsDialogOpen] = useState(false); @@ -75,7 +78,13 @@ export function TenantFineGrainedPermissionsTab({ > = {}; for (const user of relationsQuery.data) { initialMap[user.userId] = {}; - const tabs = ["profile", "permissions", "organization", "schema"]; + const tabs = [ + "profile", + "permissions", + "organization", + "schema", + "worksmobile", + ]; for (const tab of tabs) { const isWrite = user.relations.includes(`${tab}_managers`); const isRead = user.relations.includes(`${tab}_viewers`); @@ -204,7 +213,7 @@ export function TenantFineGrainedPermissionsTab({ const handleRelationChange = async ( userId: string, - tab: "profile" | "permissions" | "organization" | "schema", + tab: "profile" | "permissions" | "organization" | "schema" | "worksmobile", currentVal: "none" | "read" | "write", newVal: "none" | "read" | "write", ) => { @@ -318,6 +327,14 @@ export function TenantFineGrainedPermissionsTab({ + {!isWritable && ( +
+ {t( + "msg.admin.tenants.relations.super_admin_only_desc", + "이 화면의 권한 설정은 시스템 최고 관리자(super_admin)만 수정할 수 있습니다.", + )} +
+ )}
@@ -337,6 +354,12 @@ export function TenantFineGrainedPermissionsTab({ {t("ui.admin.tenants.detail.tab_schema", "사용자 스키마")} + + {t( + "ui.admin.tenants.detail.tab_worksmobile", + "네이버웍스 연동", + )} + {t("ui.common.action", "작업")} @@ -346,7 +369,7 @@ export function TenantFineGrainedPermissionsTab({ {relations.length === 0 ? ( {t( @@ -387,6 +410,14 @@ export function TenantFineGrainedPermissionsTab({ ? "read" : "none"; + const worksmobileVal = user.relations.includes( + "worksmobile_managers", + ) + ? "write" + : user.relations.includes("worksmobile_viewers") + ? "read" + : "none"; + const curProfileVal = localTenantPermissions[user.userId]?.profile ?? profileVal; @@ -398,6 +429,9 @@ export function TenantFineGrainedPermissionsTab({ organizationVal; const curSchemaVal = localTenantPermissions[user.userId]?.schema ?? schemaVal; + const curWorksmobileVal = + localTenantPermissions[user.userId]?.worksmobile ?? + worksmobileVal; return ( + + +