@webiny/api-audit-logs 6.4.5-beta.0 → 6.6.0-alpha.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 (93) hide show
  1. package/AuditLogsFeature.d.ts +8 -0
  2. package/AuditLogsFeature.js +43 -0
  3. package/AuditLogsFeature.js.map +1 -0
  4. package/abstractions.d.ts +8 -3
  5. package/abstractions.js +2 -1
  6. package/abstractions.js.map +1 -1
  7. package/context/AuditLogsContextValue.js +5 -3
  8. package/context/AuditLogsContextValue.js.map +1 -1
  9. package/graphql/AuditLogsGraphQLSchema.d.ts +9 -0
  10. package/graphql/AuditLogsGraphQLSchema.js +134 -0
  11. package/graphql/AuditLogsGraphQLSchema.js.map +1 -0
  12. package/index.d.ts +2 -8
  13. package/index.js +1 -25
  14. package/package.json +23 -23
  15. package/storage/types.d.ts +0 -35
  16. package/types.d.ts +1 -2
  17. package/utils/getAuditConfig.js +4 -2
  18. package/utils/getAuditConfig.js.map +1 -1
  19. package/context/index.d.ts +0 -9
  20. package/context/index.js +0 -31
  21. package/context/index.js.map +0 -1
  22. package/graphql/schema.d.ts +0 -3
  23. package/graphql/schema.js +0 -115
  24. package/graphql/schema.js.map +0 -1
  25. package/index.js.map +0 -1
  26. package/storage/AccessPatternHandler.d.ts +0 -14
  27. package/storage/AccessPatternHandler.js +0 -39
  28. package/storage/AccessPatternHandler.js.map +0 -1
  29. package/storage/Converter.d.ts +0 -16
  30. package/storage/Converter.js +0 -49
  31. package/storage/Converter.js.map +0 -1
  32. package/storage/Storage.d.ts +0 -18
  33. package/storage/Storage.js +0 -81
  34. package/storage/Storage.js.map +0 -1
  35. package/storage/abstractions/AccessPattern.d.ts +0 -24
  36. package/storage/abstractions/AccessPattern.js +0 -0
  37. package/storage/abstractions/AccessPatternHandler.d.ts +0 -13
  38. package/storage/abstractions/AccessPatternHandler.js +0 -0
  39. package/storage/abstractions/Converter.d.ts +0 -6
  40. package/storage/abstractions/Converter.js +0 -0
  41. package/storage/accessPatterns/AppAccessPattern.d.ts +0 -9
  42. package/storage/accessPatterns/AppAccessPattern.js +0 -35
  43. package/storage/accessPatterns/AppAccessPattern.js.map +0 -1
  44. package/storage/accessPatterns/AppCreatedByAccessPattern.d.ts +0 -9
  45. package/storage/accessPatterns/AppCreatedByAccessPattern.js +0 -38
  46. package/storage/accessPatterns/AppCreatedByAccessPattern.js.map +0 -1
  47. package/storage/accessPatterns/AppEntityAccessPattern.d.ts +0 -9
  48. package/storage/accessPatterns/AppEntityAccessPattern.js +0 -35
  49. package/storage/accessPatterns/AppEntityAccessPattern.js.map +0 -1
  50. package/storage/accessPatterns/AppEntityActionAccessPattern.d.ts +0 -9
  51. package/storage/accessPatterns/AppEntityActionAccessPattern.js +0 -35
  52. package/storage/accessPatterns/AppEntityActionAccessPattern.js.map +0 -1
  53. package/storage/accessPatterns/AppEntityActionCreatedByAccessPattern.d.ts +0 -9
  54. package/storage/accessPatterns/AppEntityActionCreatedByAccessPattern.js +0 -38
  55. package/storage/accessPatterns/AppEntityActionCreatedByAccessPattern.js.map +0 -1
  56. package/storage/accessPatterns/AppEntityCreatedByAccessPattern.d.ts +0 -9
  57. package/storage/accessPatterns/AppEntityCreatedByAccessPattern.js +0 -38
  58. package/storage/accessPatterns/AppEntityCreatedByAccessPattern.js.map +0 -1
  59. package/storage/accessPatterns/BaseAccessPattern.d.ts +0 -32
  60. package/storage/accessPatterns/BaseAccessPattern.js +0 -60
  61. package/storage/accessPatterns/BaseAccessPattern.js.map +0 -1
  62. package/storage/accessPatterns/CreatedByAccessPattern.d.ts +0 -9
  63. package/storage/accessPatterns/CreatedByAccessPattern.js +0 -38
  64. package/storage/accessPatterns/CreatedByAccessPattern.js.map +0 -1
  65. package/storage/accessPatterns/CreatedOnAccessPattern.d.ts +0 -9
  66. package/storage/accessPatterns/CreatedOnAccessPattern.js +0 -38
  67. package/storage/accessPatterns/CreatedOnAccessPattern.js.map +0 -1
  68. package/storage/accessPatterns/DefaultAccessPattern.d.ts +0 -15
  69. package/storage/accessPatterns/DefaultAccessPattern.js +0 -35
  70. package/storage/accessPatterns/DefaultAccessPattern.js.map +0 -1
  71. package/storage/accessPatterns/EntityIdAccessPattern.d.ts +0 -9
  72. package/storage/accessPatterns/EntityIdAccessPattern.js +0 -38
  73. package/storage/accessPatterns/EntityIdAccessPattern.js.map +0 -1
  74. package/storage/accessPatterns/index.d.ts +0 -6
  75. package/storage/accessPatterns/index.js +0 -57
  76. package/storage/accessPatterns/index.js.map +0 -1
  77. package/storage/cursorSchema.d.ts +0 -4
  78. package/storage/cursorSchema.js +0 -22
  79. package/storage/cursorSchema.js.map +0 -1
  80. package/storage/entity.d.ts +0 -36
  81. package/storage/entity.js +0 -120
  82. package/storage/entity.js.map +0 -1
  83. package/storage/results/ListErrorResult.d.ts +0 -10
  84. package/storage/results/ListErrorResult.js +0 -12
  85. package/storage/results/ListErrorResult.js.map +0 -1
  86. package/storage/results/ListSuccessResult.d.ts +0 -14
  87. package/storage/results/ListSuccessResult.js +0 -17
  88. package/storage/results/ListSuccessResult.js.map +0 -1
  89. package/storage/results/index.d.ts +0 -2
  90. package/storage/results/index.js +0 -2
  91. package/storage/startKey.d.ts +0 -6
  92. package/storage/startKey.js +0 -8
  93. package/storage/startKey.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ import { type Container } from "@webiny/feature/api";
2
+ export interface AuditLogsFeatureConfig {
3
+ deleteLogsAfterDays?: number;
4
+ }
5
+ export declare const AuditLogsFeature: {
6
+ name: string;
7
+ register(container: Container, context?: AuditLogsFeatureConfig | undefined): void;
8
+ };
@@ -0,0 +1,43 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { GraphQLContextualSchema } from "@webiny/api-graphql";
3
+ import { makeExecutableSchema } from "@graphql-tools/schema";
4
+ import { EventPublisher } from "@webiny/api-core/features/eventPublisher/index.js";
5
+ import { WcpContext } from "@webiny/api-core/features/wcp/WcpContext/abstractions.js";
6
+ import { AuditLogsContext, AuditLogsStorage } from "./abstractions.js";
7
+ import { createAuditLogsContextValue } from "./context/AuditLogsContextValue.js";
8
+ import { createSubscriptionHooks } from "./subscriptions/index.js";
9
+ import { AuditLogsGraphQLSchema } from "./graphql/AuditLogsGraphQLSchema.js";
10
+ const getDeleteLogsAfterDays = (days)=>days && days > 0 ? days : 60;
11
+ const AuditLogsFeature = createFeature({
12
+ name: "AuditLogs",
13
+ register (container, config = {}) {
14
+ container.register(AuditLogsGraphQLSchema);
15
+ let initialized = false;
16
+ const STUB_SCHEMA = makeExecutableSchema({
17
+ typeDefs: "type Query\ntype Mutation",
18
+ assumeValidSDL: true
19
+ });
20
+ container.registerInstance(GraphQLContextualSchema, {
21
+ async build (ctx) {
22
+ if (initialized) return STUB_SCHEMA;
23
+ initialized = true;
24
+ const wcpContext = container.resolve(WcpContext);
25
+ if (!wcpContext.canUseFeature("auditLogs")) return STUB_SCHEMA;
26
+ const storage = container.resolve(AuditLogsStorage);
27
+ const eventPublisher = container.resolve(EventPublisher);
28
+ ctx.auditLogs = createAuditLogsContextValue({
29
+ getContext: ()=>ctx,
30
+ deleteLogsAfterDays: getDeleteLogsAfterDays(config.deleteLogsAfterDays),
31
+ storage,
32
+ eventPublisher
33
+ });
34
+ container.registerInstance(AuditLogsContext, ctx.auditLogs);
35
+ createSubscriptionHooks(ctx);
36
+ return STUB_SCHEMA;
37
+ }
38
+ });
39
+ }
40
+ });
41
+ export { AuditLogsFeature };
42
+
43
+ //# sourceMappingURL=AuditLogsFeature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogsFeature.js","sources":["../src/AuditLogsFeature.ts"],"sourcesContent":["import { createFeature, type Container } from \"@webiny/feature/api\";\nimport { GraphQLContextualSchema } from \"@webiny/api-graphql\";\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport { EventPublisher } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport { WcpContext } from \"@webiny/api-core/features/wcp/WcpContext/abstractions.js\";\nimport { AuditLogsContext, AuditLogsStorage } from \"./abstractions.js\";\nimport type { GraphQLSchema } from \"graphql\";\nimport { createAuditLogsContextValue } from \"./context/AuditLogsContextValue.js\";\nimport { createSubscriptionHooks } from \"./subscriptions/index.js\";\nimport { AuditLogsGraphQLSchema } from \"./graphql/AuditLogsGraphQLSchema.js\";\n\nexport interface AuditLogsFeatureConfig {\n deleteLogsAfterDays?: number;\n}\n\nconst getDeleteLogsAfterDays = (days?: number): number => {\n return days && days > 0 ? days : 60;\n};\n\nexport const AuditLogsFeature = createFeature({\n name: \"AuditLogs\",\n register(container: Container, config: AuditLogsFeatureConfig = {}) {\n container.register(AuditLogsGraphQLSchema);\n\n let initialized = false;\n\n const STUB_SCHEMA: GraphQLSchema = makeExecutableSchema({\n typeDefs: \"type Query\\ntype Mutation\",\n assumeValidSDL: true\n });\n\n container.registerInstance(GraphQLContextualSchema, {\n async build(ctx: Record<string, any>): Promise<GraphQLSchema> {\n if (initialized) {\n return STUB_SCHEMA;\n }\n initialized = true;\n\n const wcpContext = container.resolve(WcpContext);\n if (!wcpContext.canUseFeature(\"auditLogs\")) {\n return STUB_SCHEMA;\n }\n\n const storage = container.resolve(AuditLogsStorage);\n const eventPublisher = container.resolve(EventPublisher);\n\n ctx.auditLogs = createAuditLogsContextValue({\n getContext: () => ctx as any,\n deleteLogsAfterDays: getDeleteLogsAfterDays(config.deleteLogsAfterDays),\n storage,\n eventPublisher\n });\n\n container.registerInstance(AuditLogsContext, ctx.auditLogs);\n createSubscriptionHooks(ctx as any);\n\n return STUB_SCHEMA;\n }\n });\n }\n});\n"],"names":["getDeleteLogsAfterDays","days","AuditLogsFeature","createFeature","container","config","AuditLogsGraphQLSchema","initialized","STUB_SCHEMA","makeExecutableSchema","GraphQLContextualSchema","ctx","wcpContext","WcpContext","storage","AuditLogsStorage","eventPublisher","EventPublisher","createAuditLogsContextValue","AuditLogsContext","createSubscriptionHooks"],"mappings":";;;;;;;;;AAeA,MAAMA,yBAAyB,CAACC,OACrBA,QAAQA,OAAO,IAAIA,OAAO;AAG9B,MAAMC,mBAAmBC,cAAc;IAC1C,MAAM;IACN,UAASC,SAAoB,EAAEC,SAAiC,CAAC,CAAC;QAC9DD,UAAU,QAAQ,CAACE;QAEnB,IAAIC,cAAc;QAElB,MAAMC,cAA6BC,qBAAqB;YACpD,UAAU;YACV,gBAAgB;QACpB;QAEAL,UAAU,gBAAgB,CAACM,yBAAyB;YAChD,MAAM,OAAMC,GAAwB;gBAChC,IAAIJ,aACA,OAAOC;gBAEXD,cAAc;gBAEd,MAAMK,aAAaR,UAAU,OAAO,CAACS;gBACrC,IAAI,CAACD,WAAW,aAAa,CAAC,cAC1B,OAAOJ;gBAGX,MAAMM,UAAUV,UAAU,OAAO,CAACW;gBAClC,MAAMC,iBAAiBZ,UAAU,OAAO,CAACa;gBAEzCN,IAAI,SAAS,GAAGO,4BAA4B;oBACxC,YAAY,IAAMP;oBAClB,qBAAqBX,uBAAuBK,OAAO,mBAAmB;oBACtES;oBACAE;gBACJ;gBAEAZ,UAAU,gBAAgB,CAACe,kBAAkBR,IAAI,SAAS;gBAC1DS,wBAAwBT;gBAExB,OAAOH;YACX;QACJ;IACJ;AACJ"}
package/abstractions.d.ts CHANGED
@@ -1,5 +1,10 @@
1
- import type { AuditLogsContext as Context } from "./types.js";
2
- export declare const AuditLogsContext: import("@webiny/di").Abstraction<Context>;
1
+ import type { AuditLogsContext as IAuditLogsContext } from "./types.js";
2
+ import type { IStorage } from "./storage/abstractions/Storage.js";
3
+ export declare const AuditLogsContext: import("@webiny/di").Abstraction<IAuditLogsContext>;
3
4
  export declare namespace AuditLogsContext {
4
- type Interface = Context;
5
+ type Interface = IAuditLogsContext;
6
+ }
7
+ export declare const AuditLogsStorage: import("@webiny/di").Abstraction<IStorage>;
8
+ export declare namespace AuditLogsStorage {
9
+ type Interface = IStorage;
5
10
  }
package/abstractions.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createAbstraction } from "@webiny/feature/api";
2
2
  const AuditLogsContext = createAbstraction("AuditLogsContext");
3
- export { AuditLogsContext };
3
+ const AuditLogsStorage = createAbstraction("AuditLogsStorage");
4
+ export { AuditLogsContext, AuditLogsStorage };
4
5
 
5
6
  //# sourceMappingURL=abstractions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"abstractions.js","sources":["../src/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { AuditLogsContext as Context } from \"~/types.js\";\n\n// TODO: this is a bridge for legacy context; needs review and refactor of code that uses it.\n\nexport const AuditLogsContext = createAbstraction<Context>(\"AuditLogsContext\");\n\nexport namespace AuditLogsContext {\n export type Interface = Context;\n}\n"],"names":["AuditLogsContext","createAbstraction"],"mappings":";AAKO,MAAMA,mBAAmBC,kBAA2B"}
1
+ {"version":3,"file":"abstractions.js","sources":["../src/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { AuditLogsContext as IAuditLogsContext } from \"~/types.js\";\nimport type { IStorage } from \"~/storage/abstractions/Storage.js\";\n\n// NOTE: this token is registered with (and used as) the full audit-logs request context —\n// handlers resolve it for `.container` and pass it to getAuditConfig. The interface must\n// therefore be the context, not the AuditLogsContextValue facade. The proper fix (drop the\n// whole-context injection in favour of an `AuditLogs` facade token + removing context.auditLogs)\n// is the context-removal migration, tracked separately.\nexport const AuditLogsContext = createAbstraction<IAuditLogsContext>(\"AuditLogsContext\");\n\nexport namespace AuditLogsContext {\n export type Interface = IAuditLogsContext;\n}\n\nexport const AuditLogsStorage = createAbstraction<IStorage>(\"AuditLogsStorage\");\n\nexport namespace AuditLogsStorage {\n export type Interface = IStorage;\n}\n"],"names":["AuditLogsContext","createAbstraction","AuditLogsStorage"],"mappings":";AASO,MAAMA,mBAAmBC,kBAAqC;AAM9D,MAAMC,mBAAmBD,kBAA4B"}
@@ -1,6 +1,8 @@
1
1
  import { convertExpiresAtDaysToDate } from "../utils/expiresAt.js";
2
2
  import { mdbid } from "@webiny/utils/mdbid.js";
3
3
  import { NotAuthorizedError } from "@webiny/api-core/features/security/shared/index.js";
4
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
5
+ import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
4
6
  import { AuditLogAfterCreateEvent, AuditLogAfterUpdateEvent, AuditLogBeforeCreateEvent, AuditLogBeforeUpdateEvent } from "../events/index.js";
5
7
  class AuditLogsContextValueImpl {
6
8
  constructor(params){
@@ -101,7 +103,7 @@ class AuditLogsContextValueImpl {
101
103
  }
102
104
  async checkPermissions(auditLog) {
103
105
  if (!auditLog.action) throw new Error("Audit log action is not defined. Cannot check permissions.");
104
- const permissions = await this.getContext().security.getPermissions("al.*");
106
+ const permissions = await this.getContext().container.resolve(IdentityContext).getPermissions("al.*");
105
107
  for (const permission of permissions){
106
108
  if ("*" === permission.name) return;
107
109
  if ("al.*" === permission.name) return;
@@ -112,10 +114,10 @@ class AuditLogsContextValueImpl {
112
114
  });
113
115
  }
114
116
  getTenantId() {
115
- return this.getContext().tenancy.getCurrentTenant().id;
117
+ return this.getContext().container.resolve(TenantContext).getTenant().id;
116
118
  }
117
119
  getIdentity() {
118
- const identity = this.getContext().security.getIdentity();
120
+ const identity = this.getContext().container.resolve(IdentityContext).getIdentity();
119
121
  return {
120
122
  id: identity.id,
121
123
  type: identity.type,
@@ -1 +1 @@
1
- {"version":3,"file":"context/AuditLogsContextValue.js","sources":["../../src/context/AuditLogsContextValue.ts"],"sourcesContent":["import type {\n AuditLogPayload,\n AuditLogsContext,\n AuditLogsContextValue,\n IListAuditLogsParams,\n IListAuditLogsResult\n} from \"~/types.js\";\nimport { convertExpiresAtDaysToDate } from \"~/utils/expiresAt.js\";\nimport type { IAuditLog, IAuditLogCreatedBy } from \"~/storage/types.js\";\nimport { mdbid } from \"@webiny/utils/mdbid.js\";\nimport type { IStorage, IStorageListParams } from \"~/storage/abstractions/Storage.js\";\nimport { NotAuthorizedError } from \"@webiny/api-core/features/security/shared/index.js\";\nimport type { EventPublisher } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport {\n AuditLogBeforeCreateEvent,\n AuditLogAfterCreateEvent,\n AuditLogBeforeUpdateEvent,\n AuditLogAfterUpdateEvent\n} from \"~/events/index.js\";\n\nexport interface IAuditLogsContextValueParams {\n getContext: () => AuditLogsContext;\n deleteLogsAfterDays: number;\n storage: IStorage;\n eventPublisher: EventPublisher.Interface;\n}\n\nclass AuditLogsContextValueImpl implements AuditLogsContextValue {\n private readonly getContext;\n public readonly deleteLogsAfterDays;\n private readonly storage: IStorage;\n private readonly eventPublisher: EventPublisher.Interface;\n\n public constructor(params: IAuditLogsContextValueParams) {\n this.getContext = params.getContext;\n this.deleteLogsAfterDays = params.deleteLogsAfterDays;\n this.storage = params.storage;\n this.eventPublisher = params.eventPublisher;\n }\n\n public async createAuditLog(payload: AuditLogPayload): Promise<IAuditLog> {\n const context = this.getContext();\n const expiresAt = convertExpiresAtDaysToDate(this.deleteLogsAfterDays);\n\n const auditLog: IAuditLog = {\n id: mdbid(),\n tenant: this.getTenantId(),\n createdBy: this.getIdentity(),\n createdOn: new Date(),\n ...payload,\n content: JSON.stringify(payload.content),\n expiresAt\n };\n await this.checkPermissions(auditLog);\n\n const beforeCreateEvent = new AuditLogBeforeCreateEvent({\n auditLog: auditLog,\n context,\n setAuditLog(input) {\n Object.assign(auditLog, input);\n }\n });\n await this.eventPublisher.publish(beforeCreateEvent);\n\n const result = await this.storage.store({\n data: auditLog\n });\n if (result.success) {\n const afterCreateEvent = new AuditLogAfterCreateEvent({\n auditLog: auditLog,\n context\n });\n await this.eventPublisher.publish(afterCreateEvent);\n return result.data;\n }\n throw result.error;\n }\n\n public async updateAuditLog(\n original: IAuditLog,\n payload: Partial<AuditLogPayload>\n ): Promise<IAuditLog> {\n const context = this.getContext();\n const auditLog: IAuditLog = {\n ...original,\n ...payload,\n content: payload.content ? JSON.stringify(payload.content) : original.content\n };\n await this.checkPermissions(auditLog);\n\n const beforeUpdateEvent = new AuditLogBeforeUpdateEvent({\n original,\n auditLog,\n context,\n setAuditLog(input) {\n Object.assign(auditLog, input);\n }\n });\n await this.eventPublisher.publish(beforeUpdateEvent);\n\n const result = await this.storage.store({\n data: auditLog\n });\n if (result.success) {\n const afterUpdateEvent = new AuditLogAfterUpdateEvent({\n original: original,\n auditLog: auditLog,\n context\n });\n await this.eventPublisher.publish(afterUpdateEvent);\n return result.data;\n }\n throw result.error;\n }\n\n public async getAuditLog(id: string): Promise<IAuditLog | null> {\n const result = await this.storage.fetch({\n id,\n tenant: this.getTenantId()\n });\n if (result.success) {\n await this.checkPermissions(result.data);\n return result.data;\n }\n throw result.error;\n }\n\n public async listAuditLogs(params: IListAuditLogsParams): Promise<IListAuditLogsResult> {\n const result = await this.storage.list({\n ...params,\n tenant: this.getTenantId()\n } as unknown as IStorageListParams);\n if (result.success) {\n return {\n items: result.data,\n meta: {\n cursor: result.meta.after || null,\n hasMoreItems: result.meta.hasMoreItems\n }\n };\n }\n throw result.error;\n }\n\n private async checkPermissions(auditLog: Pick<IAuditLog, \"action\">): Promise<void> {\n if (!auditLog.action) {\n throw new Error(\"Audit log action is not defined. Cannot check permissions.\");\n }\n const permissions = await this.getContext().security.getPermissions(\"al.*\");\n for (const permission of permissions) {\n if (permission.name === \"*\") {\n return;\n }\n if (permission.name === \"al.*\") {\n return;\n } else if (permission.name === `al.${auditLog.action}`) {\n return;\n }\n }\n\n throw new NotAuthorizedError({\n message: \"You cannot access audit logs.\"\n });\n }\n\n private getTenantId(): string {\n return this.getContext().tenancy.getCurrentTenant().id;\n }\n\n private getIdentity(): IAuditLogCreatedBy {\n const identity = this.getContext().security.getIdentity();\n return {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName || \"unknown\"\n };\n }\n}\n\nexport const createAuditLogsContextValue = (\n params: IAuditLogsContextValueParams\n): AuditLogsContextValue => {\n return new AuditLogsContextValueImpl(params);\n};\n"],"names":["AuditLogsContextValueImpl","params","payload","context","expiresAt","convertExpiresAtDaysToDate","auditLog","mdbid","Date","JSON","beforeCreateEvent","AuditLogBeforeCreateEvent","input","Object","result","afterCreateEvent","AuditLogAfterCreateEvent","original","beforeUpdateEvent","AuditLogBeforeUpdateEvent","afterUpdateEvent","AuditLogAfterUpdateEvent","id","Error","permissions","permission","NotAuthorizedError","identity","createAuditLogsContextValue"],"mappings":"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"}
1
+ {"version":3,"file":"context/AuditLogsContextValue.js","sources":["../../src/context/AuditLogsContextValue.ts"],"sourcesContent":["import type {\n AuditLogPayload,\n AuditLogsContext,\n AuditLogsContextValue,\n IListAuditLogsParams,\n IListAuditLogsResult\n} from \"~/types.js\";\nimport { convertExpiresAtDaysToDate } from \"~/utils/expiresAt.js\";\nimport type { IAuditLog, IAuditLogCreatedBy } from \"~/storage/types.js\";\nimport { mdbid } from \"@webiny/utils/mdbid.js\";\nimport type { IStorage, IStorageListParams } from \"~/storage/abstractions/Storage.js\";\nimport { NotAuthorizedError } from \"@webiny/api-core/features/security/shared/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport type { EventPublisher } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport {\n AuditLogBeforeCreateEvent,\n AuditLogAfterCreateEvent,\n AuditLogBeforeUpdateEvent,\n AuditLogAfterUpdateEvent\n} from \"~/events/index.js\";\n\nexport interface IAuditLogsContextValueParams {\n getContext: () => AuditLogsContext;\n deleteLogsAfterDays: number;\n storage: IStorage;\n eventPublisher: EventPublisher.Interface;\n}\n\nclass AuditLogsContextValueImpl implements AuditLogsContextValue {\n private readonly getContext;\n public readonly deleteLogsAfterDays;\n private readonly storage: IStorage;\n private readonly eventPublisher: EventPublisher.Interface;\n\n public constructor(params: IAuditLogsContextValueParams) {\n this.getContext = params.getContext;\n this.deleteLogsAfterDays = params.deleteLogsAfterDays;\n this.storage = params.storage;\n this.eventPublisher = params.eventPublisher;\n }\n\n public async createAuditLog(payload: AuditLogPayload): Promise<IAuditLog> {\n const context = this.getContext();\n const expiresAt = convertExpiresAtDaysToDate(this.deleteLogsAfterDays);\n\n const auditLog: IAuditLog = {\n id: mdbid(),\n tenant: this.getTenantId(),\n createdBy: this.getIdentity(),\n createdOn: new Date(),\n ...payload,\n content: JSON.stringify(payload.content),\n expiresAt\n };\n await this.checkPermissions(auditLog);\n\n const beforeCreateEvent = new AuditLogBeforeCreateEvent({\n auditLog: auditLog,\n context,\n setAuditLog(input) {\n Object.assign(auditLog, input);\n }\n });\n await this.eventPublisher.publish(beforeCreateEvent);\n\n const result = await this.storage.store({\n data: auditLog\n });\n if (result.success) {\n const afterCreateEvent = new AuditLogAfterCreateEvent({\n auditLog: auditLog,\n context\n });\n await this.eventPublisher.publish(afterCreateEvent);\n return result.data;\n }\n throw result.error;\n }\n\n public async updateAuditLog(\n original: IAuditLog,\n payload: Partial<AuditLogPayload>\n ): Promise<IAuditLog> {\n const context = this.getContext();\n const auditLog: IAuditLog = {\n ...original,\n ...payload,\n content: payload.content ? JSON.stringify(payload.content) : original.content\n };\n await this.checkPermissions(auditLog);\n\n const beforeUpdateEvent = new AuditLogBeforeUpdateEvent({\n original,\n auditLog,\n context,\n setAuditLog(input) {\n Object.assign(auditLog, input);\n }\n });\n await this.eventPublisher.publish(beforeUpdateEvent);\n\n const result = await this.storage.store({\n data: auditLog\n });\n if (result.success) {\n const afterUpdateEvent = new AuditLogAfterUpdateEvent({\n original: original,\n auditLog: auditLog,\n context\n });\n await this.eventPublisher.publish(afterUpdateEvent);\n return result.data;\n }\n throw result.error;\n }\n\n public async getAuditLog(id: string): Promise<IAuditLog | null> {\n const result = await this.storage.fetch({\n id,\n tenant: this.getTenantId()\n });\n if (result.success) {\n await this.checkPermissions(result.data);\n return result.data;\n }\n throw result.error;\n }\n\n public async listAuditLogs(params: IListAuditLogsParams): Promise<IListAuditLogsResult> {\n const result = await this.storage.list({\n ...params,\n tenant: this.getTenantId()\n } as unknown as IStorageListParams);\n if (result.success) {\n return {\n items: result.data,\n meta: {\n cursor: result.meta.after || null,\n hasMoreItems: result.meta.hasMoreItems\n }\n };\n }\n throw result.error;\n }\n\n private async checkPermissions(auditLog: Pick<IAuditLog, \"action\">): Promise<void> {\n if (!auditLog.action) {\n throw new Error(\"Audit log action is not defined. Cannot check permissions.\");\n }\n const permissions = await this.getContext()\n .container.resolve(IdentityContext)\n .getPermissions(\"al.*\");\n for (const permission of permissions) {\n if (permission.name === \"*\") {\n return;\n }\n if (permission.name === \"al.*\") {\n return;\n } else if (permission.name === `al.${auditLog.action}`) {\n return;\n }\n }\n\n throw new NotAuthorizedError({\n message: \"You cannot access audit logs.\"\n });\n }\n\n private getTenantId(): string {\n return this.getContext().container.resolve(TenantContext).getTenant().id;\n }\n\n private getIdentity(): IAuditLogCreatedBy {\n const identity = this.getContext().container.resolve(IdentityContext).getIdentity();\n return {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName || \"unknown\"\n };\n }\n}\n\nexport const createAuditLogsContextValue = (\n params: IAuditLogsContextValueParams\n): AuditLogsContextValue => {\n return new AuditLogsContextValueImpl(params);\n};\n"],"names":["AuditLogsContextValueImpl","params","payload","context","expiresAt","convertExpiresAtDaysToDate","auditLog","mdbid","Date","JSON","beforeCreateEvent","AuditLogBeforeCreateEvent","input","Object","result","afterCreateEvent","AuditLogAfterCreateEvent","original","beforeUpdateEvent","AuditLogBeforeUpdateEvent","afterUpdateEvent","AuditLogAfterUpdateEvent","id","Error","permissions","IdentityContext","permission","NotAuthorizedError","TenantContext","identity","createAuditLogsContextValue"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { CoreGraphQLSchemaFactory } from "@webiny/api-graphql/graphql/abstractions.js";
2
+ import { GraphQLSchemaBuilder } from "@webiny/api-graphql/features/GraphQLSchemaBuilder/abstractions.js";
3
+ declare class AuditLogsGraphQLSchemaImpl implements CoreGraphQLSchemaFactory.Interface {
4
+ execute(builder: GraphQLSchemaBuilder.Interface): CoreGraphQLSchemaFactory.Return;
5
+ }
6
+ export declare const AuditLogsGraphQLSchema: typeof AuditLogsGraphQLSchemaImpl & {
7
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-graphql/graphql/abstractions.core.js").ICoreGraphQLSchemaFactory>;
8
+ };
9
+ export {};
@@ -0,0 +1,134 @@
1
+ import { NotFoundError, resolve, resolveList } from "@webiny/api-graphql";
2
+ import { CoreGraphQLSchemaFactory } from "@webiny/api-graphql/graphql/abstractions.js";
3
+ import { createZodError } from "@webiny/utils";
4
+ import { AuditLogsContext } from "../abstractions.js";
5
+ import { getValidationSchema, listValidationSchema } from "./validation.js";
6
+ const TYPE_DEFS = `
7
+ type AuditLogCreatedBy {
8
+ id: ID!
9
+ displayName: String
10
+ type: String
11
+ }
12
+ type AuditLog {
13
+ id: ID!
14
+ createdBy: AuditLogCreatedBy!
15
+ createdOn: DateTime!
16
+ app: String!
17
+ action: String!
18
+ message: String!
19
+ entity: String!
20
+ entityId: String!
21
+ tags: [String!]!
22
+ expiresAt: DateTime!
23
+ content: String
24
+ }
25
+
26
+ type AuditLogListMeta {
27
+ cursor: String
28
+ hasMoreItems: Boolean!
29
+ }
30
+
31
+ type AuditLogError {
32
+ code: String
33
+ message: String!
34
+ data: JSON
35
+ stack: String
36
+ }
37
+
38
+ type AuditLogListResponse {
39
+ data: [AuditLog!]
40
+ meta: AuditLogListMeta
41
+ error: AuditLogError
42
+ }
43
+
44
+ type AuditLogGetResponse {
45
+ data: AuditLog
46
+ error: AuditLogError
47
+ }
48
+
49
+ enum AuditLogsSort {
50
+ ASC
51
+ DESC
52
+ }
53
+
54
+ input ListAuditLogsWhere {
55
+ app: String
56
+ action: String
57
+ createdBy: String
58
+ entity: String
59
+ entityId: String
60
+ createdOn_gte: DateTime
61
+ createdOn_lte: DateTime
62
+ }
63
+
64
+ type AuditLogsQuery {
65
+ getAuditLog(id: ID!): AuditLogGetResponse
66
+ listAuditLogs(
67
+ where: ListAuditLogsWhere
68
+ sort: AuditLogsSort
69
+ limit: Number
70
+ after: String
71
+ ): AuditLogListResponse!
72
+ }
73
+
74
+ extend type Query {
75
+ auditLogs: AuditLogsQuery
76
+ }
77
+ `;
78
+ class AuditLogsGraphQLSchemaImpl {
79
+ async execute(builder) {
80
+ builder.addTypeDefs(TYPE_DEFS);
81
+ builder.addResolver({
82
+ path: "Query.auditLogs",
83
+ dependencies: [],
84
+ resolver: ()=>()=>({})
85
+ });
86
+ builder.addResolver({
87
+ path: "AuditLogsQuery.getAuditLog",
88
+ dependencies: [
89
+ AuditLogsContext
90
+ ],
91
+ resolver (auditLogs) {
92
+ return async ({ args })=>resolve(async ()=>{
93
+ const validation = await getValidationSchema.safeParseAsync(args);
94
+ if (!validation.success) throw createZodError(validation.error);
95
+ const result = await auditLogs.getAuditLog(validation.data.id);
96
+ if (!result) throw new NotFoundError(`Audit log with id "${validation.data.id}" not found.`);
97
+ return result;
98
+ });
99
+ }
100
+ });
101
+ builder.addResolver({
102
+ path: "AuditLogsQuery.listAuditLogs",
103
+ dependencies: [
104
+ AuditLogsContext
105
+ ],
106
+ resolver (auditLogs) {
107
+ return async ({ args })=>resolveList(async ()=>{
108
+ const validation = await listValidationSchema.safeParseAsync(args);
109
+ if (!validation.success) throw createZodError(validation.error);
110
+ const result = await auditLogs.listAuditLogs({
111
+ ...validation.data,
112
+ ...validation.data.where
113
+ });
114
+ if (result.error) throw result.error;
115
+ return {
116
+ items: result.items,
117
+ meta: {
118
+ ...result.meta,
119
+ totalCount: 0
120
+ }
121
+ };
122
+ });
123
+ }
124
+ });
125
+ return builder;
126
+ }
127
+ }
128
+ const AuditLogsGraphQLSchema = CoreGraphQLSchemaFactory.createImplementation({
129
+ implementation: AuditLogsGraphQLSchemaImpl,
130
+ dependencies: []
131
+ });
132
+ export { AuditLogsGraphQLSchema };
133
+
134
+ //# sourceMappingURL=AuditLogsGraphQLSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql/AuditLogsGraphQLSchema.js","sources":["../../src/graphql/AuditLogsGraphQLSchema.ts"],"sourcesContent":["import { NotFoundError, resolve, resolveList } from \"@webiny/api-graphql\";\nimport { CoreGraphQLSchemaFactory } from \"@webiny/api-graphql/graphql/abstractions.js\";\nimport { GraphQLSchemaBuilder } from \"@webiny/api-graphql/features/GraphQLSchemaBuilder/abstractions.js\";\nimport { createZodError } from \"@webiny/utils\";\nimport { AuditLogsContext } from \"~/abstractions.js\";\nimport type { AuditLogsContextValue } from \"~/types.js\";\nimport { getValidationSchema, listValidationSchema } from \"./validation.js\";\n\ninterface IListAuditLogsWhere {\n app?: string;\n action?: string;\n createdBy?: string;\n entity?: string;\n entityId?: string;\n createdOn_gte?: Date;\n createdOn_lte?: Date;\n}\n\ninterface IListAuditLogsArgs {\n where?: IListAuditLogsWhere;\n sort?: \"ASC\" | \"DESC\";\n limit?: number;\n after?: string;\n}\n\nconst TYPE_DEFS = /* GraphQL */ `\n type AuditLogCreatedBy {\n id: ID!\n displayName: String\n type: String\n }\n type AuditLog {\n id: ID!\n createdBy: AuditLogCreatedBy!\n createdOn: DateTime!\n app: String!\n action: String!\n message: String!\n entity: String!\n entityId: String!\n tags: [String!]!\n expiresAt: DateTime!\n content: String\n }\n\n type AuditLogListMeta {\n cursor: String\n hasMoreItems: Boolean!\n }\n\n type AuditLogError {\n code: String\n message: String!\n data: JSON\n stack: String\n }\n\n type AuditLogListResponse {\n data: [AuditLog!]\n meta: AuditLogListMeta\n error: AuditLogError\n }\n\n type AuditLogGetResponse {\n data: AuditLog\n error: AuditLogError\n }\n\n enum AuditLogsSort {\n ASC\n DESC\n }\n\n input ListAuditLogsWhere {\n app: String\n action: String\n createdBy: String\n entity: String\n entityId: String\n createdOn_gte: DateTime\n createdOn_lte: DateTime\n }\n\n type AuditLogsQuery {\n getAuditLog(id: ID!): AuditLogGetResponse\n listAuditLogs(\n where: ListAuditLogsWhere\n sort: AuditLogsSort\n limit: Number\n after: String\n ): AuditLogListResponse!\n }\n\n extend type Query {\n auditLogs: AuditLogsQuery\n }\n`;\n\nclass AuditLogsGraphQLSchemaImpl implements CoreGraphQLSchemaFactory.Interface {\n public async execute(builder: GraphQLSchemaBuilder.Interface): CoreGraphQLSchemaFactory.Return {\n builder.addTypeDefs(TYPE_DEFS);\n\n builder.addResolver({\n path: \"Query.auditLogs\",\n dependencies: [],\n resolver: () => () => ({})\n });\n\n builder.addResolver<{ id: string }>({\n path: \"AuditLogsQuery.getAuditLog\",\n dependencies: [AuditLogsContext],\n resolver(auditLogs: AuditLogsContextValue) {\n return async ({ args }) => {\n return resolve(async () => {\n const validation = await getValidationSchema.safeParseAsync(args);\n\n if (!validation.success) {\n throw createZodError(validation.error);\n }\n\n const result = await auditLogs.getAuditLog(validation.data.id);\n if (!result) {\n throw new NotFoundError(\n `Audit log with id \"${validation.data.id}\" not found.`\n );\n }\n return result;\n });\n };\n }\n });\n\n builder.addResolver<IListAuditLogsArgs>({\n path: \"AuditLogsQuery.listAuditLogs\",\n dependencies: [AuditLogsContext],\n resolver(auditLogs: AuditLogsContextValue) {\n return async ({ args }) => {\n return resolveList(async () => {\n const validation = await listValidationSchema.safeParseAsync(args);\n if (!validation.success) {\n throw createZodError(validation.error);\n }\n const result = await auditLogs.listAuditLogs({\n ...validation.data,\n ...validation.data.where\n });\n if (result.error) {\n throw result.error;\n }\n return {\n items: result.items,\n meta: {\n ...result.meta,\n totalCount: 0\n }\n };\n });\n };\n }\n });\n\n return builder;\n }\n}\n\nexport const AuditLogsGraphQLSchema = CoreGraphQLSchemaFactory.createImplementation({\n implementation: AuditLogsGraphQLSchemaImpl,\n dependencies: []\n});\n"],"names":["TYPE_DEFS","AuditLogsGraphQLSchemaImpl","builder","AuditLogsContext","auditLogs","args","resolve","validation","getValidationSchema","createZodError","result","NotFoundError","resolveList","listValidationSchema","AuditLogsGraphQLSchema","CoreGraphQLSchemaFactory"],"mappings":";;;;;AAyBA,MAAMA,YAA0B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEjC,CAAC;AAED,MAAMC;IACF,MAAa,QAAQC,OAAuC,EAAmC;QAC3FA,QAAQ,WAAW,CAACF;QAEpBE,QAAQ,WAAW,CAAC;YAChB,MAAM;YACN,cAAc,EAAE;YAChB,UAAU,IAAM,IAAO,EAAC;QAC5B;QAEAA,QAAQ,WAAW,CAAiB;YAChC,MAAM;YACN,cAAc;gBAACC;aAAiB;YAChC,UAASC,SAAgC;gBACrC,OAAO,OAAO,EAAEC,IAAI,EAAE,GACXC,QAAQ;wBACX,MAAMC,aAAa,MAAMC,oBAAoB,cAAc,CAACH;wBAE5D,IAAI,CAACE,WAAW,OAAO,EACnB,MAAME,eAAeF,WAAW,KAAK;wBAGzC,MAAMG,SAAS,MAAMN,UAAU,WAAW,CAACG,WAAW,IAAI,CAAC,EAAE;wBAC7D,IAAI,CAACG,QACD,MAAM,IAAIC,cACN,CAAC,mBAAmB,EAAEJ,WAAW,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC;wBAG9D,OAAOG;oBACX;YAER;QACJ;QAEAR,QAAQ,WAAW,CAAqB;YACpC,MAAM;YACN,cAAc;gBAACC;aAAiB;YAChC,UAASC,SAAgC;gBACrC,OAAO,OAAO,EAAEC,IAAI,EAAE,GACXO,YAAY;wBACf,MAAML,aAAa,MAAMM,qBAAqB,cAAc,CAACR;wBAC7D,IAAI,CAACE,WAAW,OAAO,EACnB,MAAME,eAAeF,WAAW,KAAK;wBAEzC,MAAMG,SAAS,MAAMN,UAAU,aAAa,CAAC;4BACzC,GAAGG,WAAW,IAAI;4BAClB,GAAGA,WAAW,IAAI,CAAC,KAAK;wBAC5B;wBACA,IAAIG,OAAO,KAAK,EACZ,MAAMA,OAAO,KAAK;wBAEtB,OAAO;4BACH,OAAOA,OAAO,KAAK;4BACnB,MAAM;gCACF,GAAGA,OAAO,IAAI;gCACd,YAAY;4BAChB;wBACJ;oBACJ;YAER;QACJ;QAEA,OAAOR;IACX;AACJ;AAEO,MAAMY,yBAAyBC,yBAAyB,oBAAoB,CAAC;IAChF,gBAAgBd;IAChB,cAAc,EAAE;AACpB"}
package/index.d.ts CHANGED
@@ -1,9 +1,3 @@
1
- import { ContextPlugin } from "@webiny/api";
2
- import type { DynamoDBDocument } from "@webiny/aws-sdk/client-dynamodb/index.js";
3
- export interface ICreateAuditLogsParams {
4
- deleteLogsAfterDays: number | undefined;
5
- tableName?: string;
6
- documentClient?: DynamoDBDocument;
7
- }
8
- export declare const createAuditLogs: (params?: ICreateAuditLogsParams) => (ContextPlugin<import("./types.js").AuditLogsContext> | import("@webiny/handler-graphql/index.js").GraphQLSchemaPlugin<import("./types.js").AuditLogsContext>)[];
9
1
  export * from "./config.js";
2
+ export { AuditLogsFeature } from "./AuditLogsFeature.js";
3
+ export type { AuditLogsFeatureConfig } from "./AuditLogsFeature.js";
package/index.js CHANGED
@@ -1,26 +1,2 @@
1
- import { ContextPlugin } from "@webiny/api";
2
- import { createSubscriptionHooks } from "./subscriptions/index.js";
3
- import { createAuditLogsContext } from "./context/index.js";
4
- import { createGraphQLSchema } from "./graphql/schema.js";
5
- import { AuditLogsContext } from "./abstractions.js";
6
1
  export * from "./config.js";
7
- const createAuditLogs = (params)=>{
8
- const subscriptionsPlugin = new ContextPlugin((context)=>{
9
- if (!context.wcp.canUseFeature("auditLogs")) return;
10
- context.container.registerInstance(AuditLogsContext, context);
11
- createSubscriptionHooks(context);
12
- });
13
- subscriptionsPlugin.name = "auditLogs.context.subscriptions";
14
- return [
15
- subscriptionsPlugin,
16
- createGraphQLSchema(),
17
- createAuditLogsContext({
18
- tableName: params?.tableName,
19
- deleteLogsAfterDays: params?.deleteLogsAfterDays,
20
- documentClient: params?.documentClient
21
- })
22
- ];
23
- };
24
- export { createAuditLogs };
25
-
26
- //# sourceMappingURL=index.js.map
2
+ export { AuditLogsFeature } from "./AuditLogsFeature.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-audit-logs",
3
- "version": "6.4.5-beta.0",
3
+ "version": "6.6.0-alpha.0",
4
4
  "exports": {
5
5
  ".": "./index.js",
6
6
  "./*": "./*"
@@ -22,32 +22,32 @@
22
22
  "access": "public"
23
23
  },
24
24
  "devDependencies": {
25
- "@webiny/handler-aws": "6.4.5-beta.0",
26
- "@webiny/plugins": "6.4.5-beta.0",
27
- "@webiny/project-utils": "6.4.5-beta.0",
25
+ "@webiny/api-headless-cms-testing": "6.6.0-alpha.0",
26
+ "@webiny/di": "1.0.2",
27
+ "@webiny/event-handler-core": "6.6.0-alpha.0",
28
+ "@webiny/handler": "6.6.0-alpha.0",
29
+ "@webiny/plugins": "6.6.0-alpha.0",
30
+ "@webiny/project-utils": "6.6.0-alpha.0",
28
31
  "graphql": "16.14.2",
29
- "typescript": "6.0.3",
32
+ "typescript": "7.0.2",
30
33
  "vitest": "4.1.10"
31
34
  },
32
35
  "dependencies": {
33
- "@webiny/api": "6.4.5-beta.0",
34
- "@webiny/api-aco": "6.4.5-beta.0",
35
- "@webiny/api-core": "6.4.5-beta.0",
36
- "@webiny/api-file-manager": "6.4.5-beta.0",
37
- "@webiny/api-headless-cms": "6.4.5-beta.0",
38
- "@webiny/api-mailer": "6.4.5-beta.0",
39
- "@webiny/api-website-builder": "6.4.5-beta.0",
40
- "@webiny/aws-sdk": "6.4.5-beta.0",
41
- "@webiny/build-tools": "6.4.5-beta.0",
42
- "@webiny/common-audit-logs": "6.4.5-beta.0",
43
- "@webiny/db-dynamodb": "6.4.5-beta.0",
44
- "@webiny/error": "6.4.5-beta.0",
45
- "@webiny/feature": "6.4.5-beta.0",
46
- "@webiny/handler": "6.4.5-beta.0",
47
- "@webiny/handler-db": "6.4.5-beta.0",
48
- "@webiny/handler-graphql": "6.4.5-beta.0",
49
- "@webiny/utils": "6.4.5-beta.0",
50
- "@webiny/wcp": "6.4.5-beta.0",
36
+ "@graphql-tools/schema": "10.0.38",
37
+ "@webiny/api": "6.6.0-alpha.0",
38
+ "@webiny/api-aco": "6.6.0-alpha.0",
39
+ "@webiny/api-core": "6.6.0-alpha.0",
40
+ "@webiny/api-file-manager": "6.6.0-alpha.0",
41
+ "@webiny/api-graphql": "6.6.0-alpha.0",
42
+ "@webiny/api-headless-cms": "6.6.0-alpha.0",
43
+ "@webiny/api-mailer": "6.6.0-alpha.0",
44
+ "@webiny/api-website-builder": "6.6.0-alpha.0",
45
+ "@webiny/build-tools": "6.6.0-alpha.0",
46
+ "@webiny/common-audit-logs": "6.6.0-alpha.0",
47
+ "@webiny/error": "6.6.0-alpha.0",
48
+ "@webiny/feature": "6.6.0-alpha.0",
49
+ "@webiny/utils": "6.6.0-alpha.0",
50
+ "@webiny/wcp": "6.6.0-alpha.0",
51
51
  "zod": "4.4.3"
52
52
  },
53
53
  "webiny": {
@@ -17,38 +17,3 @@ export interface IAuditLog {
17
17
  expiresAt: Date;
18
18
  content: string;
19
19
  }
20
- export interface IStorageAuditLog extends Omit<IAuditLog, "createdOn" | "content" | "expiresAt"> {
21
- expiresAt: string;
22
- createdOn: string;
23
- content: string;
24
- }
25
- export interface IStorageItem {
26
- PK: string;
27
- SK: string;
28
- TYPE: string;
29
- GSI_TENANT: string;
30
- GSI1_PK: string;
31
- GSI1_SK: number;
32
- GSI2_PK: string;
33
- GSI2_SK: number;
34
- GSI3_PK: string;
35
- GSI3_SK: number;
36
- GSI4_PK: string;
37
- GSI4_SK: number;
38
- GSI5_PK: string;
39
- GSI5_SK: number;
40
- GSI6_PK: string;
41
- GSI6_SK: number;
42
- GSI7_PK: string;
43
- GSI7_SK: number;
44
- GSI8_PK: string;
45
- GSI8_SK: number;
46
- GSI9_PK: string;
47
- GSI9_SK: number;
48
- data: IStorageAuditLog;
49
- expiresAt: number;
50
- }
51
- export interface IIndexStorageItem {
52
- PK: string;
53
- SK: string;
54
- }
package/types.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import type { GenericRecord } from "@webiny/api/types.js";
2
2
  import type { Action, App, Entity } from "@webiny/common-audit-logs/types.js";
3
- import type { DbContext } from "@webiny/handler-db/types.js";
4
3
  import type { ApiCoreContext } from "@webiny/api-core/types/core.js";
5
4
  import type { IAuditLog } from "./storage/types.js";
6
5
  import type { IStorageListParams } from "./storage/abstractions/Storage.js";
@@ -33,7 +32,7 @@ export interface AuditLogsContextValue {
33
32
  getAuditLog(id: string): Promise<IAuditLog | null>;
34
33
  listAuditLogs(params: IListAuditLogsParams): Promise<IListAuditLogsResult>;
35
34
  }
36
- export interface AuditLogsContext extends ApiCoreContext, Pick<DbContext, "db"> {
35
+ export interface AuditLogsContext extends ApiCoreContext {
37
36
  auditLogs: AuditLogsContextValue;
38
37
  }
39
38
  export interface AuditObject {
@@ -1,4 +1,5 @@
1
1
  import _webiny_error from "@webiny/error";
2
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
2
3
  const createAuditLog = async (params)=>{
3
4
  const { context, payload } = params;
4
5
  try {
@@ -60,11 +61,12 @@ const getAuditConfig = (audit)=>async (message, content, entityId, context)=>{
60
61
  tags: []
61
62
  };
62
63
  const delay = audit.action.newEntryDelay || 0;
63
- if (!context.security.getIdentity()?.id) {
64
+ const identityContext = context.container.resolve(IdentityContext);
65
+ if (!identityContext.getIdentity()?.id) {
64
66
  console.log("No identity - skipping audit log creation.");
65
67
  return null;
66
68
  }
67
- return await context.security.withoutAuthorization(async ()=>{
69
+ return await identityContext.withoutAuthorization(async ()=>{
68
70
  if (delay > 0) {
69
71
  try {
70
72
  return await createOrMergeAuditLog({
@@ -1 +1 @@
1
- {"version":3,"file":"utils/getAuditConfig.js","sources":["../../src/utils/getAuditConfig.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport type { AuditAction, AuditLogPayload, AuditLogsContext } from \"~/types.js\";\nimport type { IAuditLog } from \"~/storage/types.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\ninterface CreateAuditLogParams {\n context: Pick<AuditLogsContext, \"auditLogs\">;\n payload: AuditLogPayload;\n}\n\nconst createAuditLog = async (params: CreateAuditLogParams): Promise<IAuditLog> => {\n const { context, payload } = params;\n\n try {\n return await context.auditLogs.createAuditLog(payload);\n } catch (error) {\n throw WebinyError.from(error);\n }\n};\n\ninterface CreateOrMergeAuditLogParams {\n context: AuditLogsContext;\n payload: AuditLogPayload;\n delay: number;\n}\n\nconst createAuditLogDelayDate = (delay: number | undefined) => {\n if (!delay) {\n return undefined;\n }\n const date = new Date();\n date.setTime(date.getTime() - delay * 1000);\n return date;\n};\n\nconst createOrMergeAuditLog = async (params: CreateOrMergeAuditLogParams): Promise<IAuditLog> => {\n const { context, payload, delay } = params;\n\n const results = await context.auditLogs.listAuditLogs({\n app: payload.app,\n entityId: payload.entityId,\n limit: 1,\n createdOn_gte: createAuditLogDelayDate(delay),\n sort: \"DESC\"\n });\n if (results.error) {\n throw WebinyError.from(results.error);\n }\n const original = results.items?.[0];\n if (!original) {\n return createAuditLog(params);\n }\n // Update latest audit log with new \"after\" payload.\n const beforePayloadData = original.content ? JSON.parse(original.content)?.before : undefined;\n /**\n * We can assume that there is a possible \"after\" in the payload data.\n */\n const afterPayloadData = payload.content?.after;\n const updatedPayloadData = beforePayloadData\n ? {\n before: beforePayloadData,\n after: afterPayloadData\n }\n : payload.content;\n\n try {\n return await context.auditLogs.updateAuditLog(original, {\n ...payload,\n content: updatedPayloadData\n });\n } catch (ex) {\n throw WebinyError.from(ex);\n }\n};\n\nexport const getAuditConfig = (audit: AuditAction) => {\n return async (\n message: string,\n content: GenericRecord,\n entityId: string,\n context: AuditLogsContext\n ): Promise<IAuditLog | null> => {\n if (!context.auditLogs) {\n console.log(\"No AuditLogs defined.\");\n return null;\n } else if (!audit) {\n console.log(`No Audit Action defined!`);\n return null;\n }\n\n const payload: AuditLogPayload = {\n message,\n app: audit.app.app,\n entityId,\n entity: audit.entity.type,\n action: audit.action.type,\n content,\n tags: []\n };\n\n const delay = audit.action.newEntryDelay || 0;\n\n if (!context.security.getIdentity()?.id) {\n console.log(\"No identity - skipping audit log creation.\");\n return null;\n }\n\n return await context.security.withoutAuthorization(async () => {\n // Check if there is delay on audit log creation for this action.\n if (delay > 0) {\n try {\n return await createOrMergeAuditLog({\n context,\n payload,\n delay\n });\n } catch {\n // Don't care at this point!\n }\n return null;\n }\n return await createAuditLog({\n context,\n payload\n });\n });\n };\n};\n"],"names":["createAuditLog","params","context","payload","error","WebinyError","createAuditLogDelayDate","delay","date","Date","createOrMergeAuditLog","results","original","beforePayloadData","JSON","undefined","afterPayloadData","updatedPayloadData","ex","getAuditConfig","audit","message","content","entityId","console"],"mappings":";AAUA,MAAMA,iBAAiB,OAAOC;IAC1B,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGF;IAE7B,IAAI;QACA,OAAO,MAAMC,QAAQ,SAAS,CAAC,cAAc,CAACC;IAClD,EAAE,OAAOC,OAAO;QACZ,MAAMC,cAAAA,IAAgB,CAACD;IAC3B;AACJ;AAQA,MAAME,0BAA0B,CAACC;IAC7B,IAAI,CAACA,OACD;IAEJ,MAAMC,OAAO,IAAIC;IACjBD,KAAK,OAAO,CAACA,KAAK,OAAO,KAAKD,AAAQ,OAARA;IAC9B,OAAOC;AACX;AAEA,MAAME,wBAAwB,OAAOT;IACjC,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEI,KAAK,EAAE,GAAGN;IAEpC,MAAMU,UAAU,MAAMT,QAAQ,SAAS,CAAC,aAAa,CAAC;QAClD,KAAKC,QAAQ,GAAG;QAChB,UAAUA,QAAQ,QAAQ;QAC1B,OAAO;QACP,eAAeG,wBAAwBC;QACvC,MAAM;IACV;IACA,IAAII,QAAQ,KAAK,EACb,MAAMN,cAAAA,IAAgB,CAACM,QAAQ,KAAK;IAExC,MAAMC,WAAWD,QAAQ,KAAK,EAAE,CAAC,EAAE;IACnC,IAAI,CAACC,UACD,OAAOZ,eAAeC;IAG1B,MAAMY,oBAAoBD,SAAS,OAAO,GAAGE,KAAK,KAAK,CAACF,SAAS,OAAO,GAAG,SAASG;IAIpF,MAAMC,mBAAmBb,QAAQ,OAAO,EAAE;IAC1C,MAAMc,qBAAqBJ,oBACrB;QACI,QAAQA;QACR,OAAOG;IACX,IACAb,QAAQ,OAAO;IAErB,IAAI;QACA,OAAO,MAAMD,QAAQ,SAAS,CAAC,cAAc,CAACU,UAAU;YACpD,GAAGT,OAAO;YACV,SAASc;QACb;IACJ,EAAE,OAAOC,IAAI;QACT,MAAMb,cAAAA,IAAgB,CAACa;IAC3B;AACJ;AAEO,MAAMC,iBAAiB,CAACC,QACpB,OACHC,SACAC,SACAC,UACArB;QAEA,IAAKA,QAAQ,SAAS,EAGf;YAAA,IAAI,CAACkB,OAAO;gBACfI,QAAQ,GAAG,CAAC;gBACZ,OAAO;YACX;QAAA,OANwB;YACpBA,QAAQ,GAAG,CAAC;YACZ,OAAO;QACX;QAKA,MAAMrB,UAA2B;YAC7BkB;YACA,KAAKD,MAAM,GAAG,CAAC,GAAG;YAClBG;YACA,QAAQH,MAAM,MAAM,CAAC,IAAI;YACzB,QAAQA,MAAM,MAAM,CAAC,IAAI;YACzBE;YACA,MAAM,EAAE;QACZ;QAEA,MAAMf,QAAQa,MAAM,MAAM,CAAC,aAAa,IAAI;QAE5C,IAAI,CAAClB,QAAQ,QAAQ,CAAC,WAAW,IAAI,IAAI;YACrCsB,QAAQ,GAAG,CAAC;YACZ,OAAO;QACX;QAEA,OAAO,MAAMtB,QAAQ,QAAQ,CAAC,oBAAoB,CAAC;YAE/C,IAAIK,QAAQ,GAAG;gBACX,IAAI;oBACA,OAAO,MAAMG,sBAAsB;wBAC/BR;wBACAC;wBACAI;oBACJ;gBACJ,EAAE,OAAM,CAER;gBACA,OAAO;YACX;YACA,OAAO,MAAMP,eAAe;gBACxBE;gBACAC;YACJ;QACJ;IACJ"}
1
+ {"version":3,"file":"utils/getAuditConfig.js","sources":["../../src/utils/getAuditConfig.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/abstractions.js\";\nimport type { AuditAction, AuditLogPayload, AuditLogsContext } from \"~/types.js\";\nimport type { IAuditLog } from \"~/storage/types.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\ninterface CreateAuditLogParams {\n context: Pick<AuditLogsContext, \"auditLogs\">;\n payload: AuditLogPayload;\n}\n\nconst createAuditLog = async (params: CreateAuditLogParams): Promise<IAuditLog> => {\n const { context, payload } = params;\n\n try {\n return await context.auditLogs.createAuditLog(payload);\n } catch (error) {\n throw WebinyError.from(error);\n }\n};\n\ninterface CreateOrMergeAuditLogParams {\n context: AuditLogsContext;\n payload: AuditLogPayload;\n delay: number;\n}\n\nconst createAuditLogDelayDate = (delay: number | undefined) => {\n if (!delay) {\n return undefined;\n }\n const date = new Date();\n date.setTime(date.getTime() - delay * 1000);\n return date;\n};\n\nconst createOrMergeAuditLog = async (params: CreateOrMergeAuditLogParams): Promise<IAuditLog> => {\n const { context, payload, delay } = params;\n\n const results = await context.auditLogs.listAuditLogs({\n app: payload.app,\n entityId: payload.entityId,\n limit: 1,\n createdOn_gte: createAuditLogDelayDate(delay),\n sort: \"DESC\"\n });\n if (results.error) {\n throw WebinyError.from(results.error);\n }\n const original = results.items?.[0];\n if (!original) {\n return createAuditLog(params);\n }\n // Update latest audit log with new \"after\" payload.\n const beforePayloadData = original.content ? JSON.parse(original.content)?.before : undefined;\n /**\n * We can assume that there is a possible \"after\" in the payload data.\n */\n const afterPayloadData = payload.content?.after;\n const updatedPayloadData = beforePayloadData\n ? {\n before: beforePayloadData,\n after: afterPayloadData\n }\n : payload.content;\n\n try {\n return await context.auditLogs.updateAuditLog(original, {\n ...payload,\n content: updatedPayloadData\n });\n } catch (ex) {\n throw WebinyError.from(ex);\n }\n};\n\nexport const getAuditConfig = (audit: AuditAction) => {\n return async (\n message: string,\n content: GenericRecord,\n entityId: string,\n context: AuditLogsContext\n ): Promise<IAuditLog | null> => {\n if (!context.auditLogs) {\n console.log(\"No AuditLogs defined.\");\n return null;\n } else if (!audit) {\n console.log(`No Audit Action defined!`);\n return null;\n }\n\n const payload: AuditLogPayload = {\n message,\n app: audit.app.app,\n entityId,\n entity: audit.entity.type,\n action: audit.action.type,\n content,\n tags: []\n };\n\n const delay = audit.action.newEntryDelay || 0;\n\n const identityContext = context.container.resolve(IdentityContext);\n if (!identityContext.getIdentity()?.id) {\n console.log(\"No identity - skipping audit log creation.\");\n return null;\n }\n\n return await identityContext.withoutAuthorization(async () => {\n // Check if there is delay on audit log creation for this action.\n if (delay > 0) {\n try {\n return await createOrMergeAuditLog({\n context,\n payload,\n delay\n });\n } catch {\n // Don't care at this point!\n }\n return null;\n }\n return await createAuditLog({\n context,\n payload\n });\n });\n };\n};\n"],"names":["createAuditLog","params","context","payload","error","WebinyError","createAuditLogDelayDate","delay","date","Date","createOrMergeAuditLog","results","original","beforePayloadData","JSON","undefined","afterPayloadData","updatedPayloadData","ex","getAuditConfig","audit","message","content","entityId","console","identityContext","IdentityContext"],"mappings":";;AAWA,MAAMA,iBAAiB,OAAOC;IAC1B,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGF;IAE7B,IAAI;QACA,OAAO,MAAMC,QAAQ,SAAS,CAAC,cAAc,CAACC;IAClD,EAAE,OAAOC,OAAO;QACZ,MAAMC,cAAAA,IAAgB,CAACD;IAC3B;AACJ;AAQA,MAAME,0BAA0B,CAACC;IAC7B,IAAI,CAACA,OACD;IAEJ,MAAMC,OAAO,IAAIC;IACjBD,KAAK,OAAO,CAACA,KAAK,OAAO,KAAKD,AAAQ,OAARA;IAC9B,OAAOC;AACX;AAEA,MAAME,wBAAwB,OAAOT;IACjC,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEI,KAAK,EAAE,GAAGN;IAEpC,MAAMU,UAAU,MAAMT,QAAQ,SAAS,CAAC,aAAa,CAAC;QAClD,KAAKC,QAAQ,GAAG;QAChB,UAAUA,QAAQ,QAAQ;QAC1B,OAAO;QACP,eAAeG,wBAAwBC;QACvC,MAAM;IACV;IACA,IAAII,QAAQ,KAAK,EACb,MAAMN,cAAAA,IAAgB,CAACM,QAAQ,KAAK;IAExC,MAAMC,WAAWD,QAAQ,KAAK,EAAE,CAAC,EAAE;IACnC,IAAI,CAACC,UACD,OAAOZ,eAAeC;IAG1B,MAAMY,oBAAoBD,SAAS,OAAO,GAAGE,KAAK,KAAK,CAACF,SAAS,OAAO,GAAG,SAASG;IAIpF,MAAMC,mBAAmBb,QAAQ,OAAO,EAAE;IAC1C,MAAMc,qBAAqBJ,oBACrB;QACI,QAAQA;QACR,OAAOG;IACX,IACAb,QAAQ,OAAO;IAErB,IAAI;QACA,OAAO,MAAMD,QAAQ,SAAS,CAAC,cAAc,CAACU,UAAU;YACpD,GAAGT,OAAO;YACV,SAASc;QACb;IACJ,EAAE,OAAOC,IAAI;QACT,MAAMb,cAAAA,IAAgB,CAACa;IAC3B;AACJ;AAEO,MAAMC,iBAAiB,CAACC,QACpB,OACHC,SACAC,SACAC,UACArB;QAEA,IAAKA,QAAQ,SAAS,EAGf;YAAA,IAAI,CAACkB,OAAO;gBACfI,QAAQ,GAAG,CAAC;gBACZ,OAAO;YACX;QAAA,OANwB;YACpBA,QAAQ,GAAG,CAAC;YACZ,OAAO;QACX;QAKA,MAAMrB,UAA2B;YAC7BkB;YACA,KAAKD,MAAM,GAAG,CAAC,GAAG;YAClBG;YACA,QAAQH,MAAM,MAAM,CAAC,IAAI;YACzB,QAAQA,MAAM,MAAM,CAAC,IAAI;YACzBE;YACA,MAAM,EAAE;QACZ;QAEA,MAAMf,QAAQa,MAAM,MAAM,CAAC,aAAa,IAAI;QAE5C,MAAMK,kBAAkBvB,QAAQ,SAAS,CAAC,OAAO,CAACwB;QAClD,IAAI,CAACD,gBAAgB,WAAW,IAAI,IAAI;YACpCD,QAAQ,GAAG,CAAC;YACZ,OAAO;QACX;QAEA,OAAO,MAAMC,gBAAgB,oBAAoB,CAAC;YAE9C,IAAIlB,QAAQ,GAAG;gBACX,IAAI;oBACA,OAAO,MAAMG,sBAAsB;wBAC/BR;wBACAC;wBACAI;oBACJ;gBACJ,EAAE,OAAM,CAER;gBACA,OAAO;YACX;YACA,OAAO,MAAMP,eAAe;gBACxBE;gBACAC;YACJ;QACJ;IACJ"}
@@ -1,9 +0,0 @@
1
- import { ContextPlugin } from "@webiny/api";
2
- import type { DynamoDBDocument } from "@webiny/aws-sdk/client-dynamodb/index.js";
3
- import type { AuditLogsContext } from "../types.js";
4
- export interface ISetupContextOptions {
5
- deleteLogsAfterDays: number | undefined;
6
- tableName: string | undefined;
7
- documentClient: DynamoDBDocument | undefined;
8
- }
9
- export declare const createAuditLogsContext: (params?: ISetupContextOptions) => ContextPlugin<AuditLogsContext>;
package/context/index.js DELETED
@@ -1,31 +0,0 @@
1
- import { ContextPlugin } from "@webiny/api";
2
- import { EventPublisher } from "@webiny/api-core/features/eventPublisher/index.js";
3
- import { createAuditLogsContextValue } from "./AuditLogsContextValue.js";
4
- import { createStorage } from "../storage/Storage.js";
5
- import { CompressionHandler } from "@webiny/utils/exports/api.js";
6
- const getDeleteLogsAfterDays = (days)=>{
7
- if (days && days > 0) return days;
8
- return 60;
9
- };
10
- const createAuditLogsContext = (params)=>{
11
- const plugin = new ContextPlugin(async (context)=>{
12
- const compressionHandler = context.container.resolve(CompressionHandler);
13
- const storage = createStorage({
14
- tableName: params?.tableName,
15
- client: params?.documentClient || context.db.driver.getClient(),
16
- compressionHandler
17
- });
18
- const eventPublisher = context.container.resolve(EventPublisher);
19
- context.auditLogs = createAuditLogsContextValue({
20
- getContext: ()=>context,
21
- deleteLogsAfterDays: getDeleteLogsAfterDays(params?.deleteLogsAfterDays),
22
- storage,
23
- eventPublisher
24
- });
25
- });
26
- plugin.name = "audit-logs.createContext";
27
- return plugin;
28
- };
29
- export { createAuditLogsContext };
30
-
31
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context/index.js","sources":["../../src/context/index.ts"],"sourcesContent":["import { ContextPlugin } from \"@webiny/api\";\nimport { EventPublisher } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport type { DynamoDBDocument } from \"@webiny/aws-sdk/client-dynamodb/index.js\";\nimport type { AuditLogsContext } from \"~/types.js\";\nimport { createAuditLogsContextValue } from \"./AuditLogsContextValue.js\";\nimport { createStorage } from \"~/storage/Storage.js\";\nimport { CompressionHandler } from \"@webiny/utils/exports/api.js\";\n\nexport interface ISetupContextOptions {\n deleteLogsAfterDays: number | undefined;\n tableName: string | undefined;\n documentClient: DynamoDBDocument | undefined;\n}\n\nconst getDeleteLogsAfterDays = (days?: number): number => {\n if (days && days > 0) {\n return days;\n }\n /**\n * Default days to delete logs after.\n */\n return 60;\n};\n\nexport const createAuditLogsContext = (params?: ISetupContextOptions) => {\n const plugin = new ContextPlugin<AuditLogsContext>(async context => {\n const compressionHandler = context.container.resolve(CompressionHandler);\n\n const storage = createStorage({\n tableName: params?.tableName,\n client: params?.documentClient || (context.db.driver.getClient() as DynamoDBDocument),\n compressionHandler\n });\n\n const eventPublisher = context.container.resolve(EventPublisher);\n\n context.auditLogs = createAuditLogsContextValue({\n getContext: () => {\n return context;\n },\n deleteLogsAfterDays: getDeleteLogsAfterDays(params?.deleteLogsAfterDays),\n storage,\n eventPublisher\n });\n });\n\n plugin.name = \"audit-logs.createContext\";\n\n return plugin;\n};\n"],"names":["getDeleteLogsAfterDays","days","createAuditLogsContext","params","plugin","ContextPlugin","context","compressionHandler","CompressionHandler","storage","createStorage","eventPublisher","EventPublisher","createAuditLogsContextValue"],"mappings":";;;;;AAcA,MAAMA,yBAAyB,CAACC;IAC5B,IAAIA,QAAQA,OAAO,GACf,OAAOA;IAKX,OAAO;AACX;AAEO,MAAMC,yBAAyB,CAACC;IACnC,MAAMC,SAAS,IAAIC,cAAgC,OAAMC;QACrD,MAAMC,qBAAqBD,QAAQ,SAAS,CAAC,OAAO,CAACE;QAErD,MAAMC,UAAUC,cAAc;YAC1B,WAAWP,QAAQ;YACnB,QAAQA,QAAQ,kBAAmBG,QAAQ,EAAE,CAAC,MAAM,CAAC,SAAS;YAC9DC;QACJ;QAEA,MAAMI,iBAAiBL,QAAQ,SAAS,CAAC,OAAO,CAACM;QAEjDN,QAAQ,SAAS,GAAGO,4BAA4B;YAC5C,YAAY,IACDP;YAEX,qBAAqBN,uBAAuBG,QAAQ;YACpDM;YACAE;QACJ;IACJ;IAEAP,OAAO,IAAI,GAAG;IAEd,OAAOA;AACX"}
@@ -1,3 +0,0 @@
1
- import { GraphQLSchemaPlugin } from "@webiny/handler-graphql";
2
- import type { AuditLogsContext } from "../types.js";
3
- export declare const createGraphQLSchema: () => GraphQLSchemaPlugin<AuditLogsContext>;