@strapi/admin 5.52.2 → 5.53.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/admin/admin/src/components/Filters.js +9 -9
- package/dist/admin/admin/src/components/Filters.js.map +1 -1
- package/dist/admin/admin/src/components/Filters.mjs +10 -10
- package/dist/admin/admin/src/components/Filters.mjs.map +1 -1
- package/dist/admin/admin/src/components/Pagination.js +2 -2
- package/dist/admin/admin/src/components/Pagination.js.map +1 -1
- package/dist/admin/admin/src/components/Pagination.mjs +3 -3
- package/dist/admin/admin/src/components/Pagination.mjs.map +1 -1
- package/dist/admin/admin/src/components/SearchInput.js +7 -8
- package/dist/admin/admin/src/components/SearchInput.js.map +1 -1
- package/dist/admin/admin/src/components/SearchInput.mjs +8 -9
- package/dist/admin/admin/src/components/SearchInput.mjs.map +1 -1
- package/dist/admin/admin/src/components/Table.js +2 -2
- package/dist/admin/admin/src/components/Table.js.map +1 -1
- package/dist/admin/admin/src/components/Table.mjs +3 -3
- package/dist/admin/admin/src/components/Table.mjs.map +1 -1
- package/dist/admin/admin/src/hooks/useQueryParams.js +35 -1
- package/dist/admin/admin/src/hooks/useQueryParams.js.map +1 -1
- package/dist/admin/admin/src/hooks/useQueryParams.mjs +34 -2
- package/dist/admin/admin/src/hooks/useQueryParams.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +18 -0
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +18 -0
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +118 -43
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +118 -45
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/ee/admin/src/constants.js +6 -0
- package/dist/admin/ee/admin/src/constants.js.map +1 -1
- package/dist/admin/ee/admin/src/constants.mjs +6 -0
- package/dist/admin/ee/admin/src/constants.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js +40 -12
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs +43 -15
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.js +177 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.js.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.mjs +175 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.mjs.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.js +173 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.js.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.mjs +151 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.mjs.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +10 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +10 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
- package/dist/admin/index.js +4 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/admin/shared/utils/audit-log-export.js +16 -0
- package/dist/admin/shared/utils/audit-log-export.js.map +1 -0
- package/dist/admin/shared/utils/audit-log-export.mjs +9 -0
- package/dist/admin/shared/utils/audit-log-export.mjs.map +1 -0
- package/dist/admin/src/components/Filters.d.ts +1 -0
- package/dist/admin/src/hooks/useQueryParams.d.ts +13 -1
- package/dist/admin/src/index.d.ts +1 -1
- package/dist/admin/src/utils/getFetchClient.d.ts +9 -2
- package/dist/admin/tests/store.d.ts +4 -0
- package/dist/admin/tests/utils.d.ts +4 -0
- package/dist/ee/admin/src/constants.d.ts +4 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.d.ts +10 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.d.ts +18 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +9 -0
- package/dist/ee/server/src/audit-logs/controllers/audit-logs.d.ts +1 -0
- package/dist/ee/server/src/audit-logs/controllers/audit-logs.d.ts.map +1 -1
- package/dist/ee/server/src/audit-logs/routes/audit-logs.d.ts.map +1 -1
- package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts +24 -3
- package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts.map +1 -1
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +8 -2
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts.map +1 -1
- package/dist/ee/server/src/audit-logs/utils/csv.d.ts +5 -0
- package/dist/ee/server/src/audit-logs/utils/csv.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/utils/export-token.d.ts +5 -0
- package/dist/ee/server/src/audit-logs/utils/export-token.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/utils.d.ts +10 -0
- package/dist/ee/server/src/audit-logs/utils.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/validation/audit-logs.d.ts +2 -0
- package/dist/ee/server/src/audit-logs/validation/audit-logs.d.ts.map +1 -1
- package/dist/ee/server/src/config/admin-actions.d.ts.map +1 -1
- package/dist/ee/server/src/index.d.ts +1 -0
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.js +50 -0
- package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.mjs +51 -1
- package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.mjs.map +1 -1
- package/dist/server/ee/server/src/audit-logs/routes/audit-logs.js +13 -4
- package/dist/server/ee/server/src/audit-logs/routes/audit-logs.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/routes/audit-logs.mjs +13 -4
- package/dist/server/ee/server/src/audit-logs/routes/audit-logs.mjs.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.js +201 -7
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs +201 -8
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +119 -34
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +119 -34
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
- package/dist/server/ee/server/src/audit-logs/utils/csv.js +33 -0
- package/dist/server/ee/server/src/audit-logs/utils/csv.js.map +1 -0
- package/dist/server/ee/server/src/audit-logs/utils/csv.mjs +29 -0
- package/dist/server/ee/server/src/audit-logs/utils/csv.mjs.map +1 -0
- package/dist/server/ee/server/src/audit-logs/utils/export-token.js +33 -0
- package/dist/server/ee/server/src/audit-logs/utils/export-token.js.map +1 -0
- package/dist/server/ee/server/src/audit-logs/utils/export-token.mjs +29 -0
- package/dist/server/ee/server/src/audit-logs/utils/export-token.mjs.map +1 -0
- package/dist/server/ee/server/src/audit-logs/utils.js +14 -0
- package/dist/server/ee/server/src/audit-logs/utils.js.map +1 -0
- package/dist/server/ee/server/src/audit-logs/utils.mjs +12 -0
- package/dist/server/ee/server/src/audit-logs/utils.mjs.map +1 -0
- package/dist/server/ee/server/src/audit-logs/validation/audit-logs.js +11 -0
- package/dist/server/ee/server/src/audit-logs/validation/audit-logs.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/validation/audit-logs.mjs +11 -1
- package/dist/server/ee/server/src/audit-logs/validation/audit-logs.mjs.map +1 -1
- package/dist/server/ee/server/src/config/admin-actions.js +8 -0
- package/dist/server/ee/server/src/config/admin-actions.js.map +1 -1
- package/dist/server/ee/server/src/config/admin-actions.mjs +8 -0
- package/dist/server/ee/server/src/config/admin-actions.mjs.map +1 -1
- package/dist/server/ee/server/src/index.js +10 -0
- package/dist/server/ee/server/src/index.js.map +1 -1
- package/dist/server/ee/server/src/index.mjs +10 -0
- package/dist/server/ee/server/src/index.mjs.map +1 -1
- package/dist/server/shared/utils/audit-log-export.js +22 -0
- package/dist/server/shared/utils/audit-log-export.js.map +1 -0
- package/dist/server/shared/utils/audit-log-export.mjs +12 -0
- package/dist/server/shared/utils/audit-log-export.mjs.map +1 -0
- package/dist/shared/contracts/audit-logs.d.ts +15 -1
- package/dist/shared/contracts/audit-logs.d.ts.map +1 -1
- package/dist/shared/utils/audit-log-export.d.ts +9 -0
- package/dist/shared/utils/audit-log-export.d.ts.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface AdminUserLike {
|
|
2
|
+
username?: string | null;
|
|
3
|
+
firstname?: string | null;
|
|
4
|
+
lastname?: string | null;
|
|
5
|
+
email: string;
|
|
6
|
+
}
|
|
7
|
+
/** How an admin user is named across audit logs */
|
|
8
|
+
declare const getDisplayName: (user: AdminUserLike) => string;
|
|
9
|
+
export { getDisplayName };
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/audit-logs/utils.ts"],"names":[],"mappings":"AAAA,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mDAAmD;AACnD,QAAA,MAAM,cAAc,GAAI,MAAM,aAAa,KAAG,MAU7C,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export declare const validateFindMany: (body: unknown, errorMessage?: string) => Promise<any>;
|
|
2
2
|
export declare const validateFindManyUsers: (body: unknown, errorMessage?: string) => Promise<any>;
|
|
3
|
+
export declare const validateExport: (body: unknown, errorMessage?: string) => Promise<any>;
|
|
3
4
|
declare const _default: {
|
|
4
5
|
validateFindMany: (body: unknown, errorMessage?: string) => Promise<any>;
|
|
5
6
|
validateFindManyUsers: (body: unknown, errorMessage?: string) => Promise<any>;
|
|
7
|
+
validateExport: (body: unknown, errorMessage?: string) => Promise<any>;
|
|
6
8
|
};
|
|
7
9
|
export default _default;
|
|
8
10
|
//# sourceMappingURL=audit-logs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logs.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/audit-logs/validation/audit-logs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"audit-logs.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/audit-logs/validation/audit-logs.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,gBAAgB,wDAA+D,CAAC;AAC7F,eAAO,MAAM,qBAAqB,wDAEhC,CAAC;AACH,eAAO,MAAM,cAAc,wDAA6D,CAAC;;;;;;AAEzF,wBAIE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-actions.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/config/admin-actions.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"admin-actions.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/config/admin-actions.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,wBAqCE"}
|
|
@@ -5,6 +5,7 @@ declare const getAdminEE: () => {
|
|
|
5
5
|
findMany(ctx: import("koa").Context): Promise<void>;
|
|
6
6
|
findManyUsers(ctx: import("koa").Context): Promise<void>;
|
|
7
7
|
findOne(ctx: import("koa").Context): Promise<void>;
|
|
8
|
+
export(ctx: import("koa").Context): Promise<void>;
|
|
8
9
|
} | undefined;
|
|
9
10
|
authentication: {
|
|
10
11
|
getProviders(ctx: import("koa").Context): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../ee/server/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../ee/server/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAe1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4Be;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;wBAsBxB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var zlib = require('zlib');
|
|
4
|
+
var utils = require('@strapi/utils');
|
|
5
|
+
var auditLogExport = require('../../../../../shared/utils/audit-log-export.js');
|
|
3
6
|
var auditLogs = require('../validation/audit-logs.js');
|
|
4
7
|
|
|
8
|
+
const EXPORT_INVALID_CONTINUATION_MESSAGE = 'The export continuation is invalid or has expired. Restart the export.';
|
|
9
|
+
const EXPORT_TOO_LARGE_MESSAGE = 'The export matches more entries than the configured limit. Add filters to reduce it.';
|
|
5
10
|
var auditLogsController = {
|
|
6
11
|
async findMany (ctx) {
|
|
7
12
|
const { query } = ctx.request;
|
|
@@ -26,6 +31,51 @@ var auditLogsController = {
|
|
|
26
31
|
const body = await auditLogs.findOne(id);
|
|
27
32
|
ctx.body = body;
|
|
28
33
|
strapi.telemetry.send('didWatchAnAuditLog');
|
|
34
|
+
},
|
|
35
|
+
async export (ctx) {
|
|
36
|
+
const { query } = ctx.request;
|
|
37
|
+
const validatedQuery = await auditLogs.validateExport(query);
|
|
38
|
+
const auditLogs$1 = strapi.get('audit-logs');
|
|
39
|
+
const isContinuation = validatedQuery.cursor !== undefined;
|
|
40
|
+
if (isContinuation && !auditLogs$1.isTrustedContinuation(validatedQuery)) {
|
|
41
|
+
throw new utils.errors.ValidationError(EXPORT_INVALID_CONTINUATION_MESSAGE);
|
|
42
|
+
}
|
|
43
|
+
if (!isContinuation) {
|
|
44
|
+
if (await auditLogs$1.isExportTooLarge({
|
|
45
|
+
filters: validatedQuery.filters ?? null
|
|
46
|
+
})) {
|
|
47
|
+
throw new utils.errors.PayloadTooLargeError(EXPORT_TOO_LARGE_MESSAGE);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const { stream, nextCursor, until, isNewExport, partSize, exportToken } = await auditLogs$1.createExportStream(validatedQuery);
|
|
51
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
52
|
+
ctx.set('Content-Type', 'text/csv; charset=utf-8');
|
|
53
|
+
ctx.set('Content-Disposition', `attachment; filename="audit-logs-${date}.csv"`);
|
|
54
|
+
ctx.set(auditLogExport.AUDIT_LOGS_EXPORT_UNTIL_HEADER, String(until));
|
|
55
|
+
ctx.set(auditLogExport.AUDIT_LOGS_EXPORT_PART_SIZE_HEADER, String(partSize));
|
|
56
|
+
ctx.set(auditLogExport.AUDIT_LOGS_EXPORT_TOKEN_HEADER, exportToken);
|
|
57
|
+
ctx.set(auditLogExport.AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER, nextCursor !== null ? String(nextCursor) : auditLogExport.AUDIT_LOGS_EXPORT_CURSOR_DONE);
|
|
58
|
+
const exposedHeaders = [
|
|
59
|
+
ctx.response.get('Access-Control-Expose-Headers'),
|
|
60
|
+
auditLogExport.AUDIT_LOGS_EXPORT_UNTIL_HEADER,
|
|
61
|
+
auditLogExport.AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,
|
|
62
|
+
auditLogExport.AUDIT_LOGS_EXPORT_PART_SIZE_HEADER,
|
|
63
|
+
auditLogExport.AUDIT_LOGS_EXPORT_TOKEN_HEADER,
|
|
64
|
+
'Content-Disposition'
|
|
65
|
+
].filter(Boolean).join(', ');
|
|
66
|
+
ctx.set('Access-Control-Expose-Headers', exposedHeaders);
|
|
67
|
+
ctx.vary('Accept-Encoding');
|
|
68
|
+
if (ctx.acceptsEncodings('gzip', 'identity') === 'gzip') {
|
|
69
|
+
ctx.set('Content-Encoding', 'gzip');
|
|
70
|
+
const gzip = zlib.createGzip();
|
|
71
|
+
stream.on('error', (error)=>gzip.destroy(error));
|
|
72
|
+
ctx.body = stream.pipe(gzip);
|
|
73
|
+
} else {
|
|
74
|
+
ctx.body = stream;
|
|
75
|
+
}
|
|
76
|
+
if (isNewExport) {
|
|
77
|
+
strapi.telemetry.send('didExportAuditLogs');
|
|
78
|
+
}
|
|
29
79
|
}
|
|
30
80
|
};
|
|
31
81
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logs.js","sources":["../../../../../../../ee/server/src/audit-logs/controllers/audit-logs.ts"],"sourcesContent":["import type { Context } from 'koa';\n\nimport { validateFindMany, validateFindManyUsers } from '../validation/audit-logs';\n\nexport default {\n async findMany(ctx: Context) {\n const { query } = ctx.request;\n await validateFindMany(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findMany(query);\n\n ctx.body = body;\n },\n\n async findManyUsers(ctx: Context) {\n const { query } = ctx.request;\n const { page, pageSize } = await validateFindManyUsers(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findManyUsers({ page, pageSize });\n\n ctx.body = body;\n },\n\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findOne(id);\n\n ctx.body = body;\n\n strapi.telemetry.send('didWatchAnAuditLog');\n },\n};\n"],"names":["findMany","ctx","query","request","validateFindMany","auditLogs","strapi","get","body","findManyUsers","page","pageSize","validateFindManyUsers","findOne","id","params","telemetry","send"],"mappings":"
|
|
1
|
+
{"version":3,"file":"audit-logs.js","sources":["../../../../../../../ee/server/src/audit-logs/controllers/audit-logs.ts"],"sourcesContent":["import { createGzip } from 'zlib';\n\nimport type { Context } from 'koa';\nimport { errors } from '@strapi/utils';\n\nimport {\n AUDIT_LOGS_EXPORT_CURSOR_DONE,\n AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,\n AUDIT_LOGS_EXPORT_PART_SIZE_HEADER,\n AUDIT_LOGS_EXPORT_TOKEN_HEADER,\n AUDIT_LOGS_EXPORT_UNTIL_HEADER,\n} from '../../../../../shared/utils/audit-log-export';\nimport { validateExport, validateFindMany, validateFindManyUsers } from '../validation/audit-logs';\n\nconst EXPORT_INVALID_CONTINUATION_MESSAGE =\n 'The export continuation is invalid or has expired. Restart the export.';\nconst EXPORT_TOO_LARGE_MESSAGE =\n 'The export matches more entries than the configured limit. Add filters to reduce it.';\n\nexport default {\n async findMany(ctx: Context) {\n const { query } = ctx.request;\n await validateFindMany(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findMany(query);\n\n ctx.body = body;\n },\n\n async findManyUsers(ctx: Context) {\n const { query } = ctx.request;\n const { page, pageSize } = await validateFindManyUsers(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findManyUsers({ page, pageSize });\n\n ctx.body = body;\n },\n\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findOne(id);\n\n ctx.body = body;\n\n strapi.telemetry.send('didWatchAnAuditLog');\n },\n\n async export(ctx: Context) {\n const { query } = ctx.request;\n const validatedQuery = await validateExport(query);\n\n const auditLogs = strapi.get('audit-logs');\n\n const isContinuation = validatedQuery.cursor !== undefined;\n\n if (isContinuation && !auditLogs.isTrustedContinuation(validatedQuery)) {\n throw new errors.ValidationError(EXPORT_INVALID_CONTINUATION_MESSAGE);\n }\n\n if (!isContinuation) {\n if (await auditLogs.isExportTooLarge({ filters: validatedQuery.filters ?? null })) {\n throw new errors.PayloadTooLargeError(EXPORT_TOO_LARGE_MESSAGE);\n }\n }\n\n const { stream, nextCursor, until, isNewExport, partSize, exportToken } =\n await auditLogs.createExportStream(validatedQuery);\n\n const date = new Date().toISOString().slice(0, 10);\n\n ctx.set('Content-Type', 'text/csv; charset=utf-8');\n ctx.set('Content-Disposition', `attachment; filename=\"audit-logs-${date}.csv\"`);\n ctx.set(AUDIT_LOGS_EXPORT_UNTIL_HEADER, String(until));\n ctx.set(AUDIT_LOGS_EXPORT_PART_SIZE_HEADER, String(partSize));\n ctx.set(AUDIT_LOGS_EXPORT_TOKEN_HEADER, exportToken);\n ctx.set(\n AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,\n nextCursor !== null ? String(nextCursor) : AUDIT_LOGS_EXPORT_CURSOR_DONE\n );\n\n const exposedHeaders = [\n ctx.response.get('Access-Control-Expose-Headers'),\n AUDIT_LOGS_EXPORT_UNTIL_HEADER,\n AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,\n AUDIT_LOGS_EXPORT_PART_SIZE_HEADER,\n AUDIT_LOGS_EXPORT_TOKEN_HEADER,\n 'Content-Disposition',\n ]\n .filter(Boolean)\n .join(', ');\n ctx.set('Access-Control-Expose-Headers', exposedHeaders);\n\n ctx.vary('Accept-Encoding');\n if (ctx.acceptsEncodings('gzip', 'identity') === 'gzip') {\n ctx.set('Content-Encoding', 'gzip');\n const gzip = createGzip();\n stream.on('error', (error: Error) => gzip.destroy(error));\n ctx.body = stream.pipe(gzip);\n } else {\n ctx.body = stream;\n }\n\n if (isNewExport) {\n strapi.telemetry.send('didExportAuditLogs');\n }\n },\n};\n"],"names":["EXPORT_INVALID_CONTINUATION_MESSAGE","EXPORT_TOO_LARGE_MESSAGE","findMany","ctx","query","request","validateFindMany","auditLogs","strapi","get","body","findManyUsers","page","pageSize","validateFindManyUsers","findOne","id","params","telemetry","send","export","validatedQuery","validateExport","isContinuation","cursor","undefined","isTrustedContinuation","errors","ValidationError","isExportTooLarge","filters","PayloadTooLargeError","stream","nextCursor","until","isNewExport","partSize","exportToken","createExportStream","date","Date","toISOString","slice","set","AUDIT_LOGS_EXPORT_UNTIL_HEADER","String","AUDIT_LOGS_EXPORT_PART_SIZE_HEADER","AUDIT_LOGS_EXPORT_TOKEN_HEADER","AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER","AUDIT_LOGS_EXPORT_CURSOR_DONE","exposedHeaders","response","filter","Boolean","join","vary","acceptsEncodings","gzip","createGzip","on","error","destroy","pipe"],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createGzip } from 'zlib';
|
|
2
|
+
import { errors } from '@strapi/utils';
|
|
3
|
+
import { AUDIT_LOGS_EXPORT_UNTIL_HEADER, AUDIT_LOGS_EXPORT_PART_SIZE_HEADER, AUDIT_LOGS_EXPORT_TOKEN_HEADER, AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER, AUDIT_LOGS_EXPORT_CURSOR_DONE } from '../../../../../shared/utils/audit-log-export.mjs';
|
|
4
|
+
import { validateExport, validateFindManyUsers, validateFindMany } from '../validation/audit-logs.mjs';
|
|
2
5
|
|
|
6
|
+
const EXPORT_INVALID_CONTINUATION_MESSAGE = 'The export continuation is invalid or has expired. Restart the export.';
|
|
7
|
+
const EXPORT_TOO_LARGE_MESSAGE = 'The export matches more entries than the configured limit. Add filters to reduce it.';
|
|
3
8
|
var auditLogsController = {
|
|
4
9
|
async findMany (ctx) {
|
|
5
10
|
const { query } = ctx.request;
|
|
@@ -24,6 +29,51 @@ var auditLogsController = {
|
|
|
24
29
|
const body = await auditLogs.findOne(id);
|
|
25
30
|
ctx.body = body;
|
|
26
31
|
strapi.telemetry.send('didWatchAnAuditLog');
|
|
32
|
+
},
|
|
33
|
+
async export (ctx) {
|
|
34
|
+
const { query } = ctx.request;
|
|
35
|
+
const validatedQuery = await validateExport(query);
|
|
36
|
+
const auditLogs = strapi.get('audit-logs');
|
|
37
|
+
const isContinuation = validatedQuery.cursor !== undefined;
|
|
38
|
+
if (isContinuation && !auditLogs.isTrustedContinuation(validatedQuery)) {
|
|
39
|
+
throw new errors.ValidationError(EXPORT_INVALID_CONTINUATION_MESSAGE);
|
|
40
|
+
}
|
|
41
|
+
if (!isContinuation) {
|
|
42
|
+
if (await auditLogs.isExportTooLarge({
|
|
43
|
+
filters: validatedQuery.filters ?? null
|
|
44
|
+
})) {
|
|
45
|
+
throw new errors.PayloadTooLargeError(EXPORT_TOO_LARGE_MESSAGE);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const { stream, nextCursor, until, isNewExport, partSize, exportToken } = await auditLogs.createExportStream(validatedQuery);
|
|
49
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
50
|
+
ctx.set('Content-Type', 'text/csv; charset=utf-8');
|
|
51
|
+
ctx.set('Content-Disposition', `attachment; filename="audit-logs-${date}.csv"`);
|
|
52
|
+
ctx.set(AUDIT_LOGS_EXPORT_UNTIL_HEADER, String(until));
|
|
53
|
+
ctx.set(AUDIT_LOGS_EXPORT_PART_SIZE_HEADER, String(partSize));
|
|
54
|
+
ctx.set(AUDIT_LOGS_EXPORT_TOKEN_HEADER, exportToken);
|
|
55
|
+
ctx.set(AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER, nextCursor !== null ? String(nextCursor) : AUDIT_LOGS_EXPORT_CURSOR_DONE);
|
|
56
|
+
const exposedHeaders = [
|
|
57
|
+
ctx.response.get('Access-Control-Expose-Headers'),
|
|
58
|
+
AUDIT_LOGS_EXPORT_UNTIL_HEADER,
|
|
59
|
+
AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,
|
|
60
|
+
AUDIT_LOGS_EXPORT_PART_SIZE_HEADER,
|
|
61
|
+
AUDIT_LOGS_EXPORT_TOKEN_HEADER,
|
|
62
|
+
'Content-Disposition'
|
|
63
|
+
].filter(Boolean).join(', ');
|
|
64
|
+
ctx.set('Access-Control-Expose-Headers', exposedHeaders);
|
|
65
|
+
ctx.vary('Accept-Encoding');
|
|
66
|
+
if (ctx.acceptsEncodings('gzip', 'identity') === 'gzip') {
|
|
67
|
+
ctx.set('Content-Encoding', 'gzip');
|
|
68
|
+
const gzip = createGzip();
|
|
69
|
+
stream.on('error', (error)=>gzip.destroy(error));
|
|
70
|
+
ctx.body = stream.pipe(gzip);
|
|
71
|
+
} else {
|
|
72
|
+
ctx.body = stream;
|
|
73
|
+
}
|
|
74
|
+
if (isNewExport) {
|
|
75
|
+
strapi.telemetry.send('didExportAuditLogs');
|
|
76
|
+
}
|
|
27
77
|
}
|
|
28
78
|
};
|
|
29
79
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logs.mjs","sources":["../../../../../../../ee/server/src/audit-logs/controllers/audit-logs.ts"],"sourcesContent":["import type { Context } from 'koa';\n\nimport { validateFindMany, validateFindManyUsers } from '../validation/audit-logs';\n\nexport default {\n async findMany(ctx: Context) {\n const { query } = ctx.request;\n await validateFindMany(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findMany(query);\n\n ctx.body = body;\n },\n\n async findManyUsers(ctx: Context) {\n const { query } = ctx.request;\n const { page, pageSize } = await validateFindManyUsers(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findManyUsers({ page, pageSize });\n\n ctx.body = body;\n },\n\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findOne(id);\n\n ctx.body = body;\n\n strapi.telemetry.send('didWatchAnAuditLog');\n },\n};\n"],"names":["findMany","ctx","query","request","validateFindMany","auditLogs","strapi","get","body","findManyUsers","page","pageSize","validateFindManyUsers","findOne","id","params","telemetry","send"],"mappings":"
|
|
1
|
+
{"version":3,"file":"audit-logs.mjs","sources":["../../../../../../../ee/server/src/audit-logs/controllers/audit-logs.ts"],"sourcesContent":["import { createGzip } from 'zlib';\n\nimport type { Context } from 'koa';\nimport { errors } from '@strapi/utils';\n\nimport {\n AUDIT_LOGS_EXPORT_CURSOR_DONE,\n AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,\n AUDIT_LOGS_EXPORT_PART_SIZE_HEADER,\n AUDIT_LOGS_EXPORT_TOKEN_HEADER,\n AUDIT_LOGS_EXPORT_UNTIL_HEADER,\n} from '../../../../../shared/utils/audit-log-export';\nimport { validateExport, validateFindMany, validateFindManyUsers } from '../validation/audit-logs';\n\nconst EXPORT_INVALID_CONTINUATION_MESSAGE =\n 'The export continuation is invalid or has expired. Restart the export.';\nconst EXPORT_TOO_LARGE_MESSAGE =\n 'The export matches more entries than the configured limit. Add filters to reduce it.';\n\nexport default {\n async findMany(ctx: Context) {\n const { query } = ctx.request;\n await validateFindMany(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findMany(query);\n\n ctx.body = body;\n },\n\n async findManyUsers(ctx: Context) {\n const { query } = ctx.request;\n const { page, pageSize } = await validateFindManyUsers(query);\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findManyUsers({ page, pageSize });\n\n ctx.body = body;\n },\n\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const auditLogs = strapi.get('audit-logs');\n const body = await auditLogs.findOne(id);\n\n ctx.body = body;\n\n strapi.telemetry.send('didWatchAnAuditLog');\n },\n\n async export(ctx: Context) {\n const { query } = ctx.request;\n const validatedQuery = await validateExport(query);\n\n const auditLogs = strapi.get('audit-logs');\n\n const isContinuation = validatedQuery.cursor !== undefined;\n\n if (isContinuation && !auditLogs.isTrustedContinuation(validatedQuery)) {\n throw new errors.ValidationError(EXPORT_INVALID_CONTINUATION_MESSAGE);\n }\n\n if (!isContinuation) {\n if (await auditLogs.isExportTooLarge({ filters: validatedQuery.filters ?? null })) {\n throw new errors.PayloadTooLargeError(EXPORT_TOO_LARGE_MESSAGE);\n }\n }\n\n const { stream, nextCursor, until, isNewExport, partSize, exportToken } =\n await auditLogs.createExportStream(validatedQuery);\n\n const date = new Date().toISOString().slice(0, 10);\n\n ctx.set('Content-Type', 'text/csv; charset=utf-8');\n ctx.set('Content-Disposition', `attachment; filename=\"audit-logs-${date}.csv\"`);\n ctx.set(AUDIT_LOGS_EXPORT_UNTIL_HEADER, String(until));\n ctx.set(AUDIT_LOGS_EXPORT_PART_SIZE_HEADER, String(partSize));\n ctx.set(AUDIT_LOGS_EXPORT_TOKEN_HEADER, exportToken);\n ctx.set(\n AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,\n nextCursor !== null ? String(nextCursor) : AUDIT_LOGS_EXPORT_CURSOR_DONE\n );\n\n const exposedHeaders = [\n ctx.response.get('Access-Control-Expose-Headers'),\n AUDIT_LOGS_EXPORT_UNTIL_HEADER,\n AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER,\n AUDIT_LOGS_EXPORT_PART_SIZE_HEADER,\n AUDIT_LOGS_EXPORT_TOKEN_HEADER,\n 'Content-Disposition',\n ]\n .filter(Boolean)\n .join(', ');\n ctx.set('Access-Control-Expose-Headers', exposedHeaders);\n\n ctx.vary('Accept-Encoding');\n if (ctx.acceptsEncodings('gzip', 'identity') === 'gzip') {\n ctx.set('Content-Encoding', 'gzip');\n const gzip = createGzip();\n stream.on('error', (error: Error) => gzip.destroy(error));\n ctx.body = stream.pipe(gzip);\n } else {\n ctx.body = stream;\n }\n\n if (isNewExport) {\n strapi.telemetry.send('didExportAuditLogs');\n }\n },\n};\n"],"names":["EXPORT_INVALID_CONTINUATION_MESSAGE","EXPORT_TOO_LARGE_MESSAGE","findMany","ctx","query","request","validateFindMany","auditLogs","strapi","get","body","findManyUsers","page","pageSize","validateFindManyUsers","findOne","id","params","telemetry","send","export","validatedQuery","validateExport","isContinuation","cursor","undefined","isTrustedContinuation","errors","ValidationError","isExportTooLarge","filters","PayloadTooLargeError","stream","nextCursor","until","isNewExport","partSize","exportToken","createExportStream","date","Date","toISOString","slice","set","AUDIT_LOGS_EXPORT_UNTIL_HEADER","String","AUDIT_LOGS_EXPORT_PART_SIZE_HEADER","AUDIT_LOGS_EXPORT_TOKEN_HEADER","AUDIT_LOGS_EXPORT_NEXT_CURSOR_HEADER","AUDIT_LOGS_EXPORT_CURSOR_DONE","exposedHeaders","response","filter","Boolean","join","vary","acceptsEncodings","gzip","createGzip","on","error","destroy","pipe"],"mappings":";;;;;AAcA,MAAMA,mCAAAA,GACJ,wEAAA;AACF,MAAMC,wBAAAA,GACJ,sFAAA;AAEF,0BAAe;AACb,IAAA,MAAMC,UAASC,GAAY,EAAA;AACzB,QAAA,MAAM,EAAEC,KAAK,EAAE,GAAGD,IAAIE,OAAO;AAC7B,QAAA,MAAMC,gBAAAA,CAAiBF,KAAAA,CAAAA;QAEvB,MAAMG,SAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAAC,YAAA,CAAA;AAC7B,QAAA,MAAMC,IAAAA,GAAO,MAAMH,SAAAA,CAAUL,QAAQ,CAACE,KAAAA,CAAAA;AAEtCD,QAAAA,GAAAA,CAAIO,IAAI,GAAGA,IAAAA;AACb,IAAA,CAAA;AAEA,IAAA,MAAMC,eAAcR,GAAY,EAAA;AAC9B,QAAA,MAAM,EAAEC,KAAK,EAAE,GAAGD,IAAIE,OAAO;AAC7B,QAAA,MAAM,EAAEO,IAAI,EAAEC,QAAQ,EAAE,GAAG,MAAMC,qBAAAA,CAAsBV,KAAAA,CAAAA;QAEvD,MAAMG,SAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAAC,YAAA,CAAA;AAC7B,QAAA,MAAMC,IAAAA,GAAO,MAAMH,SAAAA,CAAUI,aAAa,CAAC;AAAEC,YAAAA,IAAAA;AAAMC,YAAAA;AAAS,SAAA,CAAA;AAE5DV,QAAAA,GAAAA,CAAIO,IAAI,GAAGA,IAAAA;AACb,IAAA,CAAA;AAEA,IAAA,MAAMK,SAAQZ,GAAY,EAAA;AACxB,QAAA,MAAM,EAAEa,EAAE,EAAE,GAAGb,IAAIc,MAAM;QAEzB,MAAMV,SAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAAC,YAAA,CAAA;AAC7B,QAAA,MAAMC,IAAAA,GAAO,MAAMH,SAAAA,CAAUQ,OAAO,CAACC,EAAAA,CAAAA;AAErCb,QAAAA,GAAAA,CAAIO,IAAI,GAAGA,IAAAA;QAEXF,MAAAA,CAAOU,SAAS,CAACC,IAAI,CAAC,oBAAA,CAAA;AACxB,IAAA,CAAA;AAEA,IAAA,MAAMC,QAAOjB,GAAY,EAAA;AACvB,QAAA,MAAM,EAAEC,KAAK,EAAE,GAAGD,IAAIE,OAAO;QAC7B,MAAMgB,cAAAA,GAAiB,MAAMC,cAAAA,CAAelB,KAAAA,CAAAA;QAE5C,MAAMG,SAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAAC,YAAA,CAAA;QAE7B,MAAMc,cAAAA,GAAiBF,cAAAA,CAAeG,MAAM,KAAKC,SAAAA;AAEjD,QAAA,IAAIF,cAAAA,IAAkB,CAAChB,SAAAA,CAAUmB,qBAAqB,CAACL,cAAAA,CAAAA,EAAiB;YACtE,MAAM,IAAIM,MAAAA,CAAOC,eAAe,CAAC5B,mCAAAA,CAAAA;AACnC,QAAA;AAEA,QAAA,IAAI,CAACuB,cAAAA,EAAgB;YACnB,IAAI,MAAMhB,SAAAA,CAAUsB,gBAAgB,CAAC;gBAAEC,OAAAA,EAAST,cAAAA,CAAeS,OAAO,IAAI;aAAK,CAAA,EAAI;gBACjF,MAAM,IAAIH,MAAAA,CAAOI,oBAAoB,CAAC9B,wBAAAA,CAAAA;AACxC,YAAA;AACF,QAAA;AAEA,QAAA,MAAM,EAAE+B,MAAM,EAAEC,UAAU,EAAEC,KAAK,EAAEC,WAAW,EAAEC,QAAQ,EAAEC,WAAW,EAAE,GACrE,MAAM9B,SAAAA,CAAU+B,kBAAkB,CAACjB,cAAAA,CAAAA;AAErC,QAAA,MAAMkB,OAAO,IAAIC,IAAAA,EAAAA,CAAOC,WAAW,EAAA,CAAGC,KAAK,CAAC,CAAA,EAAG,EAAA,CAAA;QAE/CvC,GAAAA,CAAIwC,GAAG,CAAC,cAAA,EAAgB,yBAAA,CAAA;QACxBxC,GAAAA,CAAIwC,GAAG,CAAC,qBAAA,EAAuB,CAAC,iCAAiC,EAAEJ,IAAAA,CAAK,KAAK,CAAC,CAAA;QAC9EpC,GAAAA,CAAIwC,GAAG,CAACC,8BAAAA,EAAgCC,MAAAA,CAAOX,KAAAA,CAAAA,CAAAA;QAC/C/B,GAAAA,CAAIwC,GAAG,CAACG,kCAAAA,EAAoCD,MAAAA,CAAOT,QAAAA,CAAAA,CAAAA;QACnDjC,GAAAA,CAAIwC,GAAG,CAACI,8BAAAA,EAAgCV,WAAAA,CAAAA;AACxClC,QAAAA,GAAAA,CAAIwC,GAAG,CACLK,oCAAAA,EACAf,UAAAA,KAAe,IAAA,GAAOY,OAAOZ,UAAAA,CAAAA,GAAcgB,6BAAAA,CAAAA;AAG7C,QAAA,MAAMC,cAAAA,GAAiB;YACrB/C,GAAAA,CAAIgD,QAAQ,CAAC1C,GAAG,CAAC,+BAAA,CAAA;AACjBmC,YAAAA,8BAAAA;AACAI,YAAAA,oCAAAA;AACAF,YAAAA,kCAAAA;AACAC,YAAAA,8BAAAA;AACA,YAAA;AACD,SAAA,CACEK,MAAM,CAACC,OAAAA,CAAAA,CACPC,IAAI,CAAC,IAAA,CAAA;QACRnD,GAAAA,CAAIwC,GAAG,CAAC,+BAAA,EAAiCO,cAAAA,CAAAA;AAEzC/C,QAAAA,GAAAA,CAAIoD,IAAI,CAAC,iBAAA,CAAA;AACT,QAAA,IAAIpD,GAAAA,CAAIqD,gBAAgB,CAAC,MAAA,EAAQ,gBAAgB,MAAA,EAAQ;YACvDrD,GAAAA,CAAIwC,GAAG,CAAC,kBAAA,EAAoB,MAAA,CAAA;AAC5B,YAAA,MAAMc,IAAAA,GAAOC,UAAAA,EAAAA;AACb1B,YAAAA,MAAAA,CAAO2B,EAAE,CAAC,OAAA,EAAS,CAACC,KAAAA,GAAiBH,IAAAA,CAAKI,OAAO,CAACD,KAAAA,CAAAA,CAAAA;AAClDzD,YAAAA,GAAAA,CAAIO,IAAI,GAAGsB,MAAAA,CAAO8B,IAAI,CAACL,IAAAA,CAAAA;QACzB,CAAA,MAAO;AACLtD,YAAAA,GAAAA,CAAIO,IAAI,GAAGsB,MAAAA;AACb,QAAA;AAEA,QAAA,IAAIG,WAAAA,EAAa;YACf3B,MAAAA,CAAOU,SAAS,CAACC,IAAI,CAAC,oBAAA,CAAA;AACxB,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var utils = require('../../routes/utils.js');
|
|
4
4
|
|
|
5
|
-
const getRouteConfig = (
|
|
5
|
+
const getRouteConfig = (actions = [
|
|
6
|
+
'admin::audit-logs.read'
|
|
7
|
+
])=>({
|
|
6
8
|
middlewares: [
|
|
7
9
|
utils.enableFeatureMiddleware('audit-logs')
|
|
8
10
|
],
|
|
@@ -11,9 +13,7 @@ const getRouteConfig = ()=>({
|
|
|
11
13
|
{
|
|
12
14
|
name: 'admin::hasPermissions',
|
|
13
15
|
config: {
|
|
14
|
-
actions
|
|
15
|
-
'admin::audit-logs.read'
|
|
16
|
-
]
|
|
16
|
+
actions
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
]
|
|
@@ -33,6 +33,15 @@ var auditLogsRoutes = {
|
|
|
33
33
|
handler: 'audit-logs.findManyUsers',
|
|
34
34
|
config: getRouteConfig()
|
|
35
35
|
},
|
|
36
|
+
{
|
|
37
|
+
method: 'GET',
|
|
38
|
+
path: '/audit-logs/export',
|
|
39
|
+
handler: 'audit-logs.export',
|
|
40
|
+
config: getRouteConfig([
|
|
41
|
+
'admin::audit-logs.read',
|
|
42
|
+
'admin::audit-logs.export'
|
|
43
|
+
])
|
|
44
|
+
},
|
|
36
45
|
{
|
|
37
46
|
method: 'GET',
|
|
38
47
|
path: '/audit-logs/:id',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logs.js","sources":["../../../../../../../ee/server/src/audit-logs/routes/audit-logs.ts"],"sourcesContent":["import { enableFeatureMiddleware } from '../../routes/utils';\n\nconst getRouteConfig = () => ({\n middlewares: [enableFeatureMiddleware('audit-logs')],\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions
|
|
1
|
+
{"version":3,"file":"audit-logs.js","sources":["../../../../../../../ee/server/src/audit-logs/routes/audit-logs.ts"],"sourcesContent":["import { enableFeatureMiddleware } from '../../routes/utils';\n\nconst getRouteConfig = (actions: string[] = ['admin::audit-logs.read']) => ({\n middlewares: [enableFeatureMiddleware('audit-logs')],\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions,\n },\n },\n ],\n});\n\nexport default {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/audit-logs',\n handler: 'audit-logs.findMany',\n config: getRouteConfig(),\n },\n {\n method: 'GET',\n path: '/audit-logs/users',\n handler: 'audit-logs.findManyUsers',\n config: getRouteConfig(),\n },\n {\n method: 'GET',\n path: '/audit-logs/export',\n handler: 'audit-logs.export',\n config: getRouteConfig(['admin::audit-logs.read', 'admin::audit-logs.export']),\n },\n {\n method: 'GET',\n path: '/audit-logs/:id',\n handler: 'audit-logs.findOne',\n config: getRouteConfig(),\n },\n ],\n};\n"],"names":["getRouteConfig","actions","middlewares","enableFeatureMiddleware","policies","name","config","type","routes","method","path","handler"],"mappings":";;;;AAEA,MAAMA,cAAAA,GAAiB,CAACC,OAAAA,GAAoB;AAAC,IAAA;AAAyB,CAAA,IAAM;QAC1EC,WAAAA,EAAa;YAACC,6BAAAA,CAAwB,YAAA;AAAc,SAAA;QACpDC,QAAAA,EAAU;AACR,YAAA,6BAAA;AACA,YAAA;gBACEC,IAAAA,EAAM,uBAAA;gBACNC,MAAAA,EAAQ;AACNL,oBAAAA;AACF;AACF;AACD;KACH,CAAA;AAEA,sBAAe;IACbM,IAAAA,EAAM,OAAA;IACNC,MAAAA,EAAQ;AACN,QAAA;YACEC,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,aAAA;YACNC,OAAAA,EAAS,qBAAA;YACTL,MAAAA,EAAQN,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,mBAAA;YACNC,OAAAA,EAAS,0BAAA;YACTL,MAAAA,EAAQN,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,oBAAA;YACNC,OAAAA,EAAS,mBAAA;AACTL,YAAAA,MAAAA,EAAQN,cAAAA,CAAe;AAAC,gBAAA,wBAAA;AAA0B,gBAAA;AAA2B,aAAA;AAC/E,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,iBAAA;YACNC,OAAAA,EAAS,oBAAA;YACTL,MAAAA,EAAQN,cAAAA;AACV;AACD;AACH,CAAA;;;;"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { enableFeatureMiddleware } from '../../routes/utils.mjs';
|
|
2
2
|
|
|
3
|
-
const getRouteConfig = (
|
|
3
|
+
const getRouteConfig = (actions = [
|
|
4
|
+
'admin::audit-logs.read'
|
|
5
|
+
])=>({
|
|
4
6
|
middlewares: [
|
|
5
7
|
enableFeatureMiddleware('audit-logs')
|
|
6
8
|
],
|
|
@@ -9,9 +11,7 @@ const getRouteConfig = ()=>({
|
|
|
9
11
|
{
|
|
10
12
|
name: 'admin::hasPermissions',
|
|
11
13
|
config: {
|
|
12
|
-
actions
|
|
13
|
-
'admin::audit-logs.read'
|
|
14
|
-
]
|
|
14
|
+
actions
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
]
|
|
@@ -31,6 +31,15 @@ var auditLogsRoutes = {
|
|
|
31
31
|
handler: 'audit-logs.findManyUsers',
|
|
32
32
|
config: getRouteConfig()
|
|
33
33
|
},
|
|
34
|
+
{
|
|
35
|
+
method: 'GET',
|
|
36
|
+
path: '/audit-logs/export',
|
|
37
|
+
handler: 'audit-logs.export',
|
|
38
|
+
config: getRouteConfig([
|
|
39
|
+
'admin::audit-logs.read',
|
|
40
|
+
'admin::audit-logs.export'
|
|
41
|
+
])
|
|
42
|
+
},
|
|
34
43
|
{
|
|
35
44
|
method: 'GET',
|
|
36
45
|
path: '/audit-logs/:id',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logs.mjs","sources":["../../../../../../../ee/server/src/audit-logs/routes/audit-logs.ts"],"sourcesContent":["import { enableFeatureMiddleware } from '../../routes/utils';\n\nconst getRouteConfig = () => ({\n middlewares: [enableFeatureMiddleware('audit-logs')],\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions
|
|
1
|
+
{"version":3,"file":"audit-logs.mjs","sources":["../../../../../../../ee/server/src/audit-logs/routes/audit-logs.ts"],"sourcesContent":["import { enableFeatureMiddleware } from '../../routes/utils';\n\nconst getRouteConfig = (actions: string[] = ['admin::audit-logs.read']) => ({\n middlewares: [enableFeatureMiddleware('audit-logs')],\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions,\n },\n },\n ],\n});\n\nexport default {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/audit-logs',\n handler: 'audit-logs.findMany',\n config: getRouteConfig(),\n },\n {\n method: 'GET',\n path: '/audit-logs/users',\n handler: 'audit-logs.findManyUsers',\n config: getRouteConfig(),\n },\n {\n method: 'GET',\n path: '/audit-logs/export',\n handler: 'audit-logs.export',\n config: getRouteConfig(['admin::audit-logs.read', 'admin::audit-logs.export']),\n },\n {\n method: 'GET',\n path: '/audit-logs/:id',\n handler: 'audit-logs.findOne',\n config: getRouteConfig(),\n },\n ],\n};\n"],"names":["getRouteConfig","actions","middlewares","enableFeatureMiddleware","policies","name","config","type","routes","method","path","handler"],"mappings":";;AAEA,MAAMA,cAAAA,GAAiB,CAACC,OAAAA,GAAoB;AAAC,IAAA;AAAyB,CAAA,IAAM;QAC1EC,WAAAA,EAAa;YAACC,uBAAAA,CAAwB,YAAA;AAAc,SAAA;QACpDC,QAAAA,EAAU;AACR,YAAA,6BAAA;AACA,YAAA;gBACEC,IAAAA,EAAM,uBAAA;gBACNC,MAAAA,EAAQ;AACNL,oBAAAA;AACF;AACF;AACD;KACH,CAAA;AAEA,sBAAe;IACbM,IAAAA,EAAM,OAAA;IACNC,MAAAA,EAAQ;AACN,QAAA;YACEC,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,aAAA;YACNC,OAAAA,EAAS,qBAAA;YACTL,MAAAA,EAAQN,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,mBAAA;YACNC,OAAAA,EAAS,0BAAA;YACTL,MAAAA,EAAQN,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,oBAAA;YACNC,OAAAA,EAAS,mBAAA;AACTL,YAAAA,MAAAA,EAAQN,cAAAA,CAAe;AAAC,gBAAA,wBAAA;AAA0B,gBAAA;AAA2B,aAAA;AAC/E,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,iBAAA;YACNC,OAAAA,EAAS,oBAAA;YACTL,MAAAA,EAAQN,cAAAA;AACV;AACD;AACH,CAAA;;;;"}
|
|
@@ -1,18 +1,93 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var stream = require('stream');
|
|
4
|
+
var auditLogExport = require('../../../../../shared/utils/audit-log-export.js');
|
|
5
|
+
var utils = require('../utils.js');
|
|
6
|
+
var csv = require('../utils/csv.js');
|
|
7
|
+
var exportToken = require('../utils/export-token.js');
|
|
8
|
+
|
|
9
|
+
const EXPORT_CSV_COLUMNS = [
|
|
10
|
+
'id',
|
|
11
|
+
'action',
|
|
12
|
+
'date',
|
|
13
|
+
'user_id',
|
|
14
|
+
'user_email',
|
|
15
|
+
'user_display_name',
|
|
16
|
+
'origin',
|
|
17
|
+
'payload'
|
|
18
|
+
];
|
|
19
|
+
const EXPORT_USER_COLUMNS = [
|
|
20
|
+
'id',
|
|
21
|
+
'email',
|
|
22
|
+
'username',
|
|
23
|
+
'firstname',
|
|
24
|
+
'lastname'
|
|
25
|
+
];
|
|
26
|
+
const EXPORT_BATCH_SIZE = 5000;
|
|
3
27
|
const getSanitizedUser = (user)=>{
|
|
4
|
-
let displayName = user.email;
|
|
5
|
-
if (user.username) {
|
|
6
|
-
displayName = user.username;
|
|
7
|
-
} else if (user.firstname && user.lastname) {
|
|
8
|
-
displayName = `${user.firstname} ${user.lastname}`;
|
|
9
|
-
}
|
|
10
28
|
return {
|
|
11
29
|
id: user.id,
|
|
12
30
|
email: user.email,
|
|
13
|
-
displayName
|
|
31
|
+
displayName: utils.getDisplayName(user)
|
|
14
32
|
};
|
|
15
33
|
};
|
|
34
|
+
const serializeCsvPayload = (payload)=>{
|
|
35
|
+
if (payload === null || payload === undefined) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
39
|
+
};
|
|
40
|
+
const parseCsvPayload = (payload)=>{
|
|
41
|
+
if (typeof payload === 'string') {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(payload);
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return typeof payload === 'object' ? payload : null;
|
|
49
|
+
};
|
|
50
|
+
const getExportSecret = (strapi)=>{
|
|
51
|
+
const secret = strapi.config.get('admin.auth.secret');
|
|
52
|
+
if (typeof secret !== 'string' || secret.length === 0) {
|
|
53
|
+
throw new Error('The audit logs export requires admin.auth.secret to be set in config/admin.js.');
|
|
54
|
+
}
|
|
55
|
+
return secret;
|
|
56
|
+
};
|
|
57
|
+
const isTrustedExportContinuation = (strapi, query)=>{
|
|
58
|
+
return query.cursor !== undefined && query.until !== undefined && exportToken.verifyExportToken(getExportSecret(strapi), query.token, query.until, query.filters);
|
|
59
|
+
};
|
|
60
|
+
const buildExportWhere = (filtersWhere, untilId, afterId)=>({
|
|
61
|
+
$and: [
|
|
62
|
+
filtersWhere ?? {},
|
|
63
|
+
{
|
|
64
|
+
id: {
|
|
65
|
+
$lte: untilId
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
...afterId > 0 ? [
|
|
69
|
+
{
|
|
70
|
+
id: {
|
|
71
|
+
$gt: afterId
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
] : []
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
const toCsvLine = (row)=>{
|
|
78
|
+
const user = row.user ? getSanitizedUser(row.user) : null;
|
|
79
|
+
const { payload } = row;
|
|
80
|
+
return csv.serializeCsvLine([
|
|
81
|
+
row.id,
|
|
82
|
+
row.action,
|
|
83
|
+
row.date instanceof Date ? row.date.toISOString() : row.date,
|
|
84
|
+
user?.id ?? null,
|
|
85
|
+
user?.email ?? null,
|
|
86
|
+
user?.displayName ?? null,
|
|
87
|
+
parseCsvPayload(payload)?.origin ?? null,
|
|
88
|
+
serializeCsvPayload(payload)
|
|
89
|
+
]);
|
|
90
|
+
};
|
|
16
91
|
/**
|
|
17
92
|
* @description
|
|
18
93
|
* Manages audit logs interaction with the database. Accessible via strapi.get('audit-logs')
|
|
@@ -72,6 +147,124 @@ const getSanitizedUser = (user)=>{
|
|
|
72
147
|
pagination
|
|
73
148
|
};
|
|
74
149
|
},
|
|
150
|
+
async isExportTooLarge (query) {
|
|
151
|
+
const maxRows = strapi.config.get('admin.auditLogs.exportMaxRows', auditLogExport.AUDIT_LOGS_EXPORT_DEFAULT_MAX_ROWS);
|
|
152
|
+
const { where } = strapi.get('query-params').transform('admin::audit-log', {
|
|
153
|
+
filters: query.filters ?? undefined
|
|
154
|
+
});
|
|
155
|
+
const beyondCap = await strapi.db.query('admin::audit-log').findMany({
|
|
156
|
+
select: [
|
|
157
|
+
'id'
|
|
158
|
+
],
|
|
159
|
+
where: where ?? {},
|
|
160
|
+
orderBy: {
|
|
161
|
+
id: 'asc'
|
|
162
|
+
},
|
|
163
|
+
offset: maxRows,
|
|
164
|
+
limit: 1
|
|
165
|
+
});
|
|
166
|
+
return beyondCap.length > 0;
|
|
167
|
+
},
|
|
168
|
+
isTrustedContinuation (query) {
|
|
169
|
+
return isTrustedExportContinuation(strapi, query);
|
|
170
|
+
},
|
|
171
|
+
async createExportStream (query) {
|
|
172
|
+
getExportSecret(strapi);
|
|
173
|
+
const { cursor, pageSize, until, token, page: _page, sort: _sort, ...filtersQuery } = query;
|
|
174
|
+
const configuredPartSize = strapi.config.get('admin.auditLogs.exportPartRows', auditLogExport.AUDIT_LOGS_EXPORT_PART_ROWS);
|
|
175
|
+
const partSize = Math.max(1, Math.min(pageSize ?? configuredPartSize, auditLogExport.AUDIT_LOGS_EXPORT_PART_MAX_ROWS));
|
|
176
|
+
const { where: filtersWhere } = strapi.get('query-params').transform('admin::audit-log', filtersQuery);
|
|
177
|
+
const isNewExport = !isTrustedExportContinuation(strapi, query);
|
|
178
|
+
if (isNewExport) {
|
|
179
|
+
await strapi.eventHub.emit(auditLogExport.AUDIT_LOG_EXPORT_EVENT, {
|
|
180
|
+
filters: filtersQuery.filters ?? null
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
let frozenUntil = isNewExport ? undefined : until;
|
|
184
|
+
if (frozenUntil === undefined) {
|
|
185
|
+
const [lastRow] = await strapi.db.query('admin::audit-log').findMany({
|
|
186
|
+
select: [
|
|
187
|
+
'id'
|
|
188
|
+
],
|
|
189
|
+
orderBy: {
|
|
190
|
+
id: 'desc'
|
|
191
|
+
},
|
|
192
|
+
limit: 1
|
|
193
|
+
});
|
|
194
|
+
frozenUntil = lastRow?.id ?? 0;
|
|
195
|
+
}
|
|
196
|
+
const untilId = frozenUntil ?? 0;
|
|
197
|
+
const getWhere = (afterId)=>buildExportWhere(filtersWhere, untilId, afterId);
|
|
198
|
+
const boundary = await strapi.db.query('admin::audit-log').findMany({
|
|
199
|
+
select: [
|
|
200
|
+
'id'
|
|
201
|
+
],
|
|
202
|
+
where: getWhere(cursor ?? 0),
|
|
203
|
+
orderBy: {
|
|
204
|
+
id: 'asc'
|
|
205
|
+
},
|
|
206
|
+
offset: partSize - 1,
|
|
207
|
+
limit: 2
|
|
208
|
+
});
|
|
209
|
+
const nextCursor = boundary.length > 1 ? boundary[0].id : null;
|
|
210
|
+
const partUpperBound = nextCursor ?? untilId;
|
|
211
|
+
async function* csvChunks() {
|
|
212
|
+
if (isNewExport) {
|
|
213
|
+
yield csv.CSV_BOM + csv.serializeCsvLine(EXPORT_CSV_COLUMNS);
|
|
214
|
+
}
|
|
215
|
+
let lastId = cursor ?? 0;
|
|
216
|
+
let remaining = partSize;
|
|
217
|
+
while(remaining > 0){
|
|
218
|
+
const batchLimit = Math.min(EXPORT_BATCH_SIZE, remaining);
|
|
219
|
+
const rows = await strapi.db.query('admin::audit-log').findMany({
|
|
220
|
+
select: [
|
|
221
|
+
'id',
|
|
222
|
+
'action',
|
|
223
|
+
'date',
|
|
224
|
+
'payload'
|
|
225
|
+
],
|
|
226
|
+
populate: {
|
|
227
|
+
user: {
|
|
228
|
+
select: EXPORT_USER_COLUMNS
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
where: buildExportWhere(filtersWhere, partUpperBound, lastId),
|
|
232
|
+
orderBy: {
|
|
233
|
+
id: 'asc'
|
|
234
|
+
},
|
|
235
|
+
limit: batchLimit
|
|
236
|
+
});
|
|
237
|
+
if (rows.length === 0) {
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
yield rows.map(toCsvLine).join('');
|
|
241
|
+
lastId = rows[rows.length - 1].id;
|
|
242
|
+
remaining -= rows.length;
|
|
243
|
+
if (rows.length < batchLimit) {
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function* loggedCsvChunks() {
|
|
249
|
+
try {
|
|
250
|
+
yield* csvChunks();
|
|
251
|
+
} catch (error) {
|
|
252
|
+
strapi.log.error(`Audit logs export failed after the response started, the CSV part is truncated: ${error}`);
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
stream: stream.Readable.from(loggedCsvChunks(), {
|
|
258
|
+
objectMode: false,
|
|
259
|
+
highWaterMark: 64 * 1024
|
|
260
|
+
}),
|
|
261
|
+
nextCursor,
|
|
262
|
+
until: untilId,
|
|
263
|
+
isNewExport,
|
|
264
|
+
partSize,
|
|
265
|
+
exportToken: isNewExport ? exportToken.signExportToken(getExportSecret(strapi), untilId, filtersQuery.filters) : token
|
|
266
|
+
};
|
|
267
|
+
},
|
|
75
268
|
async findManyUsers (query) {
|
|
76
269
|
const { page = 1, pageSize = 10 } = query;
|
|
77
270
|
const userAttribute = strapi.db.metadata.get('admin::audit-log').attributes.user;
|
|
@@ -140,4 +333,5 @@ const getSanitizedUser = (user)=>{
|
|
|
140
333
|
};
|
|
141
334
|
|
|
142
335
|
exports.createAuditLogsService = createAuditLogsService;
|
|
336
|
+
exports.toCsvLine = toCsvLine;
|
|
143
337
|
//# sourceMappingURL=audit-logs.js.map
|