forked from baron/baron-sso
custom claim 권한체크 확인
This commit is contained in:
@@ -84,6 +84,7 @@ interface IdTokenClaimItem {
|
||||
key: string;
|
||||
value: string;
|
||||
valueType: ClaimValueType;
|
||||
nullable: boolean;
|
||||
readPermission: CustomClaimPermission;
|
||||
writePermission: CustomClaimPermission;
|
||||
}
|
||||
@@ -169,6 +170,7 @@ function createIdTokenClaimItem(id: string): IdTokenClaimItem {
|
||||
key: "",
|
||||
value: "",
|
||||
valueType: "text",
|
||||
nullable: false,
|
||||
readPermission: "admin_only",
|
||||
writePermission: "admin_only",
|
||||
};
|
||||
@@ -217,6 +219,7 @@ function readIdTokenClaimsMetadata(
|
||||
key: keyValue,
|
||||
value: valueValue,
|
||||
valueType: valueTypeValue,
|
||||
nullable: record.nullable === true,
|
||||
readPermission: isCustomClaimPermission(record.readPermission)
|
||||
? record.readPermission
|
||||
: "admin_only",
|
||||
@@ -231,8 +234,12 @@ function readIdTokenClaimsMetadata(
|
||||
function normalizeClaimPreviewValue(
|
||||
value: string,
|
||||
valueType: ClaimValueType,
|
||||
nullable: boolean,
|
||||
): unknown {
|
||||
const trimmed = value.trim();
|
||||
if (nullable && trimmed === "") {
|
||||
return null;
|
||||
}
|
||||
if (valueType === "number") {
|
||||
if (trimmed === "") return "";
|
||||
const parsed = Number(trimmed);
|
||||
@@ -284,7 +291,11 @@ function buildIdTokenClaimsPreview(
|
||||
continue;
|
||||
}
|
||||
|
||||
rpClaims[key] = normalizeClaimPreviewValue(item.value, item.valueType);
|
||||
rpClaims[key] = normalizeClaimPreviewValue(
|
||||
item.value,
|
||||
item.valueType,
|
||||
item.nullable,
|
||||
);
|
||||
}
|
||||
|
||||
if (Object.keys(rpClaims).length > 0) {
|
||||
@@ -755,6 +766,25 @@ function ClientGeneralPage() {
|
||||
);
|
||||
};
|
||||
|
||||
const setIdTokenClaimPermissionAllowed = (
|
||||
id: string,
|
||||
field: "readPermission" | "writePermission",
|
||||
allowed: boolean,
|
||||
) => {
|
||||
const permission = allowed ? "user_and_admin" : "admin_only";
|
||||
setIdTokenClaims((current) =>
|
||||
current.map((claim) => {
|
||||
if (claim.id !== id) {
|
||||
return claim;
|
||||
}
|
||||
return {
|
||||
...claim,
|
||||
[field]: permission,
|
||||
};
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const removeIdTokenClaim = (id: string) => {
|
||||
setIdTokenClaims((current) => current.filter((claim) => claim.id !== id));
|
||||
};
|
||||
@@ -1090,6 +1120,7 @@ function ClientGeneralPage() {
|
||||
return createClient(payload);
|
||||
}
|
||||
|
||||
await queryClient.cancelQueries({ queryKey: ["client", clientId] });
|
||||
const updated = await updateClient(clientId as string, payload);
|
||||
if (status !== initialStatus) {
|
||||
await updateClientStatus(clientId as string, status);
|
||||
@@ -1097,6 +1128,10 @@ function ClientGeneralPage() {
|
||||
return updated;
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
const resultClientId = result?.client?.id ?? clientId;
|
||||
if (resultClientId) {
|
||||
queryClient.setQueryData(["client", resultClientId], result);
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ["clients"] });
|
||||
if (status !== initialStatus) {
|
||||
setInitialStatus(status);
|
||||
@@ -2109,20 +2144,26 @@ function ClientGeneralPage() {
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-bold">
|
||||
{t(
|
||||
"ui.dev.clients.general.id_token_claims.table.read_permission",
|
||||
"ui.dev.clients.general.id_token_claims.table.nullable",
|
||||
"Nullable",
|
||||
)}
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-bold">
|
||||
{t(
|
||||
"ui.dev.clients.general.id_token_claims.table.read_user_allowed",
|
||||
"Read",
|
||||
)}
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-bold">
|
||||
{t(
|
||||
"ui.dev.clients.general.id_token_claims.table.write_permission",
|
||||
"ui.dev.clients.general.id_token_claims.table.write_user_allowed",
|
||||
"Write",
|
||||
)}
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left font-bold">
|
||||
{t(
|
||||
"ui.dev.clients.general.id_token_claims.table.value",
|
||||
"Value",
|
||||
"ui.dev.clients.general.id_token_claims.table.default_value",
|
||||
"Default Value",
|
||||
)}
|
||||
</th>
|
||||
<th className="px-4 py-3 text-right font-bold">
|
||||
@@ -2227,66 +2268,65 @@ function ClientGeneralPage() {
|
||||
</select>
|
||||
</td>
|
||||
<td className="px-4 py-3 align-top">
|
||||
<select
|
||||
value={claim.readPermission}
|
||||
onChange={(e) =>
|
||||
updateIdTokenClaim(
|
||||
claim.id,
|
||||
"readPermission",
|
||||
e.target.value as CustomClaimPermission,
|
||||
)
|
||||
}
|
||||
aria-label={t(
|
||||
"ui.dev.clients.general.id_token_claims.read_permission_label",
|
||||
"읽기 권한",
|
||||
)}
|
||||
className="h-9 w-full rounded-md border border-input bg-background px-3 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
disabled={isGeneralSettingsReadOnly}
|
||||
>
|
||||
<option value="admin_only">
|
||||
{t(
|
||||
"ui.common.custom_claim_permission.admin_only",
|
||||
"관리자만 가능",
|
||||
<div className="flex h-9 items-center">
|
||||
<Switch
|
||||
checked={claim.nullable}
|
||||
onCheckedChange={(checked) =>
|
||||
updateIdTokenClaim(
|
||||
claim.id,
|
||||
"nullable",
|
||||
checked,
|
||||
)
|
||||
}
|
||||
aria-label={t(
|
||||
"ui.dev.clients.general.id_token_claims.nullable_label",
|
||||
"Nullable",
|
||||
)}
|
||||
</option>
|
||||
<option value="user_and_admin">
|
||||
{t(
|
||||
"ui.common.custom_claim_permission.user_and_admin",
|
||||
"사용자 및 관리자 가능",
|
||||
)}
|
||||
</option>
|
||||
</select>
|
||||
disabled={isGeneralSettingsReadOnly}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3 align-top">
|
||||
<select
|
||||
value={claim.writePermission}
|
||||
onChange={(e) =>
|
||||
updateIdTokenClaim(
|
||||
claim.id,
|
||||
"writePermission",
|
||||
e.target.value as CustomClaimPermission,
|
||||
)
|
||||
}
|
||||
aria-label={t(
|
||||
"ui.dev.clients.general.id_token_claims.write_permission_label",
|
||||
"쓰기 권한",
|
||||
)}
|
||||
className="h-9 w-full rounded-md border border-input bg-background px-3 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
disabled={isGeneralSettingsReadOnly}
|
||||
>
|
||||
<option value="admin_only">
|
||||
{t(
|
||||
"ui.common.custom_claim_permission.admin_only",
|
||||
"관리자만 가능",
|
||||
<div className="flex h-9 items-center">
|
||||
<Switch
|
||||
checked={
|
||||
claim.readPermission === "user_and_admin"
|
||||
}
|
||||
onCheckedChange={(checked) =>
|
||||
setIdTokenClaimPermissionAllowed(
|
||||
claim.id,
|
||||
"readPermission",
|
||||
checked,
|
||||
)
|
||||
}
|
||||
aria-label={t(
|
||||
"ui.dev.clients.general.id_token_claims.read_user_allowed_label",
|
||||
"Read 사용자 허용",
|
||||
)}
|
||||
</option>
|
||||
<option value="user_and_admin">
|
||||
{t(
|
||||
"ui.common.custom_claim_permission.user_and_admin",
|
||||
"사용자 및 관리자 가능",
|
||||
disabled={isGeneralSettingsReadOnly}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3 align-top">
|
||||
<div className="flex h-9 items-center">
|
||||
<Switch
|
||||
checked={
|
||||
claim.writePermission === "user_and_admin"
|
||||
}
|
||||
onCheckedChange={(checked) =>
|
||||
setIdTokenClaimPermissionAllowed(
|
||||
claim.id,
|
||||
"writePermission",
|
||||
checked,
|
||||
)
|
||||
}
|
||||
aria-label={t(
|
||||
"ui.dev.clients.general.id_token_claims.write_user_allowed_label",
|
||||
"Write 사용자 허용",
|
||||
)}
|
||||
</option>
|
||||
</select>
|
||||
disabled={isGeneralSettingsReadOnly}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3 align-top">
|
||||
<Input
|
||||
@@ -2301,7 +2341,7 @@ function ClientGeneralPage() {
|
||||
className="h-9 font-mono text-xs"
|
||||
placeholder={t(
|
||||
"ui.dev.clients.general.id_token_claims.value_placeholder",
|
||||
"Enter the claim value",
|
||||
"Enter the default value",
|
||||
)}
|
||||
disabled={isGeneralSettingsReadOnly}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user