refactor(core): Decouple event bus from internal hooks (no-changelog) (#9724)
This commit is contained in:
@@ -24,6 +24,7 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||
import { ApplicationError } from 'n8n-workflow';
|
||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||
import { EventRelay } from '@/eventbus/event-relay.service';
|
||||
|
||||
@RestController()
|
||||
export class AuthController {
|
||||
@@ -35,6 +36,7 @@ export class AuthController {
|
||||
private readonly userService: UserService,
|
||||
private readonly license: License,
|
||||
private readonly userRepository: UserRepository,
|
||||
private readonly eventRelay: EventRelay,
|
||||
private readonly postHog?: PostHogClient,
|
||||
) {}
|
||||
|
||||
@@ -90,16 +92,17 @@ export class AuthController {
|
||||
}
|
||||
|
||||
this.authService.issueCookie(res, user, req.browserId);
|
||||
void this.internalHooks.onUserLoginSuccess({
|
||||
|
||||
this.eventRelay.emit('user-logged-in', {
|
||||
user,
|
||||
authenticationMethod: usedAuthenticationMethod,
|
||||
});
|
||||
|
||||
return await this.userService.toPublic(user, { posthog: this.postHog, withScopes: true });
|
||||
}
|
||||
void this.internalHooks.onUserLoginFailed({
|
||||
user: email,
|
||||
this.eventRelay.emit('user-login-failed', {
|
||||
authenticationMethod: usedAuthenticationMethod,
|
||||
userEmail: email,
|
||||
reason: 'wrong credentials',
|
||||
});
|
||||
throw new AuthError('Wrong username or password. Do you have caps lock on?');
|
||||
@@ -177,6 +180,7 @@ export class AuthController {
|
||||
}
|
||||
|
||||
void this.internalHooks.onUserInviteEmailClick({ inviter, invitee });
|
||||
this.eventRelay.emit('user-invite-email-click', { inviter, invitee });
|
||||
|
||||
const { firstName, lastName } = inviter;
|
||||
return { inviter: { firstName, lastName } };
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Push } from '@/push';
|
||||
import { CommunityPackagesService } from '@/services/communityPackages.service';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||
import { EventRelay } from '@/eventbus/event-relay.service';
|
||||
|
||||
const {
|
||||
PACKAGE_NOT_INSTALLED,
|
||||
@@ -38,6 +39,7 @@ export class CommunityPackagesController {
|
||||
private readonly push: Push,
|
||||
private readonly internalHooks: InternalHooks,
|
||||
private readonly communityPackagesService: CommunityPackagesService,
|
||||
private readonly eventRelay: EventRelay,
|
||||
) {}
|
||||
|
||||
// TODO: move this into a new decorator `@IfConfig('executions.mode', 'queue')`
|
||||
@@ -114,6 +116,14 @@ export class CommunityPackagesController {
|
||||
package_version: parsed.version,
|
||||
failure_reason: errorMessage,
|
||||
});
|
||||
this.eventRelay.emit('community-package-installed', {
|
||||
user: req.user,
|
||||
inputString: name,
|
||||
packageName: parsed.packageName,
|
||||
success: false,
|
||||
packageVersion: parsed.version,
|
||||
failureReason: errorMessage,
|
||||
});
|
||||
|
||||
let message = [`Error loading package "${name}" `, errorMessage].join(':');
|
||||
if (error instanceof Error && error.cause instanceof Error) {
|
||||
@@ -144,6 +154,16 @@ export class CommunityPackagesController {
|
||||
package_author: installedPackage.authorName,
|
||||
package_author_email: installedPackage.authorEmail,
|
||||
});
|
||||
this.eventRelay.emit('community-package-installed', {
|
||||
user: req.user,
|
||||
inputString: name,
|
||||
packageName: parsed.packageName,
|
||||
success: true,
|
||||
packageVersion: parsed.version,
|
||||
packageNodeNames: installedPackage.installedNodes.map((node) => node.name),
|
||||
packageAuthor: installedPackage.authorName,
|
||||
packageAuthorEmail: installedPackage.authorEmail,
|
||||
});
|
||||
|
||||
return installedPackage;
|
||||
}
|
||||
@@ -233,6 +253,14 @@ export class CommunityPackagesController {
|
||||
package_author: installedPackage.authorName,
|
||||
package_author_email: installedPackage.authorEmail,
|
||||
});
|
||||
this.eventRelay.emit('community-package-deleted', {
|
||||
user: req.user,
|
||||
packageName: name,
|
||||
packageVersion: installedPackage.installedVersion,
|
||||
packageNodeNames: installedPackage.installedNodes.map((node) => node.name),
|
||||
packageAuthor: installedPackage.authorName,
|
||||
packageAuthorEmail: installedPackage.authorEmail,
|
||||
});
|
||||
}
|
||||
|
||||
@Patch('/')
|
||||
@@ -281,6 +309,15 @@ export class CommunityPackagesController {
|
||||
package_author: newInstalledPackage.authorName,
|
||||
package_author_email: newInstalledPackage.authorEmail,
|
||||
});
|
||||
this.eventRelay.emit('community-package-updated', {
|
||||
user: req.user,
|
||||
packageName: name,
|
||||
packageVersionCurrent: previouslyInstalledPackage.installedVersion,
|
||||
packageVersionNew: newInstalledPackage.installedVersion,
|
||||
packageNodeNames: newInstalledPackage.installedNodes.map((n) => n.name),
|
||||
packageAuthor: newInstalledPackage.authorName,
|
||||
packageAuthorEmail: newInstalledPackage.authorEmail,
|
||||
});
|
||||
|
||||
return newInstalledPackage;
|
||||
} catch (error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||
import { InternalHooks } from '@/InternalHooks';
|
||||
import { ExternalHooks } from '@/ExternalHooks';
|
||||
import { EventRelay } from '@/eventbus/event-relay.service';
|
||||
|
||||
@RestController('/invitations')
|
||||
export class InvitationController {
|
||||
@@ -31,6 +32,7 @@ export class InvitationController {
|
||||
private readonly passwordUtility: PasswordUtility,
|
||||
private readonly userRepository: UserRepository,
|
||||
private readonly postHog: PostHogClient,
|
||||
private readonly eventRelay: EventRelay,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -170,6 +172,7 @@ export class InvitationController {
|
||||
user_type: 'email',
|
||||
was_disabled_ldap_user: false,
|
||||
});
|
||||
this.eventRelay.emit('user-signed-up', { user: updatedUser });
|
||||
|
||||
const publicInvitee = await this.userService.toPublic(invitee);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import { InternalHooks } from '@/InternalHooks';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||
import { isApiEnabled } from '@/PublicApi';
|
||||
import { EventRelay } from '@/eventbus/event-relay.service';
|
||||
|
||||
export const isApiEnabledMiddleware: RequestHandler = (_, res, next) => {
|
||||
if (isApiEnabled()) {
|
||||
@@ -42,6 +43,7 @@ export class MeController {
|
||||
private readonly userService: UserService,
|
||||
private readonly passwordUtility: PasswordUtility,
|
||||
private readonly userRepository: UserRepository,
|
||||
private readonly eventRelay: EventRelay,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -96,11 +98,9 @@ export class MeController {
|
||||
|
||||
this.authService.issueCookie(res, user, req.browserId);
|
||||
|
||||
const updatedKeys = Object.keys(payload);
|
||||
void this.internalHooks.onUserUpdate({
|
||||
user,
|
||||
fields_changed: updatedKeys,
|
||||
});
|
||||
const fieldsChanged = Object.keys(payload);
|
||||
void this.internalHooks.onUserUpdate({ user, fields_changed: fieldsChanged });
|
||||
this.eventRelay.emit('user-updated', { user, fieldsChanged });
|
||||
|
||||
const publicUser = await this.userService.toPublic(user);
|
||||
|
||||
@@ -149,10 +149,8 @@ export class MeController {
|
||||
|
||||
this.authService.issueCookie(res, updatedUser, req.browserId);
|
||||
|
||||
void this.internalHooks.onUserUpdate({
|
||||
user: updatedUser,
|
||||
fields_changed: ['password'],
|
||||
});
|
||||
void this.internalHooks.onUserUpdate({ user: updatedUser, fields_changed: ['password'] });
|
||||
this.eventRelay.emit('user-updated', { user: updatedUser, fieldsChanged: ['password'] });
|
||||
|
||||
await this.externalHooks.run('user.password.update', [updatedUser.email, updatedUser.password]);
|
||||
|
||||
@@ -200,10 +198,8 @@ export class MeController {
|
||||
|
||||
await this.userService.update(req.user.id, { apiKey });
|
||||
|
||||
void this.internalHooks.onApiKeyCreated({
|
||||
user: req.user,
|
||||
public_api: false,
|
||||
});
|
||||
void this.internalHooks.onApiKeyCreated({ user: req.user, public_api: false });
|
||||
this.eventRelay.emit('api-key-created', { user: req.user });
|
||||
|
||||
return { apiKey };
|
||||
}
|
||||
@@ -223,10 +219,8 @@ export class MeController {
|
||||
async deleteAPIKey(req: AuthenticatedRequest) {
|
||||
await this.userService.update(req.user.id, { apiKey: null });
|
||||
|
||||
void this.internalHooks.onApiKeyDeleted({
|
||||
user: req.user,
|
||||
public_api: false,
|
||||
});
|
||||
void this.internalHooks.onApiKeyDeleted({ user: req.user, public_api: false });
|
||||
this.eventRelay.emit('api-key-deleted', { user: req.user });
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||
import { UnprocessableRequestError } from '@/errors/response-errors/unprocessable.error';
|
||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||
import { EventRelay } from '@/eventbus/event-relay.service';
|
||||
|
||||
@RestController()
|
||||
export class PasswordResetController {
|
||||
@@ -36,6 +37,7 @@ export class PasswordResetController {
|
||||
private readonly license: License,
|
||||
private readonly passwordUtility: PasswordUtility,
|
||||
private readonly userRepository: UserRepository,
|
||||
private readonly eventRelay: EventRelay,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -123,6 +125,7 @@ export class PasswordResetController {
|
||||
message_type: 'Reset password',
|
||||
public_api: false,
|
||||
});
|
||||
this.eventRelay.emit('email-failed', { user, messageType: 'Reset password' });
|
||||
if (error instanceof Error) {
|
||||
throw new InternalServerError(`Please contact your administrator: ${error.message}`);
|
||||
}
|
||||
@@ -136,6 +139,7 @@ export class PasswordResetController {
|
||||
});
|
||||
|
||||
void this.internalHooks.onUserPasswordResetRequestClick({ user });
|
||||
this.eventRelay.emit('user-password-reset-request-click', { user });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,6 +172,7 @@ export class PasswordResetController {
|
||||
|
||||
this.logger.info('Reset-password token resolved successfully', { userId: user.id });
|
||||
void this.internalHooks.onUserPasswordResetEmailClick({ user });
|
||||
this.eventRelay.emit('user-password-reset-email-click', { user });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,10 +215,8 @@ export class PasswordResetController {
|
||||
|
||||
this.authService.issueCookie(res, user, req.browserId);
|
||||
|
||||
void this.internalHooks.onUserUpdate({
|
||||
user,
|
||||
fields_changed: ['password'],
|
||||
});
|
||||
void this.internalHooks.onUserUpdate({ user, fields_changed: ['password'] });
|
||||
this.eventRelay.emit('user-updated', { user, fieldsChanged: ['password'] });
|
||||
|
||||
// if this user used to be an LDAP users
|
||||
const ldapIdentity = user?.authIdentities?.find((i) => i.providerType === 'ldap');
|
||||
@@ -222,6 +225,7 @@ export class PasswordResetController {
|
||||
user_type: 'email',
|
||||
was_disabled_ldap_user: true,
|
||||
});
|
||||
this.eventRelay.emit('user-signed-up', { user });
|
||||
}
|
||||
|
||||
await this.externalHooks.run('user.password.update', [user.email, passwordHash]);
|
||||
|
||||
@@ -28,6 +28,7 @@ import { Project } from '@/databases/entities/Project';
|
||||
import { WorkflowService } from '@/workflows/workflow.service';
|
||||
import { CredentialsService } from '@/credentials/credentials.service';
|
||||
import { ProjectService } from '@/services/project.service';
|
||||
import { EventRelay } from '@/eventbus/event-relay.service';
|
||||
|
||||
@RestController('/users')
|
||||
export class UsersController {
|
||||
@@ -44,6 +45,7 @@ export class UsersController {
|
||||
private readonly workflowService: WorkflowService,
|
||||
private readonly credentialsService: CredentialsService,
|
||||
private readonly projectService: ProjectService,
|
||||
private readonly eventRelay: EventRelay,
|
||||
) {}
|
||||
|
||||
static ERROR_MESSAGES = {
|
||||
@@ -256,6 +258,7 @@ export class UsersController {
|
||||
telemetryData,
|
||||
publicApi: false,
|
||||
});
|
||||
this.eventRelay.emit('user-deleted', { user: req.user });
|
||||
|
||||
await this.externalHooks.run('user.deleted', [await this.userService.toPublic(userToDelete)]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user