@abpjs/permission-management 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,454 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ PermissionManagementModal: () => PermissionManagementModal,
24
+ PermissionManagementService: () => PermissionManagementService,
25
+ usePermissionManagement: () => usePermissionManagement
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/services/permission-management.service.ts
30
+ var PermissionManagementService = class {
31
+ constructor(rest) {
32
+ this.rest = rest;
33
+ }
34
+ /**
35
+ * Get permissions for a provider
36
+ * @param params Provider key and name
37
+ * @returns Promise with permission response
38
+ */
39
+ getPermissions(params) {
40
+ return this.rest.request({
41
+ method: "GET",
42
+ url: "/api/permission-management/permissions",
43
+ params
44
+ });
45
+ }
46
+ /**
47
+ * Update permissions for a provider
48
+ * @param request Update request with permissions, providerKey and providerName
49
+ * @returns Promise that resolves when update completes
50
+ */
51
+ updatePermissions(request) {
52
+ const { permissions, providerKey, providerName } = request;
53
+ return this.rest.request({
54
+ method: "PUT",
55
+ url: "/api/permission-management/permissions",
56
+ body: { permissions },
57
+ params: { providerKey, providerName }
58
+ });
59
+ }
60
+ };
61
+
62
+ // src/hooks/usePermissionManagement.ts
63
+ var import_react = require("react");
64
+ var import_core = require("@abpjs/core");
65
+ function findMargin(permissions, permission) {
66
+ const parentPermission = permissions.find((per) => per.name === permission.parentName);
67
+ if (parentPermission && parentPermission.parentName) {
68
+ let margin = 20;
69
+ return margin += findMargin(permissions, parentPermission);
70
+ }
71
+ return parentPermission ? 20 : 0;
72
+ }
73
+ function getPermissionsFromGroups(groups) {
74
+ return groups.reduce(
75
+ (acc, group) => [
76
+ ...acc,
77
+ ...group.permissions.map((p) => ({ name: p.name, isGranted: p.isGranted }))
78
+ ],
79
+ []
80
+ );
81
+ }
82
+ function usePermissionManagement() {
83
+ const restService = (0, import_core.useRestService)();
84
+ const service = (0, import_react.useMemo)(() => new PermissionManagementService(restService), [restService]);
85
+ const [groups, setGroups] = (0, import_react.useState)([]);
86
+ const [entityDisplayName, setEntityDisplayName] = (0, import_react.useState)("");
87
+ const [selectedGroup, setSelectedGroup] = (0, import_react.useState)(null);
88
+ const [permissions, setPermissions] = (0, import_react.useState)([]);
89
+ const [originalPermissions, setOriginalPermissions] = (0, import_react.useState)([]);
90
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
91
+ const [error, setError] = (0, import_react.useState)(null);
92
+ const [selectThisTab, setSelectThisTab] = (0, import_react.useState)(false);
93
+ const [selectAllTab, setSelectAllTab] = (0, import_react.useState)(false);
94
+ const isGranted = (0, import_react.useCallback)(
95
+ (permissionName) => {
96
+ const permission = permissions.find((p) => p.name === permissionName);
97
+ return permission?.isGranted ?? false;
98
+ },
99
+ [permissions]
100
+ );
101
+ const getSelectedGroupPermissions = (0, import_react.useCallback)(() => {
102
+ if (!selectedGroup) return [];
103
+ const groupPermissions = groups.find((g) => g.name === selectedGroup.name)?.permissions ?? [];
104
+ return groupPermissions.map((permission) => ({
105
+ ...permission,
106
+ margin: findMargin(groupPermissions, permission),
107
+ isGranted: isGranted(permission.name)
108
+ }));
109
+ }, [selectedGroup, groups, isGranted]);
110
+ const updateCheckboxStates = (0, import_react.useCallback)(() => {
111
+ if (selectedGroup) {
112
+ const groupPermissions = groups.find((g) => g.name === selectedGroup.name)?.permissions ?? [];
113
+ const grantedCount = groupPermissions.filter((p) => isGranted(p.name)).length;
114
+ if (grantedCount === groupPermissions.length) {
115
+ setSelectThisTab(true);
116
+ } else if (grantedCount === 0) {
117
+ setSelectThisTab(false);
118
+ }
119
+ }
120
+ const allGrantedCount = permissions.filter((p) => p.isGranted).length;
121
+ if (allGrantedCount === permissions.length) {
122
+ setSelectAllTab(true);
123
+ } else if (allGrantedCount === 0) {
124
+ setSelectAllTab(false);
125
+ }
126
+ }, [selectedGroup, groups, permissions, isGranted]);
127
+ const fetchPermissions = (0, import_react.useCallback)(
128
+ async (providerKey, providerName) => {
129
+ setIsLoading(true);
130
+ setError(null);
131
+ try {
132
+ const response = await service.getPermissions({
133
+ providerKey,
134
+ providerName
135
+ });
136
+ setGroups(response.groups);
137
+ setEntityDisplayName(response.entityDisplayName);
138
+ if (response.groups.length > 0) {
139
+ setSelectedGroup(response.groups[0]);
140
+ }
141
+ const perms = getPermissionsFromGroups(response.groups);
142
+ setPermissions(perms);
143
+ setOriginalPermissions(perms);
144
+ setIsLoading(false);
145
+ return { success: true };
146
+ } catch (err) {
147
+ const errorMessage = err instanceof Error ? err.message : "Failed to fetch permissions";
148
+ setError(errorMessage);
149
+ setIsLoading(false);
150
+ return { success: false, error: errorMessage };
151
+ }
152
+ },
153
+ [service]
154
+ );
155
+ const savePermissions = (0, import_react.useCallback)(
156
+ async (providerKey, providerName) => {
157
+ const changedPermissions = permissions.filter((perm) => {
158
+ const original = originalPermissions.find((o) => o.name === perm.name);
159
+ return original && original.isGranted !== perm.isGranted;
160
+ });
161
+ if (changedPermissions.length === 0) {
162
+ return { success: true };
163
+ }
164
+ setIsLoading(true);
165
+ setError(null);
166
+ try {
167
+ await service.updatePermissions({
168
+ providerKey,
169
+ providerName,
170
+ permissions: changedPermissions.map(({ name, isGranted: isGranted2 }) => ({
171
+ name,
172
+ isGranted: isGranted2
173
+ }))
174
+ });
175
+ setIsLoading(false);
176
+ return { success: true };
177
+ } catch (err) {
178
+ const errorMessage = err instanceof Error ? err.message : "Failed to update permissions";
179
+ setError(errorMessage);
180
+ setIsLoading(false);
181
+ return { success: false, error: errorMessage };
182
+ }
183
+ },
184
+ [service, permissions, originalPermissions]
185
+ );
186
+ const togglePermission = (0, import_react.useCallback)(
187
+ (clickedPermission) => {
188
+ setPermissions((currentPermissions) => {
189
+ const clickedPerm = currentPermissions.find((p) => p.name === clickedPermission.name);
190
+ const wasGranted = clickedPerm?.isGranted ?? false;
191
+ return currentPermissions.map((perm) => {
192
+ if (clickedPermission.name === perm.name) {
193
+ return { ...perm, isGranted: !perm.isGranted };
194
+ }
195
+ if (clickedPermission.name === clickedPermission.parentName && wasGranted) {
196
+ }
197
+ const allPerms = groups.flatMap((g) => g.permissions);
198
+ const thisPerm = allPerms.find((p) => p.name === perm.name);
199
+ if (thisPerm?.parentName === clickedPermission.name && wasGranted) {
200
+ return { ...perm, isGranted: false };
201
+ }
202
+ if (clickedPermission.parentName === perm.name && !wasGranted) {
203
+ return { ...perm, isGranted: true };
204
+ }
205
+ return perm;
206
+ });
207
+ });
208
+ setTimeout(updateCheckboxStates, 0);
209
+ },
210
+ [groups, updateCheckboxStates]
211
+ );
212
+ const toggleSelectThisTab = (0, import_react.useCallback)(() => {
213
+ if (!selectedGroup) return;
214
+ const groupPermissionNames = new Set(
215
+ groups.find((g) => g.name === selectedGroup.name)?.permissions.map((p) => p.name) ?? []
216
+ );
217
+ const newGrantedState = !selectThisTab;
218
+ setPermissions(
219
+ (currentPermissions) => currentPermissions.map(
220
+ (perm) => groupPermissionNames.has(perm.name) ? { ...perm, isGranted: newGrantedState } : perm
221
+ )
222
+ );
223
+ setSelectThisTab(newGrantedState);
224
+ setTimeout(updateCheckboxStates, 0);
225
+ }, [selectedGroup, groups, selectThisTab, updateCheckboxStates]);
226
+ const toggleSelectAll = (0, import_react.useCallback)(() => {
227
+ const newGrantedState = !selectAllTab;
228
+ setPermissions(
229
+ (currentPermissions) => currentPermissions.map((perm) => ({ ...perm, isGranted: newGrantedState }))
230
+ );
231
+ setSelectAllTab(newGrantedState);
232
+ setSelectThisTab(newGrantedState);
233
+ }, [selectAllTab]);
234
+ const handleSetSelectedGroup = (0, import_react.useCallback)(
235
+ (group) => {
236
+ setSelectedGroup(group);
237
+ setTimeout(updateCheckboxStates, 0);
238
+ },
239
+ [updateCheckboxStates]
240
+ );
241
+ const reset = (0, import_react.useCallback)(() => {
242
+ setGroups([]);
243
+ setEntityDisplayName("");
244
+ setSelectedGroup(null);
245
+ setPermissions([]);
246
+ setOriginalPermissions([]);
247
+ setIsLoading(false);
248
+ setError(null);
249
+ setSelectThisTab(false);
250
+ setSelectAllTab(false);
251
+ }, []);
252
+ return {
253
+ groups,
254
+ entityDisplayName,
255
+ selectedGroup,
256
+ permissions,
257
+ isLoading,
258
+ error,
259
+ selectThisTab,
260
+ selectAllTab,
261
+ fetchPermissions,
262
+ savePermissions,
263
+ setSelectedGroup: handleSetSelectedGroup,
264
+ togglePermission,
265
+ toggleSelectThisTab,
266
+ toggleSelectAll,
267
+ getSelectedGroupPermissions,
268
+ isGranted,
269
+ reset
270
+ };
271
+ }
272
+
273
+ // src/components/PermissionManagementModal/PermissionManagementModal.tsx
274
+ var import_react2 = require("react");
275
+ var import_core2 = require("@abpjs/core");
276
+ var import_theme_shared = require("@abpjs/theme-shared");
277
+ var import_react3 = require("@chakra-ui/react");
278
+ var import_jsx_runtime = require("react/jsx-runtime");
279
+ function PermissionManagementModal({
280
+ providerName,
281
+ providerKey,
282
+ visible,
283
+ onVisibleChange,
284
+ onSave
285
+ }) {
286
+ const { t } = (0, import_core2.useLocalization)();
287
+ const {
288
+ groups,
289
+ entityDisplayName,
290
+ selectedGroup,
291
+ isLoading,
292
+ error,
293
+ selectThisTab,
294
+ selectAllTab,
295
+ fetchPermissions,
296
+ savePermissions,
297
+ setSelectedGroup,
298
+ togglePermission,
299
+ toggleSelectThisTab,
300
+ toggleSelectAll,
301
+ getSelectedGroupPermissions,
302
+ isGranted,
303
+ reset
304
+ } = usePermissionManagement();
305
+ const selectAllCheckboxRef = (0, import_react2.useRef)(null);
306
+ const selectThisTabCheckboxRef = (0, import_react2.useRef)(null);
307
+ (0, import_react2.useEffect)(() => {
308
+ if (visible && providerKey && providerName) {
309
+ fetchPermissions(providerKey, providerName);
310
+ }
311
+ if (!visible) {
312
+ reset();
313
+ }
314
+ }, [visible, providerKey, providerName, fetchPermissions, reset]);
315
+ (0, import_react2.useEffect)(() => {
316
+ if (!selectAllCheckboxRef.current) return;
317
+ const allPermissions = groups.flatMap((g) => g.permissions);
318
+ const grantedCount = allPermissions.filter((p) => isGranted(p.name)).length;
319
+ if (grantedCount === 0) {
320
+ selectAllCheckboxRef.current.indeterminate = false;
321
+ } else if (grantedCount === allPermissions.length) {
322
+ selectAllCheckboxRef.current.indeterminate = false;
323
+ } else {
324
+ selectAllCheckboxRef.current.indeterminate = true;
325
+ }
326
+ }, [groups, isGranted]);
327
+ (0, import_react2.useEffect)(() => {
328
+ if (!selectThisTabCheckboxRef.current || !selectedGroup) return;
329
+ const groupPermissions = groups.find((g) => g.name === selectedGroup.name)?.permissions ?? [];
330
+ const grantedCount = groupPermissions.filter((p) => isGranted(p.name)).length;
331
+ if (grantedCount === 0) {
332
+ selectThisTabCheckboxRef.current.indeterminate = false;
333
+ } else if (grantedCount === groupPermissions.length) {
334
+ selectThisTabCheckboxRef.current.indeterminate = false;
335
+ } else {
336
+ selectThisTabCheckboxRef.current.indeterminate = true;
337
+ }
338
+ }, [selectedGroup, groups, isGranted]);
339
+ const handleSubmit = (0, import_react2.useCallback)(async () => {
340
+ const result = await savePermissions(providerKey, providerName);
341
+ if (result.success) {
342
+ onSave?.();
343
+ onVisibleChange?.(false);
344
+ }
345
+ }, [savePermissions, providerKey, providerName, onSave, onVisibleChange]);
346
+ const handleClose = (0, import_react2.useCallback)(() => {
347
+ onVisibleChange?.(false);
348
+ }, [onVisibleChange]);
349
+ const handlePermissionClick = (0, import_react2.useCallback)(
350
+ (permission) => {
351
+ togglePermission(permission);
352
+ },
353
+ [togglePermission]
354
+ );
355
+ const handleGroupClick = (0, import_react2.useCallback)(
356
+ (group) => {
357
+ setSelectedGroup(group);
358
+ },
359
+ [setSelectedGroup]
360
+ );
361
+ const selectedGroupPermissions = getSelectedGroupPermissions();
362
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
363
+ import_theme_shared.Modal,
364
+ {
365
+ visible,
366
+ onVisibleChange,
367
+ size: "xl",
368
+ header: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
369
+ t("AbpPermissionManagement::Permissions"),
370
+ entityDisplayName && ` - ${entityDisplayName}`
371
+ ] }),
372
+ footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_theme_shared.Button, { variant: "outline", onClick: handleClose, disabled: isLoading, children: t("AbpIdentity::Cancel") }),
374
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
375
+ import_theme_shared.Button,
376
+ {
377
+ colorPalette: "blue",
378
+ onClick: handleSubmit,
379
+ loading: isLoading,
380
+ children: t("AbpIdentity::Save")
381
+ }
382
+ )
383
+ ] }),
384
+ children: [
385
+ isLoading && groups.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Flex, { justify: "center", align: "center", py: 8, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Spinner, { size: "lg" }) }),
386
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_theme_shared.Alert, { status: "error", mb: 4, children: error }),
387
+ groups.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Box, { children: [
388
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
389
+ import_theme_shared.Checkbox,
390
+ {
391
+ ref: selectAllCheckboxRef,
392
+ id: "select-all-in-all-tabs",
393
+ checked: selectAllTab,
394
+ onChange: toggleSelectAll,
395
+ children: t("AbpPermissionManagement::SelectAllInAllTabs")
396
+ }
397
+ ),
398
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { borderBottomWidth: "1px", borderColor: "gray.200", my: 2 }),
399
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Flex, { gap: 4, children: [
400
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { w: "35%", maxH: "70vh", overflowY: "auto", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.VStack, { gap: 0, align: "stretch", children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
401
+ import_react3.Box,
402
+ {
403
+ px: 3,
404
+ py: 2,
405
+ cursor: "pointer",
406
+ bg: selectedGroup?.name === group.name ? "blue.500" : "transparent",
407
+ color: selectedGroup?.name === group.name ? "white" : "inherit",
408
+ borderRadius: "md",
409
+ _hover: {
410
+ bg: selectedGroup?.name === group.name ? "blue.600" : "gray.100"
411
+ },
412
+ onClick: () => handleGroupClick(group),
413
+ children: group.displayName
414
+ },
415
+ group.name
416
+ )) }) }),
417
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { w: "65%", children: selectedGroup && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Heading, { as: "h4", size: "md", mb: 2, children: selectedGroup.displayName }),
419
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { borderBottomWidth: "1px", borderColor: "gray.200", my: 2 }),
420
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Box, { pl: 1, pt: 1, children: [
421
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
422
+ import_theme_shared.Checkbox,
423
+ {
424
+ ref: selectThisTabCheckboxRef,
425
+ id: "select-all-in-this-tabs",
426
+ checked: selectThisTab,
427
+ onChange: toggleSelectThisTab,
428
+ children: t("AbpPermissionManagement::SelectAllInThisTab")
429
+ }
430
+ ),
431
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { borderBottomWidth: "1px", borderColor: "gray.200", my: 3 }),
432
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { maxH: "60vh", overflowY: "auto", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.VStack, { align: "stretch", gap: 2, children: selectedGroupPermissions.map((permission) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { ml: `${permission.margin}px`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
433
+ import_theme_shared.Checkbox,
434
+ {
435
+ id: permission.name,
436
+ checked: isGranted(permission.name),
437
+ onChange: () => handlePermissionClick(permission),
438
+ children: permission.displayName
439
+ }
440
+ ) }, permission.name)) }) })
441
+ ] })
442
+ ] }) })
443
+ ] })
444
+ ] })
445
+ ]
446
+ }
447
+ );
448
+ }
449
+ // Annotate the CommonJS export names for ESM import in node:
450
+ 0 && (module.exports = {
451
+ PermissionManagementModal,
452
+ PermissionManagementService,
453
+ usePermissionManagement
454
+ });