@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.
Files changed (132) hide show
  1. package/dist/admin/admin/src/components/Filters.js +9 -9
  2. package/dist/admin/admin/src/components/Filters.js.map +1 -1
  3. package/dist/admin/admin/src/components/Filters.mjs +10 -10
  4. package/dist/admin/admin/src/components/Filters.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/Pagination.js +2 -2
  6. package/dist/admin/admin/src/components/Pagination.js.map +1 -1
  7. package/dist/admin/admin/src/components/Pagination.mjs +3 -3
  8. package/dist/admin/admin/src/components/Pagination.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/SearchInput.js +7 -8
  10. package/dist/admin/admin/src/components/SearchInput.js.map +1 -1
  11. package/dist/admin/admin/src/components/SearchInput.mjs +8 -9
  12. package/dist/admin/admin/src/components/SearchInput.mjs.map +1 -1
  13. package/dist/admin/admin/src/components/Table.js +2 -2
  14. package/dist/admin/admin/src/components/Table.js.map +1 -1
  15. package/dist/admin/admin/src/components/Table.mjs +3 -3
  16. package/dist/admin/admin/src/components/Table.mjs.map +1 -1
  17. package/dist/admin/admin/src/hooks/useQueryParams.js +35 -1
  18. package/dist/admin/admin/src/hooks/useQueryParams.js.map +1 -1
  19. package/dist/admin/admin/src/hooks/useQueryParams.mjs +34 -2
  20. package/dist/admin/admin/src/hooks/useQueryParams.mjs.map +1 -1
  21. package/dist/admin/admin/src/translations/en.json.js +18 -0
  22. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  23. package/dist/admin/admin/src/translations/en.json.mjs +18 -0
  24. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  25. package/dist/admin/admin/src/utils/getFetchClient.js +118 -43
  26. package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
  27. package/dist/admin/admin/src/utils/getFetchClient.mjs +118 -45
  28. package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
  29. package/dist/admin/ee/admin/src/constants.js +6 -0
  30. package/dist/admin/ee/admin/src/constants.js.map +1 -1
  31. package/dist/admin/ee/admin/src/constants.mjs +6 -0
  32. package/dist/admin/ee/admin/src/constants.mjs.map +1 -1
  33. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js +40 -12
  34. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js.map +1 -1
  35. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs +43 -15
  36. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs.map +1 -1
  37. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.js +177 -0
  38. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.js.map +1 -0
  39. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.mjs +175 -0
  40. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.mjs.map +1 -0
  41. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.js +173 -0
  42. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.js.map +1 -0
  43. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.mjs +151 -0
  44. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.mjs.map +1 -0
  45. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +10 -1
  46. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
  47. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +10 -1
  48. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
  49. package/dist/admin/index.js +4 -0
  50. package/dist/admin/index.js.map +1 -1
  51. package/dist/admin/index.mjs +2 -2
  52. package/dist/admin/shared/utils/audit-log-export.js +16 -0
  53. package/dist/admin/shared/utils/audit-log-export.js.map +1 -0
  54. package/dist/admin/shared/utils/audit-log-export.mjs +9 -0
  55. package/dist/admin/shared/utils/audit-log-export.mjs.map +1 -0
  56. package/dist/admin/src/components/Filters.d.ts +1 -0
  57. package/dist/admin/src/hooks/useQueryParams.d.ts +13 -1
  58. package/dist/admin/src/index.d.ts +1 -1
  59. package/dist/admin/src/utils/getFetchClient.d.ts +9 -2
  60. package/dist/admin/tests/store.d.ts +4 -0
  61. package/dist/admin/tests/utils.d.ts +4 -0
  62. package/dist/ee/admin/src/constants.d.ts +4 -0
  63. package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/ExportCard.d.ts +10 -0
  64. package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useExportAuditLogs.d.ts +18 -0
  65. package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +9 -0
  66. package/dist/ee/server/src/audit-logs/controllers/audit-logs.d.ts +1 -0
  67. package/dist/ee/server/src/audit-logs/controllers/audit-logs.d.ts.map +1 -1
  68. package/dist/ee/server/src/audit-logs/routes/audit-logs.d.ts.map +1 -1
  69. package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts +24 -3
  70. package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts.map +1 -1
  71. package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +8 -2
  72. package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts.map +1 -1
  73. package/dist/ee/server/src/audit-logs/utils/csv.d.ts +5 -0
  74. package/dist/ee/server/src/audit-logs/utils/csv.d.ts.map +1 -0
  75. package/dist/ee/server/src/audit-logs/utils/export-token.d.ts +5 -0
  76. package/dist/ee/server/src/audit-logs/utils/export-token.d.ts.map +1 -0
  77. package/dist/ee/server/src/audit-logs/utils.d.ts +10 -0
  78. package/dist/ee/server/src/audit-logs/utils.d.ts.map +1 -0
  79. package/dist/ee/server/src/audit-logs/validation/audit-logs.d.ts +2 -0
  80. package/dist/ee/server/src/audit-logs/validation/audit-logs.d.ts.map +1 -1
  81. package/dist/ee/server/src/config/admin-actions.d.ts.map +1 -1
  82. package/dist/ee/server/src/index.d.ts +1 -0
  83. package/dist/ee/server/src/index.d.ts.map +1 -1
  84. package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.js +50 -0
  85. package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.js.map +1 -1
  86. package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.mjs +51 -1
  87. package/dist/server/ee/server/src/audit-logs/controllers/audit-logs.mjs.map +1 -1
  88. package/dist/server/ee/server/src/audit-logs/routes/audit-logs.js +13 -4
  89. package/dist/server/ee/server/src/audit-logs/routes/audit-logs.js.map +1 -1
  90. package/dist/server/ee/server/src/audit-logs/routes/audit-logs.mjs +13 -4
  91. package/dist/server/ee/server/src/audit-logs/routes/audit-logs.mjs.map +1 -1
  92. package/dist/server/ee/server/src/audit-logs/services/audit-logs.js +201 -7
  93. package/dist/server/ee/server/src/audit-logs/services/audit-logs.js.map +1 -1
  94. package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs +201 -8
  95. package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs.map +1 -1
  96. package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +119 -34
  97. package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
  98. package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +119 -34
  99. package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
  100. package/dist/server/ee/server/src/audit-logs/utils/csv.js +33 -0
  101. package/dist/server/ee/server/src/audit-logs/utils/csv.js.map +1 -0
  102. package/dist/server/ee/server/src/audit-logs/utils/csv.mjs +29 -0
  103. package/dist/server/ee/server/src/audit-logs/utils/csv.mjs.map +1 -0
  104. package/dist/server/ee/server/src/audit-logs/utils/export-token.js +33 -0
  105. package/dist/server/ee/server/src/audit-logs/utils/export-token.js.map +1 -0
  106. package/dist/server/ee/server/src/audit-logs/utils/export-token.mjs +29 -0
  107. package/dist/server/ee/server/src/audit-logs/utils/export-token.mjs.map +1 -0
  108. package/dist/server/ee/server/src/audit-logs/utils.js +14 -0
  109. package/dist/server/ee/server/src/audit-logs/utils.js.map +1 -0
  110. package/dist/server/ee/server/src/audit-logs/utils.mjs +12 -0
  111. package/dist/server/ee/server/src/audit-logs/utils.mjs.map +1 -0
  112. package/dist/server/ee/server/src/audit-logs/validation/audit-logs.js +11 -0
  113. package/dist/server/ee/server/src/audit-logs/validation/audit-logs.js.map +1 -1
  114. package/dist/server/ee/server/src/audit-logs/validation/audit-logs.mjs +11 -1
  115. package/dist/server/ee/server/src/audit-logs/validation/audit-logs.mjs.map +1 -1
  116. package/dist/server/ee/server/src/config/admin-actions.js +8 -0
  117. package/dist/server/ee/server/src/config/admin-actions.js.map +1 -1
  118. package/dist/server/ee/server/src/config/admin-actions.mjs +8 -0
  119. package/dist/server/ee/server/src/config/admin-actions.mjs.map +1 -1
  120. package/dist/server/ee/server/src/index.js +10 -0
  121. package/dist/server/ee/server/src/index.js.map +1 -1
  122. package/dist/server/ee/server/src/index.mjs +10 -0
  123. package/dist/server/ee/server/src/index.mjs.map +1 -1
  124. package/dist/server/shared/utils/audit-log-export.js +22 -0
  125. package/dist/server/shared/utils/audit-log-export.js.map +1 -0
  126. package/dist/server/shared/utils/audit-log-export.mjs +12 -0
  127. package/dist/server/shared/utils/audit-log-export.mjs.map +1 -0
  128. package/dist/shared/contracts/audit-logs.d.ts +15 -1
  129. package/dist/shared/contracts/audit-logs.d.ts.map +1 -1
  130. package/dist/shared/utils/audit-log-export.d.ts +9 -0
  131. package/dist/shared/utils/audit-log-export.d.ts.map +1 -0
  132. 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":"AAqBA,eAAO,MAAM,gBAAgB,wDAA+D,CAAC;AAC7F,eAAO,MAAM,qBAAqB,wDAEhC,CAAC;;;;;AAEH,wBAGE"}
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,wBA6BE"}
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;AAc1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4Be;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;wBAcxB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpD,CAAC;AAEF,eAAe,UAAU,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":";;;;AAIA,0BAAe;AACb,IAAA,MAAMA,UAASC,GAAY,EAAA;AACzB,QAAA,MAAM,EAAEC,KAAK,EAAE,GAAGD,IAAIE,OAAO;AAC7B,QAAA,MAAMC,0BAAAA,CAAiBF,KAAAA,CAAAA;QAEvB,MAAMG,WAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAAC,YAAA,CAAA;AAC7B,QAAA,MAAMC,IAAAA,GAAO,MAAMH,WAAAA,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,+BAAAA,CAAsBV,KAAAA,CAAAA;QAEvD,MAAMG,WAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAAC,YAAA,CAAA;AAC7B,QAAA,MAAMC,IAAAA,GAAO,MAAMH,WAAAA,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;AACF,CAAA;;;;"}
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 { validateFindManyUsers, validateFindMany } from '../validation/audit-logs.mjs';
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":";;AAIA,0BAAe;AACb,IAAA,MAAMA,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;AACF,CAAA;;;;"}
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: ['admin::audit-logs.read'],\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/:id',\n handler: 'audit-logs.findOne',\n config: getRouteConfig(),\n },\n ],\n};\n"],"names":["getRouteConfig","middlewares","enableFeatureMiddleware","policies","name","config","actions","type","routes","method","path","handler"],"mappings":";;;;AAEA,MAAMA,cAAAA,GAAiB,KAAO;QAC5BC,WAAAA,EAAa;YAACC,6BAAAA,CAAwB,YAAA;AAAc,SAAA;QACpDC,QAAAA,EAAU;AACR,YAAA,6BAAA;AACA,YAAA;gBACEC,IAAAA,EAAM,uBAAA;gBACNC,MAAAA,EAAQ;oBACNC,OAAAA,EAAS;AAAC,wBAAA;AAAyB;AACrC;AACF;AACD;KACH,CAAA;AAEA,sBAAe;IACbC,IAAAA,EAAM,OAAA;IACNC,MAAAA,EAAQ;AACN,QAAA;YACEC,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,aAAA;YACNC,OAAAA,EAAS,qBAAA;YACTN,MAAAA,EAAQL,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,mBAAA;YACNC,OAAAA,EAAS,0BAAA;YACTN,MAAAA,EAAQL,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,iBAAA;YACNC,OAAAA,EAAS,oBAAA;YACTN,MAAAA,EAAQL,cAAAA;AACV;AACD;AACH,CAAA;;;;"}
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: ['admin::audit-logs.read'],\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/:id',\n handler: 'audit-logs.findOne',\n config: getRouteConfig(),\n },\n ],\n};\n"],"names":["getRouteConfig","middlewares","enableFeatureMiddleware","policies","name","config","actions","type","routes","method","path","handler"],"mappings":";;AAEA,MAAMA,cAAAA,GAAiB,KAAO;QAC5BC,WAAAA,EAAa;YAACC,uBAAAA,CAAwB,YAAA;AAAc,SAAA;QACpDC,QAAAA,EAAU;AACR,YAAA,6BAAA;AACA,YAAA;gBACEC,IAAAA,EAAM,uBAAA;gBACNC,MAAAA,EAAQ;oBACNC,OAAAA,EAAS;AAAC,wBAAA;AAAyB;AACrC;AACF;AACD;KACH,CAAA;AAEA,sBAAe;IACbC,IAAAA,EAAM,OAAA;IACNC,MAAAA,EAAQ;AACN,QAAA;YACEC,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,aAAA;YACNC,OAAAA,EAAS,qBAAA;YACTN,MAAAA,EAAQL,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,mBAAA;YACNC,OAAAA,EAAS,0BAAA;YACTN,MAAAA,EAAQL,cAAAA;AACV,SAAA;AACA,QAAA;YACES,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,iBAAA;YACNC,OAAAA,EAAS,oBAAA;YACTN,MAAAA,EAAQL,cAAAA;AACV;AACD;AACH,CAAA;;;;"}
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