@burdenoff/microfe-auth 2026.520.1 → 2026.521.1
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/auth/AuthRoutes.js +8 -8
- package/dist/auth/AuthRoutes.js.map +1 -1
- package/dist/auth/components/AuthLayout.js +1 -1
- package/dist/auth/components/AuthLayout.js.map +1 -1
- package/dist/auth/hooks/useSessionOperations.d.ts.map +1 -1
- package/dist/auth/hooks/useSessionOperations.js +4 -1
- package/dist/auth/hooks/useSessionOperations.js.map +1 -1
- package/dist/auth/hooks/useUserOperations.d.ts.map +1 -1
- package/dist/auth/hooks/useUserOperations.js +26 -11
- package/dist/auth/hooks/useUserOperations.js.map +1 -1
- package/dist/auth/pages/AuditLogPage.d.ts.map +1 -1
- package/dist/auth/pages/AuditLogPage.js +49 -48
- package/dist/auth/pages/AuditLogPage.js.map +1 -1
- package/dist/auth/pages/LoginPage.d.ts.map +1 -1
- package/dist/auth/pages/LoginPage.js +3 -2
- package/dist/auth/pages/LoginPage.js.map +1 -1
- package/dist/auth/pages/PasswordResetPage.js +1 -1
- package/dist/auth/pages/PasswordResetPage.js.map +1 -1
- package/dist/auth/pages/ReactivatePage.js +1 -1
- package/dist/auth/pages/ReactivatePage.js.map +1 -1
- package/dist/auth/pages/RegisterPage.js +1 -1
- package/dist/auth/pages/RegisterPage.js.map +1 -1
- package/dist/auth/pages/SessionsPage.d.ts.map +1 -1
- package/dist/auth/pages/SessionsPage.js +26 -23
- package/dist/auth/pages/SessionsPage.js.map +1 -1
- package/dist/auth/pages/SsoCallbackPage.js +1 -1
- package/dist/auth/pages/SsoCallbackPage.js.map +1 -1
- package/dist/auth/pages/SsoConfigPage.d.ts.map +1 -1
- package/dist/auth/pages/SsoConfigPage.js +214 -190
- package/dist/auth/pages/SsoConfigPage.js.map +1 -1
- package/dist/auth/pages/SsoLoginPage.js +1 -1
- package/dist/auth/pages/SsoLoginPage.js.map +1 -1
- package/dist/auth/pages/UserProfilePage.d.ts.map +1 -1
- package/dist/auth/pages/UserProfilePage.js +254 -238
- package/dist/auth/pages/UserProfilePage.js.map +1 -1
- package/dist/auth/pages/UsersPage.d.ts.map +1 -1
- package/dist/auth/pages/UsersPage.js +0 -1
- package/dist/auth/pages/UsersPage.js.map +1 -1
- package/dist/auth/store/authStore.d.ts +20 -0
- package/dist/auth/store/authStore.d.ts.map +1 -1
- package/dist/auth/store/authStore.js.map +1 -1
- package/dist/microfe-auth.css +1 -1
- package/dist/translations/en.d.ts +12 -0
- package/dist/translations/en.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/auth/pages/AppsPage.d.ts +0 -5
- package/dist/auth/pages/AppsPage.d.ts.map +0 -1
|
@@ -6,23 +6,24 @@ import { useState as a } from "react";
|
|
|
6
6
|
import { useI18n as o } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
7
7
|
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
8
8
|
import { useFeatureFlagDetails as u } from "@burdenoff/fe-libs/shared/feature-flags";
|
|
9
|
+
import { useGatewayClient as d } from "@burdenoff/fe-libs/shared/graphql";
|
|
9
10
|
//#region src/auth/pages/AuditLogPage.tsx
|
|
10
|
-
var
|
|
11
|
-
function
|
|
12
|
-
let { t:
|
|
13
|
-
let n =
|
|
11
|
+
var f = 20;
|
|
12
|
+
function p() {
|
|
13
|
+
let { t: p } = o(), m = (e, t) => {
|
|
14
|
+
let n = p(e);
|
|
14
15
|
return n === e ? t : n;
|
|
15
|
-
}, [
|
|
16
|
-
skip: !
|
|
16
|
+
}, [h, g] = a(1), _ = (h - 1) * f, v = u("auth.audit-log")?.value === !0, { data: y, loading: b, error: x } = e({
|
|
17
|
+
skip: !v,
|
|
17
18
|
fetchPolicy: "cache-and-network",
|
|
18
19
|
variables: { pagination: {
|
|
19
|
-
limit:
|
|
20
|
-
offset:
|
|
20
|
+
limit: f,
|
|
21
|
+
offset: _
|
|
21
22
|
} }
|
|
22
|
-
}),
|
|
23
|
-
|
|
23
|
+
}), S = y?.authAuditLogs ?? [], C = S.length === f, [w, { loading: T }] = i({ client: d("workspace") }), [E, D] = a(null), O = async () => {
|
|
24
|
+
D(null);
|
|
24
25
|
try {
|
|
25
|
-
await
|
|
26
|
+
await w({ variables: { input: {
|
|
26
27
|
name: "Audit Log Export",
|
|
27
28
|
entityTypes: ["permission_audit_logs"],
|
|
28
29
|
format: "CSV",
|
|
@@ -30,9 +31,9 @@ function f() {
|
|
|
30
31
|
includeMetadata: !0
|
|
31
32
|
} } });
|
|
32
33
|
} catch (e) {
|
|
33
|
-
|
|
34
|
+
D(e instanceof Error ? e.message : "Failed to start export");
|
|
34
35
|
}
|
|
35
|
-
},
|
|
36
|
+
}, k = (e) => {
|
|
36
37
|
switch (e) {
|
|
37
38
|
case "LOGIN_SUCCESS": return "OK";
|
|
38
39
|
case "LOGIN_FAILURE": return "ER";
|
|
@@ -44,24 +45,24 @@ function f() {
|
|
|
44
45
|
default: return "AU";
|
|
45
46
|
}
|
|
46
47
|
};
|
|
47
|
-
return
|
|
48
|
+
return v ? /* @__PURE__ */ l("div", {
|
|
48
49
|
className: "max-w-4xl mx-auto p-6",
|
|
49
50
|
children: [
|
|
50
51
|
/* @__PURE__ */ l("div", {
|
|
51
52
|
className: "flex items-center justify-between mb-8",
|
|
52
53
|
children: [/* @__PURE__ */ c("h1", {
|
|
53
54
|
className: "text-3xl font-semibold text-text-primary",
|
|
54
|
-
children:
|
|
55
|
+
children: m("auth.auditLog.title", "Security Audit Log")
|
|
55
56
|
}), /* @__PURE__ */ c("button", {
|
|
56
57
|
type: "button",
|
|
57
|
-
onClick: () => void
|
|
58
|
-
disabled:
|
|
59
|
-
"aria-label":
|
|
58
|
+
onClick: () => void O(),
|
|
59
|
+
disabled: T,
|
|
60
|
+
"aria-label": m("auth.auditLog.exportAriaLabel", "Export audit log"),
|
|
60
61
|
className: "flex items-center gap-2 px-4 py-2.5 rounded-xl border border-border-default text-text-primary bg-bg-surface hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors font-medium",
|
|
61
|
-
children:
|
|
62
|
+
children: T ? /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c(n, {
|
|
62
63
|
className: "w-4 h-4 animate-spin",
|
|
63
64
|
"aria-hidden": "true"
|
|
64
|
-
}),
|
|
65
|
+
}), m("auth.auditLog.exporting", "Exporting...")] }) : /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("svg", {
|
|
65
66
|
className: "w-4 h-4",
|
|
66
67
|
fill: "none",
|
|
67
68
|
viewBox: "0 0 24 24",
|
|
@@ -73,10 +74,10 @@ function f() {
|
|
|
73
74
|
strokeWidth: 2,
|
|
74
75
|
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
75
76
|
})
|
|
76
|
-
}),
|
|
77
|
+
}), m("auth.auditLog.export", "Export")] })
|
|
77
78
|
})]
|
|
78
79
|
}),
|
|
79
|
-
|
|
80
|
+
E && /* @__PURE__ */ l("div", {
|
|
80
81
|
role: "alert",
|
|
81
82
|
className: "mb-6 flex items-start gap-3 p-4 rounded-xl bg-status-error-bg-subtle border border-status-error-border",
|
|
82
83
|
children: [/* @__PURE__ */ c(t, {
|
|
@@ -84,10 +85,10 @@ function f() {
|
|
|
84
85
|
"aria-hidden": "true"
|
|
85
86
|
}), /* @__PURE__ */ c("p", {
|
|
86
87
|
className: "text-sm text-status-error-text",
|
|
87
|
-
children:
|
|
88
|
+
children: E
|
|
88
89
|
})]
|
|
89
90
|
}),
|
|
90
|
-
|
|
91
|
+
b ? /* @__PURE__ */ l("div", {
|
|
91
92
|
"aria-live": "polite",
|
|
92
93
|
"aria-busy": "true",
|
|
93
94
|
className: "text-center py-12",
|
|
@@ -96,27 +97,27 @@ function f() {
|
|
|
96
97
|
"aria-hidden": "true"
|
|
97
98
|
}), /* @__PURE__ */ c("p", {
|
|
98
99
|
className: "mt-3 text-text-secondary",
|
|
99
|
-
children:
|
|
100
|
+
children: m("auth.auditLog.loading", "Loading audit events...")
|
|
100
101
|
})]
|
|
101
|
-
}) :
|
|
102
|
+
}) : x ? /* @__PURE__ */ c("div", {
|
|
102
103
|
role: "alert",
|
|
103
104
|
className: "text-center py-12 border border-status-error-border rounded-xl bg-status-error-bg-subtle",
|
|
104
105
|
children: /* @__PURE__ */ c("p", {
|
|
105
106
|
className: "text-status-error-text",
|
|
106
|
-
children:
|
|
107
|
+
children: m("auth.auditLog.error", "Unable to load audit events")
|
|
107
108
|
})
|
|
108
|
-
}) :
|
|
109
|
+
}) : S.length === 0 ? /* @__PURE__ */ c("div", {
|
|
109
110
|
className: "text-center py-12",
|
|
110
111
|
role: "status",
|
|
111
112
|
children: /* @__PURE__ */ c("p", {
|
|
112
113
|
className: "text-text-secondary",
|
|
113
|
-
children:
|
|
114
|
+
children: m("auth.auditLog.noEvents", "No security events recorded")
|
|
114
115
|
})
|
|
115
116
|
}) : /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("div", {
|
|
116
117
|
className: "space-y-4",
|
|
117
118
|
"aria-live": "polite",
|
|
118
|
-
"aria-busy":
|
|
119
|
-
children:
|
|
119
|
+
"aria-busy": b,
|
|
120
|
+
children: S.map((e) => /* @__PURE__ */ c("div", {
|
|
120
121
|
className: "p-6 rounded-xl border border-border-subtle bg-bg-surface shadow-sm",
|
|
121
122
|
children: /* @__PURE__ */ l("div", {
|
|
122
123
|
className: "flex items-start gap-4",
|
|
@@ -124,7 +125,7 @@ function f() {
|
|
|
124
125
|
/* @__PURE__ */ c("div", {
|
|
125
126
|
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-bg-muted text-xs font-semibold text-text-secondary",
|
|
126
127
|
"aria-hidden": "true",
|
|
127
|
-
children:
|
|
128
|
+
children: k(e.action)
|
|
128
129
|
}),
|
|
129
130
|
/* @__PURE__ */ l("div", {
|
|
130
131
|
className: "flex-1",
|
|
@@ -142,44 +143,44 @@ function f() {
|
|
|
142
143
|
}),
|
|
143
144
|
/* @__PURE__ */ l("p", {
|
|
144
145
|
className: "text-sm text-text-secondary",
|
|
145
|
-
children: [e.description ??
|
|
146
|
+
children: [e.description ?? m("auth.auditLog.defaultDescription", "Authentication event"), e.ipAddress && ` • ${e.ipAddress}`]
|
|
146
147
|
})
|
|
147
148
|
]
|
|
148
149
|
}),
|
|
149
150
|
e.action.includes("FAILURE") && /* @__PURE__ */ c("span", {
|
|
150
151
|
role: "status",
|
|
151
152
|
className: "px-3 py-1 rounded-full bg-status-error-bg-subtle text-status-error-text text-sm font-medium",
|
|
152
|
-
children:
|
|
153
|
+
children: m("auth.auditLog.failed", "Failed")
|
|
153
154
|
})
|
|
154
155
|
]
|
|
155
156
|
})
|
|
156
157
|
}, e.id))
|
|
157
158
|
}), /* @__PURE__ */ l("nav", {
|
|
158
|
-
"aria-label":
|
|
159
|
+
"aria-label": m("auth.auditLog.paginationAriaLabel", "Audit log pagination"),
|
|
159
160
|
className: "mt-6 flex items-center justify-between",
|
|
160
161
|
children: [/* @__PURE__ */ l("p", {
|
|
161
162
|
className: "text-sm text-text-secondary",
|
|
162
163
|
children: [
|
|
163
|
-
|
|
164
|
+
m("auth.auditLog.page", "Page"),
|
|
164
165
|
" ",
|
|
165
|
-
|
|
166
|
+
h
|
|
166
167
|
]
|
|
167
168
|
}), /* @__PURE__ */ l("div", {
|
|
168
169
|
className: "flex gap-2",
|
|
169
170
|
children: [/* @__PURE__ */ c("button", {
|
|
170
171
|
type: "button",
|
|
171
|
-
onClick: () =>
|
|
172
|
-
disabled:
|
|
173
|
-
"aria-label":
|
|
172
|
+
onClick: () => g((e) => Math.max(1, e - 1)),
|
|
173
|
+
disabled: h === 1,
|
|
174
|
+
"aria-label": m("auth.auditLog.previousPageAriaLabel", "Go to previous page"),
|
|
174
175
|
className: "px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors",
|
|
175
|
-
children:
|
|
176
|
+
children: m("auth.auditLog.previous", "Previous")
|
|
176
177
|
}), /* @__PURE__ */ c("button", {
|
|
177
178
|
type: "button",
|
|
178
|
-
onClick: () =>
|
|
179
|
-
disabled: !
|
|
180
|
-
"aria-label":
|
|
179
|
+
onClick: () => g((e) => e + 1),
|
|
180
|
+
disabled: !C,
|
|
181
|
+
"aria-label": m("auth.auditLog.nextPageAriaLabel", "Go to next page"),
|
|
181
182
|
className: "px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors",
|
|
182
|
-
children:
|
|
183
|
+
children: m("auth.auditLog.next", "Next")
|
|
183
184
|
})]
|
|
184
185
|
})]
|
|
185
186
|
})] })
|
|
@@ -198,17 +199,17 @@ function f() {
|
|
|
198
199
|
}),
|
|
199
200
|
/* @__PURE__ */ c("h2", {
|
|
200
201
|
className: "text-xl font-semibold text-text-primary mb-2",
|
|
201
|
-
children:
|
|
202
|
+
children: m("auth.auditLog.notAvailable", "Page Not Available")
|
|
202
203
|
}),
|
|
203
204
|
/* @__PURE__ */ c("p", {
|
|
204
205
|
className: "text-text-secondary",
|
|
205
|
-
children:
|
|
206
|
+
children: m("auth.auditLog.notEnabled", "The Security Audit Log is not enabled for your account.")
|
|
206
207
|
})
|
|
207
208
|
]
|
|
208
209
|
})
|
|
209
210
|
});
|
|
210
211
|
}
|
|
211
212
|
//#endregion
|
|
212
|
-
export {
|
|
213
|
+
export { p as AuditLogPage };
|
|
213
214
|
|
|
214
215
|
//# sourceMappingURL=AuditLogPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditLogPage.js","names":[],"sources":["../../../src/auth/pages/AuditLogPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { useFeatureFlagDetails } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { formatDateTime } from \"../utils\";\nimport { AlertIcon, SpinnerIcon } from \"../components/AuthIcons\";\nimport {\n useAuthAuditLogsQuery,\n type AuditLogEntry_AuthAuditLogFragment,\n} from \"../../generated/global-operations\";\nimport { useCreateAuthExportJobMutation } from \"../../generated/wspace-operations\";\n\nconst PAGE_SIZE = 20;\n\n/**\n * Security audit log page with pagination and export\n *\n * Fragment: AuditLogEntry_AuthAuditLog (graphql/operations/global/fragments/AuditLogEntry.fragment.graphql)\n * Query: AuthAuditLogs (graphql/operations/global/queries/auditLog.graphql)\n *\n * TODO: When authAuditLogs backend migrates to AuthAuditLogConnection type,\n * update this query to use: authAuditLogs { auditLogs: [...], totalCount, hasMore }\n * and remove the client-side hasMore approximation below.\n */\nexport function AuditLogPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const [page, setPage] = useState(1);\n const offset = (page - 1) * PAGE_SIZE;\n\n // Default-deny: only show when the flag is explicitly enabled in the system.\n // useFeatureFlag uses default-allow (returns true when not found), so we use\n // useFeatureFlagDetails + explicit value check instead.\n const auditLogFlag = useFeatureFlagDetails(\"auth.audit-log\");\n const showAuditLog = auditLogFlag?.value === true;\n\n const { data, loading, error } = useAuthAuditLogsQuery({\n skip: !showAuditLog,\n fetchPolicy: \"cache-and-network\",\n variables: { pagination: { limit: PAGE_SIZE, offset } },\n });\n\n const auditLogs = data?.authAuditLogs ?? [];\n // Approximate hasMore: if we received a full page there may be more\n const hasMore = auditLogs.length === PAGE_SIZE;\n\n const [createExportJob, { loading: isExporting }] =\n useCreateAuthExportJobMutation();\n const [exportError, setExportError] = useState<string | null>(null);\n\n const handleExport = async () => {\n setExportError(null);\n try {\n await createExportJob({\n variables: {\n input: {\n name: \"Audit Log Export\",\n // permission_audit_logs covers auth audit logs in the export system\n entityTypes: [\"permission_audit_logs\"],\n format: \"CSV\",\n exportScope: \"INDIVIDUAL\",\n includeMetadata: true,\n },\n },\n });\n } catch (err) {\n setExportError(\n err instanceof Error ? err.message : \"Failed to start export\",\n );\n }\n };\n\n const getEventMarker = (eventType: string) => {\n switch (eventType) {\n case \"LOGIN_SUCCESS\":\n return \"OK\";\n case \"LOGIN_FAILURE\":\n return \"ER\";\n case \"LOGOUT\":\n return \"LO\";\n case \"PASSWORD_CHANGE\":\n return \"PW\";\n case \"MFA_ENABLED\":\n case \"MFA_VERIFIED\":\n return \"MF\";\n case \"ANOMALY_DETECTED\":\n return \"AL\";\n default:\n return \"AU\";\n }\n };\n\n if (!showAuditLog) {\n return (\n <div className=\"max-w-4xl mx-auto p-6\">\n <div className=\"text-center py-16 border-2 border-dashed border-border-subtle rounded-xl\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center\">\n <AlertIcon\n className=\"w-8 h-8 text-status-warning-text\"\n aria-hidden=\"true\"\n />\n </div>\n <h2 className=\"text-xl font-semibold text-text-primary mb-2\">\n {tr(\"auth.auditLog.notAvailable\", \"Page Not Available\")}\n </h2>\n <p className=\"text-text-secondary\">\n {tr(\n \"auth.auditLog.notEnabled\",\n \"The Security Audit Log is not enabled for your account.\",\n )}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"max-w-4xl mx-auto p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-8\">\n <h1 className=\"text-3xl font-semibold text-text-primary\">\n {tr(\"auth.auditLog.title\", \"Security Audit Log\")}\n </h1>\n <button\n type=\"button\"\n onClick={() => void handleExport()}\n disabled={isExporting}\n aria-label={tr(\"auth.auditLog.exportAriaLabel\", \"Export audit log\")}\n className=\"flex items-center gap-2 px-4 py-2.5 rounded-xl border border-border-default text-text-primary bg-bg-surface hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors font-medium\"\n >\n {isExporting ? (\n <>\n <SpinnerIcon\n className=\"w-4 h-4 animate-spin\"\n aria-hidden=\"true\"\n />\n {tr(\"auth.auditLog.exporting\", \"Exporting...\")}\n </>\n ) : (\n <>\n <svg\n className=\"w-4 h-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n {tr(\"auth.auditLog.export\", \"Export\")}\n </>\n )}\n </button>\n </div>\n\n {/* Export error */}\n {exportError && (\n <div\n role=\"alert\"\n className=\"mb-6 flex items-start gap-3 p-4 rounded-xl bg-status-error-bg-subtle border border-status-error-border\"\n >\n <AlertIcon\n className=\"w-5 h-5 text-status-error-text flex-shrink-0 mt-0.5\"\n aria-hidden=\"true\"\n />\n <p className=\"text-sm text-status-error-text\">{exportError}</p>\n </div>\n )}\n\n {loading ? (\n <div aria-live=\"polite\" aria-busy=\"true\" className=\"text-center py-12\">\n <SpinnerIcon\n className=\"w-8 h-8 mx-auto text-text-link animate-spin\"\n aria-hidden=\"true\"\n />\n <p className=\"mt-3 text-text-secondary\">\n {tr(\"auth.auditLog.loading\", \"Loading audit events...\")}\n </p>\n </div>\n ) : error ? (\n <div\n role=\"alert\"\n className=\"text-center py-12 border border-status-error-border rounded-xl bg-status-error-bg-subtle\"\n >\n <p className=\"text-status-error-text\">\n {tr(\"auth.auditLog.error\", \"Unable to load audit events\")}\n </p>\n </div>\n ) : auditLogs.length === 0 ? (\n <div className=\"text-center py-12\" role=\"status\">\n <p className=\"text-text-secondary\">\n {tr(\"auth.auditLog.noEvents\", \"No security events recorded\")}\n </p>\n </div>\n ) : (\n <>\n <div className=\"space-y-4\" aria-live=\"polite\" aria-busy={loading}>\n {auditLogs.map((event: AuditLogEntry_AuthAuditLogFragment) => (\n <div\n key={event.id}\n className=\"p-6 rounded-xl border border-border-subtle bg-bg-surface shadow-sm\"\n >\n <div className=\"flex items-start gap-4\">\n <div\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-bg-muted text-xs font-semibold text-text-secondary\"\n aria-hidden=\"true\"\n >\n {getEventMarker(event.action)}\n </div>\n <div className=\"flex-1\">\n <h3 className=\"text-lg font-medium text-text-primary mb-1\">\n {event.action.replace(/_/g, \" \")}\n </h3>\n <p className=\"text-sm text-text-secondary mb-2\">\n <time dateTime={event.createdAt}>\n {formatDateTime(event.createdAt)}\n </time>\n </p>\n <p className=\"text-sm text-text-secondary\">\n {event.description ??\n tr(\n \"auth.auditLog.defaultDescription\",\n \"Authentication event\",\n )}\n {event.ipAddress && ` • ${event.ipAddress}`}\n </p>\n </div>\n {event.action.includes(\"FAILURE\") && (\n <span\n role=\"status\"\n className=\"px-3 py-1 rounded-full bg-status-error-bg-subtle text-status-error-text text-sm font-medium\"\n >\n {tr(\"auth.auditLog.failed\", \"Failed\")}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Pagination */}\n <nav\n aria-label={tr(\n \"auth.auditLog.paginationAriaLabel\",\n \"Audit log pagination\",\n )}\n className=\"mt-6 flex items-center justify-between\"\n >\n <p className=\"text-sm text-text-secondary\">\n {tr(\"auth.auditLog.page\", \"Page\")} {page}\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => setPage((prev) => Math.max(1, prev - 1))}\n disabled={page === 1}\n aria-label={tr(\n \"auth.auditLog.previousPageAriaLabel\",\n \"Go to previous page\",\n )}\n className=\"px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors\"\n >\n {tr(\"auth.auditLog.previous\", \"Previous\")}\n </button>\n <button\n type=\"button\"\n onClick={() => setPage((prev) => prev + 1)}\n disabled={!hasMore}\n aria-label={tr(\n \"auth.auditLog.nextPageAriaLabel\",\n \"Go to next page\",\n )}\n className=\"px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors\"\n >\n {tr(\"auth.auditLog.next\", \"Next\")}\n </button>\n </div>\n </nav>\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditLogPage.js","names":[],"sources":["../../../src/auth/pages/AuditLogPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { useGatewayClient } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { useFeatureFlagDetails } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { formatDateTime } from \"../utils\";\nimport { AlertIcon, SpinnerIcon } from \"../components/AuthIcons\";\nimport {\n useAuthAuditLogsQuery,\n type AuditLogEntry_AuthAuditLogFragment,\n} from \"../../generated/global-operations\";\nimport { useCreateAuthExportJobMutation } from \"../../generated/wspace-operations\";\n\nconst PAGE_SIZE = 20;\n\n/**\n * Security audit log page with pagination and export\n *\n * Fragment: AuditLogEntry_AuthAuditLog (graphql/operations/global/fragments/AuditLogEntry.fragment.graphql)\n * Query: AuthAuditLogs (graphql/operations/global/queries/auditLog.graphql)\n *\n * TODO: When authAuditLogs backend migrates to AuthAuditLogConnection type,\n * update this query to use: authAuditLogs { auditLogs: [...], totalCount, hasMore }\n * and remove the client-side hasMore approximation below.\n */\nexport function AuditLogPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const [page, setPage] = useState(1);\n const offset = (page - 1) * PAGE_SIZE;\n\n // Default-deny: only show when the flag is explicitly enabled in the system.\n // useFeatureFlag uses default-allow (returns true when not found), so we use\n // useFeatureFlagDetails + explicit value check instead.\n const auditLogFlag = useFeatureFlagDetails(\"auth.audit-log\");\n const showAuditLog = auditLogFlag?.value === true;\n\n const { data, loading, error } = useAuthAuditLogsQuery({\n skip: !showAuditLog,\n fetchPolicy: \"cache-and-network\",\n variables: { pagination: { limit: PAGE_SIZE, offset } },\n });\n\n const auditLogs = data?.authAuditLogs ?? [];\n // Approximate hasMore: if we received a full page there may be more\n const hasMore = auditLogs.length === PAGE_SIZE;\n\n const wspaceClient = useGatewayClient(\"workspace\");\n const [createExportJob, { loading: isExporting }] =\n useCreateAuthExportJobMutation({ client: wspaceClient });\n const [exportError, setExportError] = useState<string | null>(null);\n\n const handleExport = async () => {\n setExportError(null);\n try {\n await createExportJob({\n variables: {\n input: {\n name: \"Audit Log Export\",\n // permission_audit_logs covers auth audit logs in the export system\n entityTypes: [\"permission_audit_logs\"],\n format: \"CSV\",\n exportScope: \"INDIVIDUAL\",\n includeMetadata: true,\n },\n },\n });\n } catch (err) {\n setExportError(\n err instanceof Error ? err.message : \"Failed to start export\",\n );\n }\n };\n\n const getEventMarker = (eventType: string) => {\n switch (eventType) {\n case \"LOGIN_SUCCESS\":\n return \"OK\";\n case \"LOGIN_FAILURE\":\n return \"ER\";\n case \"LOGOUT\":\n return \"LO\";\n case \"PASSWORD_CHANGE\":\n return \"PW\";\n case \"MFA_ENABLED\":\n case \"MFA_VERIFIED\":\n return \"MF\";\n case \"ANOMALY_DETECTED\":\n return \"AL\";\n default:\n return \"AU\";\n }\n };\n\n if (!showAuditLog) {\n return (\n <div className=\"max-w-4xl mx-auto p-6\">\n <div className=\"text-center py-16 border-2 border-dashed border-border-subtle rounded-xl\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center\">\n <AlertIcon\n className=\"w-8 h-8 text-status-warning-text\"\n aria-hidden=\"true\"\n />\n </div>\n <h2 className=\"text-xl font-semibold text-text-primary mb-2\">\n {tr(\"auth.auditLog.notAvailable\", \"Page Not Available\")}\n </h2>\n <p className=\"text-text-secondary\">\n {tr(\n \"auth.auditLog.notEnabled\",\n \"The Security Audit Log is not enabled for your account.\",\n )}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"max-w-4xl mx-auto p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-8\">\n <h1 className=\"text-3xl font-semibold text-text-primary\">\n {tr(\"auth.auditLog.title\", \"Security Audit Log\")}\n </h1>\n <button\n type=\"button\"\n onClick={() => void handleExport()}\n disabled={isExporting}\n aria-label={tr(\"auth.auditLog.exportAriaLabel\", \"Export audit log\")}\n className=\"flex items-center gap-2 px-4 py-2.5 rounded-xl border border-border-default text-text-primary bg-bg-surface hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors font-medium\"\n >\n {isExporting ? (\n <>\n <SpinnerIcon\n className=\"w-4 h-4 animate-spin\"\n aria-hidden=\"true\"\n />\n {tr(\"auth.auditLog.exporting\", \"Exporting...\")}\n </>\n ) : (\n <>\n <svg\n className=\"w-4 h-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n {tr(\"auth.auditLog.export\", \"Export\")}\n </>\n )}\n </button>\n </div>\n\n {/* Export error */}\n {exportError && (\n <div\n role=\"alert\"\n className=\"mb-6 flex items-start gap-3 p-4 rounded-xl bg-status-error-bg-subtle border border-status-error-border\"\n >\n <AlertIcon\n className=\"w-5 h-5 text-status-error-text flex-shrink-0 mt-0.5\"\n aria-hidden=\"true\"\n />\n <p className=\"text-sm text-status-error-text\">{exportError}</p>\n </div>\n )}\n\n {loading ? (\n <div aria-live=\"polite\" aria-busy=\"true\" className=\"text-center py-12\">\n <SpinnerIcon\n className=\"w-8 h-8 mx-auto text-text-link animate-spin\"\n aria-hidden=\"true\"\n />\n <p className=\"mt-3 text-text-secondary\">\n {tr(\"auth.auditLog.loading\", \"Loading audit events...\")}\n </p>\n </div>\n ) : error ? (\n <div\n role=\"alert\"\n className=\"text-center py-12 border border-status-error-border rounded-xl bg-status-error-bg-subtle\"\n >\n <p className=\"text-status-error-text\">\n {tr(\"auth.auditLog.error\", \"Unable to load audit events\")}\n </p>\n </div>\n ) : auditLogs.length === 0 ? (\n <div className=\"text-center py-12\" role=\"status\">\n <p className=\"text-text-secondary\">\n {tr(\"auth.auditLog.noEvents\", \"No security events recorded\")}\n </p>\n </div>\n ) : (\n <>\n <div className=\"space-y-4\" aria-live=\"polite\" aria-busy={loading}>\n {auditLogs.map((event: AuditLogEntry_AuthAuditLogFragment) => (\n <div\n key={event.id}\n className=\"p-6 rounded-xl border border-border-subtle bg-bg-surface shadow-sm\"\n >\n <div className=\"flex items-start gap-4\">\n <div\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-bg-muted text-xs font-semibold text-text-secondary\"\n aria-hidden=\"true\"\n >\n {getEventMarker(event.action)}\n </div>\n <div className=\"flex-1\">\n <h3 className=\"text-lg font-medium text-text-primary mb-1\">\n {event.action.replace(/_/g, \" \")}\n </h3>\n <p className=\"text-sm text-text-secondary mb-2\">\n <time dateTime={event.createdAt}>\n {formatDateTime(event.createdAt)}\n </time>\n </p>\n <p className=\"text-sm text-text-secondary\">\n {event.description ??\n tr(\n \"auth.auditLog.defaultDescription\",\n \"Authentication event\",\n )}\n {event.ipAddress && ` • ${event.ipAddress}`}\n </p>\n </div>\n {event.action.includes(\"FAILURE\") && (\n <span\n role=\"status\"\n className=\"px-3 py-1 rounded-full bg-status-error-bg-subtle text-status-error-text text-sm font-medium\"\n >\n {tr(\"auth.auditLog.failed\", \"Failed\")}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Pagination */}\n <nav\n aria-label={tr(\n \"auth.auditLog.paginationAriaLabel\",\n \"Audit log pagination\",\n )}\n className=\"mt-6 flex items-center justify-between\"\n >\n <p className=\"text-sm text-text-secondary\">\n {tr(\"auth.auditLog.page\", \"Page\")} {page}\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => setPage((prev) => Math.max(1, prev - 1))}\n disabled={page === 1}\n aria-label={tr(\n \"auth.auditLog.previousPageAriaLabel\",\n \"Go to previous page\",\n )}\n className=\"px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors\"\n >\n {tr(\"auth.auditLog.previous\", \"Previous\")}\n </button>\n <button\n type=\"button\"\n onClick={() => setPage((prev) => prev + 1)}\n disabled={!hasMore}\n aria-label={tr(\n \"auth.auditLog.nextPageAriaLabel\",\n \"Go to next page\",\n )}\n className=\"px-4 py-2 rounded-lg border border-border-default text-text-primary bg-bg-surface disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors\"\n >\n {tr(\"auth.auditLog.next\", \"Next\")}\n </button>\n </div>\n </nav>\n </>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAYA,IAAM,IAAY;AAYlB,SAAgB,IAAe;CAC7B,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAa,EAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAGnC,CAAC,GAAM,KAAW,EAAS,EAAE,EAC7B,KAAU,IAAO,KAAK,GAMtB,IADe,EAAsB,iBAAiB,EACzB,UAAU,IAEvC,EAAE,SAAM,YAAS,aAAU,EAAsB;EACrD,MAAM,CAAC;EACP,aAAa;EACb,WAAW,EAAE,YAAY;GAAE,OAAO;GAAW;GAAQ,EAAE;EACxD,CAAC,EAEI,IAAY,GAAM,iBAAiB,EAAE,EAErC,IAAU,EAAU,WAAW,GAG/B,CAAC,GAAiB,EAAE,SAAS,OACjC,EAA+B,EAAE,QAFd,EAAiB,YAAY,EAEO,CAAC,EACpD,CAAC,GAAa,KAAkB,EAAwB,KAAK,EAE7D,IAAe,YAAY;AAC/B,IAAe,KAAK;AACpB,MAAI;AACF,SAAM,EAAgB,EACpB,WAAW,EACT,OAAO;IACL,MAAM;IAEN,aAAa,CAAC,wBAAwB;IACtC,QAAQ;IACR,aAAa;IACb,iBAAiB;IAClB,EACF,EACF,CAAC;WACK,GAAK;AACZ,KACE,aAAe,QAAQ,EAAI,UAAU,yBACtC;;IAIC,KAAkB,MAAsB;AAC5C,UAAQ,GAAR;GACE,KAAK,gBACH,QAAO;GACT,KAAK,gBACH,QAAO;GACT,KAAK,SACH,QAAO;GACT,KAAK,kBACH,QAAO;GACT,KAAK;GACL,KAAK,eACH,QAAO;GACT,KAAK,mBACH,QAAO;GACT,QACE,QAAO;;;AA4Bb,QAxBK,IAyBH,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,uBAAuB,qBAAqB;KAC7C,CAAA,EACL,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,KAAK,GAAc;KAClC,UAAU;KACV,cAAY,EAAG,iCAAiC,mBAAmB;KACnE,WAAU;eAET,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,WAAU;MACV,eAAY;MACZ,CAAA,EACD,EAAG,2BAA2B,eAAe,CAC7C,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD;MACE,WAAU;MACV,MAAK;MACL,SAAQ;MACR,QAAO;MACP,eAAY;gBAEZ,kBAAC,QAAD;OACE,eAAc;OACd,gBAAe;OACf,aAAa;OACb,GAAE;OACF,CAAA;MACE,CAAA,EACL,EAAG,wBAAwB,SAAS,CACpC,EAAA,CAAA;KAEE,CAAA,CACL;;GAGL,KACC,kBAAC,OAAD;IACE,MAAK;IACL,WAAU;cAFZ,CAIE,kBAAC,GAAD;KACE,WAAU;KACV,eAAY;KACZ,CAAA,EACF,kBAAC,KAAD;KAAG,WAAU;eAAkC;KAAgB,CAAA,CAC3D;;GAGP,IACC,kBAAC,OAAD;IAAK,aAAU;IAAS,aAAU;IAAO,WAAU;cAAnD,CACE,kBAAC,GAAD;KACE,WAAU;KACV,eAAY;KACZ,CAAA,EACF,kBAAC,KAAD;KAAG,WAAU;eACV,EAAG,yBAAyB,0BAA0B;KACrD,CAAA,CACA;QACJ,IACF,kBAAC,OAAD;IACE,MAAK;IACL,WAAU;cAEV,kBAAC,KAAD;KAAG,WAAU;eACV,EAAG,uBAAuB,8BAA8B;KACvD,CAAA;IACA,CAAA,GACJ,EAAU,WAAW,IACvB,kBAAC,OAAD;IAAK,WAAU;IAAoB,MAAK;cACtC,kBAAC,KAAD;KAAG,WAAU;eACV,EAAG,0BAA0B,8BAA8B;KAC1D,CAAA;IACA,CAAA,GAEN,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;IAAY,aAAU;IAAS,aAAW;cACtD,EAAU,KAAK,MACd,kBAAC,OAAD;KAEE,WAAU;eAEV,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QACE,WAAU;QACV,eAAY;kBAEX,EAAe,EAAM,OAAO;QACzB,CAAA;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAM,OAAO,QAAQ,MAAM,IAAI;UAC7B,CAAA;SACL,kBAAC,KAAD;UAAG,WAAU;oBACX,kBAAC,QAAD;WAAM,UAAU,EAAM;qBACnB,EAAe,EAAM,UAAU;WAC3B,CAAA;UACL,CAAA;SACJ,kBAAC,KAAD;UAAG,WAAU;oBAAb,CACG,EAAM,eACL,EACE,oCACA,uBACD,EACF,EAAM,aAAa,MAAM,EAAM,YAC9B;;SACA;;OACL,EAAM,OAAO,SAAS,UAAU,IAC/B,kBAAC,QAAD;QACE,MAAK;QACL,WAAU;kBAET,EAAG,wBAAwB,SAAS;QAChC,CAAA;OAEL;;KACF,EArCC,EAAM,GAqCP,CACN;IACE,CAAA,EAGN,kBAAC,OAAD;IACE,cAAY,EACV,qCACA,uBACD;IACD,WAAU;cALZ,CAOE,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAG,sBAAsB,OAAO;MAAC;MAAE;MAClC;QACJ,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,GAAS,MAAS,KAAK,IAAI,GAAG,IAAO,EAAE,CAAC;MACvD,UAAU,MAAS;MACnB,cAAY,EACV,uCACA,sBACD;MACD,WAAU;gBAET,EAAG,0BAA0B,WAAW;MAClC,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,GAAS,MAAS,IAAO,EAAE;MAC1C,UAAU,CAAC;MACX,cAAY,EACV,mCACA,kBACD;MACD,WAAU;gBAET,EAAG,sBAAsB,OAAO;MAC1B,CAAA,CACL;OACF;MACL,EAAA,CAAA;GAED;MA/LJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MACE,WAAU;MACV,eAAY;MACZ,CAAA;KACE,CAAA;IACN,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,8BAA8B,qBAAqB;KACpD,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,4BACA,0DACD;KACC,CAAA;IACA;;EACF,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/LoginPage.tsx"],"names":[],"mappings":"AA4DA;;;GAGG;AACH,wBAAgB,SAAS,
|
|
1
|
+
{"version":3,"file":"LoginPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/LoginPage.tsx"],"names":[],"mappings":"AA4DA;;;GAGG;AACH,wBAAgB,SAAS,4CA4kCxB"}
|
|
@@ -392,8 +392,8 @@ function y() {
|
|
|
392
392
|
children: /* @__PURE__ */ h(o, { className: "w-5 h-5 text-[var(--color-text-tertiary)]" })
|
|
393
393
|
}), /* @__PURE__ */ h("input", {
|
|
394
394
|
id: "email",
|
|
395
|
-
type: "
|
|
396
|
-
autoComplete: "email
|
|
395
|
+
type: "email",
|
|
396
|
+
autoComplete: "email",
|
|
397
397
|
required: !0,
|
|
398
398
|
"aria-required": "true",
|
|
399
399
|
value: G.email,
|
|
@@ -525,6 +525,7 @@ function y() {
|
|
|
525
525
|
onClick: e.onClick,
|
|
526
526
|
disabled: e.disabled,
|
|
527
527
|
title: e.tooltip,
|
|
528
|
+
"aria-label": e.name,
|
|
528
529
|
className: `flex items-center justify-center gap-2 px-4 py-3 rounded-xl border transition-all duration-200 group ${e.disabled ? "border-[var(--color-border-subtle)] bg-[var(--color-bg-disabled)] cursor-not-allowed opacity-50" : "border-[var(--color-border-default)] bg-[var(--color-bg-surface)] hover:bg-[var(--color-bg-sunken)] hover:border-[var(--color-border-strong)]"}`,
|
|
529
530
|
children: [/* @__PURE__ */ h(e.icon, { className: `w-5 h-5 ${e.disabled ? "opacity-50" : ""}` }), /* @__PURE__ */ h("span", {
|
|
530
531
|
className: `sr-only sm:not-sr-only text-sm font-medium transition-colors hidden sm:inline ${e.disabled ? "text-[var(--color-text-disabled)]" : "text-[var(--color-text-secondary)] group-hover:text-[var(--color-text-primary)]"}`,
|