strapi-security-suite
Version:
All-in-one authentication and session security plugin for Strapi v5
192 lines (191 loc) • 7.86 kB
JavaScript
import { jsxs, jsx } from "react/jsx-runtime";
import { Page } from "@strapi/strapi/admin";
import { Routes, Route } from "react-router-dom";
import { useState, useEffect } from "react";
import { Box, Typography, Alert, Flex, Divider, NumberInput, Switch, Button } from "@strapi/design-system";
function IsLoggedInDebugger() {
const [value, setValue] = useState(localStorage.getItem("isLoggedIn"));
useEffect(() => {
const originalSetItem = Storage.prototype.setItem;
Storage.prototype.setItem = function(key, val) {
if (key === "isLoggedIn") {
console.log(`🕵️ isLoggedIn changed to:`, val);
setValue(val);
}
return originalSetItem.apply(this, arguments);
};
const interval = setInterval(() => {
const current = localStorage.getItem("isLoggedIn");
setValue(current);
}, 1e3);
return () => {
clearInterval(interval);
Storage.prototype.setItem = originalSetItem;
};
}, []);
return /* @__PURE__ */ jsxs("div", { style: {
position: "fixed",
bottom: "10px",
right: "10px",
backgroundColor: "rgba(0,0,0,0.7)",
color: "lime",
padding: "10px",
borderRadius: "10px",
fontSize: "14px",
zIndex: 9999,
fontFamily: "monospace"
}, children: [
/* @__PURE__ */ jsx("strong", { children: 'localStorage["isLoggedIn"]:' }),
" ",
String(value)
] });
}
const HomePage = () => {
const [config, setConfig] = useState({
autoLogoutTime: 30,
multipleSessionsControl: false,
passwordExpiryDays: 365,
nonReusablePassword: false,
enablePasswordManagement: false
});
const [success, setSuccess] = useState(false);
useEffect(() => {
const fetchConfig = async () => {
try {
const res = await fetch("/strapi-security-suite/admin/settings");
const json = await res.json();
setConfig(json);
} catch (e) {
console.error("❌ Failed to fetch config", e);
}
};
fetchConfig();
}, []);
const handleChange = (key, value) => {
setConfig((prev) => ({ ...prev, [key]: value }));
};
const saveConfig = async () => {
try {
const res = await fetch("/strapi-security-suite/admin/settings", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(config)
});
if (res.ok) {
setSuccess(true);
setTimeout(() => setSuccess(false), 3e3);
}
} catch (err) {
console.error("❌ Save failed:", err);
}
};
return /* @__PURE__ */ jsxs(Box, { padding: 10, background: "neutral0", shadow: "filterShadow", borderRadius: "12px", children: [
/* @__PURE__ */ jsx(IsLoggedInDebugger, {}),
/* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", fontWeight: "bold", children: "Security & Session Settings" }),
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", paddingTop: 2, paddingBottom: 4, children: "Configure session duration, password policies, and security settings." }),
success && /* @__PURE__ */ jsx(Alert, { title: "Success", variant: "success", marginBottom: 4, children: "Configuration saved successfully!" }),
/* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", justifyContent: "space-between", gap: 6, paddingTop: 6, wrap: "wrap", children: [
/* @__PURE__ */ jsxs(
Box,
{
flex: "1",
minWidth: "400px",
padding: 6,
background: "neutral100",
borderRadius: "8px",
shadow: "tableShadow",
children: [
/* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "semiBold", children: "Session Management" }),
/* @__PURE__ */ jsx(Divider, { marginTop: 2, marginBottom: 4 }),
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-star", gap: 4, children: [
/* @__PURE__ */ jsxs(Flex, { direction: "row", gap: 4, children: [
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Auto Logout Time (minutes)" }),
/* @__PURE__ */ jsx(
NumberInput,
{
minValue: 1,
value: config.autoLogoutTime,
onValueChange: (value) => handleChange("autoLogoutTime", value)
}
)
] }),
/* @__PURE__ */ jsxs(Flex, { gap: 4, children: [
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Activate multiple sessions control?" }),
/* @__PURE__ */ jsx(
Switch,
{
checked: config.multipleSessionsControl,
onCheckedChange: () => handleChange("multipleSessionsControl", !config.multipleSessionsControl)
}
)
] })
] })
]
}
),
/* @__PURE__ */ jsxs(
Box,
{
flex: "1",
minWidth: "400px",
minHeight: "173px",
padding: 6,
background: "neutral100",
borderRadius: "8px",
shadow: "tableShadow",
children: [
/* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "semiBold", children: "Password Management" }),
/* @__PURE__ */ jsx(Divider, { marginTop: 2, marginBottom: 4 }),
/* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 4, children: [
/* @__PURE__ */ jsxs(Flex, { gap: 4, children: [
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Activate Password Control?" }),
/* @__PURE__ */ jsx(
Switch,
{
checked: config.enablePasswordManagement,
onCheckedChange: () => handleChange("enablePasswordManagement", !config.enablePasswordManagement)
}
)
] }),
config.enablePasswordManagement && /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 5, children: [
/* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 3, children: [
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Password Expiry (days)?" }),
/* @__PURE__ */ jsx(
NumberInput,
{
minValue: 1,
value: config.passwordExpiryDays,
onValueChange: (value) => handleChange("passwordExpiryDays", value)
}
)
] }),
/* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 3, children: [
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Activate Non-Reusable Password?" }),
/* @__PURE__ */ jsx(
Switch,
{
checked: config.nonReusablePassword,
onCheckedChange: () => handleChange("nonReusablePassword", !config.nonReusablePassword)
}
)
] })
] })
] })
]
}
)
] }),
/* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", paddingTop: 6, paddingBottom: 2, children: /* @__PURE__ */ jsx(Button, { onClick: saveConfig, variant: "secondary", size: "L", shadow: "buttonShadow", children: "Save Settings" }) })
] });
};
const App = () => {
return /* @__PURE__ */ jsxs(Routes, { children: [
/* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(HomePage, {}) }),
/* @__PURE__ */ jsx(Route, { path: "*", element: /* @__PURE__ */ jsx(Page.Error, {}) })
] });
};
export {
App
};