@usebetterdev/audit-core 0.6.0 → 0.7.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/index.cjs +196 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -1
- package/dist/index.d.ts +121 -1
- package/dist/index.js +182 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -22,20 +22,33 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AUDIT_LOG_SCHEMA: () => AUDIT_LOG_SCHEMA,
|
|
24
24
|
AuditQueryBuilder: () => AuditQueryBuilder,
|
|
25
|
+
VALID_OPERATIONS: () => VALID_OPERATIONS2,
|
|
26
|
+
VALID_SEVERITIES: () => VALID_SEVERITIES2,
|
|
27
|
+
assembleStats: () => assembleStats,
|
|
25
28
|
betterAudit: () => betterAudit,
|
|
26
29
|
createAuditApi: () => createAuditApi,
|
|
27
30
|
createAuditConsoleEndpoints: () => createAuditConsoleEndpoints,
|
|
28
31
|
createExportResponse: () => createExportResponse,
|
|
32
|
+
decodeCursor: () => decodeCursor,
|
|
33
|
+
defaultExtractor: () => defaultExtractor,
|
|
34
|
+
encodeCursor: () => encodeCursor,
|
|
35
|
+
escapeLikePattern: () => escapeLikePattern,
|
|
29
36
|
fromBearerToken: () => fromBearerToken,
|
|
30
37
|
fromCookie: () => fromCookie,
|
|
31
38
|
fromHeader: () => fromHeader,
|
|
32
39
|
getAuditContext: () => getAuditContext,
|
|
33
40
|
handleMiddleware: () => handleMiddleware,
|
|
41
|
+
interpretFilters: () => interpretFilters,
|
|
42
|
+
isAuditOperation: () => isAuditOperation,
|
|
43
|
+
isAuditSeverity: () => isAuditSeverity,
|
|
34
44
|
mergeAuditContext: () => mergeAuditContext,
|
|
35
45
|
normalizeInput: () => normalizeInput,
|
|
36
46
|
parseDuration: () => parseDuration,
|
|
47
|
+
resolveTimeFilter: () => resolveTimeFilter,
|
|
37
48
|
runExport: () => runExport,
|
|
38
|
-
runWithAuditContext: () => runWithAuditContext
|
|
49
|
+
runWithAuditContext: () => runWithAuditContext,
|
|
50
|
+
safeExtract: () => safeExtract,
|
|
51
|
+
toCount: () => toCount
|
|
39
52
|
});
|
|
40
53
|
module.exports = __toCommonJS(index_exports);
|
|
41
54
|
|
|
@@ -1509,6 +1522,171 @@ var AUDIT_LOG_SCHEMA = {
|
|
|
1509
1522
|
}
|
|
1510
1523
|
};
|
|
1511
1524
|
|
|
1525
|
+
// src/cursor.ts
|
|
1526
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1527
|
+
function encodeCursor(timestamp, id) {
|
|
1528
|
+
const payload = JSON.stringify({ t: timestamp.toISOString(), i: id });
|
|
1529
|
+
return btoa(payload);
|
|
1530
|
+
}
|
|
1531
|
+
function decodeCursor(cursor) {
|
|
1532
|
+
let parsed;
|
|
1533
|
+
try {
|
|
1534
|
+
parsed = JSON.parse(atob(cursor));
|
|
1535
|
+
} catch {
|
|
1536
|
+
throw new Error("Invalid cursor: failed to decode");
|
|
1537
|
+
}
|
|
1538
|
+
if (typeof parsed !== "object" || parsed === null || !("t" in parsed) || !("i" in parsed)) {
|
|
1539
|
+
throw new Error("Invalid cursor: missing required fields");
|
|
1540
|
+
}
|
|
1541
|
+
const record = parsed;
|
|
1542
|
+
const t = record["t"];
|
|
1543
|
+
const i = record["i"];
|
|
1544
|
+
if (typeof t !== "string" || typeof i !== "string") {
|
|
1545
|
+
throw new Error("Invalid cursor: fields must be strings");
|
|
1546
|
+
}
|
|
1547
|
+
const timestamp = new Date(t);
|
|
1548
|
+
if (isNaN(timestamp.getTime())) {
|
|
1549
|
+
throw new Error("Invalid cursor: invalid timestamp");
|
|
1550
|
+
}
|
|
1551
|
+
if (!UUID_PATTERN.test(i)) {
|
|
1552
|
+
throw new Error("Invalid cursor: id must be a valid UUID");
|
|
1553
|
+
}
|
|
1554
|
+
return { timestamp, id: i };
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
// src/escape.ts
|
|
1558
|
+
function escapeLikePattern(input) {
|
|
1559
|
+
return input.replace(/[%_\\]/g, "\\$&");
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// src/time-filter.ts
|
|
1563
|
+
function resolveTimeFilter(filter) {
|
|
1564
|
+
if ("date" in filter && filter.date !== void 0) {
|
|
1565
|
+
return filter.date;
|
|
1566
|
+
}
|
|
1567
|
+
if ("duration" in filter && filter.duration !== void 0) {
|
|
1568
|
+
return parseDuration(filter.duration);
|
|
1569
|
+
}
|
|
1570
|
+
throw new Error("TimeFilter must have either date or duration");
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
// src/filter-builder.ts
|
|
1574
|
+
function interpretFilters(filters, options) {
|
|
1575
|
+
const conditions = [];
|
|
1576
|
+
if (filters.resource !== void 0) {
|
|
1577
|
+
conditions.push({ kind: "eq", field: "tableName", value: filters.resource.tableName });
|
|
1578
|
+
if (filters.resource.recordId !== void 0) {
|
|
1579
|
+
conditions.push({ kind: "eq", field: "recordId", value: filters.resource.recordId });
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
pushArrayFilter(conditions, "actorId", filters.actorIds);
|
|
1583
|
+
pushArrayFilter(conditions, "severity", filters.severities);
|
|
1584
|
+
pushArrayFilter(conditions, "operation", filters.operations);
|
|
1585
|
+
if (filters.since !== void 0) {
|
|
1586
|
+
conditions.push({ kind: "timestampGte", value: resolveTimeFilter(filters.since) });
|
|
1587
|
+
}
|
|
1588
|
+
if (filters.until !== void 0) {
|
|
1589
|
+
conditions.push({ kind: "timestampLte", value: resolveTimeFilter(filters.until) });
|
|
1590
|
+
}
|
|
1591
|
+
if (filters.searchText !== void 0 && filters.searchText.length > 0) {
|
|
1592
|
+
const escaped = escapeLikePattern(filters.searchText);
|
|
1593
|
+
conditions.push({ kind: "search", pattern: `%${escaped}%` });
|
|
1594
|
+
}
|
|
1595
|
+
if (filters.compliance !== void 0 && filters.compliance.length > 0) {
|
|
1596
|
+
conditions.push({ kind: "compliance", tags: [...filters.compliance] });
|
|
1597
|
+
}
|
|
1598
|
+
if (options?.cursor !== void 0) {
|
|
1599
|
+
conditions.push({
|
|
1600
|
+
kind: "cursor",
|
|
1601
|
+
timestamp: options.cursor.timestamp,
|
|
1602
|
+
id: options.cursor.id,
|
|
1603
|
+
sortOrder: options.sortOrder ?? "desc"
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
return conditions;
|
|
1607
|
+
}
|
|
1608
|
+
function pushArrayFilter(conditions, field, values) {
|
|
1609
|
+
if (values === void 0 || values.length === 0) {
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
if (values.length === 1) {
|
|
1613
|
+
const first = values[0];
|
|
1614
|
+
if (first !== void 0) {
|
|
1615
|
+
conditions.push({ kind: "eq", field, value: first });
|
|
1616
|
+
}
|
|
1617
|
+
} else {
|
|
1618
|
+
conditions.push({ kind: "in", field, values: [...values] });
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
// src/stats.ts
|
|
1623
|
+
function toCount(value) {
|
|
1624
|
+
if (typeof value === "number") {
|
|
1625
|
+
return value;
|
|
1626
|
+
}
|
|
1627
|
+
if (typeof value === "string") {
|
|
1628
|
+
const n = Number(value);
|
|
1629
|
+
return Number.isNaN(n) ? 0 : n;
|
|
1630
|
+
}
|
|
1631
|
+
if (typeof value === "bigint") {
|
|
1632
|
+
return Number(value);
|
|
1633
|
+
}
|
|
1634
|
+
return 0;
|
|
1635
|
+
}
|
|
1636
|
+
function assembleStats(summaryRows, eventsPerDayRows, topActorsRows, topTablesRows, operationRows, severityRows) {
|
|
1637
|
+
const summary = summaryRows[0];
|
|
1638
|
+
const totalLogs = summary !== void 0 ? toCount(summary.totalLogs) : 0;
|
|
1639
|
+
const tablesAudited = summary !== void 0 ? toCount(summary.tablesAudited) : 0;
|
|
1640
|
+
const eventsPerDay = eventsPerDayRows.map((row) => ({
|
|
1641
|
+
date: row.date instanceof Date ? row.date.toISOString().split("T")[0] ?? "" : String(row.date),
|
|
1642
|
+
count: toCount(row.count)
|
|
1643
|
+
}));
|
|
1644
|
+
const topActors = topActorsRows.map((row) => ({
|
|
1645
|
+
actorId: String(row.actorId),
|
|
1646
|
+
count: toCount(row.count)
|
|
1647
|
+
}));
|
|
1648
|
+
const topTables = topTablesRows.map((row) => ({
|
|
1649
|
+
tableName: String(row.tableName),
|
|
1650
|
+
count: toCount(row.count)
|
|
1651
|
+
}));
|
|
1652
|
+
const operationBreakdown = {};
|
|
1653
|
+
for (const row of operationRows) {
|
|
1654
|
+
operationBreakdown[String(row.operation)] = toCount(row.count);
|
|
1655
|
+
}
|
|
1656
|
+
const severityBreakdown = {};
|
|
1657
|
+
for (const row of severityRows) {
|
|
1658
|
+
severityBreakdown[String(row.severity)] = toCount(row.count);
|
|
1659
|
+
}
|
|
1660
|
+
return {
|
|
1661
|
+
totalLogs,
|
|
1662
|
+
tablesAudited,
|
|
1663
|
+
eventsPerDay,
|
|
1664
|
+
topActors,
|
|
1665
|
+
topTables,
|
|
1666
|
+
operationBreakdown,
|
|
1667
|
+
severityBreakdown
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// src/validation.ts
|
|
1672
|
+
var VALID_OPERATIONS2 = /* @__PURE__ */ new Set([
|
|
1673
|
+
"INSERT",
|
|
1674
|
+
"UPDATE",
|
|
1675
|
+
"DELETE"
|
|
1676
|
+
]);
|
|
1677
|
+
var VALID_SEVERITIES2 = /* @__PURE__ */ new Set([
|
|
1678
|
+
"low",
|
|
1679
|
+
"medium",
|
|
1680
|
+
"high",
|
|
1681
|
+
"critical"
|
|
1682
|
+
]);
|
|
1683
|
+
function isAuditOperation(value) {
|
|
1684
|
+
return VALID_OPERATIONS2.has(value);
|
|
1685
|
+
}
|
|
1686
|
+
function isAuditSeverity(value) {
|
|
1687
|
+
return VALID_SEVERITIES2.has(value);
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1512
1690
|
// src/context-extractor.ts
|
|
1513
1691
|
function decodeJwtPayload(token) {
|
|
1514
1692
|
try {
|
|
@@ -1586,6 +1764,9 @@ function fromHeader(headerName) {
|
|
|
1586
1764
|
return value.trim();
|
|
1587
1765
|
};
|
|
1588
1766
|
}
|
|
1767
|
+
var defaultExtractor = {
|
|
1768
|
+
actor: fromBearerToken("sub")
|
|
1769
|
+
};
|
|
1589
1770
|
async function safeExtract(extractor, request, onError) {
|
|
1590
1771
|
if (!extractor) {
|
|
1591
1772
|
return void 0;
|
|
@@ -1612,19 +1793,32 @@ async function handleMiddleware(extractor, request, next, options = {}) {
|
|
|
1612
1793
|
0 && (module.exports = {
|
|
1613
1794
|
AUDIT_LOG_SCHEMA,
|
|
1614
1795
|
AuditQueryBuilder,
|
|
1796
|
+
VALID_OPERATIONS,
|
|
1797
|
+
VALID_SEVERITIES,
|
|
1798
|
+
assembleStats,
|
|
1615
1799
|
betterAudit,
|
|
1616
1800
|
createAuditApi,
|
|
1617
1801
|
createAuditConsoleEndpoints,
|
|
1618
1802
|
createExportResponse,
|
|
1803
|
+
decodeCursor,
|
|
1804
|
+
defaultExtractor,
|
|
1805
|
+
encodeCursor,
|
|
1806
|
+
escapeLikePattern,
|
|
1619
1807
|
fromBearerToken,
|
|
1620
1808
|
fromCookie,
|
|
1621
1809
|
fromHeader,
|
|
1622
1810
|
getAuditContext,
|
|
1623
1811
|
handleMiddleware,
|
|
1812
|
+
interpretFilters,
|
|
1813
|
+
isAuditOperation,
|
|
1814
|
+
isAuditSeverity,
|
|
1624
1815
|
mergeAuditContext,
|
|
1625
1816
|
normalizeInput,
|
|
1626
1817
|
parseDuration,
|
|
1818
|
+
resolveTimeFilter,
|
|
1627
1819
|
runExport,
|
|
1628
|
-
runWithAuditContext
|
|
1820
|
+
runWithAuditContext,
|
|
1821
|
+
safeExtract,
|
|
1822
|
+
toCount
|
|
1629
1823
|
});
|
|
1630
1824
|
//# sourceMappingURL=index.cjs.map
|