@carlonicora/nextjs-jsonapi 1.52.0 → 1.53.0
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/{AuthComponent-BkK4Sf3q.d.mts → AuthComponent-CK9aRRW2.d.mts} +1 -1
- package/dist/{AuthComponent-DCfP4o32.d.ts → AuthComponent-IqFWLNIU.d.ts} +1 -1
- package/dist/{BlockNoteEditor-KQPSJCYG.js → BlockNoteEditor-AROKR3J6.js} +14 -14
- package/dist/{BlockNoteEditor-KQPSJCYG.js.map → BlockNoteEditor-AROKR3J6.js.map} +1 -1
- package/dist/{BlockNoteEditor-WUVRCTQI.mjs → BlockNoteEditor-CNMSBGCL.mjs} +4 -4
- package/dist/ModulePathsInterface-49EWvbWy.d.mts +31 -0
- package/dist/ModulePathsInterface-wVS5Raa4.d.ts +31 -0
- package/dist/{auth.interface-C4kEZscm.d.ts → auth.interface-C1WjZ0fM.d.ts} +1 -1
- package/dist/{auth.interface-24ID4yhT.d.mts → auth.interface-fBFqIrw4.d.mts} +1 -1
- package/dist/billing/index.js +346 -346
- package/dist/billing/index.mjs +3 -3
- package/dist/{chunk-BUCV5VFT.mjs → chunk-FE26PIZK.mjs} +53 -2
- package/dist/chunk-FE26PIZK.mjs.map +1 -0
- package/dist/{chunk-BTLJZIDS.mjs → chunk-G5473JP3.mjs} +869 -40
- package/dist/chunk-G5473JP3.mjs.map +1 -0
- package/dist/{chunk-XNISXVQL.mjs → chunk-J2PYGXVD.mjs} +70 -1
- package/dist/chunk-J2PYGXVD.mjs.map +1 -0
- package/dist/{chunk-YKPIFJOB.js → chunk-PQIXFKHT.js} +1457 -628
- package/dist/chunk-PQIXFKHT.js.map +1 -0
- package/dist/{chunk-QIA5FOQB.js → chunk-QOLVON35.js} +71 -2
- package/dist/chunk-QOLVON35.js.map +1 -0
- package/dist/{chunk-V63TFESU.js → chunk-UJBUJALX.js} +53 -2
- package/dist/chunk-UJBUJALX.js.map +1 -0
- package/dist/client/index.d.mts +25 -7
- package/dist/client/index.d.ts +25 -7
- package/dist/client/index.js +10 -4
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +9 -3
- package/dist/components/index.d.mts +52 -10
- package/dist/components/index.d.ts +52 -10
- package/dist/components/index.js +16 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +15 -3
- package/dist/{config-CPN6QZfo.d.ts → config-DZWAFB7H.d.ts} +1 -1
- package/dist/{config-DaxjKdIo.d.mts → config-ndRJIQsP.d.mts} +1 -1
- package/dist/{content.interface-DvPs_JbX.d.mts → content.interface-B5ySfiOE.d.mts} +1 -1
- package/dist/{content.interface-Czin-YRh.d.ts → content.interface-mmz0uMwm.d.ts} +1 -1
- package/dist/contexts/index.d.mts +2 -2
- package/dist/contexts/index.d.ts +2 -2
- package/dist/contexts/index.js +4 -4
- package/dist/contexts/index.mjs +3 -3
- package/dist/core/index.d.mts +15 -10
- package/dist/core/index.d.ts +15 -10
- package/dist/core/index.js +6 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +5 -1
- package/dist/index.d.mts +47 -10
- package/dist/index.d.ts +47 -10
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -2
- package/dist/{notification.interface-DEW8hR8g.d.ts → notification.interface-COKHDQeE.d.ts} +1 -1
- package/dist/{notification.interface-DKR5WGKH.d.mts → notification.interface-DG7cq9oG.d.mts} +1 -1
- package/dist/{s3.service-BHjcTA0t.d.mts → s3.service-BoRPFx82.d.mts} +4 -4
- package/dist/{s3.service-C_K1VHyx.d.ts → s3.service-ppn9iGJU.d.ts} +4 -4
- package/dist/server/index.d.mts +4 -4
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +1 -1
- package/dist/useRbacState-DhuYYr0S.d.mts +77 -0
- package/dist/useRbacState-NnzNL2ED.d.ts +77 -0
- package/dist/{useSocket-BW6haECW.d.mts → useSocket-CtfuR5wD.d.mts} +1 -1
- package/dist/{useSocket-C9FmYuRM.d.ts → useSocket-bsV-K4qR.d.ts} +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +4 -0
- package/src/components/containers/RoundPageContainer.tsx +1 -1
- package/src/components/containers/RoundPageContainerTitle.tsx +1 -1
- package/src/components/index.ts +6 -0
- package/src/core/index.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +3 -0
- package/src/features/rbac/components/RbacContainer.tsx +82 -0
- package/src/features/rbac/components/RbacFeatureSection.tsx +66 -0
- package/src/features/rbac/components/RbacModuleTable.tsx +121 -0
- package/src/features/rbac/components/RbacPermissionCell.tsx +97 -0
- package/src/features/rbac/components/RbacPermissionPicker.tsx +179 -0
- package/src/features/rbac/components/RbacToolbar.tsx +40 -0
- package/src/features/rbac/data/ModulePaths.ts +25 -0
- package/src/features/rbac/data/ModulePathsInterface.ts +6 -0
- package/src/features/rbac/data/PermissionMapping.ts +43 -0
- package/src/features/rbac/data/PermissionMappingInterface.ts +12 -0
- package/src/features/rbac/data/RbacService.ts +47 -0
- package/src/features/rbac/data/RbacTypes.ts +15 -0
- package/src/features/rbac/data/index.ts +6 -0
- package/src/features/rbac/hooks/useRbacState.test.ts +178 -0
- package/src/features/rbac/hooks/useRbacState.ts +319 -0
- package/src/features/rbac/index.ts +19 -0
- package/src/features/rbac/rbac.module.ts +19 -0
- package/src/features/rbac/utils/RbacMigrationGenerator.test.ts +124 -0
- package/src/features/rbac/utils/RbacMigrationGenerator.ts +184 -0
- package/src/index.ts +4 -0
- package/dist/chunk-BTLJZIDS.mjs.map +0 -1
- package/dist/chunk-BUCV5VFT.mjs.map +0 -1
- package/dist/chunk-QIA5FOQB.js.map +0 -1
- package/dist/chunk-V63TFESU.js.map +0 -1
- package/dist/chunk-XNISXVQL.mjs.map +0 -1
- package/dist/chunk-YKPIFJOB.js.map +0 -1
- package/dist/useDataListRetriever-BqJSFBck.d.mts +0 -33
- package/dist/useDataListRetriever-BqJSFBck.d.ts +0 -33
- /package/dist/{BlockNoteEditor-WUVRCTQI.mjs.map → BlockNoteEditor-CNMSBGCL.mjs.map} +0 -0
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ACTION_TYPES,
|
|
3
|
+
COMPANY_ADMINISTRATOR_ROLE_ID,
|
|
4
|
+
RbacService,
|
|
2
5
|
getApiUrl,
|
|
3
6
|
getAppUrl,
|
|
4
7
|
getI18nLink,
|
|
@@ -18,7 +21,7 @@ import {
|
|
|
18
21
|
useI18nLocale,
|
|
19
22
|
useI18nRouter,
|
|
20
23
|
useI18nTranslations
|
|
21
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-FE26PIZK.mjs";
|
|
22
25
|
import {
|
|
23
26
|
AVAILABLE_OAUTH_SCOPES,
|
|
24
27
|
AuthService,
|
|
@@ -49,7 +52,7 @@ import {
|
|
|
49
52
|
showToast,
|
|
50
53
|
useComposedRefs,
|
|
51
54
|
useIsMobile
|
|
52
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-J2PYGXVD.mjs";
|
|
53
56
|
import {
|
|
54
57
|
JsonApiContext
|
|
55
58
|
} from "./chunk-VOXD3ZLY.mjs";
|
|
@@ -11873,7 +11876,7 @@ __name(AllowedUsersDetails, "AllowedUsersDetails");
|
|
|
11873
11876
|
import dynamic from "next/dynamic";
|
|
11874
11877
|
import React17 from "react";
|
|
11875
11878
|
import { jsx as jsx131 } from "react/jsx-runtime";
|
|
11876
|
-
var BlockNoteEditor = dynamic(() => import("./BlockNoteEditor-
|
|
11879
|
+
var BlockNoteEditor = dynamic(() => import("./BlockNoteEditor-CNMSBGCL.mjs"), {
|
|
11877
11880
|
ssr: false
|
|
11878
11881
|
});
|
|
11879
11882
|
var BlockNoteEditorContainer = React17.memo(/* @__PURE__ */ __name(function EditorContainer(props) {
|
|
@@ -13014,6 +13017,377 @@ function useOAuthConsent(params) {
|
|
|
13014
13017
|
}
|
|
13015
13018
|
__name(useOAuthConsent, "useOAuthConsent");
|
|
13016
13019
|
|
|
13020
|
+
// src/features/rbac/hooks/useRbacState.ts
|
|
13021
|
+
import { useCallback as useCallback22, useMemo as useMemo21, useReducer } from "react";
|
|
13022
|
+
function createInitialState() {
|
|
13023
|
+
return {
|
|
13024
|
+
original: null,
|
|
13025
|
+
featureIsCore: /* @__PURE__ */ new Map(),
|
|
13026
|
+
modulePermissions: /* @__PURE__ */ new Map(),
|
|
13027
|
+
rolePermissions: /* @__PURE__ */ new Map()
|
|
13028
|
+
};
|
|
13029
|
+
}
|
|
13030
|
+
__name(createInitialState, "createInitialState");
|
|
13031
|
+
function findModule(features, moduleId) {
|
|
13032
|
+
for (const feature of features) {
|
|
13033
|
+
for (const mod of feature.modules) {
|
|
13034
|
+
if (mod.id === moduleId) return mod;
|
|
13035
|
+
}
|
|
13036
|
+
}
|
|
13037
|
+
return void 0;
|
|
13038
|
+
}
|
|
13039
|
+
__name(findModule, "findModule");
|
|
13040
|
+
function findPermissionMapping(mappings, roleId, moduleId) {
|
|
13041
|
+
return mappings.find((pm) => pm.roleId === roleId && pm.moduleId === moduleId);
|
|
13042
|
+
}
|
|
13043
|
+
__name(findPermissionMapping, "findPermissionMapping");
|
|
13044
|
+
function rbacReducer(state, action) {
|
|
13045
|
+
switch (action.type) {
|
|
13046
|
+
case "INIT": {
|
|
13047
|
+
return {
|
|
13048
|
+
...createInitialState(),
|
|
13049
|
+
original: action.payload
|
|
13050
|
+
};
|
|
13051
|
+
}
|
|
13052
|
+
case "SET_FEATURE_IS_CORE": {
|
|
13053
|
+
const newMap = new Map(state.featureIsCore);
|
|
13054
|
+
const originalFeature = state.original?.features.find((f) => f.id === action.featureId);
|
|
13055
|
+
if (originalFeature && originalFeature.isCore === action.isCore) {
|
|
13056
|
+
newMap.delete(action.featureId);
|
|
13057
|
+
} else {
|
|
13058
|
+
newMap.set(action.featureId, action.isCore);
|
|
13059
|
+
}
|
|
13060
|
+
return { ...state, featureIsCore: newMap };
|
|
13061
|
+
}
|
|
13062
|
+
case "SET_MODULE_DEFAULT_PERMISSION": {
|
|
13063
|
+
const newMap = new Map(state.modulePermissions);
|
|
13064
|
+
const originalModule = state.original ? findModule(state.original.features, action.moduleId) : void 0;
|
|
13065
|
+
const current = newMap.get(action.moduleId) ?? { ...originalModule?.permissions };
|
|
13066
|
+
const updated = { ...current, [action.actionType]: action.value };
|
|
13067
|
+
newMap.set(action.moduleId, updated);
|
|
13068
|
+
return { ...state, modulePermissions: newMap };
|
|
13069
|
+
}
|
|
13070
|
+
case "SET_ROLE_PERMISSION": {
|
|
13071
|
+
const key = `${action.roleId}:${action.moduleId}`;
|
|
13072
|
+
const newMap = new Map(state.rolePermissions);
|
|
13073
|
+
const existing = newMap.get(key);
|
|
13074
|
+
if (existing === null) {
|
|
13075
|
+
newMap.set(key, { [action.actionType]: action.value });
|
|
13076
|
+
} else {
|
|
13077
|
+
const originalMapping = state.original ? findPermissionMapping(state.original.permissionMappings, action.roleId, action.moduleId) : void 0;
|
|
13078
|
+
const current = existing ?? (originalMapping ? { ...originalMapping.permissions } : {});
|
|
13079
|
+
newMap.set(key, { ...current, [action.actionType]: action.value });
|
|
13080
|
+
}
|
|
13081
|
+
return { ...state, rolePermissions: newMap };
|
|
13082
|
+
}
|
|
13083
|
+
case "CLEAR_ROLE_PERMISSION": {
|
|
13084
|
+
const key = `${action.roleId}:${action.moduleId}`;
|
|
13085
|
+
const newMap = new Map(state.rolePermissions);
|
|
13086
|
+
const existing = newMap.get(key);
|
|
13087
|
+
if (existing === null) return state;
|
|
13088
|
+
const originalMapping = state.original ? findPermissionMapping(state.original.permissionMappings, action.roleId, action.moduleId) : void 0;
|
|
13089
|
+
const current = existing ?? (originalMapping ? { ...originalMapping.permissions } : {});
|
|
13090
|
+
const updated = { ...current };
|
|
13091
|
+
delete updated[action.actionType];
|
|
13092
|
+
const hasAnyPermission = ACTION_TYPES.some((at) => updated[at] !== void 0);
|
|
13093
|
+
newMap.set(key, hasAnyPermission ? updated : null);
|
|
13094
|
+
return { ...state, rolePermissions: newMap };
|
|
13095
|
+
}
|
|
13096
|
+
case "CLEAR_ALL_ROLE_PERMISSIONS": {
|
|
13097
|
+
const key = `${action.roleId}:${action.moduleId}`;
|
|
13098
|
+
const newMap = new Map(state.rolePermissions);
|
|
13099
|
+
newMap.set(key, null);
|
|
13100
|
+
return { ...state, rolePermissions: newMap };
|
|
13101
|
+
}
|
|
13102
|
+
case "RESET":
|
|
13103
|
+
return {
|
|
13104
|
+
...createInitialState(),
|
|
13105
|
+
original: state.original
|
|
13106
|
+
};
|
|
13107
|
+
default:
|
|
13108
|
+
return state;
|
|
13109
|
+
}
|
|
13110
|
+
}
|
|
13111
|
+
__name(rbacReducer, "rbacReducer");
|
|
13112
|
+
function useRbacState() {
|
|
13113
|
+
const [state, dispatch] = useReducer(rbacReducer, void 0, createInitialState);
|
|
13114
|
+
const init = useCallback22(
|
|
13115
|
+
(features, roles, permissionMappings, modulePaths) => {
|
|
13116
|
+
const moduleRelationshipPaths = /* @__PURE__ */ new Map();
|
|
13117
|
+
for (const mp of modulePaths) {
|
|
13118
|
+
moduleRelationshipPaths.set(mp.moduleId, mp.paths);
|
|
13119
|
+
}
|
|
13120
|
+
dispatch({ type: "INIT", payload: { features, roles, permissionMappings, moduleRelationshipPaths } });
|
|
13121
|
+
},
|
|
13122
|
+
[]
|
|
13123
|
+
);
|
|
13124
|
+
const setFeatureIsCore = useCallback22((featureId, isCore) => {
|
|
13125
|
+
dispatch({ type: "SET_FEATURE_IS_CORE", featureId, isCore });
|
|
13126
|
+
}, []);
|
|
13127
|
+
const setModuleDefaultPermission = useCallback22((moduleId, actionType, value) => {
|
|
13128
|
+
dispatch({ type: "SET_MODULE_DEFAULT_PERMISSION", moduleId, actionType, value });
|
|
13129
|
+
}, []);
|
|
13130
|
+
const setRolePermission = useCallback22(
|
|
13131
|
+
(roleId, moduleId, actionType, value) => {
|
|
13132
|
+
dispatch({ type: "SET_ROLE_PERMISSION", roleId, moduleId, actionType, value });
|
|
13133
|
+
},
|
|
13134
|
+
[]
|
|
13135
|
+
);
|
|
13136
|
+
const clearRolePermission = useCallback22((roleId, moduleId, actionType) => {
|
|
13137
|
+
dispatch({ type: "CLEAR_ROLE_PERMISSION", roleId, moduleId, actionType });
|
|
13138
|
+
}, []);
|
|
13139
|
+
const clearAllRolePermissions = useCallback22((roleId, moduleId) => {
|
|
13140
|
+
dispatch({ type: "CLEAR_ALL_ROLE_PERMISSIONS", roleId, moduleId });
|
|
13141
|
+
}, []);
|
|
13142
|
+
const resetModulePermissions = useCallback22((moduleId, roles) => {
|
|
13143
|
+
for (const actionType of ACTION_TYPES) {
|
|
13144
|
+
dispatch({ type: "SET_MODULE_DEFAULT_PERMISSION", moduleId, actionType, value: true });
|
|
13145
|
+
}
|
|
13146
|
+
for (const role of roles) {
|
|
13147
|
+
dispatch({ type: "CLEAR_ALL_ROLE_PERMISSIONS", roleId: role.id, moduleId });
|
|
13148
|
+
}
|
|
13149
|
+
}, []);
|
|
13150
|
+
const reset = useCallback22(() => {
|
|
13151
|
+
dispatch({ type: "RESET" });
|
|
13152
|
+
}, []);
|
|
13153
|
+
const getFeatureIsCore = useCallback22(
|
|
13154
|
+
(featureId) => {
|
|
13155
|
+
if (state.featureIsCore.has(featureId)) return state.featureIsCore.get(featureId);
|
|
13156
|
+
const feature = state.original?.features.find((f) => f.id === featureId);
|
|
13157
|
+
return feature?.isCore ?? false;
|
|
13158
|
+
},
|
|
13159
|
+
[state.featureIsCore, state.original]
|
|
13160
|
+
);
|
|
13161
|
+
const getModuleDefaultPermission = useCallback22(
|
|
13162
|
+
(moduleId, actionType) => {
|
|
13163
|
+
const edited = state.modulePermissions.get(moduleId);
|
|
13164
|
+
if (edited && edited[actionType] !== void 0) return edited[actionType];
|
|
13165
|
+
if (!state.original) return void 0;
|
|
13166
|
+
const mod = findModule(state.original.features, moduleId);
|
|
13167
|
+
return mod?.permissions[actionType];
|
|
13168
|
+
},
|
|
13169
|
+
[state.modulePermissions, state.original]
|
|
13170
|
+
);
|
|
13171
|
+
const getRolePermission = useCallback22(
|
|
13172
|
+
(roleId, moduleId, actionType) => {
|
|
13173
|
+
const key = `${roleId}:${moduleId}`;
|
|
13174
|
+
if (state.rolePermissions.has(key)) {
|
|
13175
|
+
const perms = state.rolePermissions.get(key);
|
|
13176
|
+
if (perms === null || perms === void 0) return null;
|
|
13177
|
+
return perms[actionType] ?? null;
|
|
13178
|
+
}
|
|
13179
|
+
if (!state.original) return void 0;
|
|
13180
|
+
const mapping = findPermissionMapping(state.original.permissionMappings, roleId, moduleId);
|
|
13181
|
+
if (!mapping) return void 0;
|
|
13182
|
+
return mapping.permissions[actionType] ?? null;
|
|
13183
|
+
},
|
|
13184
|
+
[state.rolePermissions, state.original]
|
|
13185
|
+
);
|
|
13186
|
+
const isDirty = useMemo21(() => {
|
|
13187
|
+
return state.featureIsCore.size > 0 || state.modulePermissions.size > 0 || state.rolePermissions.size > 0;
|
|
13188
|
+
}, [state.featureIsCore, state.modulePermissions, state.rolePermissions]);
|
|
13189
|
+
const getEffectiveConfiguration = useCallback22(() => {
|
|
13190
|
+
if (!state.original) return null;
|
|
13191
|
+
const features = state.original.features.map((f) => ({
|
|
13192
|
+
id: f.id,
|
|
13193
|
+
name: f.name,
|
|
13194
|
+
isCore: state.featureIsCore.has(f.id) ? state.featureIsCore.get(f.id) : f.isCore,
|
|
13195
|
+
modules: f.modules.map((m) => {
|
|
13196
|
+
const editedPerms = state.modulePermissions.get(m.id);
|
|
13197
|
+
return {
|
|
13198
|
+
id: m.id,
|
|
13199
|
+
name: m.name,
|
|
13200
|
+
permissions: editedPerms ?? m.permissions
|
|
13201
|
+
};
|
|
13202
|
+
})
|
|
13203
|
+
}));
|
|
13204
|
+
const rolePermissionsMap = /* @__PURE__ */ new Map();
|
|
13205
|
+
for (const pm of state.original.permissionMappings) {
|
|
13206
|
+
rolePermissionsMap.set(`${pm.roleId}:${pm.moduleId}`, { ...pm.permissions });
|
|
13207
|
+
}
|
|
13208
|
+
for (const [key, perms] of state.rolePermissions) {
|
|
13209
|
+
if (perms === null) {
|
|
13210
|
+
rolePermissionsMap.delete(key);
|
|
13211
|
+
} else {
|
|
13212
|
+
rolePermissionsMap.set(key, perms);
|
|
13213
|
+
}
|
|
13214
|
+
}
|
|
13215
|
+
return {
|
|
13216
|
+
features,
|
|
13217
|
+
roles: state.original.roles,
|
|
13218
|
+
rolePermissionsMap
|
|
13219
|
+
};
|
|
13220
|
+
}, [state]);
|
|
13221
|
+
const getModuleRelationshipPaths = useCallback22(
|
|
13222
|
+
(moduleId) => {
|
|
13223
|
+
return state.original?.moduleRelationshipPaths.get(moduleId) ?? [];
|
|
13224
|
+
},
|
|
13225
|
+
[state.original]
|
|
13226
|
+
);
|
|
13227
|
+
return {
|
|
13228
|
+
original: state.original,
|
|
13229
|
+
isDirty,
|
|
13230
|
+
init,
|
|
13231
|
+
setFeatureIsCore,
|
|
13232
|
+
setModuleDefaultPermission,
|
|
13233
|
+
setRolePermission,
|
|
13234
|
+
clearRolePermission,
|
|
13235
|
+
clearAllRolePermissions,
|
|
13236
|
+
resetModulePermissions,
|
|
13237
|
+
reset,
|
|
13238
|
+
getFeatureIsCore,
|
|
13239
|
+
getModuleDefaultPermission,
|
|
13240
|
+
getRolePermission,
|
|
13241
|
+
getEffectiveConfiguration,
|
|
13242
|
+
getModuleRelationshipPaths
|
|
13243
|
+
};
|
|
13244
|
+
}
|
|
13245
|
+
__name(useRbacState, "useRbacState");
|
|
13246
|
+
|
|
13247
|
+
// src/features/rbac/utils/RbacMigrationGenerator.ts
|
|
13248
|
+
var ACTION_ENUM_MAP = {
|
|
13249
|
+
read: "Action.Read",
|
|
13250
|
+
create: "Action.Create",
|
|
13251
|
+
update: "Action.Update",
|
|
13252
|
+
delete: "Action.Delete"
|
|
13253
|
+
};
|
|
13254
|
+
function formatPermissionValue(value) {
|
|
13255
|
+
if (value === true) return "true";
|
|
13256
|
+
if (value === false) return "false";
|
|
13257
|
+
return `"${value}"`;
|
|
13258
|
+
}
|
|
13259
|
+
__name(formatPermissionValue, "formatPermissionValue");
|
|
13260
|
+
function formatPermissionsFromMap(perms) {
|
|
13261
|
+
const entries = [];
|
|
13262
|
+
for (const actionType of ACTION_TYPES) {
|
|
13263
|
+
const value = perms[actionType];
|
|
13264
|
+
if (value !== void 0) {
|
|
13265
|
+
entries.push(`{ type: ${ACTION_ENUM_MAP[actionType]}, value: ${formatPermissionValue(value)} }`);
|
|
13266
|
+
}
|
|
13267
|
+
}
|
|
13268
|
+
if (entries.length === 0) return "[]";
|
|
13269
|
+
if (entries.length === 1) return `[${entries[0]}]`;
|
|
13270
|
+
return `[
|
|
13271
|
+
${entries.join(",\n ")},
|
|
13272
|
+
]`;
|
|
13273
|
+
}
|
|
13274
|
+
__name(formatPermissionsFromMap, "formatPermissionsFromMap");
|
|
13275
|
+
function generateMigrationFile(params) {
|
|
13276
|
+
const { features, roles, rolePermissionsMap } = params;
|
|
13277
|
+
const lines = [];
|
|
13278
|
+
lines.push(`/**`);
|
|
13279
|
+
lines.push(` * RBAC Migration - Generated on ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
|
|
13280
|
+
lines.push(` * Contains features, modules, roles, and permission mappings.`);
|
|
13281
|
+
lines.push(` */`);
|
|
13282
|
+
lines.push(``);
|
|
13283
|
+
lines.push(`import { Action } from "src/common/enums/action";`);
|
|
13284
|
+
lines.push(`import { MigrationInterface } from "src/core/migrator/interfaces/migration.interface";`);
|
|
13285
|
+
lines.push(
|
|
13286
|
+
`import { featureQuery, moduleQuery, roleQuery, permissionQuery } from "src/neo4j.migrations/queries/migration.queries";`
|
|
13287
|
+
);
|
|
13288
|
+
lines.push(``);
|
|
13289
|
+
lines.push(`export const migration: MigrationInterface[] = [`);
|
|
13290
|
+
lines.push(` /* ************************************ */`);
|
|
13291
|
+
lines.push(` /* FEATURES */`);
|
|
13292
|
+
lines.push(` /* ************************************ */`);
|
|
13293
|
+
for (const feature of features) {
|
|
13294
|
+
lines.push(` {`);
|
|
13295
|
+
lines.push(` query: featureQuery,`);
|
|
13296
|
+
lines.push(` queryParams: {`);
|
|
13297
|
+
lines.push(` featureId: "${feature.id}",`);
|
|
13298
|
+
lines.push(` featureName: "${feature.name}",`);
|
|
13299
|
+
lines.push(` isCore: ${feature.isCore},`);
|
|
13300
|
+
lines.push(` },`);
|
|
13301
|
+
lines.push(` },`);
|
|
13302
|
+
}
|
|
13303
|
+
for (const feature of features) {
|
|
13304
|
+
if (feature.modules.length === 0) continue;
|
|
13305
|
+
lines.push(` /* ************************************ */`);
|
|
13306
|
+
lines.push(` /* ${feature.name.toUpperCase().padEnd(37)} */`);
|
|
13307
|
+
lines.push(` /* ************************************ */`);
|
|
13308
|
+
for (const mod of feature.modules) {
|
|
13309
|
+
lines.push(` {`);
|
|
13310
|
+
lines.push(` query: moduleQuery,`);
|
|
13311
|
+
lines.push(` queryParams: {`);
|
|
13312
|
+
lines.push(` moduleName: "${mod.name}",`);
|
|
13313
|
+
lines.push(` moduleId: "${mod.id}",`);
|
|
13314
|
+
lines.push(` featureId: "${feature.id}",`);
|
|
13315
|
+
lines.push(` permissions: JSON.stringify(${formatPermissionsFromMap(mod.permissions)}),`);
|
|
13316
|
+
lines.push(` },`);
|
|
13317
|
+
lines.push(` },`);
|
|
13318
|
+
}
|
|
13319
|
+
}
|
|
13320
|
+
lines.push(` /* ************************************ */`);
|
|
13321
|
+
lines.push(` /* ROLES */`);
|
|
13322
|
+
lines.push(` /* ************************************ */`);
|
|
13323
|
+
for (const role of roles) {
|
|
13324
|
+
lines.push(` {`);
|
|
13325
|
+
lines.push(` query: roleQuery,`);
|
|
13326
|
+
lines.push(` queryParams: {`);
|
|
13327
|
+
lines.push(` roleId: "${role.id}",`);
|
|
13328
|
+
lines.push(` roleName: "${role.name}",`);
|
|
13329
|
+
lines.push(` isSelectable: ${role.isSelectable},`);
|
|
13330
|
+
lines.push(` },`);
|
|
13331
|
+
lines.push(` },`);
|
|
13332
|
+
}
|
|
13333
|
+
lines.push(` /* ************************************ */`);
|
|
13334
|
+
lines.push(` /* PERMISSIONS */`);
|
|
13335
|
+
lines.push(` /* ************************************ */`);
|
|
13336
|
+
const allModuleIds = [];
|
|
13337
|
+
for (const feature of features) {
|
|
13338
|
+
for (const mod of feature.modules) {
|
|
13339
|
+
allModuleIds.push(mod.id);
|
|
13340
|
+
}
|
|
13341
|
+
}
|
|
13342
|
+
const allTruePermissions = { read: true, create: true, update: true, delete: true };
|
|
13343
|
+
const permsByRole = /* @__PURE__ */ new Map();
|
|
13344
|
+
permsByRole.set(
|
|
13345
|
+
COMPANY_ADMINISTRATOR_ROLE_ID,
|
|
13346
|
+
allModuleIds.map((moduleId) => ({ moduleId, permissions: allTruePermissions }))
|
|
13347
|
+
);
|
|
13348
|
+
for (const [key, perms] of rolePermissionsMap) {
|
|
13349
|
+
const [roleId, moduleId] = key.split(":");
|
|
13350
|
+
if (roleId === COMPANY_ADMINISTRATOR_ROLE_ID) continue;
|
|
13351
|
+
if (!permsByRole.has(roleId)) permsByRole.set(roleId, []);
|
|
13352
|
+
permsByRole.get(roleId).push({ moduleId, permissions: perms });
|
|
13353
|
+
}
|
|
13354
|
+
for (const [roleId, moduleMappings] of permsByRole) {
|
|
13355
|
+
const role = roles.find((r) => r.id === roleId);
|
|
13356
|
+
if (role) {
|
|
13357
|
+
lines.push(` // ${role.name}`);
|
|
13358
|
+
}
|
|
13359
|
+
for (const mapping of moduleMappings) {
|
|
13360
|
+
lines.push(` {`);
|
|
13361
|
+
lines.push(` query: permissionQuery,`);
|
|
13362
|
+
lines.push(` queryParams: {`);
|
|
13363
|
+
lines.push(` roleId: "${roleId}",`);
|
|
13364
|
+
lines.push(` moduleId: "${mapping.moduleId}",`);
|
|
13365
|
+
lines.push(` permissions: JSON.stringify(${formatPermissionsFromMap(mapping.permissions)}),`);
|
|
13366
|
+
lines.push(` },`);
|
|
13367
|
+
lines.push(` },`);
|
|
13368
|
+
}
|
|
13369
|
+
}
|
|
13370
|
+
lines.push(`];`);
|
|
13371
|
+
lines.push(``);
|
|
13372
|
+
return lines.join("\n");
|
|
13373
|
+
}
|
|
13374
|
+
__name(generateMigrationFile, "generateMigrationFile");
|
|
13375
|
+
function downloadMigrationFile(content) {
|
|
13376
|
+
const now = /* @__PURE__ */ new Date();
|
|
13377
|
+
const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}`;
|
|
13378
|
+
const filename = `${dateStr}_001.ts`;
|
|
13379
|
+
const blob = new Blob([content], { type: "text/plain" });
|
|
13380
|
+
const url = URL.createObjectURL(blob);
|
|
13381
|
+
const a = document.createElement("a");
|
|
13382
|
+
a.href = url;
|
|
13383
|
+
a.download = filename;
|
|
13384
|
+
document.body.appendChild(a);
|
|
13385
|
+
a.click();
|
|
13386
|
+
document.body.removeChild(a);
|
|
13387
|
+
URL.revokeObjectURL(url);
|
|
13388
|
+
}
|
|
13389
|
+
__name(downloadMigrationFile, "downloadMigrationFile");
|
|
13390
|
+
|
|
13017
13391
|
// src/client/index.ts
|
|
13018
13392
|
registerTableGenerator("roles", useRoleTableStructure);
|
|
13019
13393
|
registerTableGenerator("users", useUserTableStructure);
|
|
@@ -13022,12 +13396,12 @@ registerTableGenerator("companies", useCompanyTableStructure);
|
|
|
13022
13396
|
// src/components/tables/ContentListTable.tsx
|
|
13023
13397
|
import { flexRender, getCoreRowModel, getExpandedRowModel, useReactTable } from "@tanstack/react-table";
|
|
13024
13398
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
13025
|
-
import { memo, useMemo as
|
|
13399
|
+
import { memo, useMemo as useMemo22, useState as useState48 } from "react";
|
|
13026
13400
|
|
|
13027
13401
|
// src/components/tables/ContentTableSearch.tsx
|
|
13028
13402
|
import { RefreshCw, Search, X as X3 } from "lucide-react";
|
|
13029
13403
|
import { useTranslations as useTranslations47 } from "next-intl";
|
|
13030
|
-
import { useCallback as
|
|
13404
|
+
import { useCallback as useCallback23, useEffect as useEffect41, useRef as useRef21, useState as useState47 } from "react";
|
|
13031
13405
|
import { jsx as jsx143, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
13032
13406
|
function ContentTableSearch({ data }) {
|
|
13033
13407
|
const t = useTranslations47();
|
|
@@ -13037,7 +13411,7 @@ function ContentTableSearch({ data }) {
|
|
|
13037
13411
|
const [isFocused, setIsFocused] = useState47(false);
|
|
13038
13412
|
const [isSearching, setIsSearching] = useState47(false);
|
|
13039
13413
|
const isExpanded = isFocused || searchTerm.length > 0;
|
|
13040
|
-
const search =
|
|
13414
|
+
const search = useCallback23(
|
|
13041
13415
|
async (searchedTerm) => {
|
|
13042
13416
|
try {
|
|
13043
13417
|
if (searchedTerm === searchTermRef.current) return;
|
|
@@ -13130,7 +13504,7 @@ var ContentListTable = memo(/* @__PURE__ */ __name(function ContentListTable2(pr
|
|
|
13130
13504
|
dataRetriever: data,
|
|
13131
13505
|
context: props.context
|
|
13132
13506
|
});
|
|
13133
|
-
const columnVisibility =
|
|
13507
|
+
const columnVisibility = useMemo22(
|
|
13134
13508
|
() => fields.reduce(
|
|
13135
13509
|
(acc, columnId) => {
|
|
13136
13510
|
acc[columnId] = true;
|
|
@@ -13211,7 +13585,7 @@ var ContentListTable = memo(/* @__PURE__ */ __name(function ContentListTable2(pr
|
|
|
13211
13585
|
import Image9 from "next/image";
|
|
13212
13586
|
|
|
13213
13587
|
// src/features/auth/contexts/AuthContext.tsx
|
|
13214
|
-
import { createContext as createContext16, useContext as useContext17, useMemo as
|
|
13588
|
+
import { createContext as createContext16, useContext as useContext17, useMemo as useMemo23, useState as useState50 } from "react";
|
|
13215
13589
|
|
|
13216
13590
|
// src/features/auth/components/forms/Register.tsx
|
|
13217
13591
|
import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
|
|
@@ -13570,7 +13944,7 @@ var AuthContextProvider = /* @__PURE__ */ __name(({
|
|
|
13570
13944
|
const [componentType, setComponentType] = useState50(initialComponentType);
|
|
13571
13945
|
const [params, setParams] = useState50(initialParams);
|
|
13572
13946
|
const [pendingTwoFactor, setPendingTwoFactor] = useState50();
|
|
13573
|
-
const activeComponent =
|
|
13947
|
+
const activeComponent = useMemo23(() => {
|
|
13574
13948
|
if (componentType === void 0) return null;
|
|
13575
13949
|
switch (componentType) {
|
|
13576
13950
|
case 0 /* Login */:
|
|
@@ -13631,7 +14005,7 @@ __name(InnerAuthContainer, "InnerAuthContainer");
|
|
|
13631
14005
|
// src/features/auth/components/two-factor/TwoFactorSettings.tsx
|
|
13632
14006
|
import { ShieldAlert, ShieldCheck } from "lucide-react";
|
|
13633
14007
|
import { useTranslations as useTranslations56 } from "next-intl";
|
|
13634
|
-
import { useCallback as
|
|
14008
|
+
import { useCallback as useCallback24, useEffect as useEffect44, useState as useState58 } from "react";
|
|
13635
14009
|
import { v4 as v47 } from "uuid";
|
|
13636
14010
|
|
|
13637
14011
|
// src/features/auth/components/two-factor/BackupCodesDialog.tsx
|
|
@@ -14235,7 +14609,7 @@ function TwoFactorSettings() {
|
|
|
14235
14609
|
const [isLoading, setIsLoading] = useState58(true);
|
|
14236
14610
|
const [isEnabling, setIsEnabling] = useState58(false);
|
|
14237
14611
|
const [passkeyDialogOpen, setPasskeyDialogOpen] = useState58(false);
|
|
14238
|
-
const loadStatus =
|
|
14612
|
+
const loadStatus = useCallback24(async () => {
|
|
14239
14613
|
try {
|
|
14240
14614
|
const [statusData, authenticatorsList, passkeysList] = await Promise.all([
|
|
14241
14615
|
TwoFactorService.getStatus(),
|
|
@@ -15365,7 +15739,7 @@ __name(NotificationsListContainer, "NotificationsListContainer");
|
|
|
15365
15739
|
// src/features/notification/components/modals/NotificationModal.tsx
|
|
15366
15740
|
import { BellIcon } from "lucide-react";
|
|
15367
15741
|
import { useTranslations as useTranslations70 } from "next-intl";
|
|
15368
|
-
import { Fragment as Fragment35, useCallback as
|
|
15742
|
+
import { Fragment as Fragment35, useCallback as useCallback25, useEffect as useEffect52, useMemo as useMemo24, useRef as useRef23, useState as useState67 } from "react";
|
|
15369
15743
|
import { jsx as jsx174, jsxs as jsxs107 } from "react/jsx-runtime";
|
|
15370
15744
|
function NotificationModalContent({ isOpen, setIsOpen }) {
|
|
15371
15745
|
const _instanceId = useRef23(Math.random().toString(36).substr(2, 9));
|
|
@@ -15395,7 +15769,7 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
|
|
|
15395
15769
|
resetTime: 0,
|
|
15396
15770
|
isOpen: false
|
|
15397
15771
|
});
|
|
15398
|
-
const checkCircuitBreaker =
|
|
15772
|
+
const checkCircuitBreaker = useCallback25(() => {
|
|
15399
15773
|
const now = Date.now();
|
|
15400
15774
|
const breaker = circuitBreakerRef.current;
|
|
15401
15775
|
if (now > breaker.resetTime) {
|
|
@@ -15410,7 +15784,7 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
|
|
|
15410
15784
|
}
|
|
15411
15785
|
return !breaker.isOpen;
|
|
15412
15786
|
}, []);
|
|
15413
|
-
const { unreadCount, unreadIds } =
|
|
15787
|
+
const { unreadCount, unreadIds } = useMemo24(() => {
|
|
15414
15788
|
const unreadNotifications2 = notifications.filter((notif) => !notif.isRead);
|
|
15415
15789
|
return {
|
|
15416
15790
|
unreadCount: unreadNotifications2.length,
|
|
@@ -15424,7 +15798,7 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
|
|
|
15424
15798
|
if (lastLoaded === 0) loadNotifications();
|
|
15425
15799
|
}, [lastLoaded, loadNotifications]);
|
|
15426
15800
|
const processSocketNotificationsRef = useRef23(null);
|
|
15427
|
-
const processSocketNotifications =
|
|
15801
|
+
const processSocketNotifications = useCallback25(() => {
|
|
15428
15802
|
if (socketNotifications.length === 0) {
|
|
15429
15803
|
return;
|
|
15430
15804
|
}
|
|
@@ -15584,7 +15958,7 @@ __name(ReferralCodeCapture, "ReferralCodeCapture");
|
|
|
15584
15958
|
|
|
15585
15959
|
// src/features/referral/components/ReferralWidget.tsx
|
|
15586
15960
|
import { Copy as Copy2, Loader2 as Loader25, Mail, Users } from "lucide-react";
|
|
15587
|
-
import { useCallback as
|
|
15961
|
+
import { useCallback as useCallback26, useRef as useRef24, useState as useState70 } from "react";
|
|
15588
15962
|
|
|
15589
15963
|
// src/features/referral/hooks/useReferralInvite.ts
|
|
15590
15964
|
import { useState as useState68 } from "react";
|
|
@@ -15697,7 +16071,7 @@ function ReferralWidget({
|
|
|
15697
16071
|
if (!isReferralEnabled()) {
|
|
15698
16072
|
return null;
|
|
15699
16073
|
}
|
|
15700
|
-
const handleCopyLink =
|
|
16074
|
+
const handleCopyLink = useCallback26(async () => {
|
|
15701
16075
|
if (!referralUrl) return;
|
|
15702
16076
|
const success = await copyToClipboard(referralUrl);
|
|
15703
16077
|
if (success) {
|
|
@@ -15709,7 +16083,7 @@ function ReferralWidget({
|
|
|
15709
16083
|
showError(t.copyError);
|
|
15710
16084
|
}
|
|
15711
16085
|
}, [referralUrl, t.copiedMessage, t.copyError, onLinkCopied]);
|
|
15712
|
-
const handleSendInvite =
|
|
16086
|
+
const handleSendInvite = useCallback26(async () => {
|
|
15713
16087
|
if (!email || !email.includes("@")) {
|
|
15714
16088
|
showError(t.invalidEmail);
|
|
15715
16089
|
return;
|
|
@@ -15725,7 +16099,7 @@ function ReferralWidget({
|
|
|
15725
16099
|
onInviteError?.(error2);
|
|
15726
16100
|
}
|
|
15727
16101
|
}, [email, sendInvite, t.inviteSent, t.inviteError, t.invalidEmail, onInviteSent, onInviteError]);
|
|
15728
|
-
const handleEmailKeyDown =
|
|
16102
|
+
const handleEmailKeyDown = useCallback26(
|
|
15729
16103
|
(e) => {
|
|
15730
16104
|
if (e.key === "Enter" && !sending) {
|
|
15731
16105
|
e.preventDefault();
|
|
@@ -15977,7 +16351,7 @@ __name(RemoveUserFromRole, "RemoveUserFromRole");
|
|
|
15977
16351
|
// src/features/role/components/forms/UserRoleAdd.tsx
|
|
15978
16352
|
import { PlusCircle as PlusCircle2 } from "lucide-react";
|
|
15979
16353
|
import { useTranslations as useTranslations74 } from "next-intl";
|
|
15980
|
-
import { useCallback as
|
|
16354
|
+
import { useCallback as useCallback27, useEffect as useEffect56, useRef as useRef25, useState as useState72 } from "react";
|
|
15981
16355
|
import { Fragment as Fragment39, jsx as jsx182, jsxs as jsxs113 } from "react/jsx-runtime";
|
|
15982
16356
|
function UserRoleAdd({ user, refresh }) {
|
|
15983
16357
|
const [open, setOpen] = useState72(false);
|
|
@@ -16007,7 +16381,7 @@ function UserRoleAdd({ user, refresh }) {
|
|
|
16007
16381
|
);
|
|
16008
16382
|
refresh();
|
|
16009
16383
|
}, "addUserToRole");
|
|
16010
|
-
const searchRoles =
|
|
16384
|
+
const searchRoles = useCallback27(
|
|
16011
16385
|
async (term) => {
|
|
16012
16386
|
setRoles(
|
|
16013
16387
|
await RoleService.findAllRolesUserNotIn({
|
|
@@ -16117,7 +16491,7 @@ function UserRolesList({ user }) {
|
|
|
16117
16491
|
__name(UserRolesList, "UserRolesList");
|
|
16118
16492
|
|
|
16119
16493
|
// src/features/oauth/components/OAuthRedirectUriInput.tsx
|
|
16120
|
-
import { useCallback as
|
|
16494
|
+
import { useCallback as useCallback28 } from "react";
|
|
16121
16495
|
import { Plus, Trash2 as Trash23 } from "lucide-react";
|
|
16122
16496
|
import { jsx as jsx185, jsxs as jsxs114 } from "react/jsx-runtime";
|
|
16123
16497
|
function isValidRedirectUri(uri) {
|
|
@@ -16147,17 +16521,17 @@ function OAuthRedirectUriInput({
|
|
|
16147
16521
|
disabled = false,
|
|
16148
16522
|
label = "Redirect URIs"
|
|
16149
16523
|
}) {
|
|
16150
|
-
const handleAdd =
|
|
16524
|
+
const handleAdd = useCallback28(() => {
|
|
16151
16525
|
onChange([...value, ""]);
|
|
16152
16526
|
}, [value, onChange]);
|
|
16153
|
-
const handleRemove =
|
|
16527
|
+
const handleRemove = useCallback28(
|
|
16154
16528
|
(index) => {
|
|
16155
16529
|
const newUris = value.filter((_, i) => i !== index);
|
|
16156
16530
|
onChange(newUris.length > 0 ? newUris : [""]);
|
|
16157
16531
|
},
|
|
16158
16532
|
[value, onChange]
|
|
16159
16533
|
);
|
|
16160
|
-
const handleChange =
|
|
16534
|
+
const handleChange = useCallback28(
|
|
16161
16535
|
(index, newValue) => {
|
|
16162
16536
|
const newUris = [...value];
|
|
16163
16537
|
newUris[index] = newValue;
|
|
@@ -16211,7 +16585,7 @@ function OAuthRedirectUriInput({
|
|
|
16211
16585
|
__name(OAuthRedirectUriInput, "OAuthRedirectUriInput");
|
|
16212
16586
|
|
|
16213
16587
|
// src/features/oauth/components/OAuthScopeSelector.tsx
|
|
16214
|
-
import { useCallback as
|
|
16588
|
+
import { useCallback as useCallback29 } from "react";
|
|
16215
16589
|
import { jsx as jsx186, jsxs as jsxs115 } from "react/jsx-runtime";
|
|
16216
16590
|
function OAuthScopeSelector({
|
|
16217
16591
|
value,
|
|
@@ -16221,7 +16595,7 @@ function OAuthScopeSelector({
|
|
|
16221
16595
|
error,
|
|
16222
16596
|
label = "Allowed Scopes"
|
|
16223
16597
|
}) {
|
|
16224
|
-
const handleToggle =
|
|
16598
|
+
const handleToggle = useCallback29(
|
|
16225
16599
|
(scope, checked) => {
|
|
16226
16600
|
if (checked) {
|
|
16227
16601
|
onChange([...value, scope]);
|
|
@@ -16289,12 +16663,12 @@ function OAuthScopeSelector({
|
|
|
16289
16663
|
__name(OAuthScopeSelector, "OAuthScopeSelector");
|
|
16290
16664
|
|
|
16291
16665
|
// src/features/oauth/components/OAuthClientSecretDisplay.tsx
|
|
16292
|
-
import { useState as useState73, useCallback as
|
|
16666
|
+
import { useState as useState73, useCallback as useCallback30 } from "react";
|
|
16293
16667
|
import { Copy as Copy3, Check, AlertTriangle } from "lucide-react";
|
|
16294
16668
|
import { jsx as jsx187, jsxs as jsxs116 } from "react/jsx-runtime";
|
|
16295
16669
|
function OAuthClientSecretDisplay({ secret, onDismiss, open, clientName }) {
|
|
16296
16670
|
const [copied, setCopied] = useState73(false);
|
|
16297
|
-
const handleCopy =
|
|
16671
|
+
const handleCopy = useCallback30(async () => {
|
|
16298
16672
|
try {
|
|
16299
16673
|
await navigator.clipboard.writeText(secret);
|
|
16300
16674
|
setCopied(true);
|
|
@@ -16303,7 +16677,7 @@ function OAuthClientSecretDisplay({ secret, onDismiss, open, clientName }) {
|
|
|
16303
16677
|
console.error("Failed to copy to clipboard:", err);
|
|
16304
16678
|
}
|
|
16305
16679
|
}, [secret]);
|
|
16306
|
-
const handleDismiss =
|
|
16680
|
+
const handleDismiss = useCallback30(() => {
|
|
16307
16681
|
setCopied(false);
|
|
16308
16682
|
onDismiss();
|
|
16309
16683
|
}, [onDismiss]);
|
|
@@ -16486,7 +16860,7 @@ function OAuthClientList({
|
|
|
16486
16860
|
__name(OAuthClientList, "OAuthClientList");
|
|
16487
16861
|
|
|
16488
16862
|
// src/features/oauth/components/OAuthClientForm.tsx
|
|
16489
|
-
import { useState as useState74, useCallback as
|
|
16863
|
+
import { useState as useState74, useCallback as useCallback31 } from "react";
|
|
16490
16864
|
import { jsx as jsx190, jsxs as jsxs119 } from "react/jsx-runtime";
|
|
16491
16865
|
function OAuthClientForm({ client, onSubmit, onCancel, isLoading = false }) {
|
|
16492
16866
|
const isEditMode = !!client;
|
|
@@ -16498,7 +16872,7 @@ function OAuthClientForm({ client, onSubmit, onCancel, isLoading = false }) {
|
|
|
16498
16872
|
isConfidential: client?.isConfidential ?? true
|
|
16499
16873
|
});
|
|
16500
16874
|
const [errors, setErrors] = useState74({});
|
|
16501
|
-
const validate =
|
|
16875
|
+
const validate = useCallback31(() => {
|
|
16502
16876
|
const newErrors = {};
|
|
16503
16877
|
if (!formState.name.trim()) {
|
|
16504
16878
|
newErrors.name = "Application name is required";
|
|
@@ -16513,7 +16887,7 @@ function OAuthClientForm({ client, onSubmit, onCancel, isLoading = false }) {
|
|
|
16513
16887
|
setErrors(newErrors);
|
|
16514
16888
|
return Object.keys(newErrors).length === 0;
|
|
16515
16889
|
}, [formState]);
|
|
16516
|
-
const handleSubmit =
|
|
16890
|
+
const handleSubmit = useCallback31(
|
|
16517
16891
|
async (e) => {
|
|
16518
16892
|
e.preventDefault();
|
|
16519
16893
|
if (!validate()) return;
|
|
@@ -16620,7 +16994,7 @@ function OAuthClientForm({ client, onSubmit, onCancel, isLoading = false }) {
|
|
|
16620
16994
|
__name(OAuthClientForm, "OAuthClientForm");
|
|
16621
16995
|
|
|
16622
16996
|
// src/features/oauth/components/OAuthClientDetail.tsx
|
|
16623
|
-
import { useState as useState75, useCallback as
|
|
16997
|
+
import { useState as useState75, useCallback as useCallback32 } from "react";
|
|
16624
16998
|
import { format as format2 } from "date-fns";
|
|
16625
16999
|
import { Copy as Copy4, Check as Check2, RefreshCw as RefreshCw3, Pencil as Pencil2, Trash2 as Trash25, ExternalLink } from "lucide-react";
|
|
16626
17000
|
import { Fragment as Fragment40, jsx as jsx191, jsxs as jsxs120 } from "react/jsx-runtime";
|
|
@@ -16636,7 +17010,7 @@ function OAuthClientDetail({
|
|
|
16636
17010
|
const [showRegenerateConfirm, setShowRegenerateConfirm] = useState75(false);
|
|
16637
17011
|
const [isDeleting, setIsDeleting] = useState75(false);
|
|
16638
17012
|
const [isRegenerating, setIsRegenerating] = useState75(false);
|
|
16639
|
-
const copyToClipboard2 =
|
|
17013
|
+
const copyToClipboard2 = useCallback32(async (text, field) => {
|
|
16640
17014
|
try {
|
|
16641
17015
|
await navigator.clipboard.writeText(text);
|
|
16642
17016
|
setCopiedField(field);
|
|
@@ -16645,7 +17019,7 @@ function OAuthClientDetail({
|
|
|
16645
17019
|
console.error("Failed to copy:", err);
|
|
16646
17020
|
}
|
|
16647
17021
|
}, []);
|
|
16648
|
-
const handleDelete =
|
|
17022
|
+
const handleDelete = useCallback32(async () => {
|
|
16649
17023
|
if (!onDelete) return;
|
|
16650
17024
|
setIsDeleting(true);
|
|
16651
17025
|
try {
|
|
@@ -16655,7 +17029,7 @@ function OAuthClientDetail({
|
|
|
16655
17029
|
setShowDeleteConfirm(false);
|
|
16656
17030
|
}
|
|
16657
17031
|
}, [onDelete]);
|
|
16658
|
-
const handleRegenerateSecret =
|
|
17032
|
+
const handleRegenerateSecret = useCallback32(async () => {
|
|
16659
17033
|
if (!onRegenerateSecret) return;
|
|
16660
17034
|
setIsRegenerating(true);
|
|
16661
17035
|
try {
|
|
@@ -17231,7 +17605,7 @@ __name(WaitlistConfirmation, "WaitlistConfirmation");
|
|
|
17231
17605
|
import { flexRender as flexRender2, getCoreRowModel as getCoreRowModel2, useReactTable as useReactTable2 } from "@tanstack/react-table";
|
|
17232
17606
|
import { RefreshCw as RefreshCw4, Users as Users2 } from "lucide-react";
|
|
17233
17607
|
import { useTranslations as useTranslations81 } from "next-intl";
|
|
17234
|
-
import { useCallback as
|
|
17608
|
+
import { useCallback as useCallback33, useEffect as useEffect58, useState as useState78 } from "react";
|
|
17235
17609
|
|
|
17236
17610
|
// src/features/waitlist/hooks/useWaitlistTableStructure.tsx
|
|
17237
17611
|
import { Send } from "lucide-react";
|
|
@@ -17332,7 +17706,7 @@ function WaitlistList() {
|
|
|
17332
17706
|
const [total, setTotal] = useState78(0);
|
|
17333
17707
|
const [isLoading, setIsLoading] = useState78(true);
|
|
17334
17708
|
const [statusFilter, setStatusFilter] = useState78("all");
|
|
17335
|
-
const loadEntries =
|
|
17709
|
+
const loadEntries = useCallback33(async () => {
|
|
17336
17710
|
setIsLoading(true);
|
|
17337
17711
|
try {
|
|
17338
17712
|
const result = await WaitlistService.findMany({
|
|
@@ -17398,6 +17772,452 @@ function WaitlistList() {
|
|
|
17398
17772
|
}
|
|
17399
17773
|
__name(WaitlistList, "WaitlistList");
|
|
17400
17774
|
|
|
17775
|
+
// src/features/rbac/components/RbacContainer.tsx
|
|
17776
|
+
import { Loader2Icon as Loader2Icon2 } from "lucide-react";
|
|
17777
|
+
import { useTranslations as useTranslations86 } from "next-intl";
|
|
17778
|
+
import { useCallback as useCallback35, useEffect as useEffect59, useState as useState81 } from "react";
|
|
17779
|
+
|
|
17780
|
+
// src/features/rbac/components/RbacFeatureSection.tsx
|
|
17781
|
+
import { ChevronDownIcon as ChevronDownIcon8 } from "lucide-react";
|
|
17782
|
+
import { useTranslations as useTranslations84 } from "next-intl";
|
|
17783
|
+
import { useState as useState80 } from "react";
|
|
17784
|
+
|
|
17785
|
+
// src/features/rbac/components/RbacModuleTable.tsx
|
|
17786
|
+
import { RotateCcwIcon } from "lucide-react";
|
|
17787
|
+
import { useTranslations as useTranslations83 } from "next-intl";
|
|
17788
|
+
|
|
17789
|
+
// src/features/rbac/components/RbacPermissionPicker.tsx
|
|
17790
|
+
import { CheckIcon as CheckIcon9, MinusIcon as MinusIcon3, XIcon as XIcon8 } from "lucide-react";
|
|
17791
|
+
import { useTranslations as useTranslations82 } from "next-intl";
|
|
17792
|
+
import { useCallback as useCallback34, useState as useState79 } from "react";
|
|
17793
|
+
|
|
17794
|
+
// src/features/rbac/components/RbacPermissionCell.tsx
|
|
17795
|
+
import { CheckIcon as CheckIcon8, MinusIcon as MinusIcon2, XIcon as XIcon7 } from "lucide-react";
|
|
17796
|
+
import { jsx as jsx203, jsxs as jsxs132 } from "react/jsx-runtime";
|
|
17797
|
+
function RbacPermissionCell({
|
|
17798
|
+
value,
|
|
17799
|
+
originalValue,
|
|
17800
|
+
isRoleColumn = false,
|
|
17801
|
+
onClick
|
|
17802
|
+
}) {
|
|
17803
|
+
const isDirty = originalValue !== void 0 && value !== originalValue;
|
|
17804
|
+
if (isRoleColumn && (value === null || value === void 0)) {
|
|
17805
|
+
return /* @__PURE__ */ jsx203(
|
|
17806
|
+
"div",
|
|
17807
|
+
{
|
|
17808
|
+
onClick,
|
|
17809
|
+
className: cn(
|
|
17810
|
+
"flex h-8 w-full items-center justify-center rounded px-2 transition-colors hover:bg-muted cursor-pointer",
|
|
17811
|
+
isDirty && "ring-2 ring-amber-400/50"
|
|
17812
|
+
),
|
|
17813
|
+
children: /* @__PURE__ */ jsx203(MinusIcon2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
17814
|
+
}
|
|
17815
|
+
);
|
|
17816
|
+
}
|
|
17817
|
+
if (value === true) {
|
|
17818
|
+
return /* @__PURE__ */ jsx203(
|
|
17819
|
+
"div",
|
|
17820
|
+
{
|
|
17821
|
+
onClick,
|
|
17822
|
+
className: cn(
|
|
17823
|
+
"flex h-8 w-full items-center justify-center rounded px-2 transition-colors hover:bg-muted cursor-pointer",
|
|
17824
|
+
isDirty && "ring-2 ring-amber-400/50"
|
|
17825
|
+
),
|
|
17826
|
+
children: /* @__PURE__ */ jsxs132(Badge, { variant: "default", className: "bg-emerald-600 hover:bg-emerald-700 gap-1 text-xs", children: [
|
|
17827
|
+
/* @__PURE__ */ jsx203(CheckIcon8, { className: "h-3 w-3" }),
|
|
17828
|
+
/* @__PURE__ */ jsx203("span", { children: "true" })
|
|
17829
|
+
] })
|
|
17830
|
+
}
|
|
17831
|
+
);
|
|
17832
|
+
}
|
|
17833
|
+
if (value === false) {
|
|
17834
|
+
return /* @__PURE__ */ jsx203(
|
|
17835
|
+
"div",
|
|
17836
|
+
{
|
|
17837
|
+
onClick,
|
|
17838
|
+
className: cn(
|
|
17839
|
+
"flex h-8 w-full items-center justify-center rounded px-2 transition-colors hover:bg-muted cursor-pointer",
|
|
17840
|
+
isDirty && "ring-2 ring-amber-400/50"
|
|
17841
|
+
),
|
|
17842
|
+
children: /* @__PURE__ */ jsxs132(Badge, { variant: "destructive", className: "gap-1 text-xs", children: [
|
|
17843
|
+
/* @__PURE__ */ jsx203(XIcon7, { className: "h-3 w-3" }),
|
|
17844
|
+
/* @__PURE__ */ jsx203("span", { children: "false" })
|
|
17845
|
+
] })
|
|
17846
|
+
}
|
|
17847
|
+
);
|
|
17848
|
+
}
|
|
17849
|
+
const displayValue = typeof value === "string" ? value : String(value);
|
|
17850
|
+
const truncated = displayValue.length > 20 ? displayValue.substring(0, 18) + "..." : displayValue;
|
|
17851
|
+
return /* @__PURE__ */ jsxs132(Tooltip2, { children: [
|
|
17852
|
+
/* @__PURE__ */ jsx203(
|
|
17853
|
+
TooltipTrigger,
|
|
17854
|
+
{
|
|
17855
|
+
onClick,
|
|
17856
|
+
className: cn(
|
|
17857
|
+
"flex h-8 w-full items-center justify-center rounded px-2 transition-colors hover:bg-muted cursor-pointer",
|
|
17858
|
+
isDirty && "ring-2 ring-amber-400/50"
|
|
17859
|
+
),
|
|
17860
|
+
render: /* @__PURE__ */ jsx203("div", {}),
|
|
17861
|
+
children: /* @__PURE__ */ jsx203(Badge, { variant: "outline", className: "max-w-full truncate text-xs font-mono", children: truncated })
|
|
17862
|
+
}
|
|
17863
|
+
),
|
|
17864
|
+
/* @__PURE__ */ jsx203(TooltipContent, { side: "top", className: "max-w-xs", children: /* @__PURE__ */ jsx203("p", { className: "font-mono text-xs break-all", children: displayValue }) })
|
|
17865
|
+
] });
|
|
17866
|
+
}
|
|
17867
|
+
__name(RbacPermissionCell, "RbacPermissionCell");
|
|
17868
|
+
|
|
17869
|
+
// src/features/rbac/components/RbacPermissionPicker.tsx
|
|
17870
|
+
import { Fragment as Fragment42, jsx as jsx204, jsxs as jsxs133 } from "react/jsx-runtime";
|
|
17871
|
+
function RbacPermissionPicker({
|
|
17872
|
+
value,
|
|
17873
|
+
originalValue,
|
|
17874
|
+
isRoleColumn = false,
|
|
17875
|
+
knownSegments,
|
|
17876
|
+
onSetValue,
|
|
17877
|
+
onClear
|
|
17878
|
+
}) {
|
|
17879
|
+
const t = useTranslations82();
|
|
17880
|
+
const [open, setOpen] = useState79(false);
|
|
17881
|
+
const [customSegment, setCustomSegment] = useState79("");
|
|
17882
|
+
const currentSegments = typeof value === "string" ? value.split("|").filter(Boolean) : [];
|
|
17883
|
+
const toggleSegment = useCallback34(
|
|
17884
|
+
(segment) => {
|
|
17885
|
+
const newSegments = currentSegments.includes(segment) ? currentSegments.filter((s) => s !== segment) : [...currentSegments, segment];
|
|
17886
|
+
if (newSegments.length === 0) {
|
|
17887
|
+
onSetValue(false);
|
|
17888
|
+
} else {
|
|
17889
|
+
onSetValue(newSegments.join("|"));
|
|
17890
|
+
}
|
|
17891
|
+
},
|
|
17892
|
+
[currentSegments, onSetValue]
|
|
17893
|
+
);
|
|
17894
|
+
const addCustomSegment = useCallback34(() => {
|
|
17895
|
+
if (!customSegment.trim()) return;
|
|
17896
|
+
const segment = customSegment.trim();
|
|
17897
|
+
if (!currentSegments.includes(segment)) {
|
|
17898
|
+
const newSegments = [...currentSegments, segment];
|
|
17899
|
+
onSetValue(newSegments.join("|"));
|
|
17900
|
+
}
|
|
17901
|
+
setCustomSegment("");
|
|
17902
|
+
}, [customSegment, currentSegments, onSetValue]);
|
|
17903
|
+
return /* @__PURE__ */ jsxs133(Popover, { open, onOpenChange: setOpen, children: [
|
|
17904
|
+
/* @__PURE__ */ jsx204(PopoverTrigger, { children: /* @__PURE__ */ jsx204(RbacPermissionCell, { value, originalValue, isRoleColumn }) }),
|
|
17905
|
+
/* @__PURE__ */ jsx204(PopoverContent, { className: "w-72 p-3", align: "center", children: /* @__PURE__ */ jsxs133("div", { className: "space-y-3", children: [
|
|
17906
|
+
/* @__PURE__ */ jsxs133("div", { children: [
|
|
17907
|
+
/* @__PURE__ */ jsx204("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: t("rbac.quick_value") }),
|
|
17908
|
+
/* @__PURE__ */ jsxs133("div", { className: "flex gap-2", children: [
|
|
17909
|
+
/* @__PURE__ */ jsxs133(
|
|
17910
|
+
Button,
|
|
17911
|
+
{
|
|
17912
|
+
size: "sm",
|
|
17913
|
+
variant: value === true ? "default" : "outline",
|
|
17914
|
+
className: cn("flex-1 gap-1", value === true && "bg-emerald-600 hover:bg-emerald-700"),
|
|
17915
|
+
onClick: () => {
|
|
17916
|
+
onSetValue(true);
|
|
17917
|
+
setOpen(false);
|
|
17918
|
+
},
|
|
17919
|
+
children: [
|
|
17920
|
+
/* @__PURE__ */ jsx204(CheckIcon9, { className: "h-3 w-3" }),
|
|
17921
|
+
/* @__PURE__ */ jsx204("span", { children: "true" })
|
|
17922
|
+
]
|
|
17923
|
+
}
|
|
17924
|
+
),
|
|
17925
|
+
/* @__PURE__ */ jsxs133(
|
|
17926
|
+
Button,
|
|
17927
|
+
{
|
|
17928
|
+
size: "sm",
|
|
17929
|
+
variant: value === false ? "destructive" : "outline",
|
|
17930
|
+
className: "flex-1 gap-1",
|
|
17931
|
+
onClick: () => {
|
|
17932
|
+
onSetValue(false);
|
|
17933
|
+
setOpen(false);
|
|
17934
|
+
},
|
|
17935
|
+
children: [
|
|
17936
|
+
/* @__PURE__ */ jsx204(XIcon8, { className: "h-3 w-3" }),
|
|
17937
|
+
/* @__PURE__ */ jsx204("span", { children: "false" })
|
|
17938
|
+
]
|
|
17939
|
+
}
|
|
17940
|
+
)
|
|
17941
|
+
] })
|
|
17942
|
+
] }),
|
|
17943
|
+
isRoleColumn && onClear && /* @__PURE__ */ jsxs133(Fragment42, { children: [
|
|
17944
|
+
/* @__PURE__ */ jsx204(Separator, {}),
|
|
17945
|
+
/* @__PURE__ */ jsxs133(
|
|
17946
|
+
Button,
|
|
17947
|
+
{
|
|
17948
|
+
size: "sm",
|
|
17949
|
+
variant: "ghost",
|
|
17950
|
+
className: "w-full gap-1 text-muted-foreground",
|
|
17951
|
+
onClick: () => {
|
|
17952
|
+
onClear();
|
|
17953
|
+
setOpen(false);
|
|
17954
|
+
},
|
|
17955
|
+
children: [
|
|
17956
|
+
/* @__PURE__ */ jsx204(MinusIcon3, { className: "h-3 w-3" }),
|
|
17957
|
+
t("rbac.inherit_from_defaults")
|
|
17958
|
+
]
|
|
17959
|
+
}
|
|
17960
|
+
)
|
|
17961
|
+
] }),
|
|
17962
|
+
knownSegments.length > 0 && /* @__PURE__ */ jsxs133(Fragment42, { children: [
|
|
17963
|
+
/* @__PURE__ */ jsx204(Separator, {}),
|
|
17964
|
+
/* @__PURE__ */ jsxs133("div", { children: [
|
|
17965
|
+
/* @__PURE__ */ jsx204("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: t("rbac.relationships") }),
|
|
17966
|
+
/* @__PURE__ */ jsx204("div", { className: "max-h-40 space-y-1 overflow-y-auto", children: knownSegments.map((segment) => /* @__PURE__ */ jsxs133(
|
|
17967
|
+
"label",
|
|
17968
|
+
{
|
|
17969
|
+
className: "flex items-center gap-2 rounded px-1 py-0.5 text-sm hover:bg-muted cursor-pointer",
|
|
17970
|
+
children: [
|
|
17971
|
+
/* @__PURE__ */ jsx204(
|
|
17972
|
+
Checkbox,
|
|
17973
|
+
{
|
|
17974
|
+
checked: currentSegments.includes(segment),
|
|
17975
|
+
onCheckedChange: () => toggleSegment(segment)
|
|
17976
|
+
}
|
|
17977
|
+
),
|
|
17978
|
+
/* @__PURE__ */ jsx204("span", { className: "font-mono text-xs", children: segment })
|
|
17979
|
+
]
|
|
17980
|
+
},
|
|
17981
|
+
segment
|
|
17982
|
+
)) }),
|
|
17983
|
+
/* @__PURE__ */ jsxs133("div", { className: "mt-2 flex gap-1", children: [
|
|
17984
|
+
/* @__PURE__ */ jsx204(
|
|
17985
|
+
Input,
|
|
17986
|
+
{
|
|
17987
|
+
value: customSegment,
|
|
17988
|
+
onChange: (e) => setCustomSegment(e.target.value),
|
|
17989
|
+
placeholder: t("rbac.custom_segment_placeholder"),
|
|
17990
|
+
className: "h-7 text-xs font-mono",
|
|
17991
|
+
onKeyDown: (e) => {
|
|
17992
|
+
if (e.key === "Enter") {
|
|
17993
|
+
e.preventDefault();
|
|
17994
|
+
addCustomSegment();
|
|
17995
|
+
}
|
|
17996
|
+
}
|
|
17997
|
+
}
|
|
17998
|
+
),
|
|
17999
|
+
/* @__PURE__ */ jsx204(
|
|
18000
|
+
Button,
|
|
18001
|
+
{
|
|
18002
|
+
size: "sm",
|
|
18003
|
+
variant: "outline",
|
|
18004
|
+
className: "h-7 px-2 text-xs",
|
|
18005
|
+
onClick: addCustomSegment,
|
|
18006
|
+
disabled: !customSegment.trim(),
|
|
18007
|
+
children: "+"
|
|
18008
|
+
}
|
|
18009
|
+
)
|
|
18010
|
+
] }),
|
|
18011
|
+
currentSegments.length > 0 && /* @__PURE__ */ jsxs133("div", { className: "mt-2 rounded bg-muted p-2", children: [
|
|
18012
|
+
/* @__PURE__ */ jsx204("p", { className: "text-xs text-muted-foreground mb-1", children: t("rbac.preview") }),
|
|
18013
|
+
/* @__PURE__ */ jsx204("p", { className: "text-xs font-mono break-all", children: currentSegments.join("|") })
|
|
18014
|
+
] })
|
|
18015
|
+
] })
|
|
18016
|
+
] })
|
|
18017
|
+
] }) })
|
|
18018
|
+
] });
|
|
18019
|
+
}
|
|
18020
|
+
__name(RbacPermissionPicker, "RbacPermissionPicker");
|
|
18021
|
+
|
|
18022
|
+
// src/features/rbac/components/RbacModuleTable.tsx
|
|
18023
|
+
import { jsx as jsx205, jsxs as jsxs134 } from "react/jsx-runtime";
|
|
18024
|
+
var ACTION_LABELS = {
|
|
18025
|
+
read: "Read",
|
|
18026
|
+
create: "Create",
|
|
18027
|
+
update: "Update",
|
|
18028
|
+
delete: "Delete"
|
|
18029
|
+
};
|
|
18030
|
+
function RbacModuleTable({ module, roles, stateApi }) {
|
|
18031
|
+
const t = useTranslations83();
|
|
18032
|
+
const handleReset = /* @__PURE__ */ __name(() => {
|
|
18033
|
+
stateApi.resetModulePermissions(module.id, roles);
|
|
18034
|
+
}, "handleReset");
|
|
18035
|
+
return /* @__PURE__ */ jsxs134("div", { className: "rounded-lg border border-accent bg-card", children: [
|
|
18036
|
+
/* @__PURE__ */ jsxs134("div", { className: "flex items-center justify-between border-b px-4 py-2", children: [
|
|
18037
|
+
/* @__PURE__ */ jsx205("h4", { className: "text-sm font-medium", children: module.name }),
|
|
18038
|
+
/* @__PURE__ */ jsx205(
|
|
18039
|
+
Button,
|
|
18040
|
+
{
|
|
18041
|
+
variant: "ghost",
|
|
18042
|
+
size: "sm",
|
|
18043
|
+
onClick: handleReset,
|
|
18044
|
+
className: "h-7 px-2 text-muted-foreground hover:text-foreground",
|
|
18045
|
+
children: /* @__PURE__ */ jsx205(RotateCcwIcon, { className: "h-3.5 w-3.5" })
|
|
18046
|
+
}
|
|
18047
|
+
)
|
|
18048
|
+
] }),
|
|
18049
|
+
/* @__PURE__ */ jsx205("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs134("table", { className: "w-full text-sm", children: [
|
|
18050
|
+
/* @__PURE__ */ jsx205("thead", { children: /* @__PURE__ */ jsxs134("tr", { className: "border-b bg-muted/50", children: [
|
|
18051
|
+
/* @__PURE__ */ jsx205("th", { className: "px-4 py-2 text-left text-xs font-medium text-muted-foreground w-40", children: t("rbac.role") }),
|
|
18052
|
+
ACTION_TYPES.map((actionType) => /* @__PURE__ */ jsx205(
|
|
18053
|
+
"th",
|
|
18054
|
+
{
|
|
18055
|
+
className: "px-2 py-2 text-center text-xs font-medium text-muted-foreground min-w-28",
|
|
18056
|
+
children: ACTION_LABELS[actionType]
|
|
18057
|
+
},
|
|
18058
|
+
actionType
|
|
18059
|
+
))
|
|
18060
|
+
] }) }),
|
|
18061
|
+
/* @__PURE__ */ jsxs134("tbody", { children: [
|
|
18062
|
+
/* @__PURE__ */ jsxs134("tr", { className: "border-b", children: [
|
|
18063
|
+
/* @__PURE__ */ jsx205("td", { className: "px-4 py-1 text-xs font-medium text-muted-foreground", children: t("rbac.defaults") }),
|
|
18064
|
+
ACTION_TYPES.map((actionType) => {
|
|
18065
|
+
const defaultValue = stateApi.getModuleDefaultPermission(module.id, actionType) ?? false;
|
|
18066
|
+
const originalDefaultValue = module.permissions[actionType] ?? false;
|
|
18067
|
+
return /* @__PURE__ */ jsx205("td", { className: "px-2 py-1", children: /* @__PURE__ */ jsx205(
|
|
18068
|
+
RbacPermissionPicker,
|
|
18069
|
+
{
|
|
18070
|
+
value: defaultValue,
|
|
18071
|
+
originalValue: originalDefaultValue,
|
|
18072
|
+
isRoleColumn: false,
|
|
18073
|
+
knownSegments: stateApi.getModuleRelationshipPaths(module.id),
|
|
18074
|
+
onSetValue: (value) => stateApi.setModuleDefaultPermission(module.id, actionType, value)
|
|
18075
|
+
}
|
|
18076
|
+
) }, actionType);
|
|
18077
|
+
})
|
|
18078
|
+
] }),
|
|
18079
|
+
roles.filter((role) => role.id !== COMPANY_ADMINISTRATOR_ROLE_ID).map((role) => /* @__PURE__ */ jsxs134("tr", { className: "border-b last:border-b-0", children: [
|
|
18080
|
+
/* @__PURE__ */ jsx205("td", { className: "px-4 py-1 text-xs font-medium text-muted-foreground", children: role.name }),
|
|
18081
|
+
ACTION_TYPES.map((actionType) => {
|
|
18082
|
+
const roleValue = stateApi.getRolePermission(role.id, module.id, actionType);
|
|
18083
|
+
const originalMapping = stateApi.original?.permissionMappings.find(
|
|
18084
|
+
(pm) => pm.roleId === role.id && pm.moduleId === module.id
|
|
18085
|
+
);
|
|
18086
|
+
const originalRoleValue = originalMapping ? originalMapping.permissions[actionType] ?? null : void 0;
|
|
18087
|
+
return /* @__PURE__ */ jsx205("td", { className: "px-2 py-1", children: /* @__PURE__ */ jsx205(
|
|
18088
|
+
RbacPermissionPicker,
|
|
18089
|
+
{
|
|
18090
|
+
value: roleValue,
|
|
18091
|
+
originalValue: originalRoleValue,
|
|
18092
|
+
isRoleColumn: true,
|
|
18093
|
+
knownSegments: stateApi.getModuleRelationshipPaths(module.id),
|
|
18094
|
+
onSetValue: (value) => stateApi.setRolePermission(role.id, module.id, actionType, value),
|
|
18095
|
+
onClear: () => stateApi.clearRolePermission(role.id, module.id, actionType)
|
|
18096
|
+
}
|
|
18097
|
+
) }, actionType);
|
|
18098
|
+
})
|
|
18099
|
+
] }, role.id))
|
|
18100
|
+
] })
|
|
18101
|
+
] }) })
|
|
18102
|
+
] });
|
|
18103
|
+
}
|
|
18104
|
+
__name(RbacModuleTable, "RbacModuleTable");
|
|
18105
|
+
|
|
18106
|
+
// src/features/rbac/components/RbacFeatureSection.tsx
|
|
18107
|
+
import { jsx as jsx206, jsxs as jsxs135 } from "react/jsx-runtime";
|
|
18108
|
+
function RbacFeatureSection({ feature, roles, stateApi }) {
|
|
18109
|
+
const t = useTranslations84();
|
|
18110
|
+
const [isOpen, setIsOpen] = useState80(true);
|
|
18111
|
+
const featureIsCore = stateApi.getFeatureIsCore(feature.id);
|
|
18112
|
+
return /* @__PURE__ */ jsx206(Collapsible, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs135("div", { className: "rounded-lg border bg-card", children: [
|
|
18113
|
+
/* @__PURE__ */ jsx206(CollapsibleTrigger, { className: "w-full", children: /* @__PURE__ */ jsxs135("div", { className: "flex cursor-pointer items-center justify-between px-4 py-3 hover:bg-muted/50 transition-colors", children: [
|
|
18114
|
+
/* @__PURE__ */ jsxs135("div", { className: "flex items-center gap-3", children: [
|
|
18115
|
+
/* @__PURE__ */ jsx206(
|
|
18116
|
+
ChevronDownIcon8,
|
|
18117
|
+
{
|
|
18118
|
+
className: cn("h-4 w-4 text-muted-foreground transition-transform", !isOpen && "-rotate-90")
|
|
18119
|
+
}
|
|
18120
|
+
),
|
|
18121
|
+
/* @__PURE__ */ jsx206("h3", { className: "text-base font-semibold", children: feature.name }),
|
|
18122
|
+
/* @__PURE__ */ jsx206("span", { className: "text-xs text-muted-foreground", children: t("rbac.module_count", { count: feature.modules.length }) })
|
|
18123
|
+
] }),
|
|
18124
|
+
/* @__PURE__ */ jsxs135("div", { className: "flex items-center gap-2", onClick: (e) => e.stopPropagation(), children: [
|
|
18125
|
+
/* @__PURE__ */ jsx206("span", { className: "text-xs text-muted-foreground", children: t("rbac.core") }),
|
|
18126
|
+
/* @__PURE__ */ jsx206(
|
|
18127
|
+
Switch,
|
|
18128
|
+
{
|
|
18129
|
+
checked: featureIsCore,
|
|
18130
|
+
onCheckedChange: (checked) => stateApi.setFeatureIsCore(feature.id, checked),
|
|
18131
|
+
className: "data-checked:bg-accent data-unchecked:bg-gray-300"
|
|
18132
|
+
}
|
|
18133
|
+
)
|
|
18134
|
+
] })
|
|
18135
|
+
] }) }),
|
|
18136
|
+
/* @__PURE__ */ jsx206(CollapsibleContent, { children: /* @__PURE__ */ jsxs135("div", { className: "space-y-3 p-4 pt-0", children: [
|
|
18137
|
+
feature.modules.map((mod) => /* @__PURE__ */ jsx206(RbacModuleTable, { module: mod, roles, stateApi }, mod.id)),
|
|
18138
|
+
feature.modules.length === 0 && /* @__PURE__ */ jsx206("p", { className: "text-sm text-muted-foreground italic py-4 text-center", children: t("rbac.no_modules") })
|
|
18139
|
+
] }) })
|
|
18140
|
+
] }) });
|
|
18141
|
+
}
|
|
18142
|
+
__name(RbacFeatureSection, "RbacFeatureSection");
|
|
18143
|
+
|
|
18144
|
+
// src/features/rbac/components/RbacToolbar.tsx
|
|
18145
|
+
import { DownloadIcon, RotateCcwIcon as RotateCcwIcon2 } from "lucide-react";
|
|
18146
|
+
import { useTranslations as useTranslations85 } from "next-intl";
|
|
18147
|
+
import { jsx as jsx207, jsxs as jsxs136 } from "react/jsx-runtime";
|
|
18148
|
+
function RbacToolbar({ isDirty, onGenerate, onReset }) {
|
|
18149
|
+
const t = useTranslations85();
|
|
18150
|
+
return /* @__PURE__ */ jsxs136("div", { className: "flex items-center justify-between rounded-lg border bg-card px-4 py-3", children: [
|
|
18151
|
+
/* @__PURE__ */ jsxs136("div", { className: "flex items-center gap-3", children: [
|
|
18152
|
+
/* @__PURE__ */ jsx207("h2", { className: "text-lg font-semibold", children: t("rbac.title") }),
|
|
18153
|
+
isDirty && /* @__PURE__ */ jsx207(Badge, { variant: "outline", className: "border-amber-400 text-amber-600", children: t("rbac.unsaved_changes") })
|
|
18154
|
+
] }),
|
|
18155
|
+
/* @__PURE__ */ jsxs136("div", { className: "flex items-center gap-2", children: [
|
|
18156
|
+
/* @__PURE__ */ jsxs136(Button, { variant: "outline", size: "sm", onClick: onReset, disabled: !isDirty, className: "gap-1", children: [
|
|
18157
|
+
/* @__PURE__ */ jsx207(RotateCcwIcon2, { className: "h-3.5 w-3.5" }),
|
|
18158
|
+
t("rbac.reset")
|
|
18159
|
+
] }),
|
|
18160
|
+
/* @__PURE__ */ jsxs136(Button, { size: "sm", onClick: onGenerate, disabled: !isDirty, className: "gap-1", children: [
|
|
18161
|
+
/* @__PURE__ */ jsx207(DownloadIcon, { className: "h-3.5 w-3.5" }),
|
|
18162
|
+
t("rbac.generate_migration")
|
|
18163
|
+
] })
|
|
18164
|
+
] })
|
|
18165
|
+
] });
|
|
18166
|
+
}
|
|
18167
|
+
__name(RbacToolbar, "RbacToolbar");
|
|
18168
|
+
|
|
18169
|
+
// src/features/rbac/components/RbacContainer.tsx
|
|
18170
|
+
import { jsx as jsx208, jsxs as jsxs137 } from "react/jsx-runtime";
|
|
18171
|
+
function RbacContainer() {
|
|
18172
|
+
const t = useTranslations86();
|
|
18173
|
+
const stateApi = useRbacState();
|
|
18174
|
+
const [loading, setLoading] = useState81(true);
|
|
18175
|
+
const [error, setError] = useState81(null);
|
|
18176
|
+
useEffect59(() => {
|
|
18177
|
+
async function fetchData() {
|
|
18178
|
+
try {
|
|
18179
|
+
setLoading(true);
|
|
18180
|
+
const [features, roles, permissionMappings, modulePaths] = await Promise.all([
|
|
18181
|
+
RbacService.getFeatures(),
|
|
18182
|
+
RbacService.getRoles(),
|
|
18183
|
+
RbacService.getPermissionMappings(),
|
|
18184
|
+
RbacService.getModuleRelationshipPaths()
|
|
18185
|
+
]);
|
|
18186
|
+
stateApi.init(features, roles, permissionMappings, modulePaths);
|
|
18187
|
+
} catch (err) {
|
|
18188
|
+
console.error("Failed to load RBAC configuration:", err);
|
|
18189
|
+
setError(t("rbac.loading_error"));
|
|
18190
|
+
} finally {
|
|
18191
|
+
setLoading(false);
|
|
18192
|
+
}
|
|
18193
|
+
}
|
|
18194
|
+
__name(fetchData, "fetchData");
|
|
18195
|
+
fetchData();
|
|
18196
|
+
}, [t]);
|
|
18197
|
+
const handleGenerate = useCallback35(() => {
|
|
18198
|
+
const effective = stateApi.getEffectiveConfiguration();
|
|
18199
|
+
if (!effective) return;
|
|
18200
|
+
const content = generateMigrationFile({
|
|
18201
|
+
features: effective.features,
|
|
18202
|
+
roles: effective.roles,
|
|
18203
|
+
rolePermissionsMap: effective.rolePermissionsMap
|
|
18204
|
+
});
|
|
18205
|
+
downloadMigrationFile(content);
|
|
18206
|
+
}, [stateApi]);
|
|
18207
|
+
if (loading) {
|
|
18208
|
+
return /* @__PURE__ */ jsx208("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx208(Loader2Icon2, { className: "h-8 w-8 animate-spin text-muted-foreground" }) });
|
|
18209
|
+
}
|
|
18210
|
+
if (error) {
|
|
18211
|
+
return /* @__PURE__ */ jsx208("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx208("p", { className: "text-destructive", children: error }) });
|
|
18212
|
+
}
|
|
18213
|
+
if (!stateApi.original) return null;
|
|
18214
|
+
return /* @__PURE__ */ jsxs137(RoundPageContainer, { children: [
|
|
18215
|
+
/* @__PURE__ */ jsx208(RbacToolbar, { isDirty: stateApi.isDirty, onGenerate: handleGenerate, onReset: stateApi.reset }),
|
|
18216
|
+
stateApi.original.features.map((feature) => /* @__PURE__ */ jsx208(RbacFeatureSection, { feature, roles: stateApi.original.roles, stateApi }, feature.id))
|
|
18217
|
+
] });
|
|
18218
|
+
}
|
|
18219
|
+
__name(RbacContainer, "RbacContainer");
|
|
18220
|
+
|
|
17401
18221
|
export {
|
|
17402
18222
|
JsonApiProvider,
|
|
17403
18223
|
useJsonApiGet,
|
|
@@ -17836,6 +18656,15 @@ export {
|
|
|
17836
18656
|
WaitlistSuccessState,
|
|
17837
18657
|
WaitlistConfirmation,
|
|
17838
18658
|
WaitlistList,
|
|
18659
|
+
useRbacState,
|
|
18660
|
+
generateMigrationFile,
|
|
18661
|
+
downloadMigrationFile,
|
|
18662
|
+
RbacPermissionCell,
|
|
18663
|
+
RbacPermissionPicker,
|
|
18664
|
+
RbacModuleTable,
|
|
18665
|
+
RbacFeatureSection,
|
|
18666
|
+
RbacToolbar,
|
|
18667
|
+
RbacContainer,
|
|
17839
18668
|
AddUserToRole,
|
|
17840
18669
|
UserAvatarEditor,
|
|
17841
18670
|
UserDeleter,
|
|
@@ -17863,4 +18692,4 @@ export {
|
|
|
17863
18692
|
useOAuthClients,
|
|
17864
18693
|
useOAuthClient
|
|
17865
18694
|
};
|
|
17866
|
-
//# sourceMappingURL=chunk-
|
|
18695
|
+
//# sourceMappingURL=chunk-G5473JP3.mjs.map
|