strapi-plugin-oidc 1.5.2 → 1.6.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/README.md +143 -26
- package/dist/admin/{index-DWm8oOJF.js → index-DTOcUHZi.js} +342 -177
- package/dist/admin/{index-Dz3WlTpL.mjs → index-DmJadA2p.mjs} +344 -179
- package/dist/admin/{index-Dzf0bJC1.mjs → index-P9HriRms.mjs} +31 -6
- package/dist/admin/{index-CqgjBmJ5.js → index-f3cmU_tE.js} +31 -6
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +647 -175
- package/dist/server/index.mjs +648 -176
- package/package.json +1 -1
|
@@ -2,10 +2,10 @@ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useBlocker, Routes, Route } from "react-router-dom";
|
|
3
3
|
import { useNotification, useFetchClient, Page, Layouts } from "@strapi/strapi/admin";
|
|
4
4
|
import { useState, useRef, useCallback, useEffect, memo } from "react";
|
|
5
|
-
import { Typography, Flex, Box, MultiSelect, MultiSelectOption, Button,
|
|
6
|
-
import { Download, Upload, Trash,
|
|
5
|
+
import { Typography, Flex, Box, MultiSelect, MultiSelectOption, Dialog, Button, Table, Pagination, PreviousLink, NextLink, PageLink, Field, Divider, Thead, Tr, Th, Tbody, Td, IconButton, Tooltip, Alert } from "@strapi/design-system";
|
|
6
|
+
import { WarningCircle, Download, Upload, Trash, Plus, Information } from "@strapi/icons";
|
|
7
7
|
import { useIntl } from "react-intl";
|
|
8
|
-
import { g as getTrad } from "./index-
|
|
8
|
+
import { g as getTrad } from "./index-P9HriRms.mjs";
|
|
9
9
|
import styled from "styled-components";
|
|
10
10
|
function Role({ oidcRoles, roles, onChangeRole }) {
|
|
11
11
|
const { formatMessage } = useIntl();
|
|
@@ -27,6 +27,20 @@ function Role({ oidcRoles, roles, onChangeRole }) {
|
|
|
27
27
|
) }, oidcRole.oauth_type)) })
|
|
28
28
|
] });
|
|
29
29
|
}
|
|
30
|
+
function LocalizedDate({
|
|
31
|
+
date,
|
|
32
|
+
options
|
|
33
|
+
}) {
|
|
34
|
+
const userLocale = navigator.language || "en-US";
|
|
35
|
+
return new Intl.DateTimeFormat(userLocale, {
|
|
36
|
+
year: "numeric",
|
|
37
|
+
month: "short",
|
|
38
|
+
day: "numeric",
|
|
39
|
+
hour: "2-digit",
|
|
40
|
+
minute: "2-digit",
|
|
41
|
+
...options
|
|
42
|
+
}).format(new Date(date));
|
|
43
|
+
}
|
|
30
44
|
const CustomTable = styled(Table)`
|
|
31
45
|
th,
|
|
32
46
|
td,
|
|
@@ -35,20 +49,96 @@ const CustomTable = styled(Table)`
|
|
|
35
49
|
font-size: 1.3rem !important;
|
|
36
50
|
}
|
|
37
51
|
`;
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
52
|
+
function ConfirmDialog({
|
|
53
|
+
trigger,
|
|
54
|
+
title,
|
|
55
|
+
body,
|
|
56
|
+
confirmLabel,
|
|
57
|
+
onConfirm,
|
|
58
|
+
confirmVariant = "danger"
|
|
59
|
+
}) {
|
|
60
|
+
const { formatMessage } = useIntl();
|
|
61
|
+
return /* @__PURE__ */ jsxs(Dialog.Root, { children: [
|
|
62
|
+
/* @__PURE__ */ jsx(Dialog.Trigger, { children: trigger }),
|
|
63
|
+
/* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
|
64
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
|
65
|
+
/* @__PURE__ */ jsx(Dialog.Body, { icon: /* @__PURE__ */ jsx(WarningCircle, { fill: "danger600" }), children: body }),
|
|
66
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
|
67
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, variant: "tertiary", children: formatMessage(getTrad("page.cancel")) }) }),
|
|
68
|
+
/* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, variant: confirmVariant, onClick: onConfirm, children: confirmLabel }) })
|
|
69
|
+
] })
|
|
70
|
+
] })
|
|
71
|
+
] });
|
|
72
|
+
}
|
|
73
|
+
function TablePagination({ page, pageCount, onPageChange }) {
|
|
74
|
+
const { formatMessage } = useIntl();
|
|
75
|
+
if (pageCount <= 1) return null;
|
|
76
|
+
const pageLink = (num) => /* @__PURE__ */ jsx(
|
|
77
|
+
PageLink,
|
|
78
|
+
{
|
|
79
|
+
number: num,
|
|
80
|
+
href: "#",
|
|
81
|
+
onClick: (e) => {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
onPageChange(num);
|
|
84
|
+
},
|
|
85
|
+
children: formatMessage(getTrad("pagination.page"), { page: num })
|
|
86
|
+
},
|
|
87
|
+
num
|
|
88
|
+
);
|
|
89
|
+
const Ellipsis = () => /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", paddingLeft: 2, paddingRight: 2, children: "…" });
|
|
90
|
+
let pages;
|
|
91
|
+
if (pageCount <= 10) {
|
|
92
|
+
pages = Array.from({ length: pageCount }, (_, i) => pageLink(i + 1));
|
|
93
|
+
} else if (page <= 6) {
|
|
94
|
+
pages = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
95
|
+
Array.from({ length: 9 }, (_, i) => pageLink(i + 1)),
|
|
96
|
+
/* @__PURE__ */ jsx(Ellipsis, {}),
|
|
97
|
+
pageLink(pageCount)
|
|
98
|
+
] });
|
|
99
|
+
} else if (page >= pageCount - 5) {
|
|
100
|
+
pages = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
101
|
+
pageLink(1),
|
|
102
|
+
/* @__PURE__ */ jsx(Ellipsis, {}),
|
|
103
|
+
Array.from({ length: 9 }, (_, i) => pageLink(pageCount - 8 + i))
|
|
104
|
+
] });
|
|
105
|
+
} else {
|
|
106
|
+
pages = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
107
|
+
pageLink(1),
|
|
108
|
+
/* @__PURE__ */ jsx(Ellipsis, {}),
|
|
109
|
+
Array.from({ length: 7 }, (_, i) => pageLink(page - 3 + i)),
|
|
110
|
+
/* @__PURE__ */ jsx(Ellipsis, {}),
|
|
111
|
+
pageLink(pageCount)
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
return /* @__PURE__ */ jsx(Box, { paddingTop: 4, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(Pagination, { activePage: page, pageCount, children: [
|
|
115
|
+
/* @__PURE__ */ jsx(
|
|
116
|
+
PreviousLink,
|
|
117
|
+
{
|
|
118
|
+
href: "#",
|
|
119
|
+
onClick: (e) => {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
onPageChange(Math.max(1, page - 1));
|
|
122
|
+
},
|
|
123
|
+
children: formatMessage(getTrad("pagination.previous"))
|
|
124
|
+
}
|
|
125
|
+
),
|
|
126
|
+
pages,
|
|
127
|
+
/* @__PURE__ */ jsx(
|
|
128
|
+
NextLink,
|
|
129
|
+
{
|
|
130
|
+
href: "#",
|
|
131
|
+
onClick: (e) => {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
onPageChange(Math.min(pageCount, page + 1));
|
|
134
|
+
},
|
|
135
|
+
children: formatMessage(getTrad("pagination.next"))
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
] }) }) });
|
|
47
139
|
}
|
|
48
140
|
function Whitelist({
|
|
49
141
|
users,
|
|
50
|
-
roles,
|
|
51
|
-
oidcRoles = [],
|
|
52
142
|
useWhitelist,
|
|
53
143
|
loading,
|
|
54
144
|
onSave,
|
|
@@ -58,19 +148,13 @@ function Whitelist({
|
|
|
58
148
|
onExport
|
|
59
149
|
}) {
|
|
60
150
|
const [email, setEmail] = useState("");
|
|
61
|
-
const [selectedRoles, setSelectedRoles] = useState([]);
|
|
62
151
|
const [page, setPage] = useState(1);
|
|
63
152
|
const { formatMessage } = useIntl();
|
|
64
153
|
const { toggleNotification } = useNotification();
|
|
65
154
|
const fileInputRef = useRef(null);
|
|
66
|
-
const
|
|
67
|
-
const pageCount = Math.ceil(users.length /
|
|
68
|
-
const paginatedUsers = users.slice((page - 1) *
|
|
69
|
-
const getRoleNames = (roleIds) => roleIds.map((roleId) => {
|
|
70
|
-
const r = roles.find((ro) => String(ro.id) === String(roleId));
|
|
71
|
-
return r ? r.name : roleId;
|
|
72
|
-
}).join(", ");
|
|
73
|
-
const defaultRoleNames = getRoleNames(oidcRoles.flatMap((oidc) => oidc.role ?? []));
|
|
155
|
+
const PAGE_SIZE2 = 10;
|
|
156
|
+
const pageCount = Math.ceil(users.length / PAGE_SIZE2) || 1;
|
|
157
|
+
const paginatedUsers = users.slice((page - 1) * PAGE_SIZE2, page * PAGE_SIZE2);
|
|
74
158
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
75
159
|
const isValidEmail = emailRegex.test(email);
|
|
76
160
|
const onSaveEmail = useCallback(() => {
|
|
@@ -81,11 +165,10 @@ function Whitelist({
|
|
|
81
165
|
message: formatMessage(getTrad("whitelist.error.unique"))
|
|
82
166
|
});
|
|
83
167
|
} else {
|
|
84
|
-
onSave(emailText
|
|
168
|
+
onSave(emailText);
|
|
85
169
|
setEmail("");
|
|
86
|
-
setSelectedRoles([]);
|
|
87
170
|
}
|
|
88
|
-
}, [email,
|
|
171
|
+
}, [email, users, onSave, formatMessage, toggleNotification]);
|
|
89
172
|
const handleImport = useCallback(
|
|
90
173
|
async (e) => {
|
|
91
174
|
const file = e.target.files?.[0];
|
|
@@ -96,11 +179,8 @@ function Whitelist({
|
|
|
96
179
|
const text = await file.text();
|
|
97
180
|
const parsed = JSON.parse(text);
|
|
98
181
|
if (!Array.isArray(parsed)) throw new Error();
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
roles: Array.isArray(item.roles) ? item.roles : []
|
|
102
|
-
}));
|
|
103
|
-
const count = await onImport(entries);
|
|
182
|
+
const emails = parsed.filter((item) => item?.email).map((item) => String(item.email).trim().toLowerCase()).filter((email2) => emailRegex.test(email2));
|
|
183
|
+
const count = await onImport(emails);
|
|
104
184
|
if (count === 0) {
|
|
105
185
|
toggleNotification({
|
|
106
186
|
type: "info",
|
|
@@ -158,19 +238,18 @@ function Whitelist({
|
|
|
158
238
|
onChange: handleImport
|
|
159
239
|
}
|
|
160
240
|
),
|
|
161
|
-
users.length > 0 && /* @__PURE__ */
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
/* @__PURE__ */ jsx(
|
|
165
|
-
|
|
241
|
+
users.length > 0 && /* @__PURE__ */ jsx(
|
|
242
|
+
ConfirmDialog,
|
|
243
|
+
{
|
|
244
|
+
trigger: /* @__PURE__ */ jsx(Button, { size: "S", variant: "danger-light", startIcon: /* @__PURE__ */ jsx(Trash, {}), children: formatMessage(getTrad("whitelist.delete.all.label")) }),
|
|
245
|
+
title: formatMessage(getTrad("whitelist.delete.all.title")),
|
|
246
|
+
body: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", textAlign: "center", children: formatMessage(getTrad("whitelist.delete.all.description"), {
|
|
166
247
|
count: users.length
|
|
167
|
-
}) }) })
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
] })
|
|
173
|
-
] })
|
|
248
|
+
}) }) }),
|
|
249
|
+
confirmLabel: formatMessage(getTrad("whitelist.delete.all.label")),
|
|
250
|
+
onConfirm: onDeleteAll
|
|
251
|
+
}
|
|
252
|
+
)
|
|
174
253
|
] })
|
|
175
254
|
] }),
|
|
176
255
|
/* @__PURE__ */ jsxs(Flex, { gap: 4, marginTop: 5, marginBottom: 5, alignItems: "flex-start", children: [
|
|
@@ -185,18 +264,6 @@ function Whitelist({
|
|
|
185
264
|
placeholder: formatMessage(getTrad("whitelist.email.placeholder"))
|
|
186
265
|
}
|
|
187
266
|
) }) }),
|
|
188
|
-
/* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(Field.Root, { children: /* @__PURE__ */ jsx(
|
|
189
|
-
MultiSelect,
|
|
190
|
-
{
|
|
191
|
-
withTags: true,
|
|
192
|
-
placeholder: formatMessage(getTrad("whitelist.roles.placeholder")),
|
|
193
|
-
value: selectedRoles,
|
|
194
|
-
onChange: (value) => {
|
|
195
|
-
setSelectedRoles(value || []);
|
|
196
|
-
},
|
|
197
|
-
children: roles.map((role) => /* @__PURE__ */ jsx(MultiSelectOption, { value: role.id.toString(), children: role.name }, role.id))
|
|
198
|
-
}
|
|
199
|
-
) }) }),
|
|
200
267
|
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
201
268
|
Button,
|
|
202
269
|
{
|
|
@@ -210,105 +277,216 @@ function Whitelist({
|
|
|
210
277
|
) })
|
|
211
278
|
] }),
|
|
212
279
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
213
|
-
/* @__PURE__ */ jsxs(CustomTable, { colCount:
|
|
280
|
+
/* @__PURE__ */ jsxs(CustomTable, { colCount: 4, rowCount: users.length, children: [
|
|
214
281
|
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
|
|
215
282
|
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("whitelist.table.no")) }),
|
|
216
283
|
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("whitelist.table.email")) }),
|
|
217
|
-
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("whitelist.table.roles")) }),
|
|
218
284
|
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("whitelist.table.created")) }),
|
|
219
285
|
/* @__PURE__ */ jsx(Th, { style: { paddingRight: 0 }, children: " " })
|
|
220
286
|
] }) }),
|
|
221
|
-
/* @__PURE__ */ jsx(Tbody, { children: users.length === 0 ? /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
{
|
|
236
|
-
justifyContent: "flex-end",
|
|
237
|
-
onClick: (e) => e.stopPropagation(),
|
|
238
|
-
style: { width: "100%" },
|
|
239
|
-
children: /* @__PURE__ */ jsxs(Dialog.Root, { children: [
|
|
240
|
-
/* @__PURE__ */ jsx(Dialog.Trigger, { children: /* @__PURE__ */ jsx(
|
|
287
|
+
/* @__PURE__ */ jsx(Tbody, { children: users.length === 0 ? /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 4, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage(getTrad("whitelist.table.empty")) }) }) }) }) : paginatedUsers.map((user, index) => /* @__PURE__ */ jsxs(Tr, { children: [
|
|
288
|
+
/* @__PURE__ */ jsx(Td, { children: index + 1 + (page - 1) * PAGE_SIZE2 }),
|
|
289
|
+
/* @__PURE__ */ jsx(Td, { children: user.email }),
|
|
290
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(LocalizedDate, { date: user.createdAt, options: { month: "long" } }) }),
|
|
291
|
+
/* @__PURE__ */ jsx(Td, { style: { paddingRight: 0 }, children: /* @__PURE__ */ jsx(
|
|
292
|
+
Flex,
|
|
293
|
+
{
|
|
294
|
+
justifyContent: "flex-end",
|
|
295
|
+
onClick: (e) => e.stopPropagation(),
|
|
296
|
+
style: { width: "100%" },
|
|
297
|
+
children: /* @__PURE__ */ jsx(
|
|
298
|
+
ConfirmDialog,
|
|
299
|
+
{
|
|
300
|
+
trigger: /* @__PURE__ */ jsx(
|
|
241
301
|
IconButton,
|
|
242
302
|
{
|
|
243
303
|
label: formatMessage(getTrad("whitelist.delete.label")),
|
|
244
304
|
withTooltip: false,
|
|
245
305
|
children: /* @__PURE__ */ jsx(Trash, {})
|
|
246
306
|
}
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
/* @__PURE__ */ jsx(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
307
|
+
),
|
|
308
|
+
title: formatMessage(getTrad("whitelist.delete.title")),
|
|
309
|
+
body: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
|
|
310
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { id: "confirm-description", children: formatMessage(getTrad("whitelist.delete.description")) }) }),
|
|
311
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: user.email }) }),
|
|
312
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", marginTop: 2, children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(getTrad("whitelist.delete.note")) }) })
|
|
313
|
+
] }),
|
|
314
|
+
confirmLabel: formatMessage(getTrad("page.ok")),
|
|
315
|
+
onConfirm: () => onDelete(user.email),
|
|
316
|
+
confirmVariant: "danger-light"
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
) })
|
|
321
|
+
] }, user.email)) })
|
|
322
|
+
] }),
|
|
323
|
+
/* @__PURE__ */ jsx(TablePagination, { page, pageCount, onPageChange: setPage })
|
|
324
|
+
] })
|
|
325
|
+
] });
|
|
326
|
+
}
|
|
327
|
+
const PAGE_SIZE = 10;
|
|
328
|
+
const DETAILS_TEXT_STYLE = {
|
|
329
|
+
display: "block",
|
|
330
|
+
overflow: "hidden",
|
|
331
|
+
textOverflow: "ellipsis",
|
|
332
|
+
whiteSpace: "nowrap",
|
|
333
|
+
maxWidth: "180px",
|
|
334
|
+
cursor: "help"
|
|
335
|
+
};
|
|
336
|
+
function AuditLog() {
|
|
337
|
+
const { formatMessage } = useIntl();
|
|
338
|
+
const { get, del } = useFetchClient();
|
|
339
|
+
const { toggleNotification } = useNotification();
|
|
340
|
+
const [records, setRecords] = useState([]);
|
|
341
|
+
const [pagination, setPagination] = useState({
|
|
342
|
+
page: 1,
|
|
343
|
+
pageSize: PAGE_SIZE,
|
|
344
|
+
total: 0,
|
|
345
|
+
pageCount: 1
|
|
346
|
+
});
|
|
347
|
+
const [page, setPage] = useState(1);
|
|
348
|
+
const [loading, setLoading] = useState(false);
|
|
349
|
+
const fetchLogs = useCallback(
|
|
350
|
+
async (p) => {
|
|
351
|
+
setLoading(true);
|
|
352
|
+
try {
|
|
353
|
+
const response = await get(
|
|
354
|
+
`/strapi-plugin-oidc/audit-logs?page=${p}&pageSize=${PAGE_SIZE}`
|
|
355
|
+
);
|
|
356
|
+
setRecords(response.data.results ?? []);
|
|
357
|
+
setPagination(
|
|
358
|
+
response.data.pagination ?? { page: p, pageSize: PAGE_SIZE, total: 0, pageCount: 1 }
|
|
359
|
+
);
|
|
360
|
+
} catch {
|
|
361
|
+
setRecords([]);
|
|
362
|
+
} finally {
|
|
363
|
+
setLoading(false);
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
[get]
|
|
367
|
+
);
|
|
368
|
+
useEffect(() => {
|
|
369
|
+
fetchLogs(page);
|
|
370
|
+
}, [fetchLogs, page]);
|
|
371
|
+
const handleClearAll = async () => {
|
|
372
|
+
try {
|
|
373
|
+
await del("/strapi-plugin-oidc/audit-logs");
|
|
374
|
+
toggleNotification({
|
|
375
|
+
type: "success",
|
|
376
|
+
message: formatMessage(getTrad("auditlog.clear.success"))
|
|
377
|
+
});
|
|
378
|
+
fetchLogs(1);
|
|
379
|
+
} catch {
|
|
380
|
+
toggleNotification({
|
|
381
|
+
type: "danger",
|
|
382
|
+
message: formatMessage(getTrad("auditlog.clear.error"))
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
const handleExport = async () => {
|
|
387
|
+
try {
|
|
388
|
+
const cookieMatch = document.cookie.match(/(?:^|;\s*)jwtToken=([^;]+)/);
|
|
389
|
+
const token = cookieMatch ? decodeURIComponent(cookieMatch[1]) : "";
|
|
390
|
+
const response = await fetch("/strapi-plugin-oidc/audit-logs/export", {
|
|
391
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
392
|
+
});
|
|
393
|
+
if (!response.ok) {
|
|
394
|
+
toggleNotification({
|
|
395
|
+
type: "danger",
|
|
396
|
+
message: formatMessage(getTrad("auditlog.export.error"))
|
|
397
|
+
});
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const text = await response.text();
|
|
401
|
+
const blob = new Blob([text], { type: "application/x-ndjson" });
|
|
402
|
+
const url = URL.createObjectURL(blob);
|
|
403
|
+
const a = document.createElement("a");
|
|
404
|
+
a.href = url;
|
|
405
|
+
a.download = `oidc-audit-log-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.ndjson`;
|
|
406
|
+
a.click();
|
|
407
|
+
URL.revokeObjectURL(url);
|
|
408
|
+
} catch {
|
|
409
|
+
toggleNotification({
|
|
410
|
+
type: "danger",
|
|
411
|
+
message: formatMessage(getTrad("auditlog.export.error"))
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
416
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, children: [
|
|
417
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
418
|
+
pagination.total,
|
|
419
|
+
" ",
|
|
420
|
+
pagination.total === 1 ? "entry" : "entries"
|
|
273
421
|
] }),
|
|
274
|
-
|
|
422
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
275
423
|
/* @__PURE__ */ jsx(
|
|
276
|
-
|
|
424
|
+
Button,
|
|
277
425
|
{
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
children: formatMessage(getTrad("
|
|
426
|
+
size: "S",
|
|
427
|
+
variant: "tertiary",
|
|
428
|
+
startIcon: /* @__PURE__ */ jsx(Download, {}),
|
|
429
|
+
onClick: handleExport,
|
|
430
|
+
disabled: pagination.total === 0,
|
|
431
|
+
children: formatMessage(getTrad("auditlog.export"))
|
|
284
432
|
}
|
|
285
433
|
),
|
|
286
|
-
Array.from({ length: pageCount }).map((_, i) => /* @__PURE__ */ jsx(
|
|
287
|
-
PageLink,
|
|
288
|
-
{
|
|
289
|
-
number: i + 1,
|
|
290
|
-
href: "#",
|
|
291
|
-
onClick: (e) => {
|
|
292
|
-
e.preventDefault();
|
|
293
|
-
setPage(i + 1);
|
|
294
|
-
},
|
|
295
|
-
children: formatMessage(getTrad("pagination.page"), { page: i + 1 })
|
|
296
|
-
},
|
|
297
|
-
i + 1
|
|
298
|
-
)),
|
|
299
434
|
/* @__PURE__ */ jsx(
|
|
300
|
-
|
|
435
|
+
ConfirmDialog,
|
|
301
436
|
{
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
437
|
+
trigger: /* @__PURE__ */ jsx(
|
|
438
|
+
Button,
|
|
439
|
+
{
|
|
440
|
+
size: "S",
|
|
441
|
+
variant: "danger-light",
|
|
442
|
+
startIcon: /* @__PURE__ */ jsx(Trash, {}),
|
|
443
|
+
disabled: pagination.total === 0,
|
|
444
|
+
children: formatMessage(getTrad("auditlog.clear"))
|
|
445
|
+
}
|
|
446
|
+
),
|
|
447
|
+
title: formatMessage(getTrad("auditlog.clear.title")),
|
|
448
|
+
body: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", textAlign: "center", children: formatMessage(getTrad("auditlog.clear.description"), {
|
|
449
|
+
count: pagination.total
|
|
450
|
+
}) }) }),
|
|
451
|
+
confirmLabel: formatMessage(getTrad("auditlog.clear")),
|
|
452
|
+
onConfirm: handleClearAll
|
|
308
453
|
}
|
|
309
454
|
)
|
|
310
|
-
] })
|
|
311
|
-
] })
|
|
455
|
+
] })
|
|
456
|
+
] }),
|
|
457
|
+
/* @__PURE__ */ jsxs(CustomTable, { colCount: 5, rowCount: records.length, children: [
|
|
458
|
+
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
|
|
459
|
+
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.timestamp")) }),
|
|
460
|
+
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.action")) }),
|
|
461
|
+
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.email")) }),
|
|
462
|
+
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.ip")) }),
|
|
463
|
+
/* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.details")) })
|
|
464
|
+
] }) }),
|
|
465
|
+
/* @__PURE__ */ jsxs(Tbody, { children: [
|
|
466
|
+
loading && /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 5, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: "Loading…" }) }) }) }),
|
|
467
|
+
!loading && records.length === 0 && /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 5, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage(getTrad("auditlog.table.empty")) }) }) }) }),
|
|
468
|
+
!loading && records.map((record) => /* @__PURE__ */ jsxs(Tr, { children: [
|
|
469
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: /* @__PURE__ */ jsx(LocalizedDate, { date: record.createdAt, options: { second: "2-digit" } }) }) }),
|
|
470
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
471
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.action }),
|
|
472
|
+
/* @__PURE__ */ jsx(Tooltip, { label: formatMessage(getTrad(`auditlog.action.${record.action}`)), children: /* @__PURE__ */ jsx(
|
|
473
|
+
Information,
|
|
474
|
+
{
|
|
475
|
+
"aria-hidden": true,
|
|
476
|
+
style: { cursor: "help" },
|
|
477
|
+
width: "1.4rem",
|
|
478
|
+
height: "1.4rem",
|
|
479
|
+
fill: "primary600"
|
|
480
|
+
}
|
|
481
|
+
) })
|
|
482
|
+
] }) }),
|
|
483
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.email ?? "—" }) }),
|
|
484
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.ip ?? "—" }) }),
|
|
485
|
+
/* @__PURE__ */ jsx(Td, { style: { maxWidth: "200px" }, children: record.details ? /* @__PURE__ */ jsx(Tooltip, { label: record.details, side: "top", children: /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: DETAILS_TEXT_STYLE, children: record.details }) }) : /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", children: "—" }) })
|
|
486
|
+
] }, record.id))
|
|
487
|
+
] })
|
|
488
|
+
] }),
|
|
489
|
+
/* @__PURE__ */ jsx(TablePagination, { page, pageCount: pagination.pageCount, onPageChange: setPage })
|
|
312
490
|
] });
|
|
313
491
|
}
|
|
314
492
|
const AlertMessage = styled.div`
|
|
@@ -345,23 +523,6 @@ function ErrorAlertMessage({ onClose }) {
|
|
|
345
523
|
}
|
|
346
524
|
) });
|
|
347
525
|
}
|
|
348
|
-
function MatchedUserAlertMessage({
|
|
349
|
-
onClose,
|
|
350
|
-
count
|
|
351
|
-
}) {
|
|
352
|
-
const { formatMessage } = useIntl();
|
|
353
|
-
const id = count > 1 ? "whitelist.users_exists" : "whitelist.user_exists";
|
|
354
|
-
return /* @__PURE__ */ jsx(AlertMessage, { children: /* @__PURE__ */ jsx(
|
|
355
|
-
Alert,
|
|
356
|
-
{
|
|
357
|
-
title: formatMessage(getTrad("alert.title.info")),
|
|
358
|
-
variant: "default",
|
|
359
|
-
closeLabel: "",
|
|
360
|
-
onClose,
|
|
361
|
-
children: formatMessage(getTrad(id))
|
|
362
|
-
}
|
|
363
|
-
) });
|
|
364
|
-
}
|
|
365
526
|
const SwitchContainer = styled.label`
|
|
366
527
|
position: relative;
|
|
367
528
|
display: inline-block;
|
|
@@ -431,6 +592,15 @@ function CustomSwitch({ checked, onChange, label, disabled }) {
|
|
|
431
592
|
label && /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", textColor: disabled ? "neutral500" : "neutral800", children: label })
|
|
432
593
|
] });
|
|
433
594
|
}
|
|
595
|
+
function formatDatetimeForFilename(date) {
|
|
596
|
+
const year = date.getFullYear();
|
|
597
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
598
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
599
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
600
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
601
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
602
|
+
return `${year}${month}${day}_${hours}${minutes}${seconds}`;
|
|
603
|
+
}
|
|
434
604
|
function deepClone(value) {
|
|
435
605
|
return JSON.parse(JSON.stringify(value));
|
|
436
606
|
}
|
|
@@ -439,7 +609,6 @@ function useOidcSettings() {
|
|
|
439
609
|
const [loading, setLoading] = useState(false);
|
|
440
610
|
const [showSuccess, setSuccess] = useState(false);
|
|
441
611
|
const [showError, setError] = useState(false);
|
|
442
|
-
const [showMatched, setMatched] = useState(0);
|
|
443
612
|
const [initialOidcRoles, setInitialOIDCRoles] = useState([]);
|
|
444
613
|
const [oidcRoles, setOIDCRoles] = useState([]);
|
|
445
614
|
const [roles, setRoles] = useState([]);
|
|
@@ -450,6 +619,7 @@ function useOidcSettings() {
|
|
|
450
619
|
const [enforceOIDCConfig, setEnforceOIDCConfig] = useState(null);
|
|
451
620
|
const [initialUsers, setInitialUsers] = useState([]);
|
|
452
621
|
const [users, setUsers] = useState([]);
|
|
622
|
+
const [whitelistResponse, setWhitelistResponse] = useState({});
|
|
453
623
|
useEffect(() => {
|
|
454
624
|
get(`/strapi-plugin-oidc/oidc-roles`).then((response) => {
|
|
455
625
|
setOIDCRoles(response.data);
|
|
@@ -459,6 +629,7 @@ function useOidcSettings() {
|
|
|
459
629
|
setRoles(response.data.data);
|
|
460
630
|
});
|
|
461
631
|
get("/strapi-plugin-oidc/whitelist").then((response) => {
|
|
632
|
+
setWhitelistResponse(response.data);
|
|
462
633
|
setUsers(response.data.whitelistUsers);
|
|
463
634
|
setInitialUsers(deepClone(response.data.whitelistUsers));
|
|
464
635
|
setUseWhitelist(response.data.useWhitelist);
|
|
@@ -474,8 +645,8 @@ function useOidcSettings() {
|
|
|
474
645
|
);
|
|
475
646
|
setOIDCRoles(updatedRoles);
|
|
476
647
|
};
|
|
477
|
-
const onRegisterWhitelist = (email
|
|
478
|
-
const newUser = { email,
|
|
648
|
+
const onRegisterWhitelist = (email) => {
|
|
649
|
+
const newUser = { email, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
479
650
|
setUsers([...users, newUser]);
|
|
480
651
|
};
|
|
481
652
|
const onDeleteWhitelist = (email) => {
|
|
@@ -489,21 +660,19 @@ function useOidcSettings() {
|
|
|
489
660
|
setUsers([]);
|
|
490
661
|
if (useWhitelist) setEnforceOIDC(false);
|
|
491
662
|
};
|
|
492
|
-
const onImport = async (
|
|
493
|
-
const response = await post("/strapi-plugin-oidc/whitelist/import", {
|
|
663
|
+
const onImport = async (emails) => {
|
|
664
|
+
const response = await post("/strapi-plugin-oidc/whitelist/import", {
|
|
665
|
+
users: emails.map((e) => ({ email: e }))
|
|
666
|
+
});
|
|
494
667
|
const refreshed = await get("/strapi-plugin-oidc/whitelist");
|
|
495
668
|
setUsers(refreshed.data.whitelistUsers);
|
|
496
669
|
setInitialUsers(deepClone(refreshed.data.whitelistUsers));
|
|
497
670
|
return response.data.importedCount;
|
|
498
671
|
};
|
|
499
|
-
const onExport = () => {
|
|
500
|
-
const
|
|
501
|
-
const data =
|
|
502
|
-
|
|
503
|
-
roles: (userRoles || []).map((id) => roleMap.get(String(id)) ?? id)
|
|
504
|
-
}));
|
|
505
|
-
const now = /* @__PURE__ */ new Date();
|
|
506
|
-
const datetime = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}${String(now.getSeconds()).padStart(2, "0")}`;
|
|
672
|
+
const onExport = async () => {
|
|
673
|
+
const response = await get("/strapi-plugin-oidc/whitelist/export");
|
|
674
|
+
const data = response.data;
|
|
675
|
+
const datetime = formatDatetimeForFilename(/* @__PURE__ */ new Date());
|
|
507
676
|
const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
|
|
508
677
|
const url = URL.createObjectURL(blob);
|
|
509
678
|
const a = document.createElement("a");
|
|
@@ -532,8 +701,8 @@ function useOidcSettings() {
|
|
|
532
701
|
role: role.role
|
|
533
702
|
}))
|
|
534
703
|
});
|
|
535
|
-
|
|
536
|
-
users: users.map((u) => ({ email: u.email
|
|
704
|
+
await put("/strapi-plugin-oidc/whitelist/sync", {
|
|
705
|
+
users: users.map((u) => ({ email: u.email }))
|
|
537
706
|
});
|
|
538
707
|
await put("/strapi-plugin-oidc/whitelist/settings", {
|
|
539
708
|
useWhitelist,
|
|
@@ -543,16 +712,12 @@ function useOidcSettings() {
|
|
|
543
712
|
setInitialUseWhitelist(useWhitelist);
|
|
544
713
|
setInitialEnforceOIDC(enforceOIDC);
|
|
545
714
|
get("/strapi-plugin-oidc/whitelist").then((getResponse) => {
|
|
715
|
+
setWhitelistResponse(getResponse.data);
|
|
546
716
|
setUsers(getResponse.data.whitelistUsers);
|
|
547
717
|
setInitialUsers(deepClone(getResponse.data.whitelistUsers));
|
|
548
718
|
});
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
setTimeout(() => setMatched(0), 3e3);
|
|
552
|
-
} else {
|
|
553
|
-
setSuccess(true);
|
|
554
|
-
setTimeout(() => setSuccess(false), 3e3);
|
|
555
|
-
}
|
|
719
|
+
setSuccess(true);
|
|
720
|
+
setTimeout(() => setSuccess(false), 3e3);
|
|
556
721
|
} catch (e) {
|
|
557
722
|
console.error(e);
|
|
558
723
|
setError(true);
|
|
@@ -566,7 +731,6 @@ function useOidcSettings() {
|
|
|
566
731
|
loading,
|
|
567
732
|
showSuccess,
|
|
568
733
|
showError,
|
|
569
|
-
showMatched,
|
|
570
734
|
oidcRoles,
|
|
571
735
|
roles,
|
|
572
736
|
useWhitelist,
|
|
@@ -574,12 +738,12 @@ function useOidcSettings() {
|
|
|
574
738
|
enforceOIDCConfig,
|
|
575
739
|
initialEnforceOIDC,
|
|
576
740
|
users,
|
|
577
|
-
isDirty
|
|
741
|
+
isDirty,
|
|
742
|
+
auditLogEnabled: whitelistResponse.auditLogEnabled ?? true
|
|
578
743
|
},
|
|
579
744
|
actions: {
|
|
580
745
|
setSuccess,
|
|
581
746
|
setError,
|
|
582
|
-
setMatched,
|
|
583
747
|
onChangeRole,
|
|
584
748
|
onRegisterWhitelist,
|
|
585
749
|
onDeleteWhitelist,
|
|
@@ -606,7 +770,6 @@ function HomePage() {
|
|
|
606
770
|
),
|
|
607
771
|
state.showSuccess && /* @__PURE__ */ jsx(SuccessAlertMessage, { onClose: () => actions.setSuccess(false) }),
|
|
608
772
|
state.showError && /* @__PURE__ */ jsx(ErrorAlertMessage, { onClose: () => actions.setError(false) }),
|
|
609
|
-
state.showMatched > 0 && /* @__PURE__ */ jsx(MatchedUserAlertMessage, { count: state.showMatched, onClose: () => actions.setMatched(0) }),
|
|
610
773
|
/* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
611
774
|
/* @__PURE__ */ jsxs(Box, { background: "neutral0", hasRadius: true, shadow: "filterShadow", padding: 6, children: [
|
|
612
775
|
/* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: formatMessage(getTrad("roles.title")) }) }),
|
|
@@ -636,8 +799,6 @@ function HomePage() {
|
|
|
636
799
|
{
|
|
637
800
|
loading: state.loading,
|
|
638
801
|
users: state.users,
|
|
639
|
-
roles: state.roles,
|
|
640
|
-
oidcRoles: state.oidcRoles,
|
|
641
802
|
useWhitelist: state.useWhitelist,
|
|
642
803
|
onSave: actions.onRegisterWhitelist,
|
|
643
804
|
onDelete: actions.onDeleteWhitelist,
|
|
@@ -681,7 +842,11 @@ function HomePage() {
|
|
|
681
842
|
loading: state.loading,
|
|
682
843
|
children: formatMessage(getTrad("page.save"))
|
|
683
844
|
}
|
|
684
|
-
) })
|
|
845
|
+
) }),
|
|
846
|
+
state.auditLogEnabled && /* @__PURE__ */ jsxs(Box, { background: "neutral0", hasRadius: true, shadow: "filterShadow", padding: 6, children: [
|
|
847
|
+
/* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: formatMessage(getTrad("auditlog.title")) }) }),
|
|
848
|
+
/* @__PURE__ */ jsx(AuditLog, {})
|
|
849
|
+
] })
|
|
685
850
|
] }) }),
|
|
686
851
|
/* @__PURE__ */ jsx(Dialog.Root, { open: blocker.state === "blocked", children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
|
687
852
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage(getTrad("unsaved.title")) }),
|