strapi-plugin-magic-sessionmanager 4.4.7 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{Analytics-mFarhu5A.js → Analytics-B7t0WvG7.js} +2 -2
- package/dist/_chunks/{Analytics-CFlATYIp.mjs → Analytics-DmlZwyVu.mjs} +2 -2
- package/dist/_chunks/{App-CrdNlRlL.js → App-Bir8yK_r.js} +7 -3
- package/dist/_chunks/{App-BkFz8R3I.mjs → App-LfsjcXXp.mjs} +17 -13
- package/dist/_chunks/{License-BI04KWfw.js → License-B56Xklj2.js} +1 -1
- package/dist/_chunks/{License-BnbIePhc.mjs → License-OToijT0s.mjs} +1 -1
- package/dist/_chunks/{OnlineUsersWidget-D1B_2ge5.js → OnlineUsersWidget-DTEzguhS.js} +1 -1
- package/dist/_chunks/{OnlineUsersWidget-eBwttUiU.mjs → OnlineUsersWidget-Fpc0aH2z.mjs} +1 -1
- package/dist/_chunks/{Settings-BfKDErt5.mjs → Settings-Bz3lPBJ6.mjs} +119 -3
- package/dist/_chunks/{Settings-Cy-6vah_.js → Settings-CO3-iggu.js} +118 -2
- package/dist/_chunks/{UpgradePage-B8kz6Cyz.js → UpgradePage-KqUN7mDh.js} +1 -1
- package/dist/_chunks/{UpgradePage-2mV2iqDM.mjs → UpgradePage-TBx1l2mQ.mjs} +1 -1
- package/dist/_chunks/{index-BEh2DizI.js → index-CKrO7KSQ.js} +12 -6
- package/dist/_chunks/{index-B0wQeSSu.mjs → index-DuVZXuJh.mjs} +12 -6
- package/dist/_chunks/{useLicense-DFdVp_qI.js → useLicense-DHAFqFSZ.js} +1 -1
- package/dist/_chunks/{useLicense-RxDUbCoU.mjs → useLicense-Xzo6nyh3.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +13270 -8951
- package/dist/server/index.mjs +13268 -8949
- package/package.json +17 -10
|
@@ -6,8 +6,8 @@ const admin = require("@strapi/strapi/admin");
|
|
|
6
6
|
const styled = require("styled-components");
|
|
7
7
|
const designSystem = require("@strapi/design-system");
|
|
8
8
|
const icons = require("@strapi/icons");
|
|
9
|
-
const index = require("./index-
|
|
10
|
-
const useLicense = require("./useLicense-
|
|
9
|
+
const index = require("./index-CKrO7KSQ.js");
|
|
10
|
+
const useLicense = require("./useLicense-DHAFqFSZ.js");
|
|
11
11
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
12
12
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
13
13
|
const theme = {
|
|
@@ -4,8 +4,8 @@ import { useFetchClient } from "@strapi/strapi/admin";
|
|
|
4
4
|
import styled, { css, keyframes } from "styled-components";
|
|
5
5
|
import { Loader, Typography, Box, Flex, Badge } from "@strapi/design-system";
|
|
6
6
|
import { ChartBubble, Crown, User, Clock, Monitor } from "@strapi/icons";
|
|
7
|
-
import { a as pluginId } from "./index-
|
|
8
|
-
import { u as useLicense } from "./useLicense-
|
|
7
|
+
import { a as pluginId } from "./index-DuVZXuJh.mjs";
|
|
8
|
+
import { u as useLicense } from "./useLicense-Xzo6nyh3.mjs";
|
|
9
9
|
const theme = {
|
|
10
10
|
shadows: {
|
|
11
11
|
sm: "0 1px 3px 0 rgba(0, 0, 0, 0.1)",
|
|
@@ -5,10 +5,10 @@ const react = require("react");
|
|
|
5
5
|
const reactIntl = require("react-intl");
|
|
6
6
|
const admin = require("@strapi/strapi/admin");
|
|
7
7
|
const styled = require("styled-components");
|
|
8
|
-
const index = require("./index-
|
|
8
|
+
const index = require("./index-CKrO7KSQ.js");
|
|
9
9
|
const designSystem = require("@strapi/design-system");
|
|
10
10
|
const icons = require("@strapi/icons");
|
|
11
|
-
const useLicense = require("./useLicense-
|
|
11
|
+
const useLicense = require("./useLicense-DHAFqFSZ.js");
|
|
12
12
|
const StyledButtons = require("./StyledButtons-DDuxnYz8.js");
|
|
13
13
|
const reactRouterDom = require("react-router-dom");
|
|
14
14
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -2025,7 +2025,11 @@ const LicenseGuard = ({ children }) => {
|
|
|
2025
2025
|
}
|
|
2026
2026
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
2027
2027
|
};
|
|
2028
|
+
const pluginId = "magic-sessionmanager";
|
|
2029
|
+
const pluginPermissions = {
|
|
2030
|
+
access: [{ action: `plugin::${pluginId}.access`, subject: null }]
|
|
2031
|
+
};
|
|
2028
2032
|
const App = () => {
|
|
2029
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LicenseGuard, { children: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) });
|
|
2033
|
+
return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: pluginPermissions.access, children: /* @__PURE__ */ jsxRuntime.jsx(LicenseGuard, { children: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) }) });
|
|
2030
2034
|
};
|
|
2031
2035
|
exports.default = App;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from "react";
|
|
3
3
|
import { useIntl } from "react-intl";
|
|
4
|
-
import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
4
|
+
import { useFetchClient, useNotification, Page } from "@strapi/strapi/admin";
|
|
5
5
|
import styled, { css, keyframes } from "styled-components";
|
|
6
|
-
import { p as parseUserAgent, a as pluginId, g as getTranslation } from "./index-
|
|
6
|
+
import { p as parseUserAgent, a as pluginId$1, g as getTranslation } from "./index-DuVZXuJh.mjs";
|
|
7
7
|
import { Modal, Flex, Box, Typography, Divider, Button, Loader, SingleSelect, SingleSelectOption, Thead, Tr, Th, Tbody, Td, Table, TextInput } from "@strapi/design-system";
|
|
8
8
|
import { Check, Information, Monitor, Server, Clock, Cross, Earth, Shield, Crown, Phone, Download, User, Eye, Trash, Search, Key } from "@strapi/icons";
|
|
9
|
-
import { u as useLicense } from "./useLicense-
|
|
9
|
+
import { u as useLicense } from "./useLicense-Xzo6nyh3.mjs";
|
|
10
10
|
import { S as ShowHideButton, T as TertiaryButton, D as DangerButton, I as IconButtonPrimary, a as IconButtonWarning, b as IconButtonDanger } from "./StyledButtons-Cz8oYhmc.mjs";
|
|
11
11
|
import { useNavigate } from "react-router-dom";
|
|
12
12
|
const theme = {
|
|
@@ -145,7 +145,7 @@ const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
|
|
|
145
145
|
const fetchGeolocationData = async () => {
|
|
146
146
|
setGeoLoading(true);
|
|
147
147
|
try {
|
|
148
|
-
const { data } = await get(`/${pluginId}/geolocation/${session.ipAddress}`);
|
|
148
|
+
const { data } = await get(`/${pluginId$1}/geolocation/${session.ipAddress}`);
|
|
149
149
|
setGeoData(data.data);
|
|
150
150
|
} catch (err) {
|
|
151
151
|
console.error("[SessionDetailModal] Error fetching geolocation:", err);
|
|
@@ -185,7 +185,7 @@ const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
|
|
|
185
185
|
}
|
|
186
186
|
setTerminating(true);
|
|
187
187
|
try {
|
|
188
|
-
await post(`/${pluginId}/sessions/${session.id}/terminate`);
|
|
188
|
+
await post(`/${pluginId$1}/sessions/${session.id}/terminate`);
|
|
189
189
|
toggleNotification({
|
|
190
190
|
type: "success",
|
|
191
191
|
message: t("notifications.success.terminated", "Session terminated successfully")
|
|
@@ -889,7 +889,7 @@ const HomePage = () => {
|
|
|
889
889
|
const fetchSessions = async () => {
|
|
890
890
|
setLoading(true);
|
|
891
891
|
try {
|
|
892
|
-
const { data } = await get(`/${pluginId}/sessions`);
|
|
892
|
+
const { data } = await get(`/${pluginId$1}/sessions`);
|
|
893
893
|
setSessions(data.data || []);
|
|
894
894
|
} catch (err) {
|
|
895
895
|
console.error("[SessionManager] Error fetching sessions:", err);
|
|
@@ -902,7 +902,7 @@ const HomePage = () => {
|
|
|
902
902
|
return;
|
|
903
903
|
}
|
|
904
904
|
try {
|
|
905
|
-
await post(`/${pluginId}/sessions/${sessionId}/terminate`);
|
|
905
|
+
await post(`/${pluginId$1}/sessions/${sessionId}/terminate`);
|
|
906
906
|
fetchSessions();
|
|
907
907
|
} catch (err) {
|
|
908
908
|
console.error("[SessionManager] Error terminating session:", err);
|
|
@@ -913,7 +913,7 @@ const HomePage = () => {
|
|
|
913
913
|
return;
|
|
914
914
|
}
|
|
915
915
|
try {
|
|
916
|
-
await del(`/${pluginId}/sessions/${sessionId}`);
|
|
916
|
+
await del(`/${pluginId$1}/sessions/${sessionId}`);
|
|
917
917
|
fetchSessions();
|
|
918
918
|
toggleNotification({
|
|
919
919
|
type: "success",
|
|
@@ -1645,7 +1645,7 @@ const LicenseGuard = ({ children }) => {
|
|
|
1645
1645
|
const checkLicenseStatus = async () => {
|
|
1646
1646
|
setIsChecking(true);
|
|
1647
1647
|
try {
|
|
1648
|
-
const response = await get(`/${pluginId}/license/status`);
|
|
1648
|
+
const response = await get(`/${pluginId$1}/license/status`);
|
|
1649
1649
|
if (response.data.valid) {
|
|
1650
1650
|
setNeedsLicense(false);
|
|
1651
1651
|
} else {
|
|
@@ -1662,7 +1662,7 @@ const LicenseGuard = ({ children }) => {
|
|
|
1662
1662
|
e.preventDefault();
|
|
1663
1663
|
setIsCreating(true);
|
|
1664
1664
|
try {
|
|
1665
|
-
const response = await post(`/${pluginId}/license/auto-create`, {});
|
|
1665
|
+
const response = await post(`/${pluginId$1}/license/auto-create`, {});
|
|
1666
1666
|
if (response.data && response.data.success) {
|
|
1667
1667
|
toggleNotification({
|
|
1668
1668
|
type: "success",
|
|
@@ -1696,7 +1696,7 @@ const LicenseGuard = ({ children }) => {
|
|
|
1696
1696
|
}
|
|
1697
1697
|
setIsCreating(true);
|
|
1698
1698
|
try {
|
|
1699
|
-
const response = await post(`/${pluginId}/license/create`, formData);
|
|
1699
|
+
const response = await post(`/${pluginId$1}/license/create`, formData);
|
|
1700
1700
|
if (response.data && response.data.success) {
|
|
1701
1701
|
toggleNotification({
|
|
1702
1702
|
type: "success",
|
|
@@ -1729,7 +1729,7 @@ const LicenseGuard = ({ children }) => {
|
|
|
1729
1729
|
}
|
|
1730
1730
|
setIsCreating(true);
|
|
1731
1731
|
try {
|
|
1732
|
-
const response = await post(`/${pluginId}/license/store-key`, {
|
|
1732
|
+
const response = await post(`/${pluginId$1}/license/store-key`, {
|
|
1733
1733
|
licenseKey: existingLicenseKey.trim(),
|
|
1734
1734
|
email: existingEmail.trim()
|
|
1735
1735
|
});
|
|
@@ -2021,8 +2021,12 @@ const LicenseGuard = ({ children }) => {
|
|
|
2021
2021
|
}
|
|
2022
2022
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
2023
2023
|
};
|
|
2024
|
+
const pluginId = "magic-sessionmanager";
|
|
2025
|
+
const pluginPermissions = {
|
|
2026
|
+
access: [{ action: `plugin::${pluginId}.access`, subject: null }]
|
|
2027
|
+
};
|
|
2024
2028
|
const App = () => {
|
|
2025
|
-
return /* @__PURE__ */ jsx(LicenseGuard, { children: /* @__PURE__ */ jsx(HomePage, {}) });
|
|
2029
|
+
return /* @__PURE__ */ jsx(Page.Protect, { permissions: pluginPermissions.access, children: /* @__PURE__ */ jsx(LicenseGuard, { children: /* @__PURE__ */ jsx(HomePage, {}) }) });
|
|
2026
2030
|
};
|
|
2027
2031
|
export {
|
|
2028
2032
|
App as default
|
|
@@ -6,7 +6,7 @@ const designSystem = require("@strapi/design-system");
|
|
|
6
6
|
const admin = require("@strapi/strapi/admin");
|
|
7
7
|
const icons = require("@strapi/icons");
|
|
8
8
|
const styled = require("styled-components");
|
|
9
|
-
const index = require("./index-
|
|
9
|
+
const index = require("./index-CKrO7KSQ.js");
|
|
10
10
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
11
11
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
12
12
|
const theme = {
|
|
@@ -4,7 +4,7 @@ import { Loader, Box, Alert, Flex, Typography, Button, Badge, Accordion } from "
|
|
|
4
4
|
import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
5
5
|
import { ArrowClockwise, Duplicate, Download, User, Shield, Sparkle, ChartBubble } from "@strapi/icons";
|
|
6
6
|
import styled, { css, keyframes } from "styled-components";
|
|
7
|
-
import { a as pluginId } from "./index-
|
|
7
|
+
import { a as pluginId } from "./index-DuVZXuJh.mjs";
|
|
8
8
|
const theme = {
|
|
9
9
|
borderRadius: { lg: "12px" }
|
|
10
10
|
};
|
|
@@ -6,7 +6,7 @@ const reactIntl = require("react-intl");
|
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
7
|
const icons = require("@strapi/icons");
|
|
8
8
|
const admin = require("@strapi/strapi/admin");
|
|
9
|
-
const index = require("./index-
|
|
9
|
+
const index = require("./index-CKrO7KSQ.js");
|
|
10
10
|
const OnlineUsersWidget = () => {
|
|
11
11
|
const { formatMessage } = reactIntl.useIntl();
|
|
12
12
|
const { get } = admin.useFetchClient();
|
|
@@ -4,7 +4,7 @@ import { useIntl } from "react-intl";
|
|
|
4
4
|
import { Box, Typography, Flex, Grid } from "@strapi/design-system";
|
|
5
5
|
import { Check, Cross, Clock, User } from "@strapi/icons";
|
|
6
6
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
7
|
-
import { g as getTranslation } from "./index-
|
|
7
|
+
import { g as getTranslation } from "./index-DuVZXuJh.mjs";
|
|
8
8
|
const OnlineUsersWidget = () => {
|
|
9
9
|
const { formatMessage } = useIntl();
|
|
10
10
|
const { get } = useFetchClient();
|
|
@@ -3,10 +3,10 @@ import { useState, useEffect } from "react";
|
|
|
3
3
|
import { useIntl } from "react-intl";
|
|
4
4
|
import { Flex, Loader, Typography, Button, Box, Badge, Accordion, Grid, SingleSelect, SingleSelectOption, Divider, Alert, TextInput, Toggle, NumberInput, Checkbox, Tabs } from "@strapi/design-system";
|
|
5
5
|
import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
6
|
-
import { Check, Information, Cog, Trash, Shield, Code, Duplicate, Mail } from "@strapi/icons";
|
|
6
|
+
import { Check, Information, Cog, Trash, Shield, Code, Duplicate, Clock, Mail } from "@strapi/icons";
|
|
7
7
|
import styled, { css, keyframes } from "styled-components";
|
|
8
|
-
import { a as pluginId, g as getTranslation } from "./index-
|
|
9
|
-
import { u as useLicense } from "./useLicense-
|
|
8
|
+
import { a as pluginId, g as getTranslation } from "./index-DuVZXuJh.mjs";
|
|
9
|
+
import { u as useLicense } from "./useLicense-Xzo6nyh3.mjs";
|
|
10
10
|
import { D as DangerButton, S as ShowHideButton, G as GradientButton, C as CopyButton, T as TertiaryButton, c as SecondaryButton } from "./StyledButtons-Cz8oYhmc.mjs";
|
|
11
11
|
const theme = {
|
|
12
12
|
borderRadius: { md: "8px", lg: "12px" }
|
|
@@ -345,6 +345,9 @@ const SettingsPage = () => {
|
|
|
345
345
|
cleanupInterval: 30,
|
|
346
346
|
lastSeenRateLimit: 30,
|
|
347
347
|
retentionDays: 90,
|
|
348
|
+
maxSessionAgeDays: 30,
|
|
349
|
+
strictSessionEnforcement: false,
|
|
350
|
+
trustedProxies: false,
|
|
348
351
|
enableGeolocation: true,
|
|
349
352
|
enableSecurityScoring: true,
|
|
350
353
|
blockSuspiciousSessions: false,
|
|
@@ -783,6 +786,119 @@ const SettingsPage = () => {
|
|
|
783
786
|
] })
|
|
784
787
|
}
|
|
785
788
|
),
|
|
789
|
+
/* @__PURE__ */ jsx(
|
|
790
|
+
Box,
|
|
791
|
+
{
|
|
792
|
+
background: "neutral0",
|
|
793
|
+
padding: 6,
|
|
794
|
+
style: {
|
|
795
|
+
borderRadius: theme.borderRadius.lg,
|
|
796
|
+
marginBottom: "32px",
|
|
797
|
+
border: `2px solid ${settings.strictSessionEnforcement ? "rgba(220, 38, 38, 0.25)" : "rgba(2, 132, 199, 0.12)"}`,
|
|
798
|
+
background: settings.strictSessionEnforcement ? "rgba(220, 38, 38, 0.04)" : "rgba(2, 132, 199, 0.04)"
|
|
799
|
+
},
|
|
800
|
+
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, children: [
|
|
801
|
+
/* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 3, children: [
|
|
802
|
+
/* @__PURE__ */ jsx(Shield, { style: { width: 24, height: 24, color: settings.strictSessionEnforcement ? "var(--colors-danger600, #DC2626)" : "var(--colors-primary600, #0284C7)" } }),
|
|
803
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "bold", children: t("settings.security.enforcement.title", "Session Enforcement Policy") }),
|
|
804
|
+
/* @__PURE__ */ jsx(Badge, { backgroundColor: settings.strictSessionEnforcement ? "danger100" : "neutral100", textColor: settings.strictSessionEnforcement ? "danger700" : "neutral700", children: settings.strictSessionEnforcement ? t("settings.security.enforcement.badgeStrict", "STRICT") : t("settings.security.enforcement.badgeRelaxed", "RELAXED") })
|
|
805
|
+
] }),
|
|
806
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { lineHeight: 1.6 }, children: t("settings.security.enforcement.description", "Controls how aggressively JWT tokens are tied to an active session record. Strict mode rejects any token without a matching session, which is more secure but breaks tokens issued before this plugin was installed.") }),
|
|
807
|
+
/* @__PURE__ */ jsxs(Grid.Root, { gap: 6, children: [
|
|
808
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 12, s: 12, children: /* @__PURE__ */ jsx(
|
|
809
|
+
ToggleCard,
|
|
810
|
+
{
|
|
811
|
+
$active: settings.strictSessionEnforcement,
|
|
812
|
+
onClick: () => handleChange("strictSessionEnforcement", !settings.strictSessionEnforcement),
|
|
813
|
+
children: /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: 4, style: { width: "100%" }, alignItems: "center", children: [
|
|
814
|
+
/* @__PURE__ */ jsx(GreenToggle, { $isActive: settings.strictSessionEnforcement, children: /* @__PURE__ */ jsx(
|
|
815
|
+
Toggle,
|
|
816
|
+
{
|
|
817
|
+
checked: settings.strictSessionEnforcement,
|
|
818
|
+
onChange: () => handleChange("strictSessionEnforcement", !settings.strictSessionEnforcement)
|
|
819
|
+
}
|
|
820
|
+
) }),
|
|
821
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, style: { flex: 1 }, children: [
|
|
822
|
+
/* @__PURE__ */ jsx(
|
|
823
|
+
Typography,
|
|
824
|
+
{
|
|
825
|
+
variant: "delta",
|
|
826
|
+
fontWeight: "bold",
|
|
827
|
+
textColor: settings.strictSessionEnforcement ? "success700" : "neutral800",
|
|
828
|
+
style: { fontSize: "15px" },
|
|
829
|
+
children: t("settings.security.enforcement.strict.title", "Strict Session Enforcement")
|
|
830
|
+
}
|
|
831
|
+
),
|
|
832
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px", lineHeight: "1.5" }, children: t("settings.security.enforcement.strict.description", "Reject every authenticated request that does not have a matching session record. Recommended for production.") })
|
|
833
|
+
] })
|
|
834
|
+
] })
|
|
835
|
+
}
|
|
836
|
+
) }),
|
|
837
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(Box, { children: [
|
|
838
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: [
|
|
839
|
+
/* @__PURE__ */ jsx(Clock, { style: { width: 14, height: 14, verticalAlign: "middle", marginRight: 6 } }),
|
|
840
|
+
t("settings.security.enforcement.maxAge.title", "Max Session Age")
|
|
841
|
+
] }),
|
|
842
|
+
/* @__PURE__ */ jsxs(
|
|
843
|
+
SingleSelect,
|
|
844
|
+
{
|
|
845
|
+
value: String(settings.maxSessionAgeDays),
|
|
846
|
+
onChange: (value) => handleChange("maxSessionAgeDays", parseInt(value)),
|
|
847
|
+
children: [
|
|
848
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "1", children: t("settings.security.enforcement.maxAge.1day", "1 day (Very Strict)") }),
|
|
849
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "7", children: t("settings.security.enforcement.maxAge.7days", "7 days") }),
|
|
850
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "14", children: t("settings.security.enforcement.maxAge.14days", "14 days") }),
|
|
851
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "30", children: t("settings.security.enforcement.maxAge.30days", "30 days (Recommended)") }),
|
|
852
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "60", children: t("settings.security.enforcement.maxAge.60days", "60 days") }),
|
|
853
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "90", children: t("settings.security.enforcement.maxAge.90days", "90 days") }),
|
|
854
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "180", children: t("settings.security.enforcement.maxAge.180days", "180 days") }),
|
|
855
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "365", children: t("settings.security.enforcement.maxAge.365days", "1 year") })
|
|
856
|
+
]
|
|
857
|
+
}
|
|
858
|
+
),
|
|
859
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: t("settings.security.enforcement.maxAge.hint", "Sessions older than {days} days are automatically terminated, even if still active", { days: settings.maxSessionAgeDays }) })
|
|
860
|
+
] }) }),
|
|
861
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsx(
|
|
862
|
+
ToggleCard,
|
|
863
|
+
{
|
|
864
|
+
$active: settings.trustedProxies,
|
|
865
|
+
onClick: () => handleChange("trustedProxies", !settings.trustedProxies),
|
|
866
|
+
children: /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: 4, style: { width: "100%" }, alignItems: "center", children: [
|
|
867
|
+
/* @__PURE__ */ jsx(GreenToggle, { $isActive: settings.trustedProxies, children: /* @__PURE__ */ jsx(
|
|
868
|
+
Toggle,
|
|
869
|
+
{
|
|
870
|
+
checked: settings.trustedProxies,
|
|
871
|
+
onChange: () => handleChange("trustedProxies", !settings.trustedProxies)
|
|
872
|
+
}
|
|
873
|
+
) }),
|
|
874
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, style: { flex: 1 }, children: [
|
|
875
|
+
/* @__PURE__ */ jsx(
|
|
876
|
+
Typography,
|
|
877
|
+
{
|
|
878
|
+
variant: "delta",
|
|
879
|
+
fontWeight: "bold",
|
|
880
|
+
textColor: settings.trustedProxies ? "success700" : "neutral800",
|
|
881
|
+
style: { fontSize: "15px" },
|
|
882
|
+
children: t("settings.security.enforcement.trustedProxies.title", "Trust Upstream Proxy")
|
|
883
|
+
}
|
|
884
|
+
),
|
|
885
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px", lineHeight: "1.5" }, children: t("settings.security.enforcement.trustedProxies.description", "Only enable when Strapi sits behind a trusted reverse proxy (nginx, Cloudflare). Otherwise clients can spoof X-Forwarded-For.") })
|
|
886
|
+
] })
|
|
887
|
+
] })
|
|
888
|
+
}
|
|
889
|
+
) })
|
|
890
|
+
] }),
|
|
891
|
+
!settings.strictSessionEnforcement && /* @__PURE__ */ jsx(
|
|
892
|
+
Alert,
|
|
893
|
+
{
|
|
894
|
+
variant: "warning",
|
|
895
|
+
title: t("settings.security.enforcement.warning.title", "Running in Relaxed Mode"),
|
|
896
|
+
children: t("settings.security.enforcement.warning.body", "Tokens without a matching session record are allowed through. Manual session termination is still enforced via the token hash, but we strongly recommend enabling strict mode in production.")
|
|
897
|
+
}
|
|
898
|
+
)
|
|
899
|
+
] })
|
|
900
|
+
}
|
|
901
|
+
),
|
|
786
902
|
/* @__PURE__ */ jsx(Box, { background: "neutral100", padding: 5, style: { borderRadius: theme.borderRadius.md, marginBottom: "32px" }, children: /* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
|
|
787
903
|
/* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsx(
|
|
788
904
|
ToggleCard,
|
|
@@ -7,8 +7,8 @@ const designSystem = require("@strapi/design-system");
|
|
|
7
7
|
const admin = require("@strapi/strapi/admin");
|
|
8
8
|
const icons = require("@strapi/icons");
|
|
9
9
|
const styled = require("styled-components");
|
|
10
|
-
const index = require("./index-
|
|
11
|
-
const useLicense = require("./useLicense-
|
|
10
|
+
const index = require("./index-CKrO7KSQ.js");
|
|
11
|
+
const useLicense = require("./useLicense-DHAFqFSZ.js");
|
|
12
12
|
const StyledButtons = require("./StyledButtons-DDuxnYz8.js");
|
|
13
13
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
14
14
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
@@ -349,6 +349,9 @@ const SettingsPage = () => {
|
|
|
349
349
|
cleanupInterval: 30,
|
|
350
350
|
lastSeenRateLimit: 30,
|
|
351
351
|
retentionDays: 90,
|
|
352
|
+
maxSessionAgeDays: 30,
|
|
353
|
+
strictSessionEnforcement: false,
|
|
354
|
+
trustedProxies: false,
|
|
352
355
|
enableGeolocation: true,
|
|
353
356
|
enableSecurityScoring: true,
|
|
354
357
|
blockSuspiciousSessions: false,
|
|
@@ -787,6 +790,119 @@ const SettingsPage = () => {
|
|
|
787
790
|
] })
|
|
788
791
|
}
|
|
789
792
|
),
|
|
793
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
794
|
+
designSystem.Box,
|
|
795
|
+
{
|
|
796
|
+
background: "neutral0",
|
|
797
|
+
padding: 6,
|
|
798
|
+
style: {
|
|
799
|
+
borderRadius: theme.borderRadius.lg,
|
|
800
|
+
marginBottom: "32px",
|
|
801
|
+
border: `2px solid ${settings.strictSessionEnforcement ? "rgba(220, 38, 38, 0.25)" : "rgba(2, 132, 199, 0.12)"}`,
|
|
802
|
+
background: settings.strictSessionEnforcement ? "rgba(220, 38, 38, 0.04)" : "rgba(2, 132, 199, 0.04)"
|
|
803
|
+
},
|
|
804
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 4, children: [
|
|
805
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 3, children: [
|
|
806
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Shield, { style: { width: 24, height: 24, color: settings.strictSessionEnforcement ? "var(--colors-danger600, #DC2626)" : "var(--colors-primary600, #0284C7)" } }),
|
|
807
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", children: t("settings.security.enforcement.title", "Session Enforcement Policy") }),
|
|
808
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: settings.strictSessionEnforcement ? "danger100" : "neutral100", textColor: settings.strictSessionEnforcement ? "danger700" : "neutral700", children: settings.strictSessionEnforcement ? t("settings.security.enforcement.badgeStrict", "STRICT") : t("settings.security.enforcement.badgeRelaxed", "RELAXED") })
|
|
809
|
+
] }),
|
|
810
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", style: { lineHeight: 1.6 }, children: t("settings.security.enforcement.description", "Controls how aggressively JWT tokens are tied to an active session record. Strict mode rejects any token without a matching session, which is more secure but breaks tokens issued before this plugin was installed.") }),
|
|
811
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 6, children: [
|
|
812
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
813
|
+
ToggleCard,
|
|
814
|
+
{
|
|
815
|
+
$active: settings.strictSessionEnforcement,
|
|
816
|
+
onClick: () => handleChange("strictSessionEnforcement", !settings.strictSessionEnforcement),
|
|
817
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "row", gap: 4, style: { width: "100%" }, alignItems: "center", children: [
|
|
818
|
+
/* @__PURE__ */ jsxRuntime.jsx(GreenToggle, { $isActive: settings.strictSessionEnforcement, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
819
|
+
designSystem.Toggle,
|
|
820
|
+
{
|
|
821
|
+
checked: settings.strictSessionEnforcement,
|
|
822
|
+
onChange: () => handleChange("strictSessionEnforcement", !settings.strictSessionEnforcement)
|
|
823
|
+
}
|
|
824
|
+
) }),
|
|
825
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, style: { flex: 1 }, children: [
|
|
826
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
827
|
+
designSystem.Typography,
|
|
828
|
+
{
|
|
829
|
+
variant: "delta",
|
|
830
|
+
fontWeight: "bold",
|
|
831
|
+
textColor: settings.strictSessionEnforcement ? "success700" : "neutral800",
|
|
832
|
+
style: { fontSize: "15px" },
|
|
833
|
+
children: t("settings.security.enforcement.strict.title", "Strict Session Enforcement")
|
|
834
|
+
}
|
|
835
|
+
),
|
|
836
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px", lineHeight: "1.5" }, children: t("settings.security.enforcement.strict.description", "Reject every authenticated request that does not have a matching session record. Recommended for production.") })
|
|
837
|
+
] })
|
|
838
|
+
] })
|
|
839
|
+
}
|
|
840
|
+
) }),
|
|
841
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
842
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: [
|
|
843
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Clock, { style: { width: 14, height: 14, verticalAlign: "middle", marginRight: 6 } }),
|
|
844
|
+
t("settings.security.enforcement.maxAge.title", "Max Session Age")
|
|
845
|
+
] }),
|
|
846
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
847
|
+
designSystem.SingleSelect,
|
|
848
|
+
{
|
|
849
|
+
value: String(settings.maxSessionAgeDays),
|
|
850
|
+
onChange: (value) => handleChange("maxSessionAgeDays", parseInt(value)),
|
|
851
|
+
children: [
|
|
852
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "1", children: t("settings.security.enforcement.maxAge.1day", "1 day (Very Strict)") }),
|
|
853
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "7", children: t("settings.security.enforcement.maxAge.7days", "7 days") }),
|
|
854
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "14", children: t("settings.security.enforcement.maxAge.14days", "14 days") }),
|
|
855
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: t("settings.security.enforcement.maxAge.30days", "30 days (Recommended)") }),
|
|
856
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: t("settings.security.enforcement.maxAge.60days", "60 days") }),
|
|
857
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "90", children: t("settings.security.enforcement.maxAge.90days", "90 days") }),
|
|
858
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "180", children: t("settings.security.enforcement.maxAge.180days", "180 days") }),
|
|
859
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "365", children: t("settings.security.enforcement.maxAge.365days", "1 year") })
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
),
|
|
863
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: t("settings.security.enforcement.maxAge.hint", "Sessions older than {days} days are automatically terminated, even if still active", { days: settings.maxSessionAgeDays }) })
|
|
864
|
+
] }) }),
|
|
865
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
866
|
+
ToggleCard,
|
|
867
|
+
{
|
|
868
|
+
$active: settings.trustedProxies,
|
|
869
|
+
onClick: () => handleChange("trustedProxies", !settings.trustedProxies),
|
|
870
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "row", gap: 4, style: { width: "100%" }, alignItems: "center", children: [
|
|
871
|
+
/* @__PURE__ */ jsxRuntime.jsx(GreenToggle, { $isActive: settings.trustedProxies, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
872
|
+
designSystem.Toggle,
|
|
873
|
+
{
|
|
874
|
+
checked: settings.trustedProxies,
|
|
875
|
+
onChange: () => handleChange("trustedProxies", !settings.trustedProxies)
|
|
876
|
+
}
|
|
877
|
+
) }),
|
|
878
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, style: { flex: 1 }, children: [
|
|
879
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
880
|
+
designSystem.Typography,
|
|
881
|
+
{
|
|
882
|
+
variant: "delta",
|
|
883
|
+
fontWeight: "bold",
|
|
884
|
+
textColor: settings.trustedProxies ? "success700" : "neutral800",
|
|
885
|
+
style: { fontSize: "15px" },
|
|
886
|
+
children: t("settings.security.enforcement.trustedProxies.title", "Trust Upstream Proxy")
|
|
887
|
+
}
|
|
888
|
+
),
|
|
889
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px", lineHeight: "1.5" }, children: t("settings.security.enforcement.trustedProxies.description", "Only enable when Strapi sits behind a trusted reverse proxy (nginx, Cloudflare). Otherwise clients can spoof X-Forwarded-For.") })
|
|
890
|
+
] })
|
|
891
|
+
] })
|
|
892
|
+
}
|
|
893
|
+
) })
|
|
894
|
+
] }),
|
|
895
|
+
!settings.strictSessionEnforcement && /* @__PURE__ */ jsxRuntime.jsx(
|
|
896
|
+
designSystem.Alert,
|
|
897
|
+
{
|
|
898
|
+
variant: "warning",
|
|
899
|
+
title: t("settings.security.enforcement.warning.title", "Running in Relaxed Mode"),
|
|
900
|
+
children: t("settings.security.enforcement.warning.body", "Tokens without a matching session record are allowed through. Manual session termination is still enforced via the token hash, but we strongly recommend enabling strict mode in production.")
|
|
901
|
+
}
|
|
902
|
+
)
|
|
903
|
+
] })
|
|
904
|
+
}
|
|
905
|
+
),
|
|
790
906
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { background: "neutral100", padding: 5, style: { borderRadius: theme.borderRadius.md, marginBottom: "32px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 4, children: [
|
|
791
907
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
792
908
|
ToggleCard,
|
|
@@ -6,7 +6,7 @@ const admin = require("@strapi/strapi/admin");
|
|
|
6
6
|
const styled = require("styled-components");
|
|
7
7
|
const designSystem = require("@strapi/design-system");
|
|
8
8
|
const icons = require("@strapi/icons");
|
|
9
|
-
const index = require("./index-
|
|
9
|
+
const index = require("./index-CKrO7KSQ.js");
|
|
10
10
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
11
11
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
12
12
|
const Container = styled__default.default(designSystem.Box)`
|
|
@@ -4,7 +4,7 @@ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
|
4
4
|
import styled from "styled-components";
|
|
5
5
|
import { Flex, Typography, Box, Badge, Button } from "@strapi/design-system";
|
|
6
6
|
import { Check, Cross, Sparkle, Lightning, Rocket } from "@strapi/icons";
|
|
7
|
-
import { a as pluginId } from "./index-
|
|
7
|
+
import { a as pluginId } from "./index-DuVZXuJh.mjs";
|
|
8
8
|
const Container = styled(Box)`
|
|
9
9
|
padding: 32px;
|
|
10
10
|
max-width: 1400px;
|
|
@@ -436,6 +436,7 @@ const prefixPluginTranslations = (data, pluginId2) => {
|
|
|
436
436
|
const name = pluginPkg.strapi.name;
|
|
437
437
|
const index = {
|
|
438
438
|
register(app) {
|
|
439
|
+
const pluginPermissions = [{ action: `plugin::${pluginId}.access`, subject: null }];
|
|
439
440
|
app.addMenuLink({
|
|
440
441
|
to: `plugins/${pluginId}`,
|
|
441
442
|
icon: PluginIcon,
|
|
@@ -443,7 +444,8 @@ const index = {
|
|
|
443
444
|
id: `${pluginId}.plugin.name`,
|
|
444
445
|
defaultMessage: pluginPkg.strapi.displayName
|
|
445
446
|
},
|
|
446
|
-
Component: () => Promise.resolve().then(() => require("./App-
|
|
447
|
+
Component: () => Promise.resolve().then(() => require("./App-Bir8yK_r.js")),
|
|
448
|
+
permissions: pluginPermissions
|
|
447
449
|
});
|
|
448
450
|
app.createSettingSection(
|
|
449
451
|
{
|
|
@@ -459,7 +461,8 @@ const index = {
|
|
|
459
461
|
},
|
|
460
462
|
id: "upgrade",
|
|
461
463
|
to: `${pluginId}/upgrade`,
|
|
462
|
-
Component: () => Promise.resolve().then(() => require("./UpgradePage-
|
|
464
|
+
Component: () => Promise.resolve().then(() => require("./UpgradePage-KqUN7mDh.js")),
|
|
465
|
+
permissions: pluginPermissions
|
|
463
466
|
},
|
|
464
467
|
{
|
|
465
468
|
intlLabel: {
|
|
@@ -468,7 +471,8 @@ const index = {
|
|
|
468
471
|
},
|
|
469
472
|
id: "general",
|
|
470
473
|
to: `${pluginId}/general`,
|
|
471
|
-
Component: () => Promise.resolve().then(() => require("./Settings-
|
|
474
|
+
Component: () => Promise.resolve().then(() => require("./Settings-CO3-iggu.js")),
|
|
475
|
+
permissions: pluginPermissions
|
|
472
476
|
},
|
|
473
477
|
{
|
|
474
478
|
intlLabel: {
|
|
@@ -477,7 +481,8 @@ const index = {
|
|
|
477
481
|
},
|
|
478
482
|
id: "analytics",
|
|
479
483
|
to: `${pluginId}/analytics`,
|
|
480
|
-
Component: () => Promise.resolve().then(() => require("./Analytics-
|
|
484
|
+
Component: () => Promise.resolve().then(() => require("./Analytics-B7t0WvG7.js")),
|
|
485
|
+
permissions: pluginPermissions
|
|
481
486
|
},
|
|
482
487
|
{
|
|
483
488
|
intlLabel: {
|
|
@@ -486,7 +491,8 @@ const index = {
|
|
|
486
491
|
},
|
|
487
492
|
id: "license",
|
|
488
493
|
to: `${pluginId}/license`,
|
|
489
|
-
Component: () => Promise.resolve().then(() => require("./License-
|
|
494
|
+
Component: () => Promise.resolve().then(() => require("./License-B56Xklj2.js")),
|
|
495
|
+
permissions: pluginPermissions
|
|
490
496
|
}
|
|
491
497
|
]
|
|
492
498
|
);
|
|
@@ -504,7 +510,7 @@ const index = {
|
|
|
504
510
|
defaultMessage: "Online Users"
|
|
505
511
|
},
|
|
506
512
|
component: async () => {
|
|
507
|
-
const component = await Promise.resolve().then(() => require("./OnlineUsersWidget-
|
|
513
|
+
const component = await Promise.resolve().then(() => require("./OnlineUsersWidget-DTEzguhS.js"));
|
|
508
514
|
return component.default;
|
|
509
515
|
},
|
|
510
516
|
id: "online-users-widget",
|