strapi-plugin-oidc 1.8.4 → 1.9.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.
@@ -5,7 +5,7 @@ import { useState, useRef, useId, useEffect, useCallback, useReducer, useMemo, m
5
5
  import { Typography, Flex, Box, MultiSelect, MultiSelectOption, Button, Dialog, Table, Pagination, PreviousLink, NextLink, PageLink, Field, Divider, Thead, Tr, Th, Tbody, Td, IconButton, Loader, Tooltip, Alert } from "@strapi/design-system";
6
6
  import { Cross, WarningCircle, Plus, Download, Upload, Trash, Calendar, Mail, Information } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
- import { g as getTrad } from "./index-Bb9-aYb4.mjs";
8
+ import { g as getTrad, E as EMAIL_REGEX, e as en, A as AUDIT_LOG_DEFAULTS, U as UI_DEFAULTS } from "./index-LcYvW0bR.mjs";
9
9
  import styled from "styled-components";
10
10
  import { Filter, ClipboardList, Server } from "lucide-react";
11
11
  function Role({ oidcRoles, roles, onChangeRole }) {
@@ -422,7 +422,14 @@ const DayButton = styled.button`
422
422
  aspect-ratio: 1;
423
423
  border: none;
424
424
  background: ${({ $selected, $inRange, $pending, theme }) => $pending ? theme.colors.warning200 : $selected ? theme.colors.primary600 : $inRange ? theme.colors.primary100 : "transparent"};
425
- color: ${({ $selected, $inRange, $pending, $future, $alreadySelected, theme }) => $pending ? theme.colors.warning600 : $selected ? theme.colors.neutral0 : $inRange ? theme.colors.primary600 : theme.colors.neutral800};
425
+ color: ${({
426
+ $selected,
427
+ $inRange,
428
+ $pending,
429
+ $future: _future,
430
+ $alreadySelected: _alreadySelected,
431
+ theme
432
+ }) => $pending ? theme.colors.warning600 : $selected ? theme.colors.neutral0 : $inRange ? theme.colors.primary600 : theme.colors.neutral800};
426
433
  opacity: ${({ $future, $alreadySelected }) => $future || $alreadySelected ? 0.4 : 1};
427
434
  border-radius: 4px;
428
435
  cursor: pointer;
@@ -848,7 +855,6 @@ function TablePagination({ page, pageCount, onPageChange, total }) {
848
855
  ] }) });
849
856
  }
850
857
  const PAGE_SIZE$1 = 10;
851
- const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
852
858
  function Whitelist({
853
859
  users,
854
860
  useWhitelist,
@@ -1062,6 +1068,163 @@ function Whitelist({
1062
1068
  ] })
1063
1069
  ] });
1064
1070
  }
1071
+ const AUDIT_ACTIONS = [
1072
+ "login_success",
1073
+ "login_failure",
1074
+ "missing_code",
1075
+ "state_mismatch",
1076
+ "nonce_mismatch",
1077
+ "token_exchange_failed",
1078
+ "whitelist_rejected",
1079
+ "email_not_verified",
1080
+ "id_token_invalid",
1081
+ "logout",
1082
+ "session_expired",
1083
+ "user_created"
1084
+ ];
1085
+ const IP_REGEX = /^(?:(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?::[0-9a-fA-F]{1,4}){1,7}|::))$/;
1086
+ function FilterBar({
1087
+ filters,
1088
+ hasActiveFilters,
1089
+ onFiltersChange,
1090
+ onResetPage,
1091
+ onClear
1092
+ }) {
1093
+ const { formatMessage } = useIntl();
1094
+ return /* @__PURE__ */ jsxs(
1095
+ Box,
1096
+ {
1097
+ background: "neutral100",
1098
+ hasRadius: true,
1099
+ padding: 4,
1100
+ marginBottom: 4,
1101
+ borderColor: "neutral200",
1102
+ borderWidth: "1px",
1103
+ borderStyle: "solid",
1104
+ children: [
1105
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", marginBottom: 3, children: [
1106
+ /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Filter, { size: "1.6rem" }) }),
1107
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h3", children: formatMessage(getTrad("auditlog.filters")) })
1108
+ ] }),
1109
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, wrap: "wrap", children: [
1110
+ /* @__PURE__ */ jsx(
1111
+ TagDateInput,
1112
+ {
1113
+ placeholder: formatMessage(getTrad("auditlog.filters.createdAt")),
1114
+ value: filters.createdAt ?? [],
1115
+ onChange: (selections) => {
1116
+ onFiltersChange((prev) => {
1117
+ if (selections.length === 0) {
1118
+ const { createdAt: _createdAt, ...rest } = prev;
1119
+ return rest;
1120
+ }
1121
+ return { ...prev, createdAt: selections };
1122
+ });
1123
+ onResetPage();
1124
+ },
1125
+ startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Calendar, { width: "1.4rem", height: "1.4rem" }) })
1126
+ }
1127
+ ),
1128
+ /* @__PURE__ */ jsx(
1129
+ TagInput,
1130
+ {
1131
+ value: filters.action ?? [],
1132
+ onChange: (value) => onFiltersChange((prev) => ({ ...prev, action: value })),
1133
+ options: AUDIT_ACTIONS,
1134
+ placeholder: formatMessage(getTrad("auditlog.filters.action")),
1135
+ startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(ClipboardList, { size: "1.4rem" }) })
1136
+ }
1137
+ ),
1138
+ /* @__PURE__ */ jsx(
1139
+ TagInput,
1140
+ {
1141
+ value: filters.email ?? [],
1142
+ onChange: (value) => onFiltersChange((prev) => ({ ...prev, email: value })),
1143
+ placeholder: formatMessage(getTrad("auditlog.filters.email")),
1144
+ startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Mail, { width: "1.4rem", height: "1.4rem" }) }),
1145
+ validate: (v) => EMAIL_REGEX.test(v)
1146
+ }
1147
+ ),
1148
+ /* @__PURE__ */ jsx(
1149
+ TagInput,
1150
+ {
1151
+ value: filters.ip ?? [],
1152
+ onChange: (value) => onFiltersChange((prev) => ({ ...prev, ip: value })),
1153
+ placeholder: formatMessage(getTrad("auditlog.filters.ip")),
1154
+ startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Server, { size: "1.4rem" }) }),
1155
+ validate: (v) => IP_REGEX.test(v)
1156
+ }
1157
+ ),
1158
+ hasActiveFilters && /* @__PURE__ */ jsx(SizedButton, { size: "S", variant: "danger-light", startIcon: /* @__PURE__ */ jsx(Trash, {}), onClick: onClear, children: formatMessage(getTrad("auditlog.filters.clear")) })
1159
+ ] })
1160
+ ]
1161
+ }
1162
+ );
1163
+ }
1164
+ const DETAILS_TEXT_STYLE = {
1165
+ display: "block",
1166
+ overflow: "hidden",
1167
+ textOverflow: "ellipsis",
1168
+ whiteSpace: "nowrap",
1169
+ maxWidth: "180px",
1170
+ cursor: "help"
1171
+ };
1172
+ function LogTable({ records, loading, hasActiveFilters }) {
1173
+ const { formatMessage } = useIntl();
1174
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%" }, children: [
1175
+ /* @__PURE__ */ jsxs(CustomTable, { colCount: 5, rowCount: records.length, children: [
1176
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
1177
+ /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.timestamp")) }),
1178
+ /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.action")) }),
1179
+ /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.email")) }),
1180
+ /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.ip")) }),
1181
+ /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.details")) })
1182
+ ] }) }),
1183
+ /* @__PURE__ */ jsxs(Tbody, { children: [
1184
+ records.length === 0 && /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 5, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "80px" }, children: loading ? /* @__PURE__ */ jsx(Loader, { small: true }) : /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: hasActiveFilters ? formatMessage(getTrad("auditlog.filters.empty")) : formatMessage(getTrad("auditlog.table.empty")) }) }) }) }),
1185
+ records.map((record) => {
1186
+ const detailKey = record.detailsKey ? `audit.${record.detailsKey}` : null;
1187
+ const detail = detailKey && en[detailKey] ? formatMessage(getTrad(detailKey), record.detailsParams ?? {}) : null;
1188
+ return /* @__PURE__ */ jsxs(
1189
+ Tr,
1190
+ {
1191
+ style: { opacity: loading ? 0.4 : 1, transition: "opacity 0.15s" },
1192
+ children: [
1193
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: /* @__PURE__ */ jsx(LocalizedDate, { date: record.createdAt, options: { second: "2-digit" } }) }) }),
1194
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
1195
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.action }),
1196
+ /* @__PURE__ */ jsx(Tooltip, { label: formatMessage(getTrad(`auditlog.action.${record.action}`)), children: /* @__PURE__ */ jsx(
1197
+ Information,
1198
+ {
1199
+ "aria-hidden": true,
1200
+ style: { cursor: "help" },
1201
+ width: "1.4rem",
1202
+ height: "1.4rem",
1203
+ fill: "primary600"
1204
+ }
1205
+ ) })
1206
+ ] }) }),
1207
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.email ?? "—" }) }),
1208
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.ip ?? "—" }) }),
1209
+ /* @__PURE__ */ jsx(Td, { style: { maxWidth: "200px" }, children: detail ? /* @__PURE__ */ jsx(Tooltip, { label: detail, side: "top", children: /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: DETAILS_TEXT_STYLE, children: detail }) }) : /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", children: "—" }) })
1210
+ ]
1211
+ },
1212
+ record.id
1213
+ );
1214
+ })
1215
+ ] })
1216
+ ] }),
1217
+ loading && records.length > 0 && /* @__PURE__ */ jsx(
1218
+ Flex,
1219
+ {
1220
+ justifyContent: "center",
1221
+ alignItems: "center",
1222
+ style: { position: "absolute", inset: 0, pointerEvents: "none" },
1223
+ children: /* @__PURE__ */ jsx(Loader, { small: true })
1224
+ }
1225
+ )
1226
+ ] });
1227
+ }
1065
1228
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
1066
1229
  function getDefaultExportFromCjs(x) {
1067
1230
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -3603,30 +3766,6 @@ function requireLib() {
3603
3766
  }
3604
3767
  var libExports = /* @__PURE__ */ requireLib();
3605
3768
  const qs = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
3606
- const AUDIT_ACTIONS = [
3607
- "login_success",
3608
- "login_failure",
3609
- "missing_code",
3610
- "state_mismatch",
3611
- "nonce_mismatch",
3612
- "token_exchange_failed",
3613
- "whitelist_rejected",
3614
- "email_not_verified",
3615
- "id_token_invalid",
3616
- "logout",
3617
- "session_expired",
3618
- "user_created"
3619
- ];
3620
- const PAGE_SIZE = 10;
3621
- const MIN_SPINNER_MS = 400;
3622
- const DETAILS_TEXT_STYLE = {
3623
- display: "block",
3624
- overflow: "hidden",
3625
- textOverflow: "ellipsis",
3626
- whiteSpace: "nowrap",
3627
- maxWidth: "180px",
3628
- cursor: "help"
3629
- };
3630
3769
  function toWireFilters(f) {
3631
3770
  const out = {};
3632
3771
  if (f.action?.length) out.action = { $or: f.action.map((v) => ({ $eq: v })) };
@@ -3643,11 +3782,10 @@ function buildQueryString(params) {
3643
3782
  const { filters, ...rest } = params;
3644
3783
  return qs.stringify(
3645
3784
  { ...rest, filters: filters ? toWireFilters(filters) : void 0 },
3646
- {
3647
- encodeValuesOnly: true
3648
- }
3785
+ { encodeValuesOnly: true }
3649
3786
  );
3650
3787
  }
3788
+ const PAGE_SIZE = AUDIT_LOG_DEFAULTS.ADMIN_PAGE_SIZE;
3651
3789
  function useDebounced(value, delay = 300) {
3652
3790
  const [debounced, setDebounced] = useState(value);
3653
3791
  useEffect(() => {
@@ -3656,10 +3794,8 @@ function useDebounced(value, delay = 300) {
3656
3794
  }, [value, delay]);
3657
3795
  return debounced;
3658
3796
  }
3659
- function AuditLog({ title } = {}) {
3660
- const { formatMessage } = useIntl();
3661
- const { get: get2, del } = useFetchClient();
3662
- const { toggleNotification } = useNotification();
3797
+ function useAuditLogs(page, filters) {
3798
+ const { get: get2 } = useFetchClient();
3663
3799
  const [records, setRecords] = useState([]);
3664
3800
  const [pagination, setPagination] = useState({
3665
3801
  page: 1,
@@ -3667,9 +3803,7 @@ function AuditLog({ title } = {}) {
3667
3803
  total: 0,
3668
3804
  pageCount: 1
3669
3805
  });
3670
- const [page, setPage] = useState(1);
3671
3806
  const [loading, setLoading] = useState(true);
3672
- const [filters, setFilters] = useState({});
3673
3807
  const fetchGenRef = useRef(0);
3674
3808
  const debouncedFilters = useDebounced(filters);
3675
3809
  const fetchLogs = useCallback(
@@ -3691,7 +3825,7 @@ function AuditLog({ title } = {}) {
3691
3825
  };
3692
3826
  } catch {
3693
3827
  }
3694
- const remaining = MIN_SPINNER_MS - (Date.now() - startTime);
3828
+ const remaining = UI_DEFAULTS.MIN_SPINNER_MS - (Date.now() - startTime);
3695
3829
  if (remaining > 0) await new Promise((r) => setTimeout(r, remaining));
3696
3830
  if (gen !== fetchGenRef.current) return;
3697
3831
  setRecords(newRecords);
@@ -3703,6 +3837,15 @@ function AuditLog({ title } = {}) {
3703
3837
  useEffect(() => {
3704
3838
  fetchLogs(page, debouncedFilters);
3705
3839
  }, [fetchLogs, page, debouncedFilters]);
3840
+ return { records, pagination, loading };
3841
+ }
3842
+ function AuditLog({ title } = {}) {
3843
+ const { formatMessage } = useIntl();
3844
+ const { del } = useFetchClient();
3845
+ const { toggleNotification } = useNotification();
3846
+ const [page, setPage] = useState(1);
3847
+ const [filters, setFilters] = useState({});
3848
+ const { records, pagination, loading } = useAuditLogs(page, filters);
3706
3849
  const handleClearAll = async () => {
3707
3850
  try {
3708
3851
  await del("/strapi-plugin-oidc/audit-logs");
@@ -3723,9 +3866,7 @@ function AuditLog({ title } = {}) {
3723
3866
  try {
3724
3867
  const cookieMatch = document.cookie.match(/(?:^|;\s*)jwtToken=([^;]+)/);
3725
3868
  const token = cookieMatch ? decodeURIComponent(cookieMatch[1]) : "";
3726
- const queryString = buildQueryString({
3727
- filters
3728
- });
3869
+ const queryString = buildQueryString({ filters });
3729
3870
  const response = await fetch(`/strapi-plugin-oidc/audit-logs/export?${queryString}`, {
3730
3871
  headers: { Authorization: `Bearer ${token}` }
3731
3872
  });
@@ -3793,135 +3934,17 @@ function AuditLog({ title } = {}) {
3793
3934
  )
3794
3935
  ] })
3795
3936
  ] }),
3796
- /* @__PURE__ */ jsxs(
3797
- Box,
3937
+ /* @__PURE__ */ jsx(
3938
+ FilterBar,
3798
3939
  {
3799
- background: "neutral100",
3800
- hasRadius: true,
3801
- padding: 4,
3802
- marginBottom: 4,
3803
- borderColor: "neutral200",
3804
- borderWidth: "1px",
3805
- borderStyle: "solid",
3806
- children: [
3807
- /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", marginBottom: 3, children: [
3808
- /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Filter, { size: "1.6rem" }) }),
3809
- /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h3", children: formatMessage(getTrad("auditlog.filters")) })
3810
- ] }),
3811
- /* @__PURE__ */ jsxs(Flex, { gap: 2, wrap: "wrap", children: [
3812
- /* @__PURE__ */ jsx(
3813
- TagDateInput,
3814
- {
3815
- placeholder: formatMessage(getTrad("auditlog.filters.createdAt")),
3816
- value: filters.createdAt ?? [],
3817
- onChange: (selections) => {
3818
- setFilters((prev) => {
3819
- if (selections.length === 0) {
3820
- const { createdAt: _removed, ...rest } = prev;
3821
- return rest;
3822
- }
3823
- return { ...prev, createdAt: selections };
3824
- });
3825
- setPage(1);
3826
- },
3827
- startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Calendar, { width: "1.4rem", height: "1.4rem" }) })
3828
- }
3829
- ),
3830
- /* @__PURE__ */ jsx(
3831
- TagInput,
3832
- {
3833
- value: filters.action ?? [],
3834
- onChange: (value) => setFilters((prev) => ({ ...prev, action: value })),
3835
- options: AUDIT_ACTIONS,
3836
- placeholder: formatMessage(getTrad("auditlog.filters.action")),
3837
- startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(ClipboardList, { size: "1.4rem" }) })
3838
- }
3839
- ),
3840
- /* @__PURE__ */ jsx(
3841
- TagInput,
3842
- {
3843
- value: filters.email ?? [],
3844
- onChange: (value) => setFilters((prev) => ({ ...prev, email: value })),
3845
- placeholder: formatMessage(getTrad("auditlog.filters.email")),
3846
- startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Mail, { width: "1.4rem", height: "1.4rem" }) }),
3847
- validate: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)
3848
- }
3849
- ),
3850
- /* @__PURE__ */ jsx(
3851
- TagInput,
3852
- {
3853
- value: filters.ip ?? [],
3854
- onChange: (value) => setFilters((prev) => ({ ...prev, ip: value })),
3855
- placeholder: formatMessage(getTrad("auditlog.filters.ip")),
3856
- startIcon: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Server, { size: "1.4rem" }) }),
3857
- validate: (v) => /^(?:(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?::[0-9a-fA-F]{1,4}){1,7}|::))$/.test(
3858
- v
3859
- )
3860
- }
3861
- ),
3862
- hasActiveFilters && /* @__PURE__ */ jsx(
3863
- SizedButton,
3864
- {
3865
- size: "S",
3866
- variant: "danger-light",
3867
- startIcon: /* @__PURE__ */ jsx(Trash, {}),
3868
- onClick: clearFilters,
3869
- children: formatMessage(getTrad("auditlog.filters.clear"))
3870
- }
3871
- )
3872
- ] })
3873
- ]
3940
+ filters,
3941
+ hasActiveFilters,
3942
+ onFiltersChange: setFilters,
3943
+ onResetPage: () => setPage(1),
3944
+ onClear: clearFilters
3874
3945
  }
3875
3946
  ),
3876
- /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%" }, children: [
3877
- /* @__PURE__ */ jsxs(CustomTable, { colCount: 5, rowCount: records.length, children: [
3878
- /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
3879
- /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.timestamp")) }),
3880
- /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.action")) }),
3881
- /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.email")) }),
3882
- /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.ip")) }),
3883
- /* @__PURE__ */ jsx(Th, { children: formatMessage(getTrad("auditlog.table.details")) })
3884
- ] }) }),
3885
- /* @__PURE__ */ jsxs(Tbody, { children: [
3886
- records.length === 0 && /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 5, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "80px" }, children: loading ? /* @__PURE__ */ jsx(Loader, { small: true }) : /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: hasActiveFilters ? formatMessage(getTrad("auditlog.filters.empty")) : formatMessage(getTrad("auditlog.table.empty")) }) }) }) }),
3887
- records.map((record) => /* @__PURE__ */ jsxs(
3888
- Tr,
3889
- {
3890
- style: { opacity: loading ? 0.4 : 1, transition: "opacity 0.15s" },
3891
- children: [
3892
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: /* @__PURE__ */ jsx(LocalizedDate, { date: record.createdAt, options: { second: "2-digit" } }) }) }),
3893
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
3894
- /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.action }),
3895
- /* @__PURE__ */ jsx(Tooltip, { label: formatMessage(getTrad(`auditlog.action.${record.action}`)), children: /* @__PURE__ */ jsx(
3896
- Information,
3897
- {
3898
- "aria-hidden": true,
3899
- style: { cursor: "help" },
3900
- width: "1.4rem",
3901
- height: "1.4rem",
3902
- fill: "primary600"
3903
- }
3904
- ) })
3905
- ] }) }),
3906
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.email ?? "—" }) }),
3907
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: record.ip ?? "—" }) }),
3908
- /* @__PURE__ */ jsx(Td, { style: { maxWidth: "200px" }, children: record.details ? /* @__PURE__ */ jsx(Tooltip, { label: record.details, side: "top", children: /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: DETAILS_TEXT_STYLE, children: record.details }) }) : /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", children: "—" }) })
3909
- ]
3910
- },
3911
- record.id
3912
- ))
3913
- ] })
3914
- ] }),
3915
- loading && records.length > 0 && /* @__PURE__ */ jsx(
3916
- Flex,
3917
- {
3918
- justifyContent: "center",
3919
- alignItems: "center",
3920
- style: { position: "absolute", inset: 0, pointerEvents: "none" },
3921
- children: /* @__PURE__ */ jsx(Loader, { small: true })
3922
- }
3923
- )
3924
- ] }),
3947
+ /* @__PURE__ */ jsx(LogTable, { records, loading, hasActiveFilters }),
3925
3948
  /* @__PURE__ */ jsx(
3926
3949
  TablePagination,
3927
3950
  {
@@ -3991,7 +4014,7 @@ const SwitchInput = styled.input`
3991
4014
  &:checked + span:before {
3992
4015
  transform: translateX(16px);
3993
4016
  }
3994
-
4017
+
3995
4018
  &:disabled + span {
3996
4019
  pointer-events: none;
3997
4020
  }
@@ -4009,7 +4032,7 @@ const SwitchSlider = styled.span`
4009
4032
 
4010
4033
  &:before {
4011
4034
  position: absolute;
4012
- content: "";
4035
+ content: '';
4013
4036
  height: 18px;
4014
4037
  width: 18px;
4015
4038
  left: 3px;
@@ -4019,21 +4042,26 @@ const SwitchSlider = styled.span`
4019
4042
  border-radius: 50%;
4020
4043
  }
4021
4044
  `;
4022
- function CustomSwitch({ checked, onChange, label, disabled }) {
4045
+ function CustomSwitch({
4046
+ checked,
4047
+ onChange,
4048
+ label,
4049
+ disabled
4050
+ }) {
4023
4051
  return /* @__PURE__ */ jsxs(Flex, { gap: 3, children: [
4024
4052
  /* @__PURE__ */ jsxs(SwitchContainer, { $disabled: disabled, children: [
4025
- /* @__PURE__ */ jsx(
4026
- SwitchInput,
4027
- {
4028
- type: "checkbox",
4029
- checked,
4030
- onChange,
4031
- disabled
4032
- }
4033
- ),
4053
+ /* @__PURE__ */ jsx(SwitchInput, { type: "checkbox", checked, onChange, disabled }),
4034
4054
  /* @__PURE__ */ jsx(SwitchSlider, {})
4035
4055
  ] }),
4036
- label && /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", textColor: disabled ? "neutral500" : "neutral800", children: label })
4056
+ label && /* @__PURE__ */ jsx(
4057
+ Typography,
4058
+ {
4059
+ variant: "pi",
4060
+ fontWeight: "bold",
4061
+ textColor: disabled ? "neutral500" : "neutral800",
4062
+ children: label
4063
+ }
4064
+ )
4037
4065
  ] });
4038
4066
  }
4039
4067
  function formatDatetimeForFilename(date) {
@@ -4055,19 +4083,15 @@ function downloadJson(basename, data) {
4055
4083
  a.click();
4056
4084
  URL.revokeObjectURL(url);
4057
4085
  }
4086
+ const defaultSnapshot = {
4087
+ oidcRoles: [],
4088
+ users: [],
4089
+ useWhitelist: false,
4090
+ enforceOIDC: false
4091
+ };
4058
4092
  const initialState = {
4059
- current: {
4060
- oidcRoles: [],
4061
- users: [],
4062
- useWhitelist: false,
4063
- enforceOIDC: false
4064
- },
4065
- initial: {
4066
- oidcRoles: [],
4067
- users: [],
4068
- useWhitelist: false,
4069
- enforceOIDC: false
4070
- },
4093
+ current: { ...defaultSnapshot },
4094
+ initial: { ...defaultSnapshot },
4071
4095
  roles: [],
4072
4096
  enforceOIDCConfig: null,
4073
4097
  auditLogEnabled: true,
@@ -174,7 +174,10 @@ const en = {
174
174
  "user.invalid_state": "State parameter mismatch. Please restart the login flow.",
175
175
  "user.signInError": "Authentication failed. Please try again.",
176
176
  "settings.section": "OIDC",
177
- "settings.configuration": "Configuration"
177
+ "settings.configuration": "Configuration",
178
+ "audit.login_failure": "Error: {message}",
179
+ "audit.roles_updated": "Roles updated to: {roles}",
180
+ "audit.user_created": "Roles assigned: {roles}"
178
181
  };
179
182
  function getTrad(id) {
180
183
  const pluginIdWithId = `${pluginId}.${id}`;
@@ -186,9 +189,31 @@ function getTrad(id) {
186
189
  function t(id) {
187
190
  return en[id];
188
191
  }
192
+ const PLUGIN_UID = "plugin::strapi-plugin-oidc";
193
+ const PERMISSIONS = {
194
+ READ: `${PLUGIN_UID}.read`
195
+ };
196
+ const AUDIT_LOG_DEFAULTS = {
197
+ ADMIN_PAGE_SIZE: 10
198
+ };
199
+ const UI_DEFAULTS = {
200
+ MIN_SPINNER_MS: 400
201
+ };
202
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
189
203
  const name = pluginPkg.strapi.displayName;
190
204
  const index = {
191
205
  register(app) {
206
+ const AppPage = React.lazy(() => import("./index-Dq99roxb.mjs"));
207
+ const link = {
208
+ id: "configuration",
209
+ to: `/settings/${pluginId}`,
210
+ intlLabel: {
211
+ id: "settings.configuration",
212
+ defaultMessage: "Configuration"
213
+ },
214
+ Component: AppPage,
215
+ permissions: [{ action: PERMISSIONS.READ, subject: null }]
216
+ };
192
217
  app.addSettingsLink(
193
218
  {
194
219
  id: "oidc",
@@ -197,18 +222,7 @@ const index = {
197
222
  defaultMessage: "OIDC"
198
223
  }
199
224
  },
200
- {
201
- id: "configuration",
202
- to: `/settings/${pluginId}`,
203
- intlLabel: {
204
- id: "settings.configuration",
205
- defaultMessage: "Configuration"
206
- },
207
- Component: async () => {
208
- return await import("./index-BqWd-Iiq.mjs");
209
- },
210
- permissions: [{ action: "plugin::strapi-plugin-oidc.read", subject: null }]
211
- }
225
+ link
212
226
  );
213
227
  app.registerPlugin({
214
228
  id: pluginId,
@@ -342,6 +356,10 @@ const index = {
342
356
  }
343
357
  };
344
358
  export {
359
+ AUDIT_LOG_DEFAULTS as A,
360
+ EMAIL_REGEX as E,
361
+ UI_DEFAULTS as U,
362
+ en as e,
345
363
  getTrad as g,
346
364
  index as i
347
365
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const index = require("./index-Dk6TYtio.js");
3
+ const index = require("./index-BqKuUY5d.js");
4
4
  require("react");
5
5
  require("react-dom/client");
6
6
  exports.default = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "./index-Bb9-aYb4.mjs";
1
+ import { i } from "./index-LcYvW0bR.mjs";
2
2
  import "react";
3
3
  import "react-dom/client";
4
4
  export {