1
0
forked from baron/baron-sso

개발자 권한을 페이지별로 선택/부여 가능하도록 개선

This commit is contained in:
2026-06-09 16:47:20 +09:00
parent 3ed9e912e6
commit 437a3ad98d
18 changed files with 782 additions and 91 deletions

View File

@@ -17,6 +17,7 @@ import {
toggleSort,
} from "../../../../common/core/utils";
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
import {
commonTableShellClass,
commonTableViewportClass,
@@ -53,6 +54,7 @@ import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import { cn } from "../../lib/utils";
import { fetchMe } from "../auth/authApi";
import { useDeveloperAccessGate } from "../developer-access/developerAccessGate";
import { resolveClientCreateAccess } from "./clientCreateAccess";
import { ClientLogo } from "./components/ClientLogo";
@@ -101,13 +103,26 @@ function ClientsPage() {
enabled: hasAccessToken,
});
const {
hasDeveloperAccess: hasClientsPageAccess,
isDeveloperRequestPending,
canRequestDeveloperAccess,
isLoadingDeveloperAccessGate,
} = useDeveloperAccessGate({
hasAccessToken,
profileRole,
tenantId,
requiredPages: ["client_create"],
isLoadingIdentity: isLoadingMe,
});
const createAccessState = resolveClientCreateAccess({
role: profileRole,
requestStatus: requestStatus?.status,
accessStatus: requestStatus,
});
const canCreateClient = createAccessState === "can_create";
const isDeveloperRequestPending = createAccessState === "pending";
const canRequestDeveloperAccess =
const isClientCreatePending = createAccessState === "pending";
const canRequestClientCreateAccess =
createAccessState === "request_required" && !isLoadingRequest;
const [searchQuery, setSearchQuery] = useState("");
@@ -189,6 +204,7 @@ function ClientsPage() {
const isLoading =
isLoadingClients ||
isLoadingRequest ||
isLoadingDeveloperAccessGate ||
(hasAccessToken && !profileRole && isLoadingMe);
const requestSort = (key: ClientSortKey) => {
@@ -203,6 +219,38 @@ function ClientsPage() {
);
}
if (!hasClientsPageAccess) {
return (
<div className="p-8">
<div className="mx-auto max-w-2xl">
<DeveloperAccessRequestCard
title={t("ui.dev.clients.registry.subtitle", "연동 앱")}
isPending={isDeveloperRequestPending}
canRequest={canRequestDeveloperAccess}
pendingMessage={t(
"msg.dev.dashboard.access_pending",
"개발자 권한 신청을 검토 중입니다.",
)}
deniedMessage={t(
"msg.dev.clients.access_denied",
"연동 앱 페이지에 접근할 권한이 없습니다.",
)}
pendingDetailMessage={t(
"msg.dev.dashboard.access_pending_detail",
"super admin이 승인하면 개요와 개발자 기능을 사용할 수 있습니다.",
)}
deniedDetailMessage={t(
"msg.dev.clients.access_denied_detail",
"개발자 권한 신청에서 개요 또는 연동 앱 추가 권한을 선택한 뒤 승인받아주세요.",
)}
actionLabel={t("ui.dev.welcome.btn_request", "개발자 등록 신청하기")}
onAction={() => navigate("/developer-requests")}
/>
</div>
</div>
);
}
if (clientError) {
const axiosError = clientError as AxiosError<{ error?: string }>;
if (axiosError.response?.status === 403) {
@@ -255,7 +303,7 @@ function ClientsPage() {
{t("ui.dev.nav.developer_request", "개발자 권한 신청")}
</Button>
</div>
) : canRequestDeveloperAccess ? (
) : canRequestClientCreateAccess ? (
<div className="flex items-center justify-end gap-3">
<p className="max-w-xs whitespace-pre-line text-right text-sm text-muted-foreground">
{t(
@@ -458,11 +506,11 @@ function ClientsPage() {
"msg.dev.clients.empty_can_create",
"아직 등록된 연동 앱이 없습니다.",
)
: isDeveloperRequestPending
? t(
"msg.dev.clients.empty_pending",
"개발자 권한 신청을 검토 중입니다.",
)
: isClientCreatePending
? t(
"msg.dev.clients.empty_pending",
"개발자 권한 신청을 검토 중입니다.",
)
: t(
"msg.dev.clients.empty",
"조회 가능한 RP가 없습니다.",
@@ -480,7 +528,7 @@ function ClientsPage() {
"msg.dev.clients.empty_can_create_detail",
"연동 앱 추가 버튼으로 새 RP를 생성하면 이 목록에 표시됩니다.",
)
: isDeveloperRequestPending
: isClientCreatePending
? t(
"msg.dev.clients.empty_pending_detail",
"super admin이 승인하면 연동 앱을 추가할 수 있습니다.",
@@ -499,7 +547,7 @@ function ClientsPage() {
{t("ui.dev.clients.new", "연동 앱 추가")}
</button>
)}
{!isFilteredOut && canRequestDeveloperAccess && (
{!isFilteredOut && canRequestClientCreateAccess && (
<button
type="button"
className="text-primary font-bold hover:underline"
@@ -693,6 +741,7 @@ function RequestAccessModal({
organization,
reason,
tenantId,
accessPages: ["all"],
});
};