strapi-plugin-oidc 1.2.4 → 1.3.2
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 +20 -25
- package/dist/admin/{index-CYL_geya.js → index-BqyGGX8X.js} +82 -114
- package/dist/admin/{index-BD7cK7Hf.mjs → index-CFmg9Kxl.mjs} +58 -90
- package/dist/admin/{index-Cxj6lwW7.js → index-Cse9ex24.js} +78 -119
- package/dist/admin/{index-B2dKk7YS.mjs → index-D1ypRUlq.mjs} +79 -120
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +77 -57
- package/dist/server/index.mjs +77 -57
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -37,39 +37,32 @@ module.exports = ({ env }) => ({
|
|
|
37
37
|
'strapi-plugin-oidc': {
|
|
38
38
|
enabled: true,
|
|
39
39
|
config: {
|
|
40
|
-
//
|
|
41
|
-
REMEMBER_ME: false,
|
|
42
|
-
// How long the remember me session should last in days (defaults to 30 days)
|
|
43
|
-
REMEMBER_ME_DAYS: 30,
|
|
44
|
-
|
|
45
|
-
// OpenID Connect Settings
|
|
46
|
-
OIDC_REDIRECT_URI: 'http://localhost:1337/strapi-plugin-oidc/oidc/callback', // Callback URI after successful login
|
|
40
|
+
// --- Required ---
|
|
47
41
|
OIDC_CLIENT_ID: '[Client ID from OpenID Provider]',
|
|
48
42
|
OIDC_CLIENT_SECRET: '[Client Secret from OpenID Provider]',
|
|
49
|
-
|
|
50
|
-
OIDC_SCOPES: 'openid profile email', // Standard OIDC scopes
|
|
51
|
-
|
|
52
|
-
// API Endpoints required for OIDC provider
|
|
43
|
+
OIDC_REDIRECT_URI: '[Your Strapi URL]/strapi-plugin-oidc/oidc/callback',
|
|
53
44
|
OIDC_AUTHORIZATION_ENDPOINT: '[Authorization Endpoint]',
|
|
54
45
|
OIDC_TOKEN_ENDPOINT: '[Token Endpoint]',
|
|
55
46
|
OIDC_USER_INFO_ENDPOINT: '[User Info Endpoint]',
|
|
56
|
-
OIDC_USER_INFO_ENDPOINT_WITH_AUTH_HEADER: false,
|
|
57
|
-
OIDC_GRANT_TYPE: 'authorization_code',
|
|
58
47
|
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
48
|
+
// --- Defaults provided — only set if your provider differs ---
|
|
49
|
+
OIDC_SCOPES: 'openid profile email',
|
|
50
|
+
OIDC_GRANT_TYPE: 'authorization_code',
|
|
51
|
+
OIDC_FAMILY_NAME_FIELD: 'family_name', // OIDC claim for the user's surname
|
|
52
|
+
OIDC_GIVEN_NAME_FIELD: 'given_name', // OIDC claim for the user's first name
|
|
53
|
+
|
|
54
|
+
// --- Optional ---
|
|
55
|
+
OIDC_USER_INFO_ENDPOINT_WITH_AUTH_HEADER: false, // true = Bearer token header, false = query param
|
|
56
|
+
OIDC_LOGOUT_URL: '', // OIDC provider logout URL; omit to return to Strapi login instead
|
|
57
|
+
OIDC_SSO_BUTTON_TEXT: 'Login via SSO', // Text on the SSO button injected into the login page
|
|
58
|
+
OIDC_ENFORCE: null, // null = use Admin UI setting; true/false = override it in config
|
|
59
|
+
REMEMBER_ME: false, // true = persist session across browser restarts, using Strapi's built-in refresh token duration
|
|
65
60
|
},
|
|
66
61
|
},
|
|
67
62
|
// ...
|
|
68
63
|
});
|
|
69
64
|
```
|
|
70
65
|
|
|
71
|
-
Make sure to replace the placeholder values (e.g., `[Client ID from OpenID Provider]`) with the actual connection details from your chosen OIDC identity provider.
|
|
72
|
-
|
|
73
66
|
## How to Login
|
|
74
67
|
|
|
75
68
|
Once configured, you can initiate the OIDC login flow by navigating to:
|
|
@@ -77,7 +70,7 @@ Once configured, you can initiate the OIDC login flow by navigating to:
|
|
|
77
70
|
|
|
78
71
|
(e.g., `http://localhost:1337/strapi-plugin-oidc/oidc` for local development).
|
|
79
72
|
|
|
80
|
-
When the **Enforce OIDC Login** option is enabled in the Admin Settings, the standard
|
|
73
|
+
When the **Enforce OIDC Login** option is enabled in the Admin Settings, the standard login fields are removed from the login page and only the SSO button remains — click it to start the OIDC flow.
|
|
81
74
|
|
|
82
75
|
## Admin Settings
|
|
83
76
|
|
|
@@ -85,7 +78,9 @@ Once the plugin is installed and configured, you can manage the OIDC settings fr
|
|
|
85
78
|
|
|
86
79
|
- **Whitelist Management**: Restrict login to specific users by adding their email addresses to the whitelist. You can also whitelist entire email domains (e.g., `*@company.com`). If the whitelist is empty, any user who successfully authenticates via your OIDC provider will be able to log in and an account will be automatically created for them.
|
|
87
80
|
- **Default Role Assignment**: Select the default Strapi admin role that will be assigned to newly created users when they log in for the first time via OIDC.
|
|
88
|
-
- **
|
|
81
|
+
- **SSO Login Button**: A "Login via SSO" button is always injected into the Strapi login page, allowing users to authenticate via OIDC. The button text is configurable via the `OIDC_SSO_BUTTON_TEXT` config option.
|
|
82
|
+
- **Enforce OIDC Login**: When enabled, the standard email/password fields, remember me checkbox, login button, and forgot-password link are removed from the login page, leaving only the SSO button. All direct login API calls are also blocked server-side. _(Note: This option is automatically disabled and grayed out if your whitelist is empty to prevent accidentally locking everyone out of the admin panel)._
|
|
83
|
+
- **`OIDC_ENFORCE` config override**: Setting `OIDC_ENFORCE: true` or `OIDC_ENFORCE: false` in your plugin config takes priority over the Admin UI toggle and locks it. Set `OIDC_ENFORCE: false` in your config to regain access if you are ever locked out, then restart Strapi.
|
|
89
84
|
|
|
90
85
|
## Credits & Changes
|
|
91
86
|
|
|
@@ -97,10 +92,10 @@ This plugin is a hard fork of the original [`strapi-plugin-sso`](https://github.
|
|
|
97
92
|
- Redesigned the Whitelist and Role management UI (switched to native Strapi cards, added pagination, etc.).
|
|
98
93
|
- Added an OIDC logout redirect URL.
|
|
99
94
|
- Added an option to "Enforce OIDC login" with an admin toggle (automatically disabled if the whitelist is empty).
|
|
100
|
-
- Added
|
|
95
|
+
- Added "Remember Me" support for OIDC sessions, using Strapi's built-in refresh token duration and idle lifespan.
|
|
101
96
|
- Migrated the testing framework to Vitest and added comprehensive test coverage for controllers and services.
|
|
102
97
|
- Cleaned up dead code and unused dependencies to improve maintainability.
|
|
103
98
|
- Upgraded to use newer versions of Node.js.
|
|
104
99
|
- Added styled success and error pages.
|
|
105
|
-
-
|
|
100
|
+
- Always injects a "Login via SSO" button on the Strapi login page. Button text is configurable via `OIDC_SSO_BUTTON_TEXT`. When enforcement is on, standard login fields are hidden so only the SSO button is visible.
|
|
106
101
|
- Added misc. quality of life improvements and bug fixes.
|
|
@@ -7,26 +7,19 @@ 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-Cse9ex24.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);
|
|
14
|
-
function getTrad(id) {
|
|
15
|
-
const pluginIdWithId = `${index.pluginId}.${id}`;
|
|
16
|
-
return {
|
|
17
|
-
id: pluginIdWithId,
|
|
18
|
-
defaultMessage: index.en[id] || pluginIdWithId
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
14
|
function Role({ oidcRoles, roles, onChangeRole }) {
|
|
22
15
|
const { formatMessage } = reactIntl.useIntl();
|
|
23
16
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
24
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textColor: "neutral600", marginBottom: 4, children: formatMessage(getTrad("roles.notes")) }),
|
|
17
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textColor: "neutral600", marginBottom: 4, children: formatMessage(index.getTrad("roles.notes")) }),
|
|
25
18
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, marginBottom: 4, children: oidcRoles.map((oidcRole) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
26
19
|
designSystem.MultiSelect,
|
|
27
20
|
{
|
|
28
21
|
withTags: true,
|
|
29
|
-
placeholder: formatMessage(getTrad("roles.placeholder")),
|
|
22
|
+
placeholder: formatMessage(index.getTrad("roles.placeholder")),
|
|
30
23
|
value: oidcRole.role ? oidcRole.role.map((r) => String(r)) : [],
|
|
31
24
|
onChange: (value) => {
|
|
32
25
|
if (value && value.length > 0) {
|
|
@@ -78,7 +71,7 @@ function Whitelist({
|
|
|
78
71
|
if (users.some((user) => user.email === emailText)) {
|
|
79
72
|
toggleNotification({
|
|
80
73
|
type: "warning",
|
|
81
|
-
message: formatMessage(getTrad("whitelist.error.unique"))
|
|
74
|
+
message: formatMessage(index.getTrad("whitelist.error.unique"))
|
|
82
75
|
});
|
|
83
76
|
} else {
|
|
84
77
|
await onSave(emailText, selectedRoles);
|
|
@@ -90,8 +83,8 @@ function Whitelist({
|
|
|
90
83
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
91
84
|
return emailRegex.test(email);
|
|
92
85
|
}, [email]);
|
|
93
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
94
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textColor: "neutral600", marginBottom: 4, children: formatMessage(getTrad("whitelist.description")) }),
|
|
86
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textColor: "neutral600", marginBottom: 4, children: formatMessage(index.getTrad("whitelist.description")) }),
|
|
95
88
|
useWhitelist && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
96
89
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, marginTop: 5, marginBottom: 5, alignItems: "flex-start", children: [
|
|
97
90
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -102,14 +95,14 @@ function Whitelist({
|
|
|
102
95
|
value: email,
|
|
103
96
|
hasError: Boolean(email && !isValidEmail()),
|
|
104
97
|
onChange: (e) => setEmail(e.currentTarget.value),
|
|
105
|
-
placeholder: formatMessage(getTrad("whitelist.email.placeholder"))
|
|
98
|
+
placeholder: formatMessage(index.getTrad("whitelist.email.placeholder"))
|
|
106
99
|
}
|
|
107
100
|
) }) }),
|
|
108
101
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
109
102
|
designSystem.MultiSelect,
|
|
110
103
|
{
|
|
111
104
|
withTags: true,
|
|
112
|
-
placeholder: formatMessage(getTrad("whitelist.roles.placeholder")),
|
|
105
|
+
placeholder: formatMessage(index.getTrad("whitelist.roles.placeholder")),
|
|
113
106
|
value: selectedRoles,
|
|
114
107
|
onChange: (value) => {
|
|
115
108
|
setSelectedRoles(value || []);
|
|
@@ -125,20 +118,20 @@ function Whitelist({
|
|
|
125
118
|
disabled: loading || email.trim() === "" || !isValidEmail(),
|
|
126
119
|
loading,
|
|
127
120
|
onClick: onSaveEmail,
|
|
128
|
-
children: formatMessage(getTrad("page.add"))
|
|
121
|
+
children: formatMessage(index.getTrad("page.add"))
|
|
129
122
|
}
|
|
130
123
|
) })
|
|
131
124
|
] }),
|
|
132
125
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
|
|
133
126
|
/* @__PURE__ */ jsxRuntime.jsxs(CustomTable, { colCount: 5, rowCount: users.length, children: [
|
|
134
127
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
135
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(getTrad("whitelist.table.no")) }),
|
|
136
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(getTrad("whitelist.table.email")) }),
|
|
137
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(getTrad("whitelist.table.roles")) }),
|
|
138
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(getTrad("whitelist.table.created")) }),
|
|
128
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(index.getTrad("whitelist.table.no")) }),
|
|
129
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(index.getTrad("whitelist.table.email")) }),
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(index.getTrad("whitelist.table.roles")) }),
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: formatMessage(index.getTrad("whitelist.table.created")) }),
|
|
139
132
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { paddingRight: 0 }, children: " " })
|
|
140
133
|
] }) }),
|
|
141
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: users.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 5, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage(getTrad("whitelist.table.empty")) }) }) }) }) : paginatedUsers.map((user,
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: users.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 5, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage(index.getTrad("whitelist.table.empty")) }) }) }) }) : paginatedUsers.map((user, index$1) => {
|
|
142
135
|
const getRoleNames = (roleIds) => roleIds.map((roleId) => {
|
|
143
136
|
const r = roles.find((ro) => String(ro.id) === String(roleId));
|
|
144
137
|
return r ? r.name : roleId;
|
|
@@ -152,7 +145,7 @@ function Whitelist({
|
|
|
152
145
|
userRolesNames = getRoleNames(defaultRolesIds);
|
|
153
146
|
}
|
|
154
147
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
155
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children:
|
|
148
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: index$1 + 1 + (page - 1) * PAGE_SIZE }),
|
|
156
149
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: user.email }),
|
|
157
150
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: userRolesNames || "-" }),
|
|
158
151
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(LocalizedDate, { date: user.createdAt }) }),
|
|
@@ -166,27 +159,27 @@ function Whitelist({
|
|
|
166
159
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
167
160
|
designSystem.IconButton,
|
|
168
161
|
{
|
|
169
|
-
label: formatMessage(getTrad("whitelist.delete.label")),
|
|
162
|
+
label: formatMessage(index.getTrad("whitelist.delete.label")),
|
|
170
163
|
withTooltip: false,
|
|
171
164
|
children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {})
|
|
172
165
|
}
|
|
173
166
|
) }),
|
|
174
167
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
|
175
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage(getTrad("whitelist.delete.title")) }),
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage(index.getTrad("whitelist.delete.title")) }),
|
|
176
169
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { fill: "danger600" }), children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 2, children: [
|
|
177
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", children: formatMessage(getTrad("whitelist.delete.description")) }) }),
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", children: formatMessage(index.getTrad("whitelist.delete.description")) }) }),
|
|
178
171
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: user.email }) }),
|
|
179
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(getTrad("whitelist.delete.note")) }) })
|
|
172
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(index.getTrad("whitelist.delete.note")) }) })
|
|
180
173
|
] }) }),
|
|
181
174
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
|
182
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, variant: "tertiary", children: formatMessage(getTrad("page.cancel")) }) }),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, variant: "tertiary", children: formatMessage(index.getTrad("page.cancel")) }) }),
|
|
183
176
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
184
177
|
designSystem.Button,
|
|
185
178
|
{
|
|
186
179
|
fullWidth: true,
|
|
187
180
|
variant: "danger-light",
|
|
188
181
|
onClick: () => onDelete(user.email),
|
|
189
|
-
children: formatMessage(getTrad("page.ok"))
|
|
182
|
+
children: formatMessage(index.getTrad("page.ok"))
|
|
190
183
|
}
|
|
191
184
|
) })
|
|
192
185
|
] })
|
|
@@ -206,10 +199,10 @@ function Whitelist({
|
|
|
206
199
|
e.preventDefault();
|
|
207
200
|
setPage((p) => Math.max(1, p - 1));
|
|
208
201
|
},
|
|
209
|
-
children: "
|
|
202
|
+
children: formatMessage(index.getTrad("pagination.previous"))
|
|
210
203
|
}
|
|
211
204
|
),
|
|
212
|
-
Array.from({ length: pageCount }).map((_, i) => /* @__PURE__ */ jsxRuntime.
|
|
205
|
+
Array.from({ length: pageCount }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
213
206
|
designSystem.PageLink,
|
|
214
207
|
{
|
|
215
208
|
number: i + 1,
|
|
@@ -218,10 +211,7 @@ function Whitelist({
|
|
|
218
211
|
e.preventDefault();
|
|
219
212
|
setPage(i + 1);
|
|
220
213
|
},
|
|
221
|
-
children:
|
|
222
|
-
"Go to page ",
|
|
223
|
-
i + 1
|
|
224
|
-
]
|
|
214
|
+
children: formatMessage(index.getTrad("pagination.page"), { page: i + 1 })
|
|
225
215
|
},
|
|
226
216
|
i + 1
|
|
227
217
|
)),
|
|
@@ -233,12 +223,12 @@ function Whitelist({
|
|
|
233
223
|
e.preventDefault();
|
|
234
224
|
setPage((p) => Math.min(pageCount, p + 1));
|
|
235
225
|
},
|
|
236
|
-
children: "
|
|
226
|
+
children: formatMessage(index.getTrad("pagination.next"))
|
|
237
227
|
}
|
|
238
228
|
)
|
|
239
229
|
] }) }) })
|
|
240
230
|
] })
|
|
241
|
-
] })
|
|
231
|
+
] });
|
|
242
232
|
}
|
|
243
233
|
const AlertMessage = styled__default.default.div`
|
|
244
234
|
position: fixed;
|
|
@@ -250,11 +240,29 @@ const AlertMessage = styled__default.default.div`
|
|
|
250
240
|
`;
|
|
251
241
|
function SuccessAlertMessage({ onClose }) {
|
|
252
242
|
const { formatMessage } = reactIntl.useIntl();
|
|
253
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AlertMessage, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
243
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AlertMessage, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
244
|
+
designSystem.Alert,
|
|
245
|
+
{
|
|
246
|
+
title: formatMessage(index.getTrad("alert.title.success")),
|
|
247
|
+
variant: "success",
|
|
248
|
+
closeLabel: "",
|
|
249
|
+
onClose,
|
|
250
|
+
children: formatMessage(index.getTrad("page.save.success"))
|
|
251
|
+
}
|
|
252
|
+
) });
|
|
254
253
|
}
|
|
255
254
|
function ErrorAlertMessage({ onClose }) {
|
|
256
255
|
const { formatMessage } = reactIntl.useIntl();
|
|
257
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AlertMessage, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
256
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AlertMessage, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
257
|
+
designSystem.Alert,
|
|
258
|
+
{
|
|
259
|
+
title: formatMessage(index.getTrad("alert.title.error")),
|
|
260
|
+
variant: "danger",
|
|
261
|
+
closeLabel: "",
|
|
262
|
+
onClose,
|
|
263
|
+
children: formatMessage(index.getTrad("page.save.error"))
|
|
264
|
+
}
|
|
265
|
+
) });
|
|
258
266
|
}
|
|
259
267
|
function MatchedUserAlertMessage({
|
|
260
268
|
onClose,
|
|
@@ -262,7 +270,16 @@ function MatchedUserAlertMessage({
|
|
|
262
270
|
}) {
|
|
263
271
|
const { formatMessage } = reactIntl.useIntl();
|
|
264
272
|
const id = count > 1 ? "whitelist.users_exists" : "whitelist.user_exists";
|
|
265
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AlertMessage, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AlertMessage, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
274
|
+
designSystem.Alert,
|
|
275
|
+
{
|
|
276
|
+
title: formatMessage(index.getTrad("alert.title.info")),
|
|
277
|
+
variant: "default",
|
|
278
|
+
closeLabel: "",
|
|
279
|
+
onClose,
|
|
280
|
+
children: formatMessage(index.getTrad(id))
|
|
281
|
+
}
|
|
282
|
+
) });
|
|
266
283
|
}
|
|
267
284
|
const SwitchContainer = styled__default.default.label`
|
|
268
285
|
position: relative;
|
|
@@ -346,12 +363,9 @@ function useOidcSettings() {
|
|
|
346
363
|
const [useWhitelist, setUseWhitelist] = react.useState(false);
|
|
347
364
|
const [initialEnforceOIDC, setInitialEnforceOIDC] = react.useState(false);
|
|
348
365
|
const [enforceOIDC, setEnforceOIDC] = react.useState(false);
|
|
366
|
+
const [enforceOIDCConfig, setEnforceOIDCConfig] = react.useState(null);
|
|
349
367
|
const [initialUsers, setInitialUsers] = react.useState([]);
|
|
350
368
|
const [users, setUsers] = react.useState([]);
|
|
351
|
-
const [initialShowSSOButton, setInitialShowSSOButton] = react.useState(true);
|
|
352
|
-
const [showSSOButton, setShowSSOButton] = react.useState(true);
|
|
353
|
-
const [initialSSOButtonText, setInitialSSOButtonText] = react.useState("Login via SSO");
|
|
354
|
-
const [ssoButtonText, setSSOButtonText] = react.useState("Login via SSO");
|
|
355
369
|
react.useEffect(() => {
|
|
356
370
|
get(`/strapi-plugin-oidc/oidc-roles`).then((response) => {
|
|
357
371
|
setOIDCRoles(response.data);
|
|
@@ -367,10 +381,7 @@ function useOidcSettings() {
|
|
|
367
381
|
setInitialUseWhitelist(response.data.useWhitelist);
|
|
368
382
|
setEnforceOIDC(response.data.enforceOIDC);
|
|
369
383
|
setInitialEnforceOIDC(response.data.enforceOIDC);
|
|
370
|
-
|
|
371
|
-
setInitialShowSSOButton(response.data.showSSOButton !== false);
|
|
372
|
-
setSSOButtonText(response.data.ssoButtonText || "Login via SSO");
|
|
373
|
-
setInitialSSOButtonText(response.data.ssoButtonText || "Login via SSO");
|
|
384
|
+
setEnforceOIDCConfig(response.data.enforceOIDCConfig ?? null);
|
|
374
385
|
});
|
|
375
386
|
}, [get]);
|
|
376
387
|
const onChangeRole = (values, oidcId) => {
|
|
@@ -400,13 +411,7 @@ function useOidcSettings() {
|
|
|
400
411
|
const onToggleEnforce = (e) => {
|
|
401
412
|
setEnforceOIDC(e.target.checked);
|
|
402
413
|
};
|
|
403
|
-
const
|
|
404
|
-
setShowSSOButton(e.target.checked);
|
|
405
|
-
};
|
|
406
|
-
const onChangeSSOButtonText = (e) => {
|
|
407
|
-
setSSOButtonText(e.target.value);
|
|
408
|
-
};
|
|
409
|
-
const isDirty = useWhitelist !== initialUseWhitelist || enforceOIDC !== initialEnforceOIDC || showSSOButton !== initialShowSSOButton || ssoButtonText !== initialSSOButtonText || JSON.stringify(oidcRoles) !== JSON.stringify(initialOidcRoles) || JSON.stringify(users) !== JSON.stringify(initialUsers);
|
|
414
|
+
const isDirty = useWhitelist !== initialUseWhitelist || enforceOIDC !== initialEnforceOIDC || JSON.stringify(oidcRoles) !== JSON.stringify(initialOidcRoles) || JSON.stringify(users) !== JSON.stringify(initialUsers);
|
|
410
415
|
const onSaveAll = async () => {
|
|
411
416
|
setLoading(true);
|
|
412
417
|
try {
|
|
@@ -421,15 +426,11 @@ function useOidcSettings() {
|
|
|
421
426
|
});
|
|
422
427
|
await put("/strapi-plugin-oidc/whitelist/settings", {
|
|
423
428
|
useWhitelist,
|
|
424
|
-
enforceOIDC
|
|
425
|
-
showSSOButton,
|
|
426
|
-
ssoButtonText
|
|
429
|
+
enforceOIDC
|
|
427
430
|
});
|
|
428
431
|
setInitialOIDCRoles(JSON.parse(JSON.stringify(oidcRoles)));
|
|
429
432
|
setInitialUseWhitelist(useWhitelist);
|
|
430
433
|
setInitialEnforceOIDC(enforceOIDC);
|
|
431
|
-
setInitialShowSSOButton(showSSOButton);
|
|
432
|
-
setInitialSSOButtonText(ssoButtonText);
|
|
433
434
|
get("/strapi-plugin-oidc/whitelist").then((getResponse) => {
|
|
434
435
|
setUsers(getResponse.data.whitelistUsers);
|
|
435
436
|
setInitialUsers(JSON.parse(JSON.stringify(getResponse.data.whitelistUsers)));
|
|
@@ -459,10 +460,9 @@ function useOidcSettings() {
|
|
|
459
460
|
roles,
|
|
460
461
|
useWhitelist,
|
|
461
462
|
enforceOIDC,
|
|
463
|
+
enforceOIDCConfig,
|
|
462
464
|
initialEnforceOIDC,
|
|
463
465
|
users,
|
|
464
|
-
showSSOButton,
|
|
465
|
-
ssoButtonText,
|
|
466
466
|
isDirty
|
|
467
467
|
},
|
|
468
468
|
actions: {
|
|
@@ -474,8 +474,6 @@ function useOidcSettings() {
|
|
|
474
474
|
onDeleteWhitelist,
|
|
475
475
|
onToggleWhitelist,
|
|
476
476
|
onToggleEnforce,
|
|
477
|
-
onToggleShowSSOButton,
|
|
478
|
-
onChangeSSOButtonText,
|
|
479
477
|
onSaveAll
|
|
480
478
|
}
|
|
481
479
|
};
|
|
@@ -487,8 +485,8 @@ function HomePage$1() {
|
|
|
487
485
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
488
486
|
admin.Layouts.Header,
|
|
489
487
|
{
|
|
490
|
-
title: formatMessage(getTrad("page.title.oidc")),
|
|
491
|
-
subtitle: formatMessage(getTrad("page.title"))
|
|
488
|
+
title: formatMessage(index.getTrad("page.title.oidc")),
|
|
489
|
+
subtitle: formatMessage(index.getTrad("page.title"))
|
|
492
490
|
}
|
|
493
491
|
),
|
|
494
492
|
state.showSuccess && /* @__PURE__ */ jsxRuntime.jsx(SuccessAlertMessage, { onClose: () => actions.setSuccess(false) }),
|
|
@@ -496,7 +494,7 @@ function HomePage$1() {
|
|
|
496
494
|
state.showMatched > 0 && /* @__PURE__ */ jsxRuntime.jsx(MatchedUserAlertMessage, { count: state.showMatched, onClose: () => actions.setMatched(0) }),
|
|
497
495
|
/* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
498
496
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { background: "neutral0", hasRadius: true, shadow: "filterShadow", padding: 6, children: [
|
|
499
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: formatMessage(getTrad("roles.title")) }) }),
|
|
497
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: formatMessage(index.getTrad("roles.title")) }) }),
|
|
500
498
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
501
499
|
Role,
|
|
502
500
|
{
|
|
@@ -508,13 +506,13 @@ function HomePage$1() {
|
|
|
508
506
|
] }),
|
|
509
507
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { background: "neutral0", hasRadius: true, shadow: "filterShadow", padding: 6, children: [
|
|
510
508
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", paddingBottom: 4, children: [
|
|
511
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: formatMessage(getTrad("whitelist.title")) }),
|
|
509
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: formatMessage(index.getTrad("whitelist.title")) }),
|
|
512
510
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
513
511
|
CustomSwitch,
|
|
514
512
|
{
|
|
515
513
|
checked: state.useWhitelist,
|
|
516
514
|
onChange: actions.onToggleWhitelist,
|
|
517
|
-
label: state.useWhitelist ? formatMessage(getTrad("whitelist.toggle.enabled")) : formatMessage(getTrad("whitelist.toggle.disabled"))
|
|
515
|
+
label: state.useWhitelist ? formatMessage(index.getTrad("whitelist.toggle.enabled")) : formatMessage(index.getTrad("whitelist.toggle.disabled"))
|
|
518
516
|
}
|
|
519
517
|
)
|
|
520
518
|
] }),
|
|
@@ -532,58 +530,28 @@ function HomePage$1() {
|
|
|
532
530
|
)
|
|
533
531
|
] }),
|
|
534
532
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { background: "neutral0", hasRadius: true, shadow: "filterShadow", padding: 6, children: [
|
|
535
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: formatMessage(getTrad("login.settings.title")) }) }),
|
|
536
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap:
|
|
537
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
538
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 3, wrap: "wrap", children: [
|
|
539
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", style: { minWidth: "280px" }, children: formatMessage(getTrad("enforce.title")) }),
|
|
540
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { minWidth: "160px", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
541
|
-
CustomSwitch,
|
|
542
|
-
{
|
|
543
|
-
checked: state.enforceOIDC,
|
|
544
|
-
onChange: actions.onToggleEnforce,
|
|
545
|
-
disabled: state.useWhitelist && state.users.length === 0,
|
|
546
|
-
label: state.enforceOIDC ? formatMessage(getTrad("enforce.toggle.enabled")) : formatMessage(getTrad("enforce.toggle.disabled"))
|
|
547
|
-
}
|
|
548
|
-
) })
|
|
549
|
-
] }),
|
|
550
|
-
state.enforceOIDC && state.enforceOIDC !== state.initialEnforceOIDC && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { background: "danger100", padding: 3, hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
|
|
551
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { fill: "danger600" }),
|
|
552
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", children: formatMessage(getTrad("enforce.warning")) })
|
|
553
|
-
] }) })
|
|
554
|
-
] }),
|
|
533
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: formatMessage(index.getTrad("login.settings.title")) }) }),
|
|
534
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
555
535
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 3, wrap: "wrap", children: [
|
|
556
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", style: { minWidth: "280px" }, children: formatMessage(getTrad("
|
|
536
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", style: { minWidth: "280px" }, children: formatMessage(index.getTrad("enforce.title")) }),
|
|
557
537
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { minWidth: "160px", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
558
538
|
CustomSwitch,
|
|
559
539
|
{
|
|
560
|
-
checked: state.
|
|
561
|
-
onChange: actions.
|
|
562
|
-
|
|
540
|
+
checked: state.enforceOIDC,
|
|
541
|
+
onChange: actions.onToggleEnforce,
|
|
542
|
+
disabled: state.enforceOIDCConfig !== null || state.useWhitelist && state.users.length === 0,
|
|
543
|
+
label: state.enforceOIDC ? formatMessage(index.getTrad("enforce.toggle.enabled")) : formatMessage(index.getTrad("enforce.toggle.disabled"))
|
|
563
544
|
}
|
|
564
545
|
) })
|
|
565
546
|
] }),
|
|
566
|
-
state.
|
|
567
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
children: formatMessage(getTrad("login.sso.button.text.label"))
|
|
575
|
-
}
|
|
576
|
-
),
|
|
577
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: "160px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
578
|
-
designSystem.TextInput,
|
|
579
|
-
{
|
|
580
|
-
id: "sso-button-text",
|
|
581
|
-
"aria-label": formatMessage(getTrad("login.sso.button.text.label")),
|
|
582
|
-
value: state.ssoButtonText,
|
|
583
|
-
onChange: actions.onChangeSSOButtonText
|
|
584
|
-
}
|
|
585
|
-
) })
|
|
586
|
-
] })
|
|
547
|
+
state.enforceOIDCConfig !== null && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { background: "primary100", padding: 3, hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
|
|
548
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Information, { fill: "primary600" }),
|
|
549
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "primary600", children: formatMessage(index.getTrad("enforce.config.info")) })
|
|
550
|
+
] }) }),
|
|
551
|
+
state.enforceOIDCConfig === null && state.enforceOIDC && state.enforceOIDC !== state.initialEnforceOIDC && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { background: "danger100", padding: 3, hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { fill: "danger600" }),
|
|
553
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", children: formatMessage(index.getTrad("enforce.warning")) })
|
|
554
|
+
] }) })
|
|
587
555
|
] })
|
|
588
556
|
] }),
|
|
589
557
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -593,7 +561,7 @@ function HomePage$1() {
|
|
|
593
561
|
onClick: actions.onSaveAll,
|
|
594
562
|
disabled: !state.isDirty || state.loading,
|
|
595
563
|
loading: state.loading,
|
|
596
|
-
children: formatMessage(getTrad("page.save"))
|
|
564
|
+
children: formatMessage(index.getTrad("page.save"))
|
|
597
565
|
}
|
|
598
566
|
) })
|
|
599
567
|
] }) })
|