@strapi/plugin-users-permissions 5.0.0-beta.4 → 5.0.0-beta.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.
Files changed (135) hide show
  1. package/admin/src/components/FormModal/index.jsx +1 -1
  2. package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +1 -1
  3. package/admin/src/pages/EmailTemplates/components/EmailTable.jsx +13 -18
  4. package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +4 -4
  5. package/admin/src/pages/Roles/pages/ListPage/index.jsx +1 -1
  6. package/package.json +6 -6
  7. package/server/services/user.js +21 -4
  8. package/dist/_chunks/ar-BguGUqwK.js +0 -44
  9. package/dist/_chunks/ar-BguGUqwK.js.map +0 -1
  10. package/dist/_chunks/ar-CK8BRRXB.mjs +0 -44
  11. package/dist/_chunks/ar-CK8BRRXB.mjs.map +0 -1
  12. package/dist/_chunks/cs-BVigMk0l.mjs +0 -50
  13. package/dist/_chunks/cs-BVigMk0l.mjs.map +0 -1
  14. package/dist/_chunks/cs-BW8-K_GY.js +0 -50
  15. package/dist/_chunks/cs-BW8-K_GY.js.map +0 -1
  16. package/dist/_chunks/de-BKUdRFI4.mjs +0 -62
  17. package/dist/_chunks/de-BKUdRFI4.mjs.map +0 -1
  18. package/dist/_chunks/de-owXpVluI.js +0 -62
  19. package/dist/_chunks/de-owXpVluI.js.map +0 -1
  20. package/dist/_chunks/dk-BQiTK50l.mjs +0 -86
  21. package/dist/_chunks/dk-BQiTK50l.mjs.map +0 -1
  22. package/dist/_chunks/dk-LXAnbuBk.js +0 -86
  23. package/dist/_chunks/dk-LXAnbuBk.js.map +0 -1
  24. package/dist/_chunks/en-DOHtPf-2.mjs +0 -86
  25. package/dist/_chunks/en-DOHtPf-2.mjs.map +0 -1
  26. package/dist/_chunks/en-MHo5mcsU.js +0 -86
  27. package/dist/_chunks/en-MHo5mcsU.js.map +0 -1
  28. package/dist/_chunks/es-BwLCLXAQ.js +0 -86
  29. package/dist/_chunks/es-BwLCLXAQ.js.map +0 -1
  30. package/dist/_chunks/es-DNgOVMjD.mjs +0 -86
  31. package/dist/_chunks/es-DNgOVMjD.mjs.map +0 -1
  32. package/dist/_chunks/fr-DkgRugiU.mjs +0 -50
  33. package/dist/_chunks/fr-DkgRugiU.mjs.map +0 -1
  34. package/dist/_chunks/fr-DkhpSjjm.js +0 -50
  35. package/dist/_chunks/fr-DkhpSjjm.js.map +0 -1
  36. package/dist/_chunks/id-BTemOeTZ.js +0 -62
  37. package/dist/_chunks/id-BTemOeTZ.js.map +0 -1
  38. package/dist/_chunks/id-BdEsvnaF.mjs +0 -62
  39. package/dist/_chunks/id-BdEsvnaF.mjs.map +0 -1
  40. package/dist/_chunks/index-7wfWos1T.js +0 -248
  41. package/dist/_chunks/index-7wfWos1T.js.map +0 -1
  42. package/dist/_chunks/index-BPGl32Qx.mjs +0 -253
  43. package/dist/_chunks/index-BPGl32Qx.mjs.map +0 -1
  44. package/dist/_chunks/index-BQQx9fm3.js +0 -1174
  45. package/dist/_chunks/index-BQQx9fm3.js.map +0 -1
  46. package/dist/_chunks/index-BzscZzdb.js +0 -358
  47. package/dist/_chunks/index-BzscZzdb.js.map +0 -1
  48. package/dist/_chunks/index-Cgtj8fbz.js +0 -634
  49. package/dist/_chunks/index-Cgtj8fbz.js.map +0 -1
  50. package/dist/_chunks/index-DR9uuqpY.mjs +0 -1143
  51. package/dist/_chunks/index-DR9uuqpY.mjs.map +0 -1
  52. package/dist/_chunks/index-Doewayrm.mjs +0 -249
  53. package/dist/_chunks/index-Doewayrm.mjs.map +0 -1
  54. package/dist/_chunks/index-N9_Qd-tg.mjs +0 -611
  55. package/dist/_chunks/index-N9_Qd-tg.mjs.map +0 -1
  56. package/dist/_chunks/index-i37IN_fH-BF_n1AVy.mjs +0 -10310
  57. package/dist/_chunks/index-i37IN_fH-BF_n1AVy.mjs.map +0 -1
  58. package/dist/_chunks/index-i37IN_fH-_tlNeVkL.js +0 -10334
  59. package/dist/_chunks/index-i37IN_fH-_tlNeVkL.js.map +0 -1
  60. package/dist/_chunks/index-l2QT_IDT.js +0 -272
  61. package/dist/_chunks/index-l2QT_IDT.js.map +0 -1
  62. package/dist/_chunks/index-vs42H81V.mjs +0 -336
  63. package/dist/_chunks/index-vs42H81V.mjs.map +0 -1
  64. package/dist/_chunks/it-B-rv0E24.mjs +0 -62
  65. package/dist/_chunks/it-B-rv0E24.mjs.map +0 -1
  66. package/dist/_chunks/it-D1rH6V6_.js +0 -62
  67. package/dist/_chunks/it-D1rH6V6_.js.map +0 -1
  68. package/dist/_chunks/ja-C8K-VBPD.mjs +0 -48
  69. package/dist/_chunks/ja-C8K-VBPD.mjs.map +0 -1
  70. package/dist/_chunks/ja-DqShgTMf.js +0 -48
  71. package/dist/_chunks/ja-DqShgTMf.js.map +0 -1
  72. package/dist/_chunks/ko-B9DGEPWH.js +0 -86
  73. package/dist/_chunks/ko-B9DGEPWH.js.map +0 -1
  74. package/dist/_chunks/ko-Busb0wIY.mjs +0 -86
  75. package/dist/_chunks/ko-Busb0wIY.mjs.map +0 -1
  76. package/dist/_chunks/ms-ByvsQjRt.mjs +0 -49
  77. package/dist/_chunks/ms-ByvsQjRt.mjs.map +0 -1
  78. package/dist/_chunks/ms-CPBU3LWf.js +0 -49
  79. package/dist/_chunks/ms-CPBU3LWf.js.map +0 -1
  80. package/dist/_chunks/nl-5qO8Rpcy.mjs +0 -48
  81. package/dist/_chunks/nl-5qO8Rpcy.mjs.map +0 -1
  82. package/dist/_chunks/nl-CwNB6YoO.js +0 -48
  83. package/dist/_chunks/nl-CwNB6YoO.js.map +0 -1
  84. package/dist/_chunks/pl-BdIzifBE.mjs +0 -86
  85. package/dist/_chunks/pl-BdIzifBE.mjs.map +0 -1
  86. package/dist/_chunks/pl-Do9UD69f.js +0 -86
  87. package/dist/_chunks/pl-Do9UD69f.js.map +0 -1
  88. package/dist/_chunks/pt-BIO24ioG.mjs +0 -48
  89. package/dist/_chunks/pt-BIO24ioG.mjs.map +0 -1
  90. package/dist/_chunks/pt-BR-D7dZhxuP.js +0 -44
  91. package/dist/_chunks/pt-BR-D7dZhxuP.js.map +0 -1
  92. package/dist/_chunks/pt-BR-f0p23AQZ.mjs +0 -44
  93. package/dist/_chunks/pt-BR-f0p23AQZ.mjs.map +0 -1
  94. package/dist/_chunks/pt-fdvyOnUp.js +0 -48
  95. package/dist/_chunks/pt-fdvyOnUp.js.map +0 -1
  96. package/dist/_chunks/ru-C94rjPGA.js +0 -86
  97. package/dist/_chunks/ru-C94rjPGA.js.map +0 -1
  98. package/dist/_chunks/ru-VWy-IB7K.mjs +0 -86
  99. package/dist/_chunks/ru-VWy-IB7K.mjs.map +0 -1
  100. package/dist/_chunks/sk-BABEhykl.js +0 -50
  101. package/dist/_chunks/sk-BABEhykl.js.map +0 -1
  102. package/dist/_chunks/sk-B_LIcepm.mjs +0 -50
  103. package/dist/_chunks/sk-B_LIcepm.mjs.map +0 -1
  104. package/dist/_chunks/sv-ABLKOokl.mjs +0 -86
  105. package/dist/_chunks/sv-ABLKOokl.mjs.map +0 -1
  106. package/dist/_chunks/sv-Be43LhA9.js +0 -86
  107. package/dist/_chunks/sv-Be43LhA9.js.map +0 -1
  108. package/dist/_chunks/th-DKyP7ueR.mjs +0 -60
  109. package/dist/_chunks/th-DKyP7ueR.mjs.map +0 -1
  110. package/dist/_chunks/th-DgVhVLhL.js +0 -60
  111. package/dist/_chunks/th-DgVhVLhL.js.map +0 -1
  112. package/dist/_chunks/tr-B_idhkEs.js +0 -85
  113. package/dist/_chunks/tr-B_idhkEs.js.map +0 -1
  114. package/dist/_chunks/tr-qa1Q5UjC.mjs +0 -85
  115. package/dist/_chunks/tr-qa1Q5UjC.mjs.map +0 -1
  116. package/dist/_chunks/uk-BmRqbeQc.mjs +0 -49
  117. package/dist/_chunks/uk-BmRqbeQc.mjs.map +0 -1
  118. package/dist/_chunks/uk-LHOivnhP.js +0 -49
  119. package/dist/_chunks/uk-LHOivnhP.js.map +0 -1
  120. package/dist/_chunks/vi-CdVRdKDw.js +0 -50
  121. package/dist/_chunks/vi-CdVRdKDw.js.map +0 -1
  122. package/dist/_chunks/vi-HW-EdMea.mjs +0 -50
  123. package/dist/_chunks/vi-HW-EdMea.mjs.map +0 -1
  124. package/dist/_chunks/zh-5hKkVPA4.mjs +0 -86
  125. package/dist/_chunks/zh-5hKkVPA4.mjs.map +0 -1
  126. package/dist/_chunks/zh-Cuq8gMnF.js +0 -86
  127. package/dist/_chunks/zh-Cuq8gMnF.js.map +0 -1
  128. package/dist/_chunks/zh-Hans-BHilK-yc.mjs +0 -86
  129. package/dist/_chunks/zh-Hans-BHilK-yc.mjs.map +0 -1
  130. package/dist/_chunks/zh-Hans-GQDMKtY4.js +0 -86
  131. package/dist/_chunks/zh-Hans-GQDMKtY4.js.map +0 -1
  132. package/dist/admin/index.js +0 -4
  133. package/dist/admin/index.js.map +0 -1
  134. package/dist/admin/index.mjs +0 -5
  135. package/dist/admin/index.mjs.map +0 -1
@@ -1,1143 +0,0 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import * as React from "react";
3
- import { createContext, useContext, useMemo, useCallback, useReducer, forwardRef, useImperativeHandle, memo, useEffect, useState } from "react";
4
- import { translatedErrors, useNotification, useFetchClient, useAPIErrorHandler, Page, useTracking, BackButton, useQueryParams, useRBAC, SearchInput, ConfirmDialog } from "@strapi/strapi/admin";
5
- import { useNavigate, useMatch, NavLink, Routes, Route } from "react-router-dom";
6
- import { g as getTrad, P as PERMISSIONS } from "./index-Doewayrm.mjs";
7
- import { Box, Flex, Typography, Checkbox, Grid, GridItem, VisuallyHidden, Accordion, AccordionToggle, AccordionContent, Main, HeaderLayout, Button, ContentLayout, TextInput, Textarea, Link, Tbody, Tr, Td, IconButton, useNotifyAT, useFilter, useCollator, Layout, ActionLayout, Table, Thead, Th, EmptyStateLayout } from "@strapi/design-system";
8
- import { Cog, Check, Pencil, Trash, Plus } from "@strapi/icons";
9
- import { Formik, Form } from "formik";
10
- import { useIntl } from "react-intl";
11
- import { useQueries, useMutation, useQuery } from "react-query";
12
- import PropTypes from "prop-types";
13
- import upperFirst from "lodash/upperFirst";
14
- import sortBy from "lodash/sortBy";
15
- import get from "lodash/get";
16
- import styled, { css } from "styled-components";
17
- import { produce } from "immer";
18
- import isEmpty from "lodash/isEmpty";
19
- import without from "lodash/without";
20
- import map from "lodash/map";
21
- import tail from "lodash/tail";
22
- import set from "lodash/set";
23
- import take from "lodash/take";
24
- import * as yup from "yup";
25
- import { LinkButton } from "@strapi/design-system/v2";
26
- const UsersPermissions$2 = createContext({});
27
- const UsersPermissionsProvider = ({ children, value }) => {
28
- return /* @__PURE__ */ jsx(UsersPermissions$2.Provider, { value, children });
29
- };
30
- const useUsersPermissions = () => useContext(UsersPermissions$2);
31
- UsersPermissionsProvider.propTypes = {
32
- children: PropTypes.node.isRequired,
33
- value: PropTypes.object.isRequired
34
- };
35
- function formatPluginName(pluginSlug) {
36
- switch (pluginSlug) {
37
- case "application":
38
- return "Application";
39
- case "plugin::content-manager":
40
- return "Content manager";
41
- case "plugin::content-type-builder":
42
- return "Content types builder";
43
- case "plugin::documentation":
44
- return "Documentation";
45
- case "plugin::email":
46
- return "Email";
47
- case "plugin::i18n":
48
- return "i18n";
49
- case "plugin::upload":
50
- return "Upload";
51
- case "plugin::users-permissions":
52
- return "Users-permissions";
53
- default:
54
- return upperFirst(pluginSlug.replace("api::", "").replace("plugin::", ""));
55
- }
56
- }
57
- const init$1 = (initialState2, permissions) => {
58
- const collapses = Object.keys(permissions).sort().map((name) => ({ name, isOpen: false }));
59
- return { ...initialState2, collapses };
60
- };
61
- const activeCheckboxWrapperStyles = css`
62
- background: ${(props) => props.theme.colors.primary100};
63
- svg {
64
- opacity: 1;
65
- }
66
- `;
67
- const CheckboxWrapper = styled(Box)`
68
- display: flex;
69
- justify-content: space-between;
70
- align-items: center;
71
-
72
- svg {
73
- opacity: 0;
74
- path {
75
- fill: ${(props) => props.theme.colors.primary600};
76
- }
77
- }
78
-
79
- /* Show active style both on hover and when the action is selected */
80
- ${(props) => props.isActive && activeCheckboxWrapperStyles}
81
- &:hover {
82
- ${activeCheckboxWrapperStyles}
83
- }
84
- `;
85
- const Border = styled.div`
86
- flex: 1;
87
- align-self: center;
88
- border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
89
- `;
90
- const SubCategory = ({ subCategory }) => {
91
- const { formatMessage } = useIntl();
92
- const { onChange, onChangeSelectAll, onSelectedAction, selectedAction, modifiedData } = useUsersPermissions();
93
- const currentScopedModifiedData = useMemo(() => {
94
- return get(modifiedData, subCategory.name, {});
95
- }, [modifiedData, subCategory]);
96
- const hasAllActionsSelected = useMemo(() => {
97
- return Object.values(currentScopedModifiedData).every((action) => action.enabled === true);
98
- }, [currentScopedModifiedData]);
99
- const hasSomeActionsSelected = useMemo(() => {
100
- return Object.values(currentScopedModifiedData).some((action) => action.enabled === true) && !hasAllActionsSelected;
101
- }, [currentScopedModifiedData, hasAllActionsSelected]);
102
- const handleChangeSelectAll = useCallback(
103
- ({ target: { name } }) => {
104
- onChangeSelectAll({ target: { name, value: !hasAllActionsSelected } });
105
- },
106
- [hasAllActionsSelected, onChangeSelectAll]
107
- );
108
- const isActionSelected = useCallback(
109
- (actionName) => {
110
- return selectedAction === actionName;
111
- },
112
- [selectedAction]
113
- );
114
- return /* @__PURE__ */ jsxs(Box, { children: [
115
- /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
116
- /* @__PURE__ */ jsx(Box, { paddingRight: 4, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: subCategory.label }) }),
117
- /* @__PURE__ */ jsx(Border, {}),
118
- /* @__PURE__ */ jsx(Box, { paddingLeft: 4, children: /* @__PURE__ */ jsx(
119
- Checkbox,
120
- {
121
- name: subCategory.name,
122
- value: hasAllActionsSelected,
123
- onValueChange: (value) => handleChangeSelectAll({ target: { name: subCategory.name, value } }),
124
- indeterminate: hasSomeActionsSelected,
125
- children: formatMessage({ id: "app.utils.select-all", defaultMessage: "Select all" })
126
- }
127
- ) })
128
- ] }),
129
- /* @__PURE__ */ jsx(Flex, { paddingTop: 6, paddingBottom: 6, children: /* @__PURE__ */ jsx(Grid, { gap: 2, style: { flex: 1 }, children: subCategory.actions.map((action) => {
130
- const name = `${action.name}.enabled`;
131
- return /* @__PURE__ */ jsx(GridItem, { col: 6, children: /* @__PURE__ */ jsxs(CheckboxWrapper, { isActive: isActionSelected(action.name), padding: 2, hasRadius: true, children: [
132
- /* @__PURE__ */ jsx(
133
- Checkbox,
134
- {
135
- value: get(modifiedData, name, false),
136
- name,
137
- onValueChange: (value) => onChange({ target: { name, value } }),
138
- children: action.label
139
- }
140
- ),
141
- /* @__PURE__ */ jsxs(
142
- "button",
143
- {
144
- type: "button",
145
- onClick: () => onSelectedAction(action.name),
146
- style: { display: "inline-flex", alignItems: "center" },
147
- children: [
148
- /* @__PURE__ */ jsx(VisuallyHidden, { as: "span", children: formatMessage(
149
- {
150
- id: "app.utils.show-bound-route",
151
- defaultMessage: "Show bound route for {route}"
152
- },
153
- {
154
- route: action.name
155
- }
156
- ) }),
157
- /* @__PURE__ */ jsx(Cog, {})
158
- ]
159
- }
160
- )
161
- ] }) }, action.name);
162
- }) }) })
163
- ] });
164
- };
165
- SubCategory.propTypes = {
166
- subCategory: PropTypes.object.isRequired
167
- };
168
- const PermissionRow = ({ name, permissions }) => {
169
- const subCategories = useMemo(() => {
170
- return sortBy(
171
- Object.values(permissions.controllers).reduce((acc, curr, index) => {
172
- const currentName = `${name}.controllers.${Object.keys(permissions.controllers)[index]}`;
173
- const actions = sortBy(
174
- Object.keys(curr).reduce((acc2, current) => {
175
- return [
176
- ...acc2,
177
- {
178
- ...curr[current],
179
- label: current,
180
- name: `${currentName}.${current}`
181
- }
182
- ];
183
- }, []),
184
- "label"
185
- );
186
- return [
187
- ...acc,
188
- {
189
- actions,
190
- label: Object.keys(permissions.controllers)[index],
191
- name: currentName
192
- }
193
- ];
194
- }, []),
195
- "label"
196
- );
197
- }, [name, permissions]);
198
- return /* @__PURE__ */ jsx(Box, { padding: 6, children: subCategories.map((subCategory) => /* @__PURE__ */ jsx(SubCategory, { subCategory }, subCategory.name)) });
199
- };
200
- PermissionRow.propTypes = {
201
- name: PropTypes.string.isRequired,
202
- permissions: PropTypes.object.isRequired
203
- };
204
- const initialState$1 = {
205
- collapses: []
206
- };
207
- const reducer$1 = (state, action) => (
208
- // eslint-disable-next-line consistent-return
209
- produce(state, (draftState) => {
210
- switch (action.type) {
211
- case "TOGGLE_COLLAPSE": {
212
- draftState.collapses = state.collapses.map((collapse, index) => {
213
- if (index === action.index) {
214
- return { ...collapse, isOpen: !collapse.isOpen };
215
- }
216
- return { ...collapse, isOpen: false };
217
- });
218
- break;
219
- }
220
- default:
221
- return draftState;
222
- }
223
- })
224
- );
225
- const Permissions = () => {
226
- const { modifiedData } = useUsersPermissions();
227
- const { formatMessage } = useIntl();
228
- const [{ collapses }, dispatch] = useReducer(
229
- reducer$1,
230
- initialState$1,
231
- (state) => init$1(state, modifiedData)
232
- );
233
- const handleToggle = (index) => dispatch({
234
- type: "TOGGLE_COLLAPSE",
235
- index
236
- });
237
- return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 1, children: collapses.map((collapse, index) => /* @__PURE__ */ jsxs(
238
- Accordion,
239
- {
240
- expanded: collapse.isOpen,
241
- onToggle: () => handleToggle(index),
242
- variant: index % 2 === 0 ? "secondary" : void 0,
243
- children: [
244
- /* @__PURE__ */ jsx(
245
- AccordionToggle,
246
- {
247
- title: formatPluginName(collapse.name),
248
- description: formatMessage(
249
- {
250
- id: "users-permissions.Plugin.permissions.plugins.description",
251
- defaultMessage: "Define all allowed actions for the {name} plugin."
252
- },
253
- { name: collapse.name }
254
- ),
255
- variant: index % 2 ? "primary" : "secondary"
256
- }
257
- ),
258
- /* @__PURE__ */ jsx(AccordionContent, { children: /* @__PURE__ */ jsx(PermissionRow, { permissions: modifiedData[collapse.name], name: collapse.name }) })
259
- ]
260
- },
261
- collapse.name
262
- )) });
263
- };
264
- const getMethodColor = (verb) => {
265
- switch (verb) {
266
- case "POST": {
267
- return {
268
- text: "success600",
269
- border: "success200",
270
- background: "success100"
271
- };
272
- }
273
- case "GET": {
274
- return {
275
- text: "secondary600",
276
- border: "secondary200",
277
- background: "secondary100"
278
- };
279
- }
280
- case "PUT": {
281
- return {
282
- text: "warning600",
283
- border: "warning200",
284
- background: "warning100"
285
- };
286
- }
287
- case "DELETE": {
288
- return {
289
- text: "danger600",
290
- border: "danger200",
291
- background: "danger100"
292
- };
293
- }
294
- default: {
295
- return {
296
- text: "neutral600",
297
- border: "neutral200",
298
- background: "neutral100"
299
- };
300
- }
301
- }
302
- };
303
- const MethodBox = styled(Box)`
304
- margin: -1px;
305
- border-radius: ${({ theme }) => theme.spaces[1]} 0 0 ${({ theme }) => theme.spaces[1]};
306
- `;
307
- function BoundRoute({ route }) {
308
- const { formatMessage } = useIntl();
309
- const { method, handler: title, path } = route;
310
- const formattedRoute = path ? tail(path.split("/")) : [];
311
- const [controller = "", action = ""] = title ? title.split(".") : [];
312
- const colors = getMethodColor(route.method);
313
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
314
- /* @__PURE__ */ jsxs(Typography, { variant: "delta", as: "h3", children: [
315
- formatMessage({
316
- id: "users-permissions.BoundRoute.title",
317
- defaultMessage: "Bound route to"
318
- }),
319
- " ",
320
- /* @__PURE__ */ jsx("span", { children: controller }),
321
- /* @__PURE__ */ jsxs(Typography, { variant: "delta", textColor: "primary600", children: [
322
- ".",
323
- action
324
- ] })
325
- ] }),
326
- /* @__PURE__ */ jsxs(Flex, { hasRadius: true, background: "neutral0", borderColor: "neutral200", gap: 0, children: [
327
- /* @__PURE__ */ jsx(MethodBox, { background: colors.background, borderColor: colors.border, padding: 2, children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: colors.text, children: method }) }),
328
- /* @__PURE__ */ jsx(Box, { paddingLeft: 2, paddingRight: 2, children: map(formattedRoute, (value) => /* @__PURE__ */ jsxs(Typography, { textColor: value.includes(":") ? "neutral600" : "neutral900", children: [
329
- "/",
330
- value
331
- ] }, value)) })
332
- ] })
333
- ] });
334
- }
335
- BoundRoute.defaultProps = {
336
- route: {
337
- handler: "Nocontroller.error",
338
- method: "GET",
339
- path: "/there-is-no-path"
340
- }
341
- };
342
- BoundRoute.propTypes = {
343
- route: PropTypes.shape({
344
- handler: PropTypes.string,
345
- method: PropTypes.string,
346
- path: PropTypes.string
347
- })
348
- };
349
- const Policies = () => {
350
- const { formatMessage } = useIntl();
351
- const { selectedAction, routes } = useUsersPermissions();
352
- const path = without(selectedAction.split("."), "controllers");
353
- const controllerRoutes = get(routes, path[0]);
354
- const pathResolved = path.slice(1).join(".");
355
- const displayedRoutes = isEmpty(controllerRoutes) ? [] : controllerRoutes.filter((o) => o.handler.endsWith(pathResolved));
356
- return /* @__PURE__ */ jsx(
357
- GridItem,
358
- {
359
- col: 5,
360
- background: "neutral150",
361
- paddingTop: 6,
362
- paddingBottom: 6,
363
- paddingLeft: 7,
364
- paddingRight: 7,
365
- style: { minHeight: "100%" },
366
- children: selectedAction ? /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: displayedRoutes.map((route, key) => (
367
- // eslint-disable-next-line react/no-array-index-key
368
- /* @__PURE__ */ jsx(BoundRoute, { route }, key)
369
- )) }) : /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
370
- /* @__PURE__ */ jsx(Typography, { variant: "delta", as: "h3", children: formatMessage({
371
- id: "users-permissions.Policies.header.title",
372
- defaultMessage: "Advanced settings"
373
- }) }),
374
- /* @__PURE__ */ jsx(Typography, { as: "p", textColor: "neutral600", children: formatMessage({
375
- id: "users-permissions.Policies.header.hint",
376
- defaultMessage: "Select the application's actions or the plugin's actions and click on the cog icon to display the bound route"
377
- }) })
378
- ] })
379
- }
380
- );
381
- };
382
- const init = (state, permissions, routes) => {
383
- return {
384
- ...state,
385
- initialData: permissions,
386
- modifiedData: permissions,
387
- routes
388
- };
389
- };
390
- const initialState = {
391
- initialData: {},
392
- modifiedData: {},
393
- routes: {},
394
- selectedAction: "",
395
- policies: []
396
- };
397
- const reducer = (state, action) => produce(state, (draftState) => {
398
- switch (action.type) {
399
- case "ON_CHANGE": {
400
- const keysLength = action.keys.length;
401
- const isChangingCheckbox = action.keys[keysLength - 1] === "enabled";
402
- if (action.value && isChangingCheckbox) {
403
- const selectedAction = take(action.keys, keysLength - 1).join(".");
404
- draftState.selectedAction = selectedAction;
405
- }
406
- set(draftState, ["modifiedData", ...action.keys], action.value);
407
- break;
408
- }
409
- case "ON_CHANGE_SELECT_ALL": {
410
- const pathToValue = ["modifiedData", ...action.keys];
411
- const oldValues = get(state, pathToValue, {});
412
- const updatedValues = Object.keys(oldValues).reduce((acc, current) => {
413
- acc[current] = { ...oldValues[current], enabled: action.value };
414
- return acc;
415
- }, {});
416
- set(draftState, pathToValue, updatedValues);
417
- break;
418
- }
419
- case "ON_RESET": {
420
- draftState.modifiedData = state.initialData;
421
- break;
422
- }
423
- case "ON_SUBMIT_SUCCEEDED": {
424
- draftState.initialData = state.modifiedData;
425
- break;
426
- }
427
- case "SELECT_ACTION": {
428
- const { actionToSelect } = action;
429
- draftState.selectedAction = actionToSelect === state.selectedAction ? "" : actionToSelect;
430
- break;
431
- }
432
- default:
433
- return draftState;
434
- }
435
- });
436
- const UsersPermissions = forwardRef(({ permissions, routes }, ref) => {
437
- const { formatMessage } = useIntl();
438
- const [state, dispatch] = useReducer(
439
- reducer,
440
- initialState,
441
- (state2) => init(state2, permissions, routes)
442
- );
443
- useImperativeHandle(ref, () => ({
444
- getPermissions() {
445
- return {
446
- permissions: state.modifiedData
447
- };
448
- },
449
- resetForm() {
450
- dispatch({ type: "ON_RESET" });
451
- },
452
- setFormAfterSubmit() {
453
- dispatch({ type: "ON_SUBMIT_SUCCEEDED" });
454
- }
455
- }));
456
- const handleChange = ({ target: { name, value } }) => dispatch({
457
- type: "ON_CHANGE",
458
- keys: name.split("."),
459
- value: value === "empty__string_value" ? "" : value
460
- });
461
- const handleChangeSelectAll = ({ target: { name, value } }) => dispatch({
462
- type: "ON_CHANGE_SELECT_ALL",
463
- keys: name.split("."),
464
- value
465
- });
466
- const handleSelectedAction = (actionToSelect) => dispatch({
467
- type: "SELECT_ACTION",
468
- actionToSelect
469
- });
470
- const providerValue = {
471
- ...state,
472
- onChange: handleChange,
473
- onChangeSelectAll: handleChangeSelectAll,
474
- onSelectedAction: handleSelectedAction
475
- };
476
- return /* @__PURE__ */ jsx(UsersPermissionsProvider, { value: providerValue, children: /* @__PURE__ */ jsxs(Grid, { gap: 0, shadow: "filterShadow", hasRadius: true, background: "neutral0", children: [
477
- /* @__PURE__ */ jsx(GridItem, { col: 7, paddingTop: 6, paddingBottom: 6, paddingLeft: 7, paddingRight: 7, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
478
- /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
479
- /* @__PURE__ */ jsx(Typography, { variant: "delta", as: "h2", children: formatMessage({
480
- id: getTrad("Plugins.header.title"),
481
- defaultMessage: "Permissions"
482
- }) }),
483
- /* @__PURE__ */ jsx(Typography, { as: "p", textColor: "neutral600", children: formatMessage({
484
- id: getTrad("Plugins.header.description"),
485
- defaultMessage: "Only actions bound by a route are listed below."
486
- }) })
487
- ] }),
488
- /* @__PURE__ */ jsx(Permissions, {})
489
- ] }) }),
490
- /* @__PURE__ */ jsx(Policies, {})
491
- ] }) });
492
- });
493
- UsersPermissions.propTypes = {
494
- permissions: PropTypes.object.isRequired,
495
- routes: PropTypes.object.isRequired
496
- };
497
- const UsersPermissions$1 = memo(UsersPermissions);
498
- const createRoleSchema = yup.object().shape({
499
- name: yup.string().required(translatedErrors.required.id),
500
- description: yup.string().required(translatedErrors.required.id)
501
- });
502
- const cleanPermissions = (permissions) => Object.keys(permissions).reduce((acc, current) => {
503
- const currentPermission = permissions[current].controllers;
504
- const cleanedControllers = Object.keys(currentPermission).reduce((acc2, curr) => {
505
- if (isEmpty(currentPermission[curr])) {
506
- return acc2;
507
- }
508
- acc2[curr] = currentPermission[curr];
509
- return acc2;
510
- }, {});
511
- if (isEmpty(cleanedControllers)) {
512
- return acc;
513
- }
514
- acc[current] = { controllers: cleanedControllers };
515
- return acc;
516
- }, {});
517
- const usePlugins = () => {
518
- const { toggleNotification } = useNotification();
519
- const { get: get2 } = useFetchClient();
520
- const { formatAPIError } = useAPIErrorHandler(getTrad);
521
- const [
522
- {
523
- data: permissions,
524
- isLoading: isLoadingPermissions,
525
- error: permissionsError,
526
- refetch: refetchPermissions
527
- },
528
- { data: routes, isLoading: isLoadingRoutes, error: routesError, refetch: refetchRoutes }
529
- ] = useQueries([
530
- {
531
- queryKey: ["users-permissions", "permissions"],
532
- async queryFn() {
533
- const {
534
- data: { permissions: permissions2 }
535
- } = await get2(`/users-permissions/permissions`);
536
- return permissions2;
537
- }
538
- },
539
- {
540
- queryKey: ["users-permissions", "routes"],
541
- async queryFn() {
542
- const {
543
- data: { routes: routes2 }
544
- } = await get2(`/users-permissions/routes`);
545
- return routes2;
546
- }
547
- }
548
- ]);
549
- const refetchQueries = async () => {
550
- await Promise.all([refetchPermissions(), refetchRoutes()]);
551
- };
552
- useEffect(() => {
553
- if (permissionsError) {
554
- toggleNotification({
555
- type: "danger",
556
- message: formatAPIError(permissionsError)
557
- });
558
- }
559
- }, [toggleNotification, permissionsError, formatAPIError]);
560
- useEffect(() => {
561
- if (routesError) {
562
- toggleNotification({
563
- type: "danger",
564
- message: formatAPIError(routesError)
565
- });
566
- }
567
- }, [toggleNotification, routesError, formatAPIError]);
568
- const isLoading = isLoadingPermissions || isLoadingRoutes;
569
- return {
570
- // TODO: these return values need to be memoized, otherwise
571
- // they will create infinite rendering loops when used as
572
- // effect dependencies
573
- permissions: permissions ? cleanPermissions(permissions) : {},
574
- routes: routes ?? {},
575
- getData: refetchQueries,
576
- isLoading
577
- };
578
- };
579
- const CreatePage = () => {
580
- const { formatMessage } = useIntl();
581
- const { toggleNotification } = useNotification();
582
- const navigate = useNavigate();
583
- const { isLoading: isLoadingPlugins, permissions, routes } = usePlugins();
584
- const { trackUsage } = useTracking();
585
- const permissionsRef = React.useRef();
586
- const { post } = useFetchClient();
587
- const mutation = useMutation((body) => post(`/users-permissions/roles`, body), {
588
- onError() {
589
- toggleNotification({
590
- type: "danger",
591
- message: formatMessage({
592
- id: "notification.error",
593
- defaultMessage: "An error occurred"
594
- })
595
- });
596
- },
597
- onSuccess() {
598
- trackUsage("didCreateRole");
599
- toggleNotification({
600
- type: "success",
601
- message: formatMessage({
602
- id: getTrad("Settings.roles.created"),
603
- defaultMessage: "Role created"
604
- })
605
- });
606
- navigate(-1);
607
- }
608
- });
609
- const handleCreateRoleSubmit = async (data) => {
610
- const permissions2 = permissionsRef.current.getPermissions();
611
- await mutation.mutate({ ...data, ...permissions2, users: [] });
612
- };
613
- return /* @__PURE__ */ jsxs(Main, { children: [
614
- /* @__PURE__ */ jsx(Page.Title, { children: formatMessage(
615
- { id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
616
- { name: "Roles" }
617
- ) }),
618
- /* @__PURE__ */ jsx(
619
- Formik,
620
- {
621
- enableReinitialize: true,
622
- initialValues: { name: "", description: "" },
623
- onSubmit: handleCreateRoleSubmit,
624
- validationSchema: createRoleSchema,
625
- children: ({ handleSubmit, values, handleChange, errors }) => /* @__PURE__ */ jsxs(Form, { noValidate: true, onSubmit: handleSubmit, children: [
626
- /* @__PURE__ */ jsx(
627
- HeaderLayout,
628
- {
629
- primaryAction: !isLoadingPlugins && /* @__PURE__ */ jsx(Button, { type: "submit", loading: mutation.isLoading, startIcon: /* @__PURE__ */ jsx(Check, {}), children: formatMessage({
630
- id: "global.save",
631
- defaultMessage: "Save"
632
- }) }),
633
- title: formatMessage({
634
- id: "Settings.roles.create.title",
635
- defaultMessage: "Create a role"
636
- }),
637
- subtitle: formatMessage({
638
- id: "Settings.roles.create.description",
639
- defaultMessage: "Define the rights given to the role"
640
- })
641
- }
642
- ),
643
- /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(
644
- Flex,
645
- {
646
- background: "neutral0",
647
- direction: "column",
648
- alignItems: "stretch",
649
- gap: 7,
650
- hasRadius: true,
651
- paddingTop: 6,
652
- paddingBottom: 6,
653
- paddingLeft: 7,
654
- paddingRight: 7,
655
- shadow: "filterShadow",
656
- children: [
657
- /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", children: [
658
- /* @__PURE__ */ jsx(Typography, { variant: "delta", as: "h2", children: formatMessage({
659
- id: getTrad("EditPage.form.roles"),
660
- defaultMessage: "Role details"
661
- }) }),
662
- /* @__PURE__ */ jsxs(Grid, { gap: 4, children: [
663
- /* @__PURE__ */ jsx(GridItem, { col: 6, children: /* @__PURE__ */ jsx(
664
- TextInput,
665
- {
666
- name: "name",
667
- value: values.name || "",
668
- onChange: handleChange,
669
- label: formatMessage({
670
- id: "global.name",
671
- defaultMessage: "Name"
672
- }),
673
- error: errors?.name ? formatMessage({ id: errors.name, defaultMessage: "Name is required" }) : false,
674
- required: true
675
- }
676
- ) }),
677
- /* @__PURE__ */ jsx(GridItem, { col: 6, children: /* @__PURE__ */ jsx(
678
- Textarea,
679
- {
680
- id: "description",
681
- value: values.description || "",
682
- onChange: handleChange,
683
- label: formatMessage({
684
- id: "global.description",
685
- defaultMessage: "Description"
686
- }),
687
- error: errors?.description ? formatMessage({
688
- id: errors.description,
689
- defaultMessage: "Description is required"
690
- }) : false,
691
- required: true
692
- }
693
- ) })
694
- ] })
695
- ] }),
696
- !isLoadingPlugins && /* @__PURE__ */ jsx(
697
- UsersPermissions$1,
698
- {
699
- ref: permissionsRef,
700
- permissions,
701
- routes
702
- }
703
- )
704
- ]
705
- }
706
- ) })
707
- ] })
708
- }
709
- )
710
- ] });
711
- };
712
- const ProtectedRolesCreatePage = () => /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.createRole, children: /* @__PURE__ */ jsx(CreatePage, {}) });
713
- const EditPage = () => {
714
- const { formatMessage } = useIntl();
715
- const { toggleNotification } = useNotification();
716
- const {
717
- params: { id }
718
- } = useMatch(`/settings/users-permissions/roles/:id`);
719
- const { get: get2 } = useFetchClient();
720
- const { isLoading: isLoadingPlugins, routes } = usePlugins();
721
- const {
722
- data: role,
723
- isLoading: isLoadingRole,
724
- refetch: refetchRole
725
- } = useQuery(["users-permissions", "role", id], async () => {
726
- const {
727
- data: { role: role2 }
728
- } = await get2(`/users-permissions/roles/${id}`);
729
- return role2;
730
- });
731
- const permissionsRef = React.useRef();
732
- const { put } = useFetchClient();
733
- const { formatAPIError } = useAPIErrorHandler();
734
- const mutation = useMutation((body) => put(`/users-permissions/roles/${id}`, body), {
735
- onError(error) {
736
- toggleNotification({
737
- type: "danger",
738
- message: formatAPIError(error)
739
- });
740
- },
741
- async onSuccess() {
742
- toggleNotification({
743
- type: "success",
744
- message: formatMessage({
745
- id: getTrad("Settings.roles.created"),
746
- defaultMessage: "Role edited"
747
- })
748
- });
749
- await refetchRole();
750
- }
751
- });
752
- const handleEditRoleSubmit = async (data) => {
753
- const permissions = permissionsRef.current.getPermissions();
754
- await mutation.mutate({ ...data, ...permissions, users: [] });
755
- };
756
- if (isLoadingRole) {
757
- return /* @__PURE__ */ jsx(Page.Loading, {});
758
- }
759
- return /* @__PURE__ */ jsxs(Main, { children: [
760
- /* @__PURE__ */ jsx(Page.Title, { children: formatMessage(
761
- { id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
762
- { name: "Roles" }
763
- ) }),
764
- /* @__PURE__ */ jsx(
765
- Formik,
766
- {
767
- enableReinitialize: true,
768
- initialValues: { name: role.name, description: role.description },
769
- onSubmit: handleEditRoleSubmit,
770
- validationSchema: createRoleSchema,
771
- children: ({ handleSubmit, values, handleChange, errors }) => /* @__PURE__ */ jsxs(Form, { noValidate: true, onSubmit: handleSubmit, children: [
772
- /* @__PURE__ */ jsx(
773
- HeaderLayout,
774
- {
775
- primaryAction: !isLoadingPlugins ? /* @__PURE__ */ jsx(
776
- Button,
777
- {
778
- disabled: role.code === "strapi-super-admin",
779
- type: "submit",
780
- loading: mutation.isLoading,
781
- startIcon: /* @__PURE__ */ jsx(Check, {}),
782
- children: formatMessage({
783
- id: "global.save",
784
- defaultMessage: "Save"
785
- })
786
- }
787
- ) : null,
788
- title: role.name,
789
- subtitle: role.description,
790
- navigationAction: /* @__PURE__ */ jsx(BackButton, {})
791
- }
792
- ),
793
- /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(
794
- Flex,
795
- {
796
- background: "neutral0",
797
- direction: "column",
798
- alignItems: "stretch",
799
- gap: 7,
800
- hasRadius: true,
801
- paddingTop: 6,
802
- paddingBottom: 6,
803
- paddingLeft: 7,
804
- paddingRight: 7,
805
- shadow: "filterShadow",
806
- children: [
807
- /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
808
- /* @__PURE__ */ jsx(Typography, { variant: "delta", as: "h2", children: formatMessage({
809
- id: getTrad("EditPage.form.roles"),
810
- defaultMessage: "Role details"
811
- }) }),
812
- /* @__PURE__ */ jsxs(Grid, { gap: 4, children: [
813
- /* @__PURE__ */ jsx(GridItem, { col: 6, children: /* @__PURE__ */ jsx(
814
- TextInput,
815
- {
816
- name: "name",
817
- value: values.name || "",
818
- onChange: handleChange,
819
- label: formatMessage({
820
- id: "global.name",
821
- defaultMessage: "Name"
822
- }),
823
- error: errors?.name ? formatMessage({ id: errors.name, defaultMessage: "Name is required" }) : false,
824
- required: true
825
- }
826
- ) }),
827
- /* @__PURE__ */ jsx(GridItem, { col: 6, children: /* @__PURE__ */ jsx(
828
- Textarea,
829
- {
830
- id: "description",
831
- value: values.description || "",
832
- onChange: handleChange,
833
- label: formatMessage({
834
- id: "global.description",
835
- defaultMessage: "Description"
836
- }),
837
- error: errors?.description ? formatMessage({
838
- id: errors.description,
839
- defaultMessage: "Description is required"
840
- }) : false,
841
- required: true
842
- }
843
- ) })
844
- ] })
845
- ] }),
846
- !isLoadingPlugins && /* @__PURE__ */ jsx(
847
- UsersPermissions$1,
848
- {
849
- ref: permissionsRef,
850
- permissions: role.permissions,
851
- routes
852
- }
853
- )
854
- ]
855
- }
856
- ) })
857
- ] })
858
- }
859
- )
860
- ] });
861
- };
862
- const ProtectedRolesEditPage = () => /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.updateRole, children: /* @__PURE__ */ jsx(EditPage, {}) });
863
- const EditLink = styled(Link)`
864
- align-items: center;
865
- height: ${32 / 16}rem;
866
- display: flex;
867
- justify-content: center;
868
- padding: ${({ theme }) => `${theme.spaces[2]}}`};
869
- width: ${32 / 16}rem;
870
-
871
- svg {
872
- height: ${12 / 16}rem;
873
- width: ${12 / 16}rem;
874
-
875
- path {
876
- fill: ${({ theme }) => theme.colors.neutral500};
877
- }
878
- }
879
-
880
- &:hover,
881
- &:focus {
882
- svg {
883
- path {
884
- fill: ${({ theme }) => theme.colors.neutral800};
885
- }
886
- }
887
- }
888
- `;
889
- const TableBody = ({ sortedRoles, canDelete, canUpdate, setRoleToDelete, onDelete }) => {
890
- const { formatMessage } = useIntl();
891
- const navigate = useNavigate();
892
- const [showConfirmDelete, setShowConfirmDelete] = onDelete;
893
- const checkCanDeleteRole = (role) => canDelete && !["public", "authenticated"].includes(role.type);
894
- const handleClickDelete = (id) => {
895
- setRoleToDelete(id);
896
- setShowConfirmDelete(!showConfirmDelete);
897
- };
898
- return /* @__PURE__ */ jsx(Tbody, { children: sortedRoles?.map((role) => /* @__PURE__ */ jsxs(Tr, { onClick: () => navigate(role.id.toString()), children: [
899
- /* @__PURE__ */ jsx(Td, { width: "20%", children: /* @__PURE__ */ jsx(Typography, { children: role.name }) }),
900
- /* @__PURE__ */ jsx(Td, { width: "50%", children: /* @__PURE__ */ jsx(Typography, { children: role.description }) }),
901
- /* @__PURE__ */ jsx(Td, { width: "30%", children: /* @__PURE__ */ jsx(Typography, { children: formatMessage(
902
- {
903
- id: "Roles.RoleRow.user-count",
904
- defaultMessage: "{number, plural, =0 {# user} one {# user} other {# users}}"
905
- },
906
- { number: role.nb_users }
907
- ) }) }),
908
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "end", onClick: (e) => e.stopPropagation(), children: [
909
- canUpdate ? /* @__PURE__ */ jsx(
910
- EditLink,
911
- {
912
- to: role.id.toString(),
913
- "aria-label": formatMessage(
914
- { id: "app.component.table.edit", defaultMessage: "Edit {target}" },
915
- { target: `${role.name}` }
916
- ),
917
- children: /* @__PURE__ */ jsx(Pencil, {})
918
- }
919
- ) : null,
920
- checkCanDeleteRole(role) && /* @__PURE__ */ jsx(
921
- IconButton,
922
- {
923
- onClick: () => handleClickDelete(role.id.toString()),
924
- noBorder: true,
925
- icon: /* @__PURE__ */ jsx(Trash, {}),
926
- label: formatMessage(
927
- { id: "global.delete-target", defaultMessage: "Delete {target}" },
928
- { target: `${role.name}` }
929
- )
930
- }
931
- )
932
- ] }) })
933
- ] }, role.name)) });
934
- };
935
- TableBody.defaultProps = {
936
- canDelete: false,
937
- canUpdate: false
938
- };
939
- TableBody.propTypes = {
940
- onDelete: PropTypes.array.isRequired,
941
- permissions: PropTypes.object.isRequired,
942
- setRoleToDelete: PropTypes.func.isRequired,
943
- sortedRoles: PropTypes.array.isRequired,
944
- canDelete: PropTypes.bool,
945
- canUpdate: PropTypes.bool
946
- };
947
- const RolesListPage = () => {
948
- const { trackUsage } = useTracking();
949
- const { formatMessage, locale } = useIntl();
950
- const { toggleNotification } = useNotification();
951
- const { notifyStatus } = useNotifyAT();
952
- const [{ query }] = useQueryParams();
953
- const _q = query?._q || "";
954
- const [showConfirmDelete, setShowConfirmDelete] = useState(false);
955
- const [roleToDelete, setRoleToDelete] = useState();
956
- const { del, get: get2 } = useFetchClient();
957
- const {
958
- isLoading: isLoadingForPermissions,
959
- allowedActions: { canRead, canDelete, canCreate, canUpdate }
960
- } = useRBAC({
961
- create: PERMISSIONS.createRole,
962
- read: PERMISSIONS.readRoles,
963
- update: PERMISSIONS.updateRole,
964
- delete: PERMISSIONS.deleteRole
965
- });
966
- const {
967
- isLoading: isLoadingForData,
968
- data: { roles },
969
- isFetching,
970
- refetch
971
- } = useQuery("get-roles", () => fetchData(toggleNotification, formatMessage, notifyStatus), {
972
- initialData: {},
973
- enabled: canRead
974
- });
975
- const { contains } = useFilter(locale, {
976
- sensitivity: "base"
977
- });
978
- const formatter = useCollator(locale, {
979
- sensitivity: "base"
980
- });
981
- const isLoading = isLoadingForData || isFetching || isLoadingForPermissions;
982
- const handleShowConfirmDelete = () => {
983
- setShowConfirmDelete(!showConfirmDelete);
984
- };
985
- const deleteData = async (id, formatMessage2, toggleNotification2) => {
986
- try {
987
- await del(`/users-permissions/roles/${id}`);
988
- } catch (error) {
989
- toggleNotification2({
990
- type: "danger",
991
- message: formatMessage2({ id: "notification.error", defaultMessage: "An error occured" })
992
- });
993
- }
994
- };
995
- const fetchData = async (toggleNotification2, formatMessage2, notifyStatus2) => {
996
- try {
997
- const { data } = await get2("/users-permissions/roles");
998
- notifyStatus2("The roles have loaded successfully");
999
- return data;
1000
- } catch (err) {
1001
- toggleNotification2({
1002
- type: "danger",
1003
- message: formatMessage2({ id: "notification.error", defaultMessage: "An error occurred" })
1004
- });
1005
- throw new Error(err);
1006
- }
1007
- };
1008
- const emptyLayout = {
1009
- roles: {
1010
- id: getTrad("Roles.empty"),
1011
- defaultMessage: "You don't have any roles yet."
1012
- },
1013
- search: {
1014
- id: getTrad("Roles.empty.search"),
1015
- defaultMessage: "No roles match the search."
1016
- }
1017
- };
1018
- const pageTitle = formatMessage({
1019
- id: "global.roles",
1020
- defaultMessage: "Roles"
1021
- });
1022
- const deleteMutation = useMutation((id) => deleteData(id, formatMessage, toggleNotification), {
1023
- async onSuccess() {
1024
- await refetch();
1025
- }
1026
- });
1027
- const handleConfirmDelete = async () => {
1028
- await deleteMutation.mutateAsync(roleToDelete);
1029
- setShowConfirmDelete(!showConfirmDelete);
1030
- };
1031
- const sortedRoles = (roles || []).filter((role) => contains(role.name, _q) || contains(role.description, _q)).sort(
1032
- (a, b) => formatter.compare(a.name, b.name) || formatter.compare(a.description, b.description)
1033
- );
1034
- const emptyContent = _q && !sortedRoles.length ? "search" : "roles";
1035
- const colCount = 4;
1036
- const rowCount = (roles?.length || 0) + 1;
1037
- if (isLoading) {
1038
- return /* @__PURE__ */ jsx(Page.Loading, {});
1039
- }
1040
- return /* @__PURE__ */ jsxs(Layout, { children: [
1041
- /* @__PURE__ */ jsx(Page.Title, { children: formatMessage(
1042
- { id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
1043
- { name: pageTitle }
1044
- ) }),
1045
- /* @__PURE__ */ jsxs(Page.Main, { children: [
1046
- /* @__PURE__ */ jsx(
1047
- HeaderLayout,
1048
- {
1049
- title: formatMessage({
1050
- id: "global.roles",
1051
- defaultMessage: "Roles"
1052
- }),
1053
- subtitle: formatMessage({
1054
- id: "Settings.roles.list.description",
1055
- defaultMessage: "List of roles"
1056
- }),
1057
- primaryAction: canCreate ? /* @__PURE__ */ jsx(
1058
- LinkButton,
1059
- {
1060
- to: "new",
1061
- as: NavLink,
1062
- onClick: () => trackUsage("willCreateRole"),
1063
- startIcon: /* @__PURE__ */ jsx(Plus, {}),
1064
- size: "S",
1065
- children: formatMessage({
1066
- id: getTrad("List.button.roles"),
1067
- defaultMessage: "Add new role"
1068
- })
1069
- }
1070
- ) : null,
1071
- navigationAction: /* @__PURE__ */ jsx(BackButton, {})
1072
- }
1073
- ),
1074
- /* @__PURE__ */ jsx(
1075
- ActionLayout,
1076
- {
1077
- startActions: /* @__PURE__ */ jsx(
1078
- SearchInput,
1079
- {
1080
- label: formatMessage({
1081
- id: "app.component.search.label",
1082
- defaultMessage: "Search"
1083
- })
1084
- }
1085
- )
1086
- }
1087
- ),
1088
- /* @__PURE__ */ jsxs(ContentLayout, { children: [
1089
- !canRead && /* @__PURE__ */ jsx(Page.NoPermissions, {}),
1090
- canRead && sortedRoles && sortedRoles?.length ? /* @__PURE__ */ jsxs(Table, { colCount, rowCount, children: [
1091
- /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
1092
- /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: formatMessage({ id: "global.name", defaultMessage: "Name" }) }) }),
1093
- /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: formatMessage({
1094
- id: "global.description",
1095
- defaultMessage: "Description"
1096
- }) }) }),
1097
- /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: formatMessage({
1098
- id: "global.users",
1099
- defaultMessage: "Users"
1100
- }) }) }),
1101
- /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(VisuallyHidden, { children: formatMessage({
1102
- id: "global.actions",
1103
- defaultMessage: "Actions"
1104
- }) }) })
1105
- ] }) }),
1106
- /* @__PURE__ */ jsx(
1107
- TableBody,
1108
- {
1109
- sortedRoles,
1110
- canDelete,
1111
- canUpdate,
1112
- permissions: PERMISSIONS,
1113
- setRoleToDelete,
1114
- onDelete: [showConfirmDelete, setShowConfirmDelete]
1115
- }
1116
- )
1117
- ] }) : /* @__PURE__ */ jsx(EmptyStateLayout, { content: formatMessage(emptyLayout[emptyContent]) })
1118
- ] }),
1119
- /* @__PURE__ */ jsx(
1120
- ConfirmDialog,
1121
- {
1122
- onConfirm: handleConfirmDelete,
1123
- onClose: handleShowConfirmDelete,
1124
- isOpen: showConfirmDelete
1125
- }
1126
- )
1127
- ] })
1128
- ] });
1129
- };
1130
- const ProtectedRolesListPage = () => {
1131
- return /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.accessRoles, children: /* @__PURE__ */ jsx(RolesListPage, {}) });
1132
- };
1133
- const Roles = () => {
1134
- return /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.accessRoles, children: /* @__PURE__ */ jsxs(Routes, { children: [
1135
- /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(ProtectedRolesListPage, {}) }),
1136
- /* @__PURE__ */ jsx(Route, { path: "new", element: /* @__PURE__ */ jsx(ProtectedRolesCreatePage, {}) }),
1137
- /* @__PURE__ */ jsx(Route, { path: ":id", element: /* @__PURE__ */ jsx(ProtectedRolesEditPage, {}) })
1138
- ] }) });
1139
- };
1140
- export {
1141
- Roles as default
1142
- };
1143
- //# sourceMappingURL=index-DR9uuqpY.mjs.map