7154 deleted event is not emitted when calling destroyone (#7159)
Closes #7154
This commit is contained in:
@ -35,6 +35,7 @@ import {
|
|||||||
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
|
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
|
||||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||||
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||||
|
import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event';
|
||||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||||
@ -284,10 +285,94 @@ export class GraphqlQueryRunnerService {
|
|||||||
async destroyOne<ObjectRecord extends IRecord = IRecord>(
|
async destroyOne<ObjectRecord extends IRecord = IRecord>(
|
||||||
args: DestroyOneResolverArgs,
|
args: DestroyOneResolverArgs,
|
||||||
options: WorkspaceQueryRunnerOptions,
|
options: WorkspaceQueryRunnerOptions,
|
||||||
): Promise<ObjectRecord> {
|
): Promise<ObjectRecord | undefined> {
|
||||||
const graphqlQueryDestroyOneResolverService =
|
const graphqlQueryDestroyOneResolverService =
|
||||||
new GraphqlQueryDestroyOneResolverService(this.twentyORMGlobalManager);
|
new GraphqlQueryDestroyOneResolverService(this.twentyORMGlobalManager);
|
||||||
|
|
||||||
return graphqlQueryDestroyOneResolverService.destroyOne(args, options);
|
const { authContext, objectMetadataItem } = options;
|
||||||
|
|
||||||
|
assertMutationNotOnRemoteObject(objectMetadataItem);
|
||||||
|
assertIsValidUuid(args.id);
|
||||||
|
|
||||||
|
const hookedArgs =
|
||||||
|
await this.workspaceQueryHookService.executePreQueryHooks(
|
||||||
|
authContext,
|
||||||
|
objectMetadataItem.nameSingular,
|
||||||
|
'destroyOne',
|
||||||
|
args,
|
||||||
|
);
|
||||||
|
|
||||||
|
const computedArgs = (await this.queryRunnerArgsFactory.create(
|
||||||
|
hookedArgs,
|
||||||
|
options,
|
||||||
|
ResolverArgsType.DestroyOne,
|
||||||
|
)) as DestroyOneResolverArgs;
|
||||||
|
|
||||||
|
const result = (await graphqlQueryDestroyOneResolverService.destroyOne(
|
||||||
|
computedArgs,
|
||||||
|
options,
|
||||||
|
)) as ObjectRecord;
|
||||||
|
|
||||||
|
await this.workspaceQueryHookService.executePostQueryHooks(
|
||||||
|
authContext,
|
||||||
|
objectMetadataItem.nameSingular,
|
||||||
|
'destroyOne',
|
||||||
|
[result],
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.triggerWebhooks<IRecord>(
|
||||||
|
[result],
|
||||||
|
CallWebhookJobsJobOperation.destroy,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.emitDestroyEvents<IRecord>([result], authContext, objectMetadataItem);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private emitDestroyEvents<BaseRecord extends IRecord = IRecord>(
|
||||||
|
records: BaseRecord[],
|
||||||
|
authContext: AuthContext,
|
||||||
|
objectMetadataItem: ObjectMetadataInterface,
|
||||||
|
) {
|
||||||
|
this.workspaceEventEmitter.emit(
|
||||||
|
`${objectMetadataItem.nameSingular}.destroyed`,
|
||||||
|
records.map((record) => {
|
||||||
|
return {
|
||||||
|
userId: authContext.user?.id,
|
||||||
|
recordId: record.id,
|
||||||
|
objectMetadata: objectMetadataItem,
|
||||||
|
properties: {
|
||||||
|
before: this.removeNestedProperties(record),
|
||||||
|
},
|
||||||
|
} satisfies ObjectRecordDeleteEvent<any>;
|
||||||
|
}),
|
||||||
|
authContext.workspace.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeNestedProperties<Record extends IRecord = IRecord>(
|
||||||
|
record: Record,
|
||||||
|
) {
|
||||||
|
if (!record) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sanitizedRecord = {};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(record)) {
|
||||||
|
if (value && typeof value === 'object' && value['edges']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === '__typename') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sanitizedRecord[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sanitizedRecord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export enum CallWebhookJobsJobOperation {
|
|||||||
create = 'create',
|
create = 'create',
|
||||||
update = 'update',
|
update = 'update',
|
||||||
delete = 'delete',
|
delete = 'delete',
|
||||||
|
destroy = 'destroy',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CallWebhookJobsJobData = {
|
export type CallWebhookJobsJobData = {
|
||||||
|
|||||||
@ -49,6 +49,13 @@ export class EntityEventsToDbListener {
|
|||||||
return this.handle(payload);
|
return this.handle(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnEvent('*.destroyed')
|
||||||
|
async handleDestroy(
|
||||||
|
payload: WorkspaceEventBatch<ObjectRecordUpdateEvent<any>>,
|
||||||
|
) {
|
||||||
|
return this.handle(payload);
|
||||||
|
}
|
||||||
|
|
||||||
private async handle(payload: WorkspaceEventBatch<ObjectRecordBaseEvent>) {
|
private async handle(payload: WorkspaceEventBatch<ObjectRecordBaseEvent>) {
|
||||||
const filteredEvents = payload.events.filter(
|
const filteredEvents = payload.events.filter(
|
||||||
(event) => event.objectMetadata?.isAuditLogged,
|
(event) => event.objectMetadata?.isAuditLogged,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
DeleteManyResolverArgs,
|
DeleteManyResolverArgs,
|
||||||
DeleteOneResolverArgs,
|
DeleteOneResolverArgs,
|
||||||
DestroyManyResolverArgs,
|
DestroyManyResolverArgs,
|
||||||
|
DestroyOneResolverArgs,
|
||||||
FindDuplicatesResolverArgs,
|
FindDuplicatesResolverArgs,
|
||||||
FindManyResolverArgs,
|
FindManyResolverArgs,
|
||||||
FindOneResolverArgs,
|
FindOneResolverArgs,
|
||||||
@ -39,4 +40,6 @@ export type WorkspacePreQueryHookPayload<T> = T extends 'createMany'
|
|||||||
? RestoreManyResolverArgs
|
? RestoreManyResolverArgs
|
||||||
: T extends 'destroyMany'
|
: T extends 'destroyMany'
|
||||||
? DestroyManyResolverArgs
|
? DestroyManyResolverArgs
|
||||||
: never;
|
: T extends 'destroyOne'
|
||||||
|
? DestroyOneResolverArgs
|
||||||
|
: never;
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export enum ResolverArgsType {
|
|||||||
DeleteMany = 'DeleteMany',
|
DeleteMany = 'DeleteMany',
|
||||||
RestoreMany = 'RestoreMany',
|
RestoreMany = 'RestoreMany',
|
||||||
DestroyMany = 'DestroyMany',
|
DestroyMany = 'DestroyMany',
|
||||||
|
DestroyOne = 'DestroyOne',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FindManyResolverArgs<
|
export interface FindManyResolverArgs<
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event';
|
||||||
|
|
||||||
|
export class ObjectRecordDestroyEvent<T> extends ObjectRecordBaseEvent {
|
||||||
|
properties: {
|
||||||
|
before: T;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -19,8 +19,8 @@ export class CalendarEventCleanerConnectedAccountListener {
|
|||||||
private readonly calendarQueueService: MessageQueueService,
|
private readonly calendarQueueService: MessageQueueService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@OnEvent('connectedAccount.deleted')
|
@OnEvent('connectedAccount.destroyed')
|
||||||
async handleDeletedEvent(
|
async handleDestroyedEvent(
|
||||||
payload: WorkspaceEventBatch<
|
payload: WorkspaceEventBatch<
|
||||||
ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity>
|
ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity>
|
||||||
>,
|
>,
|
||||||
|
|||||||
@ -15,8 +15,8 @@ export class ConnectedAccountListener {
|
|||||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@OnEvent('connectedAccount.deleted')
|
@OnEvent('connectedAccount.destroyed')
|
||||||
async handleDeletedEvent(
|
async handleDestroyedEvent(
|
||||||
payload: WorkspaceEventBatch<
|
payload: WorkspaceEventBatch<
|
||||||
ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity>
|
ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity>
|
||||||
>,
|
>,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
|||||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
|
|
||||||
@WorkspaceQueryHook(`connectedAccount.deleteOne`)
|
@WorkspaceQueryHook(`connectedAccount.destroyOne`)
|
||||||
export class ConnectedAccountDeleteOnePreQueryHook
|
export class ConnectedAccountDeleteOnePreQueryHook
|
||||||
implements WorkspaceQueryHookInstance
|
implements WorkspaceQueryHookInstance
|
||||||
{
|
{
|
||||||
@ -34,7 +34,7 @@ export class ConnectedAccountDeleteOnePreQueryHook
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.workspaceEventEmitter.emit(
|
this.workspaceEventEmitter.emit(
|
||||||
'messageChannel.deleted',
|
'messageChannel.destroyed',
|
||||||
messageChannels.map(
|
messageChannels.map(
|
||||||
(messageChannel) =>
|
(messageChannel) =>
|
||||||
({
|
({
|
||||||
|
|||||||
@ -19,8 +19,8 @@ export class MessagingMessageCleanerConnectedAccountListener {
|
|||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@OnEvent('connectedAccount.deleted')
|
@OnEvent('connectedAccount.destroyed')
|
||||||
async handleDeletedEvent(
|
async handleDestroyedEvent(
|
||||||
payload: WorkspaceEventBatch<
|
payload: WorkspaceEventBatch<
|
||||||
ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity>
|
ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity>
|
||||||
>,
|
>,
|
||||||
|
|||||||
@ -19,8 +19,8 @@ export class MessagingMessageImportManagerMessageChannelListener {
|
|||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@OnEvent('messageChannel.deleted')
|
@OnEvent('messageChannel.destroyed')
|
||||||
async handleDeletedEvent(
|
async handleDestroyedEvent(
|
||||||
payload: WorkspaceEventBatch<
|
payload: WorkspaceEventBatch<
|
||||||
ObjectRecordDeleteEvent<MessageChannelWorkspaceEntity>
|
ObjectRecordDeleteEvent<MessageChannelWorkspaceEntity>
|
||||||
>,
|
>,
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { OnEvent } from '@nestjs/event-emitter';
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
|
|
||||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
|
||||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
|
||||||
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||||
import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event';
|
import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event';
|
||||||
|
import { ObjectRecordDestroyEvent } from 'src/engine/core-modules/event-emitter/types/object-record-destroy.event';
|
||||||
import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
|
import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
|
||||||
|
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||||
|
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||||
@ -49,11 +50,19 @@ export class DatabaseEventTriggerListener {
|
|||||||
await this.handleEvent(payload);
|
await this.handleEvent(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnEvent('*.destroyed')
|
||||||
|
async handleObjectRecordDestroyEvent(
|
||||||
|
payload: WorkspaceEventBatch<ObjectRecordDestroyEvent<any>>,
|
||||||
|
) {
|
||||||
|
await this.handleEvent(payload);
|
||||||
|
}
|
||||||
|
|
||||||
private async handleEvent(
|
private async handleEvent(
|
||||||
payload: WorkspaceEventBatch<
|
payload: WorkspaceEventBatch<
|
||||||
| ObjectRecordCreateEvent<any>
|
| ObjectRecordCreateEvent<any>
|
||||||
| ObjectRecordUpdateEvent<any>
|
| ObjectRecordUpdateEvent<any>
|
||||||
| ObjectRecordDeleteEvent<any>
|
| ObjectRecordDeleteEvent<any>
|
||||||
|
| ObjectRecordDestroyEvent<any>
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
const workspaceId = payload.workspaceId;
|
const workspaceId = payload.workspaceId;
|
||||||
|
|||||||
Reference in New Issue
Block a user