diff --git a/devfront/src/components/common/ForbiddenMessage.tsx b/devfront/src/components/common/ForbiddenMessage.tsx index 2a496ba3..97c2af01 100644 --- a/devfront/src/components/common/ForbiddenMessage.tsx +++ b/devfront/src/components/common/ForbiddenMessage.tsx @@ -4,7 +4,7 @@ import { t } from "../../lib/i18n"; import { resolveProfileRole } from "../../lib/role"; interface Props { - resourceToken: "audit" | "clients"; + resourceToken: "audit" | "clients" | "consents"; } export function ForbiddenMessage({ resourceToken }: Props) { @@ -28,17 +28,33 @@ export function ForbiddenMessage({ resourceToken }: Props) { "테넌트 관리자 권한이 올바르게 설정되지 않았거나 만료되었습니다.", ); } else if (role === "user" || role === "tenant_member") { - explanation = t( - "msg.dev.forbidden.user", - "일반 사용자 계정은 담당 RP(앱) 관리자 권한이 부여된 경우에만 해당 기능을 사용할 수 있습니다. 권한이 필요하면 관리자에게 요청하세요.", - ); + if (resourceToken === "consents") { + explanation = t( + "msg.dev.forbidden.user.consents", + "해당 앱(RP)에 대한 동의 내역 조회는 'RP 관리자', '동의 조회', '동의 회수' 관계가 부여된 경우에만 사용할 수 있습니다. 권한이 필요하면 관리자에게 요청하세요.", + ); + } else if (resourceToken === "audit") { + explanation = t( + "msg.dev.forbidden.user.audit", + "해당 앱(RP)에 대한 감사 로그 조회는 'RP 관리자', '감사 조회' 관계가 부여된 경우에만 사용할 수 있습니다. 권한이 필요하면 관리자에게 요청하세요.", + ); + } else { + explanation = t( + "msg.dev.forbidden.user.clients", + "일반 사용자 계정은 담당 RP(앱)에 대한 운영 또는 관리 관계가 부여된 경우에만 해당 기능을 사용할 수 있습니다. 권한이 필요하면 관리자에게 요청하세요.", + ); + } } + const resourceLabel = + resourceToken === "audit" + ? t("ui.dev.audit.title", "Audit Logs") + : resourceToken === "consents" + ? t("ui.dev.clients.consents.title", "User Consent Grants") + : t("ui.dev.clients.registry.subtitle", "연동 앱"); + const title = t("msg.dev.forbidden.title", "{{resource}} 접근 권한 없음", { - resource: - resourceToken === "audit" - ? t("ui.dev.audit.title", "Audit Logs") - : t("ui.dev.clients.registry.subtitle", "연동 앱"), + resource: resourceLabel, }); return ( diff --git a/devfront/src/features/clients/ClientConsentsPage.tsx b/devfront/src/features/clients/ClientConsentsPage.tsx index c2498d7d..728b80a3 100644 --- a/devfront/src/features/clients/ClientConsentsPage.tsx +++ b/devfront/src/features/clients/ClientConsentsPage.tsx @@ -1,4 +1,5 @@ import { useMutation, useQuery } from "@tanstack/react-query"; +import type { AxiosError } from "axios"; import { ArrowLeft, ChevronLeft, @@ -9,6 +10,7 @@ import { } from "lucide-react"; import { useState } from "react"; import { Link, useParams } from "react-router-dom"; +import { ForbiddenMessage } from "../../components/common/ForbiddenMessage"; import { Badge } from "../../components/ui/badge"; import { Button } from "../../components/ui/button"; import { @@ -161,6 +163,57 @@ function ClientConsentsPage() { } }; + if (error) { + const axiosError = error as AxiosError<{ error?: string }>; + if (axiosError.response?.status === 403) { + return ( +
+ {t( + "ui.dev.clients.consents.title", + "User Consent Grants", + )} +
+{t("msg.dev.clients.consents.empty", "No consents found.")}
+