strapi-plugin-oidc 1.3.2 → 1.4.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 +93 -44
- package/dist/admin/{index-D1ypRUlq.mjs → index-8hB6LKml.mjs} +15 -2
- package/dist/admin/{index-CFmg9Kxl.mjs → index-BTTGSnuQ.mjs} +142 -9
- package/dist/admin/{index-Cse9ex24.js → index-CZDixCh4.js} +15 -2
- package/dist/admin/{index-BqyGGX8X.js → index-QZkv75Xp.js} +138 -5
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +169 -126
- package/dist/server/index.mjs +169 -126
- package/package.json +11 -4
|
@@ -7,7 +7,7 @@ const react = require("react");
|
|
|
7
7
|
const designSystem = require("@strapi/design-system");
|
|
8
8
|
const icons = require("@strapi/icons");
|
|
9
9
|
const reactIntl = require("react-intl");
|
|
10
|
-
const index = require("./index-
|
|
10
|
+
const index = require("./index-CZDixCh4.js");
|
|
11
11
|
const styled = require("styled-components");
|
|
12
12
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
13
13
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
@@ -56,13 +56,17 @@ function Whitelist({
|
|
|
56
56
|
useWhitelist,
|
|
57
57
|
loading,
|
|
58
58
|
onSave,
|
|
59
|
-
onDelete
|
|
59
|
+
onDelete,
|
|
60
|
+
onDeleteAll,
|
|
61
|
+
onImport,
|
|
62
|
+
onExport
|
|
60
63
|
}) {
|
|
61
64
|
const [email, setEmail] = react.useState("");
|
|
62
65
|
const [selectedRoles, setSelectedRoles] = react.useState([]);
|
|
63
66
|
const [page, setPage] = react.useState(1);
|
|
64
67
|
const { formatMessage } = reactIntl.useIntl();
|
|
65
68
|
const { toggleNotification } = admin.useNotification();
|
|
69
|
+
const fileInputRef = react.useRef(null);
|
|
66
70
|
const PAGE_SIZE = 10;
|
|
67
71
|
const pageCount = Math.ceil(users.length / PAGE_SIZE) || 1;
|
|
68
72
|
const paginatedUsers = users.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
|
|
@@ -83,9 +87,93 @@ function Whitelist({
|
|
|
83
87
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
84
88
|
return emailRegex.test(email);
|
|
85
89
|
}, [email]);
|
|
90
|
+
const handleImport = react.useCallback(
|
|
91
|
+
async (e) => {
|
|
92
|
+
const file = e.target.files?.[0];
|
|
93
|
+
if (!fileInputRef.current) return;
|
|
94
|
+
fileInputRef.current.value = "";
|
|
95
|
+
if (!file) return;
|
|
96
|
+
try {
|
|
97
|
+
const text = await file.text();
|
|
98
|
+
const parsed = JSON.parse(text);
|
|
99
|
+
if (!Array.isArray(parsed)) throw new Error();
|
|
100
|
+
const entries = parsed.filter((item) => item?.email).map((item) => ({
|
|
101
|
+
email: String(item.email),
|
|
102
|
+
roles: Array.isArray(item.roles) ? item.roles : []
|
|
103
|
+
}));
|
|
104
|
+
const count = await onImport(entries);
|
|
105
|
+
if (count === 0) {
|
|
106
|
+
toggleNotification({
|
|
107
|
+
type: "info",
|
|
108
|
+
message: formatMessage(index.getTrad("whitelist.import.none"))
|
|
109
|
+
});
|
|
110
|
+
} else {
|
|
111
|
+
toggleNotification({
|
|
112
|
+
type: "success",
|
|
113
|
+
message: formatMessage(index.getTrad("whitelist.import.success"), { count })
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
toggleNotification({
|
|
118
|
+
type: "warning",
|
|
119
|
+
message: formatMessage(index.getTrad("whitelist.import.error"))
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
[onImport, formatMessage, toggleNotification]
|
|
124
|
+
);
|
|
86
125
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
87
126
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textColor: "neutral600", marginBottom: 4, children: formatMessage(index.getTrad("whitelist.description")) }),
|
|
88
127
|
useWhitelist && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
128
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, children: [
|
|
129
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(index.getTrad("whitelist.count"), { count: users.length }) }),
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
132
|
+
designSystem.Button,
|
|
133
|
+
{
|
|
134
|
+
size: "S",
|
|
135
|
+
variant: "tertiary",
|
|
136
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
|
|
137
|
+
onClick: onExport,
|
|
138
|
+
disabled: users.length === 0,
|
|
139
|
+
children: formatMessage(index.getTrad("whitelist.export"))
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
143
|
+
designSystem.Button,
|
|
144
|
+
{
|
|
145
|
+
size: "S",
|
|
146
|
+
variant: "tertiary",
|
|
147
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Upload, {}),
|
|
148
|
+
onClick: () => fileInputRef.current?.click(),
|
|
149
|
+
children: formatMessage(index.getTrad("whitelist.import"))
|
|
150
|
+
}
|
|
151
|
+
),
|
|
152
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
153
|
+
"input",
|
|
154
|
+
{
|
|
155
|
+
ref: fileInputRef,
|
|
156
|
+
type: "file",
|
|
157
|
+
accept: ".json,application/json",
|
|
158
|
+
style: { display: "none" },
|
|
159
|
+
onChange: handleImport
|
|
160
|
+
}
|
|
161
|
+
),
|
|
162
|
+
users.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Root, { children: [
|
|
163
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "danger-light", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}), children: formatMessage(index.getTrad("whitelist.delete.all.label")) }) }),
|
|
164
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
|
165
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage(index.getTrad("whitelist.delete.all.title")) }),
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { fill: "danger600" }), children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", textAlign: "center", children: formatMessage(index.getTrad("whitelist.delete.all.description"), {
|
|
167
|
+
count: users.length
|
|
168
|
+
}) }) }) }),
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, variant: "tertiary", children: formatMessage(index.getTrad("page.cancel")) }) }),
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, variant: "danger", onClick: onDeleteAll, children: formatMessage(index.getTrad("whitelist.delete.all.label")) }) })
|
|
172
|
+
] })
|
|
173
|
+
] })
|
|
174
|
+
] })
|
|
175
|
+
] })
|
|
176
|
+
] }),
|
|
89
177
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, marginTop: 5, marginBottom: 5, alignItems: "flex-start", children: [
|
|
90
178
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
91
179
|
designSystem.Field.Input,
|
|
@@ -137,17 +225,22 @@ function Whitelist({
|
|
|
137
225
|
return r ? r.name : roleId;
|
|
138
226
|
}).join(", ");
|
|
139
227
|
let userRolesNames = getRoleNames(user.roles || []);
|
|
228
|
+
let isDefault = false;
|
|
140
229
|
if (!userRolesNames) {
|
|
141
230
|
const defaultRolesIds = oidcRoles.reduce((acc, oidc) => {
|
|
142
231
|
if (oidc.role) acc.push(...oidc.role);
|
|
143
232
|
return acc;
|
|
144
233
|
}, []);
|
|
145
234
|
userRolesNames = getRoleNames(defaultRolesIds);
|
|
235
|
+
isDefault = Boolean(userRolesNames);
|
|
146
236
|
}
|
|
147
237
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
148
238
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: index$1 + 1 + (page - 1) * PAGE_SIZE }),
|
|
149
239
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: user.email }),
|
|
150
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: userRolesNames
|
|
240
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: userRolesNames ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
241
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: userRolesNames }),
|
|
242
|
+
isDefault && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "(Default)" })
|
|
243
|
+
] }) : "-" }),
|
|
151
244
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(LocalizedDate, { date: user.createdAt }) }),
|
|
152
245
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { style: { paddingRight: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
153
246
|
designSystem.Flex,
|
|
@@ -351,7 +444,7 @@ function CustomSwitch({ checked, onChange, label, disabled }) {
|
|
|
351
444
|
] });
|
|
352
445
|
}
|
|
353
446
|
function useOidcSettings() {
|
|
354
|
-
const { get, put } = admin.useFetchClient();
|
|
447
|
+
const { get, put, post } = admin.useFetchClient();
|
|
355
448
|
const [loading, setLoading] = react.useState(false);
|
|
356
449
|
const [showSuccess, setSuccess] = react.useState(false);
|
|
357
450
|
const [showError, setError] = react.useState(false);
|
|
@@ -401,6 +494,31 @@ function useOidcSettings() {
|
|
|
401
494
|
setEnforceOIDC(false);
|
|
402
495
|
}
|
|
403
496
|
};
|
|
497
|
+
const onDeleteAll = () => {
|
|
498
|
+
setUsers([]);
|
|
499
|
+
if (useWhitelist) setEnforceOIDC(false);
|
|
500
|
+
};
|
|
501
|
+
const onImport = async (entries) => {
|
|
502
|
+
const response = await post("/strapi-plugin-oidc/whitelist/import", { users: entries });
|
|
503
|
+
const refreshed = await get("/strapi-plugin-oidc/whitelist");
|
|
504
|
+
setUsers(refreshed.data.whitelistUsers);
|
|
505
|
+
setInitialUsers(JSON.parse(JSON.stringify(refreshed.data.whitelistUsers)));
|
|
506
|
+
return response.data.importedCount;
|
|
507
|
+
};
|
|
508
|
+
const onExport = () => {
|
|
509
|
+
const roleMap = new Map(roles.map((r) => [String(r.id), r.name]));
|
|
510
|
+
const data = users.map(({ email, roles: userRoles }) => ({
|
|
511
|
+
email,
|
|
512
|
+
roles: (userRoles || []).map((id) => roleMap.get(String(id)) ?? id)
|
|
513
|
+
}));
|
|
514
|
+
const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
|
|
515
|
+
const url = URL.createObjectURL(blob);
|
|
516
|
+
const a = document.createElement("a");
|
|
517
|
+
a.href = url;
|
|
518
|
+
a.download = "whitelist.json";
|
|
519
|
+
a.click();
|
|
520
|
+
URL.revokeObjectURL(url);
|
|
521
|
+
};
|
|
404
522
|
const onToggleWhitelist = (e) => {
|
|
405
523
|
const checked = e.target.checked;
|
|
406
524
|
setUseWhitelist(checked);
|
|
@@ -472,6 +590,9 @@ function useOidcSettings() {
|
|
|
472
590
|
onChangeRole,
|
|
473
591
|
onRegisterWhitelist,
|
|
474
592
|
onDeleteWhitelist,
|
|
593
|
+
onDeleteAll,
|
|
594
|
+
onImport,
|
|
595
|
+
onExport,
|
|
475
596
|
onToggleWhitelist,
|
|
476
597
|
onToggleEnforce,
|
|
477
598
|
onSaveAll
|
|
@@ -481,6 +602,7 @@ function useOidcSettings() {
|
|
|
481
602
|
function HomePage$1() {
|
|
482
603
|
const { formatMessage } = reactIntl.useIntl();
|
|
483
604
|
const { state, actions } = useOidcSettings();
|
|
605
|
+
const blocker = reactRouterDom.useBlocker(state.isDirty);
|
|
484
606
|
return /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Protect, { permissions: [{ action: "plugin::strapi-plugin-oidc.read", subject: null }], children: [
|
|
485
607
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
486
608
|
admin.Layouts.Header,
|
|
@@ -525,7 +647,10 @@ function HomePage$1() {
|
|
|
525
647
|
oidcRoles: state.oidcRoles,
|
|
526
648
|
useWhitelist: state.useWhitelist,
|
|
527
649
|
onSave: actions.onRegisterWhitelist,
|
|
528
|
-
onDelete: actions.onDeleteWhitelist
|
|
650
|
+
onDelete: actions.onDeleteWhitelist,
|
|
651
|
+
onDeleteAll: actions.onDeleteAll,
|
|
652
|
+
onImport: actions.onImport,
|
|
653
|
+
onExport: actions.onExport
|
|
529
654
|
}
|
|
530
655
|
)
|
|
531
656
|
] }),
|
|
@@ -564,6 +689,14 @@ function HomePage$1() {
|
|
|
564
689
|
children: formatMessage(index.getTrad("page.save"))
|
|
565
690
|
}
|
|
566
691
|
) })
|
|
692
|
+
] }) }),
|
|
693
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: blocker.state === "blocked", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
|
694
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage(index.getTrad("unsaved.title")) }),
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: formatMessage(index.getTrad("unsaved.description")) }),
|
|
696
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
|
697
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", onClick: () => blocker.reset?.(), children: formatMessage(index.getTrad("unsaved.cancel")) }) }),
|
|
698
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger", onClick: () => blocker.proceed?.(), children: formatMessage(index.getTrad("unsaved.confirm")) }) })
|
|
699
|
+
] })
|
|
567
700
|
] }) })
|
|
568
701
|
] });
|
|
569
702
|
}
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -506,6 +506,48 @@ async function removeEmail(ctx) {
|
|
|
506
506
|
await whitelistService2.removeUser(id);
|
|
507
507
|
ctx.body = {};
|
|
508
508
|
}
|
|
509
|
+
async function deleteAll(ctx) {
|
|
510
|
+
await strapi.db.query("plugin::strapi-plugin-oidc.whitelists").deleteMany({});
|
|
511
|
+
ctx.body = {};
|
|
512
|
+
}
|
|
513
|
+
async function importUsers(ctx) {
|
|
514
|
+
const { users } = ctx.request.body;
|
|
515
|
+
if (!Array.isArray(users)) {
|
|
516
|
+
ctx.status = 400;
|
|
517
|
+
ctx.body = { error: "Expected { users: [{email, roles}] }" };
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const allRoles = await strapi.query("admin::role").findMany({});
|
|
521
|
+
const roleNameToId = new Map(allRoles.map((r) => [r.name, String(r.id)]));
|
|
522
|
+
const resolveRole = (nameOrId) => roleNameToId.get(nameOrId) ?? nameOrId;
|
|
523
|
+
const normalized = users.filter((u) => u?.email).map((u) => ({
|
|
524
|
+
email: String(u.email).trim().toLowerCase(),
|
|
525
|
+
roles: (Array.isArray(u.roles) ? u.roles : []).map(resolveRole)
|
|
526
|
+
}));
|
|
527
|
+
const seen = /* @__PURE__ */ new Set();
|
|
528
|
+
const deduped = normalized.filter((u) => {
|
|
529
|
+
if (seen.has(u.email)) return false;
|
|
530
|
+
seen.add(u.email);
|
|
531
|
+
return true;
|
|
532
|
+
});
|
|
533
|
+
const strapiUsers = await strapi.query("admin::user").findMany({
|
|
534
|
+
where: { email: { $in: deduped.map((u) => u.email) } },
|
|
535
|
+
populate: ["roles"]
|
|
536
|
+
});
|
|
537
|
+
const strapiUserMap = new Map(strapiUsers.map((u) => [u.email, u]));
|
|
538
|
+
const whitelistService2 = strapi.plugin("strapi-plugin-oidc").service("whitelist");
|
|
539
|
+
const existing = await whitelistService2.getUsers();
|
|
540
|
+
const existingEmails = new Set(existing.map((u) => u.email));
|
|
541
|
+
let importedCount = 0;
|
|
542
|
+
for (const user of deduped) {
|
|
543
|
+
if (existingEmails.has(user.email)) continue;
|
|
544
|
+
const strapiUser = strapiUserMap.get(user.email);
|
|
545
|
+
const finalRoles = strapiUser?.roles?.length ? strapiUser.roles.map((r) => String(r.id)) : user.roles;
|
|
546
|
+
await whitelistService2.registerUser(user.email, finalRoles);
|
|
547
|
+
importedCount++;
|
|
548
|
+
}
|
|
549
|
+
ctx.body = { importedCount };
|
|
550
|
+
}
|
|
509
551
|
async function syncUsers(ctx) {
|
|
510
552
|
let { users } = ctx.request.body;
|
|
511
553
|
users = users.map((u) => ({ ...u, email: String(u.email).toLowerCase() }));
|
|
@@ -547,7 +589,9 @@ const whitelist = {
|
|
|
547
589
|
publicSettings,
|
|
548
590
|
register,
|
|
549
591
|
removeEmail,
|
|
550
|
-
|
|
592
|
+
deleteAll,
|
|
593
|
+
syncUsers,
|
|
594
|
+
importUsers
|
|
551
595
|
};
|
|
552
596
|
const controllers = {
|
|
553
597
|
oidc,
|
|
@@ -571,134 +615,133 @@ const rateLimitMiddleware = async (ctx, next) => {
|
|
|
571
615
|
rateLimitMap.set(ip, requestStamps);
|
|
572
616
|
await next();
|
|
573
617
|
};
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
policies: [
|
|
581
|
-
"admin::isAuthenticatedAdmin",
|
|
582
|
-
{ name: "admin::hasPermissions", config: { actions: ["plugin::strapi-plugin-oidc.read"] } }
|
|
583
|
-
]
|
|
584
|
-
}
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
method: "PUT",
|
|
588
|
-
path: "/oidc-roles",
|
|
589
|
-
handler: "role.update",
|
|
590
|
-
config: {
|
|
591
|
-
policies: [
|
|
592
|
-
"admin::isAuthenticatedAdmin",
|
|
593
|
-
{
|
|
594
|
-
name: "admin::hasPermissions",
|
|
595
|
-
config: { actions: ["plugin::strapi-plugin-oidc.update"] }
|
|
596
|
-
}
|
|
597
|
-
]
|
|
598
|
-
}
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
method: "GET",
|
|
602
|
-
path: "/oidc",
|
|
603
|
-
handler: "oidc.oidcSignIn",
|
|
604
|
-
config: {
|
|
605
|
-
auth: false,
|
|
606
|
-
middlewares: [rateLimitMiddleware]
|
|
607
|
-
}
|
|
608
|
-
},
|
|
609
|
-
{
|
|
610
|
-
method: "GET",
|
|
611
|
-
path: "/oidc/callback",
|
|
612
|
-
handler: "oidc.oidcSignInCallback",
|
|
613
|
-
config: {
|
|
614
|
-
auth: false,
|
|
615
|
-
middlewares: [rateLimitMiddleware]
|
|
616
|
-
}
|
|
617
|
-
},
|
|
618
|
-
{
|
|
619
|
-
method: "GET",
|
|
620
|
-
path: "/logout",
|
|
621
|
-
handler: "oidc.logout",
|
|
622
|
-
config: {
|
|
623
|
-
auth: false
|
|
624
|
-
}
|
|
625
|
-
},
|
|
626
|
-
{
|
|
627
|
-
method: "GET",
|
|
628
|
-
path: "/whitelist",
|
|
629
|
-
handler: "whitelist.info",
|
|
630
|
-
config: {
|
|
631
|
-
policies: [
|
|
632
|
-
"admin::isAuthenticatedAdmin",
|
|
633
|
-
{ name: "admin::hasPermissions", config: { actions: ["plugin::strapi-plugin-oidc.read"] } }
|
|
634
|
-
]
|
|
635
|
-
}
|
|
636
|
-
},
|
|
637
|
-
{
|
|
638
|
-
method: "PUT",
|
|
639
|
-
path: "/whitelist/settings",
|
|
640
|
-
handler: "whitelist.updateSettings",
|
|
641
|
-
config: {
|
|
642
|
-
policies: [
|
|
643
|
-
"admin::isAuthenticatedAdmin",
|
|
644
|
-
{
|
|
645
|
-
name: "admin::hasPermissions",
|
|
646
|
-
config: { actions: ["plugin::strapi-plugin-oidc.update"] }
|
|
647
|
-
}
|
|
648
|
-
]
|
|
649
|
-
}
|
|
650
|
-
},
|
|
651
|
-
{
|
|
652
|
-
method: "GET",
|
|
653
|
-
path: "/settings/public",
|
|
654
|
-
handler: "whitelist.publicSettings",
|
|
655
|
-
config: {
|
|
656
|
-
auth: false
|
|
657
|
-
}
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
method: "PUT",
|
|
661
|
-
path: "/whitelist/sync",
|
|
662
|
-
handler: "whitelist.syncUsers",
|
|
663
|
-
config: {
|
|
664
|
-
policies: [
|
|
665
|
-
"admin::isAuthenticatedAdmin",
|
|
666
|
-
{
|
|
667
|
-
name: "admin::hasPermissions",
|
|
668
|
-
config: { actions: ["plugin::strapi-plugin-oidc.update"] }
|
|
669
|
-
}
|
|
670
|
-
]
|
|
671
|
-
}
|
|
672
|
-
},
|
|
673
|
-
{
|
|
674
|
-
method: "POST",
|
|
675
|
-
path: "/whitelist",
|
|
676
|
-
handler: "whitelist.register",
|
|
677
|
-
config: {
|
|
678
|
-
policies: [
|
|
679
|
-
"admin::isAuthenticatedAdmin",
|
|
680
|
-
{
|
|
681
|
-
name: "admin::hasPermissions",
|
|
682
|
-
config: { actions: ["plugin::strapi-plugin-oidc.update"] }
|
|
683
|
-
}
|
|
684
|
-
]
|
|
618
|
+
const adminPolicies = (action) => ({
|
|
619
|
+
policies: [
|
|
620
|
+
"admin::isAuthenticatedAdmin",
|
|
621
|
+
{
|
|
622
|
+
name: "admin::hasPermissions",
|
|
623
|
+
config: { actions: [`plugin::strapi-plugin-oidc.${action}`] }
|
|
685
624
|
}
|
|
625
|
+
]
|
|
626
|
+
});
|
|
627
|
+
const routes = {
|
|
628
|
+
admin: {
|
|
629
|
+
type: "admin",
|
|
630
|
+
routes: [
|
|
631
|
+
{
|
|
632
|
+
method: "GET",
|
|
633
|
+
path: "/oidc-roles",
|
|
634
|
+
handler: "role.find",
|
|
635
|
+
config: adminPolicies("read")
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
method: "PUT",
|
|
639
|
+
path: "/oidc-roles",
|
|
640
|
+
handler: "role.update",
|
|
641
|
+
config: adminPolicies("update")
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
method: "GET",
|
|
645
|
+
path: "/oidc",
|
|
646
|
+
handler: "oidc.oidcSignIn",
|
|
647
|
+
config: { auth: false, middlewares: [rateLimitMiddleware] }
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
method: "GET",
|
|
651
|
+
path: "/oidc/callback",
|
|
652
|
+
handler: "oidc.oidcSignInCallback",
|
|
653
|
+
config: { auth: false, middlewares: [rateLimitMiddleware] }
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
method: "GET",
|
|
657
|
+
path: "/logout",
|
|
658
|
+
handler: "oidc.logout",
|
|
659
|
+
config: { auth: false }
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
method: "GET",
|
|
663
|
+
path: "/whitelist",
|
|
664
|
+
handler: "whitelist.info",
|
|
665
|
+
config: adminPolicies("read")
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
method: "PUT",
|
|
669
|
+
path: "/whitelist/settings",
|
|
670
|
+
handler: "whitelist.updateSettings",
|
|
671
|
+
config: adminPolicies("update")
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
method: "GET",
|
|
675
|
+
path: "/settings/public",
|
|
676
|
+
handler: "whitelist.publicSettings",
|
|
677
|
+
config: { auth: false }
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
method: "PUT",
|
|
681
|
+
path: "/whitelist/sync",
|
|
682
|
+
handler: "whitelist.syncUsers",
|
|
683
|
+
config: adminPolicies("update")
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
method: "POST",
|
|
687
|
+
path: "/whitelist/import",
|
|
688
|
+
handler: "whitelist.importUsers",
|
|
689
|
+
config: adminPolicies("update")
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
method: "POST",
|
|
693
|
+
path: "/whitelist",
|
|
694
|
+
handler: "whitelist.register",
|
|
695
|
+
config: adminPolicies("update")
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
method: "DELETE",
|
|
699
|
+
path: "/whitelist/:id",
|
|
700
|
+
handler: "whitelist.removeEmail",
|
|
701
|
+
config: adminPolicies("update")
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
method: "DELETE",
|
|
705
|
+
path: "/whitelist",
|
|
706
|
+
handler: "whitelist.deleteAll",
|
|
707
|
+
config: adminPolicies("update")
|
|
708
|
+
}
|
|
709
|
+
]
|
|
686
710
|
},
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
711
|
+
// API-token-authenticated routes for programmatic whitelist management.
|
|
712
|
+
// Accessible at /strapi-plugin-oidc/... using a Strapi API token
|
|
713
|
+
// (full-access or custom) in the Authorization: Bearer <token> header.
|
|
714
|
+
"content-api": {
|
|
715
|
+
type: "content-api",
|
|
716
|
+
routes: [
|
|
717
|
+
{
|
|
718
|
+
method: "GET",
|
|
719
|
+
path: "/whitelist",
|
|
720
|
+
handler: "whitelist.info"
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
method: "POST",
|
|
724
|
+
path: "/whitelist",
|
|
725
|
+
handler: "whitelist.register"
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
method: "POST",
|
|
729
|
+
path: "/whitelist/import",
|
|
730
|
+
handler: "whitelist.importUsers"
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
method: "DELETE",
|
|
734
|
+
path: "/whitelist/:id",
|
|
735
|
+
handler: "whitelist.removeEmail"
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
method: "DELETE",
|
|
739
|
+
path: "/whitelist",
|
|
740
|
+
handler: "whitelist.deleteAll"
|
|
741
|
+
}
|
|
742
|
+
]
|
|
700
743
|
}
|
|
701
|
-
|
|
744
|
+
};
|
|
702
745
|
const policies = {};
|
|
703
746
|
function renderHtmlTemplate(title, content) {
|
|
704
747
|
return `
|