feat: 권한관리 권한맵핑 작업

This commit is contained in:
2025-06-10 16:54:21 +09:00
parent 597acfdba7
commit d86f56ed7e
5 changed files with 83 additions and 25 deletions
@@ -6,6 +6,8 @@ import type {
RoleAuthorizationsList,
RoleAuthorizationsData,
RoleAuthorizations,
WithRoleIdRoleAuthorizationsParams,
RoleAuthorizationsByRoleIdList,
} from "../model/role-authorization-interface";
export class RoleAuthorizationsApiService implements RoleAuthorizationsService {
@@ -19,6 +21,16 @@ export class RoleAuthorizationsApiService implements RoleAuthorizationsService {
return response.data;
}
public async getRoleAuthorizationsListByRoleId(
params: WithRoleIdRoleAuthorizationsParams,
): Promise<RoleAuthorizationsByRoleIdList> {
const response = await client.get<RoleAuthorizationsByRoleIdList>(
`${ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS}`,
{ params },
);
return response.data;
}
public async createRoleAuthorizations(
data: RoleAuthorizationsData,
): Promise<RoleAuthorizations> {
@@ -6,4 +6,6 @@ export {
type RoleAuthorizationsList,
type RoleAuthorizationsFormData,
type RoleAuthorizationsData,
type RoleAuthorizationsByRoleId,
type RoleAuthorizationsByRoleIdList,
} from "./model/role-authorization-interface";
@@ -7,6 +7,12 @@ export interface RoleAuthorizationsParams extends PageableParams {
authorizationNo?: string;
}
export interface WithRoleIdRoleAuthorizationsParams extends PageableParams {
keywordType?: string;
keyword?: string;
roleId?: string;
}
export interface RoleAuthorizations {
roleId: string;
roleName: string;
@@ -16,6 +22,16 @@ export interface RoleAuthorizations {
authYn: string;
}
export interface RoleAuthorizationsByRoleId {
roleId: string;
authorizationNo: number;
authorizationName: string;
urlPatternValue: string;
httpMethodCode: string;
sortSeq: number;
createdAt: boolean;
}
export const roleAuthorizationsSchema = z.object({
roleId: z.string(),
authorizationNo: z.number(),
@@ -27,6 +43,8 @@ export const roleAuthorizationsFormSchema = z.object({
});
export type RoleAuthorizationsList = PageableList<RoleAuthorizations>;
export type RoleAuthorizationsByRoleIdList =
PageableList<RoleAuthorizationsByRoleId>;
export type RoleAuthorizationsData = z.infer<typeof roleAuthorizationsSchema>[];
export type RoleAuthorizationsFormData = z.infer<
typeof roleAuthorizationsFormSchema
@@ -36,6 +54,9 @@ export interface RoleAuthorizationsService {
getRoleAuthorizationsList: (
params: RoleAuthorizationsParams,
) => Promise<RoleAuthorizationsList>;
getRoleAuthorizationsListByRoleId: (
params: WithRoleIdRoleAuthorizationsParams,
) => Promise<RoleAuthorizationsByRoleIdList>;
createRoleAuthorizations: (
data: RoleAuthorizationsData,
) => Promise<RoleAuthorizations>;
@@ -14,13 +14,10 @@ import {
DataTable,
Switch,
} from "@common/components";
import {
AuthorizationsApi,
type Authorizations,
} from "@/entities/authorization";
import {
RoleAuthorizationsApi,
type RoleAuthorizationsData,
type RoleAuthorizationsByRoleId,
} from "@/entities/role-authorization";
import { ENDPOINT } from "@/shared/config";
import { useAlertStore, useMutationWrapper } from "@/shared/lib";
@@ -42,7 +39,10 @@ function MappingRoleDialog({
const { data: authorizationList } = useQuery({
queryKey: [ENDPOINT.USER_SERVICE.AUTHORIZATIONS],
queryFn: () => AuthorizationsApi.getAuthorizationsList(),
queryFn: () =>
RoleAuthorizationsApi.getRoleAuthorizationsListByRoleId({
roleId,
}),
enabled: open,
});
@@ -61,6 +61,16 @@ function MappingRoleDialog({
mutate([{ roleId, authorizationNo, authYn: apply ? "Y" : "N" }]);
};
const handleApplyAll = (authYn: "Y" | "N") => {
mutate(
authorizationList?.content.map((authorization) => ({
roleId,
authorizationNo: authorization.authorizationNo,
authYn,
})) ?? [],
);
};
const table = useReactTable({
data: authorizationList?.content ?? [],
columns: createColumns(isPending, applyRoleAuthorization),
@@ -77,6 +87,14 @@ function MappingRoleDialog({
<DialogTitle>모듈 목록</DialogTitle>
</DialogHeader>
<div className="max-h-[40rem] overflow-y-auto">
<div className="mb-4 flex justify-end gap-2">
<Button size="sm" onClick={() => handleApplyAll("Y")}>
일괄적용
</Button>
<Button size="sm" color="gray" onClick={() => handleApplyAll("N")}>
일괄해제
</Button>
</div>
<DataTable table={table} />
</div>
</DialogContent>
@@ -87,7 +105,7 @@ function MappingRoleDialog({
const createColumns = (
isPending: boolean,
applyRoleAuthorization: (apply: boolean, authorizationNo: number) => void,
): ColumnDef<Authorizations>[] => [
): ColumnDef<RoleAuthorizationsByRoleId>[] => [
{
accessorKey: "authorizationName",
header: "API명",
@@ -111,7 +129,7 @@ const createColumns = (
header: "사용여부",
cell: ({ row }) => (
<Switch
checked={row.original.useYn === "Y"}
checked={row.original.createdAt}
onCheckedChange={(apply) =>
applyRoleAuthorization(apply, row.original.authorizationNo)
}
+23 -18
View File
@@ -26,6 +26,8 @@ type RoleFormProps = {
};
function RoleForm({ roleId, form, ...props }: RoleFormProps) {
const isModifyMode = !!roleId;
const alert = useAlertStore((state) => state.setMessage);
const [isValidRoleId, setIsValidRoleId] = useState(false);
@@ -43,7 +45,7 @@ function RoleForm({ roleId, form, ...props }: RoleFormProps) {
});
return (
<FormWrapper form={form} isModifyMode={!!roleId} {...props}>
<FormWrapper form={form} isModifyMode={isModifyMode} {...props}>
<div className="card">
<Table variant="secondary">
<colgroup>
@@ -70,21 +72,24 @@ function RoleForm({ roleId, form, ...props }: RoleFormProps) {
}}
className="w-[20rem] !text-[1.3rem]"
placeholder="권한ID를 입력하세요"
disabled={isModifyMode}
/>
</FormControl>
</FormItem>
<Button
color="green"
className="px-6"
onClick={(e) => {
e.preventDefault();
checkDuplicateRoleId(field.value);
}}
disabled={!field.value || isValidRoleId}
>
{isValidRoleId && <i className="diveicon di-check" />}
중복확인
</Button>
{!isModifyMode && (
<Button
color="green"
className="px-6"
onClick={(e) => {
e.preventDefault();
checkDuplicateRoleId(field.value);
}}
disabled={!field.value || isValidRoleId}
>
{isValidRoleId && <i className="diveicon di-check" />}
중복확인
</Button>
)}
</div>
)}
/>
@@ -137,7 +142,7 @@ function RoleForm({ roleId, form, ...props }: RoleFormProps) {
<TableCell className="border">
<FormField
control={form.control}
name="useYn"
name="mngrYn"
render={({ field }) => (
<FormItem>
<FormControl>
@@ -147,12 +152,12 @@ function RoleForm({ roleId, form, ...props }: RoleFormProps) {
onValueChange={field.onChange}
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="Y" id="useY" />
<Label htmlFor="useY">사용</Label>
<RadioGroupItem value="Y" id="mngrY" />
<Label htmlFor="mngrY">사용</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="N" id="useN" />
<Label htmlFor="useN">사용안함</Label>
<RadioGroupItem value="N" id="mngrN" />
<Label htmlFor="mngrN">사용안함</Label>
</div>
</RadioGroup>
</FormControl>