forked from baron/baron-sso
개발자 권한 접근 로직 공통화
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
resolveDeveloperAccessGate,
|
||||
shouldFetchDeveloperRequestStatus,
|
||||
shouldShowDeveloperAccessLoading,
|
||||
} from "./developerAccessGate";
|
||||
|
||||
describe("developer access gate", () => {
|
||||
it("fetches request status only for user roles", () => {
|
||||
expect(shouldFetchDeveloperRequestStatus("user")).toBe(true);
|
||||
expect(shouldFetchDeveloperRequestStatus("tenant_admin")).toBe(false);
|
||||
expect(shouldFetchDeveloperRequestStatus("rp_admin")).toBe(false);
|
||||
});
|
||||
|
||||
it("resolves access and request states from the request status", () => {
|
||||
expect(resolveDeveloperAccessGate("super_admin", "pending")).toEqual({
|
||||
hasDeveloperAccess: true,
|
||||
isDeveloperRequestPending: true,
|
||||
canRequestDeveloperAccess: false,
|
||||
});
|
||||
|
||||
expect(resolveDeveloperAccessGate("user", "approved")).toEqual({
|
||||
hasDeveloperAccess: true,
|
||||
isDeveloperRequestPending: false,
|
||||
canRequestDeveloperAccess: false,
|
||||
});
|
||||
|
||||
expect(resolveDeveloperAccessGate("user", "pending")).toEqual({
|
||||
hasDeveloperAccess: false,
|
||||
isDeveloperRequestPending: true,
|
||||
canRequestDeveloperAccess: false,
|
||||
});
|
||||
|
||||
expect(resolveDeveloperAccessGate("user", "none")).toEqual({
|
||||
hasDeveloperAccess: false,
|
||||
isDeveloperRequestPending: false,
|
||||
canRequestDeveloperAccess: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("shows the loading gate only for user requests", () => {
|
||||
expect(shouldShowDeveloperAccessLoading("user", true, false)).toBe(true);
|
||||
expect(shouldShowDeveloperAccessLoading("user", false, true)).toBe(true);
|
||||
expect(shouldShowDeveloperAccessLoading("tenant_admin", true, true)).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
fetchDeveloperRequestStatus,
|
||||
type DeveloperRequestStatus,
|
||||
} from "../../lib/devApi";
|
||||
|
||||
export type DeveloperAccessGateState = {
|
||||
hasDeveloperAccess: boolean;
|
||||
isDeveloperRequestPending: boolean;
|
||||
canRequestDeveloperAccess: boolean;
|
||||
isLoadingDeveloperAccessGate: boolean;
|
||||
};
|
||||
|
||||
function isPrivilegedDeveloperRole(profileRole: string) {
|
||||
return (
|
||||
profileRole === "super_admin" ||
|
||||
profileRole === "tenant_admin" ||
|
||||
profileRole === "rp_admin"
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveDeveloperAccessGate(
|
||||
profileRole: string,
|
||||
requestStatus?: DeveloperRequestStatus,
|
||||
): Omit<DeveloperAccessGateState, "isLoadingDeveloperAccessGate"> {
|
||||
const hasDeveloperAccess =
|
||||
isPrivilegedDeveloperRole(profileRole) || requestStatus === "approved";
|
||||
const isDeveloperRequestPending = requestStatus === "pending";
|
||||
const canRequestDeveloperAccess =
|
||||
profileRole === "user" &&
|
||||
!hasDeveloperAccess &&
|
||||
!isDeveloperRequestPending;
|
||||
|
||||
return {
|
||||
hasDeveloperAccess,
|
||||
isDeveloperRequestPending,
|
||||
canRequestDeveloperAccess,
|
||||
};
|
||||
}
|
||||
|
||||
export function shouldFetchDeveloperRequestStatus(profileRole: string) {
|
||||
return profileRole === "user";
|
||||
}
|
||||
|
||||
export function shouldShowDeveloperAccessLoading(
|
||||
profileRole: string,
|
||||
isLoadingIdentity: boolean,
|
||||
isLoadingRequestStatus: boolean,
|
||||
) {
|
||||
return (
|
||||
profileRole === "user" && (isLoadingIdentity || isLoadingRequestStatus)
|
||||
);
|
||||
}
|
||||
|
||||
export function useDeveloperAccessGate({
|
||||
hasAccessToken,
|
||||
profileRole,
|
||||
tenantId,
|
||||
isLoadingIdentity = false,
|
||||
}: {
|
||||
hasAccessToken: boolean;
|
||||
profileRole: string;
|
||||
tenantId?: string;
|
||||
isLoadingIdentity?: boolean;
|
||||
}) {
|
||||
const shouldFetchRequestStatus = shouldFetchDeveloperRequestStatus(
|
||||
profileRole,
|
||||
);
|
||||
const { data: requestStatus, isLoading: isLoadingRequestStatus } = useQuery({
|
||||
queryKey: ["developer-request", tenantId],
|
||||
queryFn: () => fetchDeveloperRequestStatus(tenantId),
|
||||
enabled: hasAccessToken && shouldFetchRequestStatus,
|
||||
});
|
||||
|
||||
const resolvedGate = resolveDeveloperAccessGate(
|
||||
profileRole,
|
||||
requestStatus?.status,
|
||||
);
|
||||
|
||||
return {
|
||||
...resolvedGate,
|
||||
isLoadingDeveloperAccessGate: shouldShowDeveloperAccessLoading(
|
||||
profileRole,
|
||||
isLoadingIdentity,
|
||||
isLoadingRequestStatus,
|
||||
),
|
||||
} satisfies DeveloperAccessGateState;
|
||||
}
|
||||
Reference in New Issue
Block a user