mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
refactor(nestjs): Implement users module
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectQueue } from '@nestjs/bull';
|
||||
import { Queue } from 'bull';
|
||||
import { events } from '@/common/events/events';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import {
|
||||
IUserInviteTenantSyncedEventPayload,
|
||||
SendInviteUserMailJobPayload,
|
||||
} from '../Users.types';
|
||||
import {
|
||||
SendInviteUserMailJob,
|
||||
SendInviteUserMailQueue,
|
||||
} from '../Users.constants';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export default class InviteSendMainNotificationSubscribe {
|
||||
constructor(
|
||||
@InjectQueue(SendInviteUserMailQueue)
|
||||
private readonly sendInviteMailQueue: Queue,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Sends mail notification.
|
||||
* @param {IUserInvitedEventPayload} payload
|
||||
*/
|
||||
@OnEvent(events.inviteUser.sendInviteTenantSynced)
|
||||
async sendMailNotification({
|
||||
invite,
|
||||
user,
|
||||
}: IUserInviteTenantSyncedEventPayload) {
|
||||
const tenant = await this.tenancyContext.getTenant();
|
||||
const authedUser = await this.tenancyContext.getSystemUser();
|
||||
|
||||
const organizationId = tenant.organizationId;
|
||||
const userId = authedUser.id;
|
||||
|
||||
this.sendInviteMailQueue.add(SendInviteUserMailJob, {
|
||||
fromUser: user,
|
||||
invite,
|
||||
userId,
|
||||
organizationId,
|
||||
} as SendInviteUserMailJobPayload);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import {
|
||||
ITenantUserInactivatedPayload,
|
||||
ITenantUserActivatedPayload,
|
||||
ITenantUserDeletedPayload,
|
||||
ITenantUserEditedPayload,
|
||||
} from '../Users.types';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ABILITIES_CACHE } from '@/modules/Roles/TenantAbilities';
|
||||
|
||||
@Injectable()
|
||||
export class PurgeUserAbilityCacheSubscriber {
|
||||
/**
|
||||
* Purges authorized user ability once the user mutate.
|
||||
*/
|
||||
@OnEvent(events.tenantUser.onEdited)
|
||||
@OnEvent(events.tenantUser.onActivated)
|
||||
@OnEvent(events.tenantUser.onInactivated)
|
||||
purgeAuthorizedUserAbility({
|
||||
tenantUser,
|
||||
}:
|
||||
| ITenantUserInactivatedPayload
|
||||
| ITenantUserActivatedPayload
|
||||
| ITenantUserDeletedPayload
|
||||
| ITenantUserEditedPayload) {
|
||||
ABILITIES_CACHE.del(tenantUser.systemUserId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
IUserInvitedEventPayload,
|
||||
IUserInviteResendEventPayload,
|
||||
IUserInviteTenantSyncedEventPayload,
|
||||
} from '../Users.types';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { TenantUser } from '@/modules/Tenancy/TenancyModels/models/TenantUser.model';
|
||||
import { UserInvite } from '../models/InviteUser.model';
|
||||
import { SystemUser } from '@/modules/System/models/SystemUser';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export class SyncSystemSendInviteSubscriber {
|
||||
constructor(
|
||||
@Inject(TenantUser.name)
|
||||
private readonly tenantUserModel: TenantModelProxy<typeof TenantUser>,
|
||||
|
||||
@Inject(SystemUser.name)
|
||||
private readonly systemUserModel: typeof SystemUser,
|
||||
|
||||
@Inject(UserInvite.name)
|
||||
private readonly inviteModel: typeof UserInvite,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly tenancyContext: TenancyContext
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Syncs send invite to system user.
|
||||
* @param {IUserInvitedEventPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.inviteUser.sendInvite)
|
||||
async syncSendInviteSystem({ inviteToken, user }: IUserInvitedEventPayload) {
|
||||
const authorizedUser = await this.tenancyContext.getSystemUser();
|
||||
const tenantId = authorizedUser.tenantId;
|
||||
|
||||
// Creates a new system user.
|
||||
const systemUser = await this.systemUserModel.query().insert({
|
||||
email: user.email,
|
||||
active: user.active,
|
||||
tenantId,
|
||||
|
||||
// Email should be verified since the user got the invite token through email.
|
||||
verified: true,
|
||||
});
|
||||
// Creates a invite user token.
|
||||
const invite = await this.inviteModel.query().insert({
|
||||
email: user.email,
|
||||
tenantId,
|
||||
userId: systemUser.id,
|
||||
token: inviteToken,
|
||||
});
|
||||
// Links the tenant user with created system user.
|
||||
await this.tenantUserModel().query().findById(user.id).patch({
|
||||
systemUserId: systemUser.id,
|
||||
});
|
||||
// Triggers `onUserSendInviteTenantSynced` event.
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.inviteUser.sendInviteTenantSynced,
|
||||
{
|
||||
invite,
|
||||
user,
|
||||
} as IUserInviteTenantSyncedEventPayload,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs resend invite to system user.
|
||||
* @param {IUserInviteResendEventPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.inviteUser.resendInvite)
|
||||
async syncResendInviteSystemUser({
|
||||
inviteToken,
|
||||
user,
|
||||
}: IUserInviteResendEventPayload) {
|
||||
const authorizedUser = await this.tenancyContext.getSystemUser();
|
||||
const tenantId = authorizedUser.tenantId;
|
||||
|
||||
// Clear all invite tokens of the given user id.
|
||||
await this.clearInviteTokensByUserId(tenantId, user.systemUserId);
|
||||
|
||||
const invite = await this.inviteModel.query().insert({
|
||||
email: user.email,
|
||||
tenantId,
|
||||
userId: user.systemUserId,
|
||||
token: inviteToken,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear invite tokens of the given user id.
|
||||
* @param {number} userId - User id.
|
||||
*/
|
||||
private clearInviteTokensByUserId = async (tenantId: number, userId: number) => {
|
||||
await this.inviteModel
|
||||
.query()
|
||||
.where({
|
||||
userId,
|
||||
tenantId,
|
||||
})
|
||||
.delete();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { omit } from 'lodash';
|
||||
import * as moment from 'moment';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { TenantUser } from '@/modules/Tenancy/TenancyModels/models/TenantUser.model';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IAcceptInviteEventPayload } from '../Users.types';
|
||||
|
||||
@Injectable()
|
||||
export class SyncTenantAcceptInviteSubscriber {
|
||||
constructor(
|
||||
@Inject(TenantUser.name)
|
||||
private readonly tenantUserModel: TenantModelProxy<typeof TenantUser>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Syncs accept invite to tenant user.
|
||||
* @param {IAcceptInviteEventPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.inviteUser.acceptInvite)
|
||||
async syncTenantAcceptInvite({
|
||||
inviteToken,
|
||||
user,
|
||||
inviteUserDTO,
|
||||
}: IAcceptInviteEventPayload) {
|
||||
await this.tenantUserModel()
|
||||
.query()
|
||||
.where('systemUserId', inviteToken.userId)
|
||||
.update({
|
||||
...omit(inviteUserDTO, ['password']),
|
||||
inviteAcceptedAt: moment().format('YYYY-MM-DD'),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { events } from '@/common/events/events';
|
||||
import { SystemUser } from '@/modules/System/models/SystemUser';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { ITenantUserDeletedPayload } from '../Users.types';
|
||||
|
||||
@Injectable()
|
||||
export class SyncTenantUserDeleteSubscriber {
|
||||
constructor(
|
||||
@Inject(SystemUser.name)
|
||||
private readonly systemUserModel: typeof SystemUser,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Deletes the system user once tenant user be deleted.
|
||||
* @param {ITenantUserDeletedPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.tenantUser.onDeleted)
|
||||
async syncSystemUserOnceUserDeleted({
|
||||
tenantUser,
|
||||
}: ITenantUserDeletedPayload) {
|
||||
await this.systemUserModel
|
||||
.query()
|
||||
.where('id', tenantUser.systemUserId)
|
||||
.delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { pick } from 'lodash';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ITenantUserActivatedPayload,
|
||||
ITenantUserEditedPayload,
|
||||
ITenantUserInactivatedPayload,
|
||||
} from '../Users.types'
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { SystemUser } from '@/modules/System/models/SystemUser';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class SyncTenantUserMutateSubscriber {
|
||||
constructor(
|
||||
@Inject(SystemUser.name)
|
||||
private readonly systemUserModel: typeof SystemUser,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param {ITenantUserEditedPayload} payload
|
||||
*/
|
||||
@OnEvent(events.tenantUser.onEdited)
|
||||
async syncSystemUserOnceEdited({ tenantUser }: ITenantUserEditedPayload) {
|
||||
await this.systemUserModel
|
||||
.query()
|
||||
.where('id', tenantUser.systemUserId)
|
||||
.patch({
|
||||
...pick(tenantUser, [
|
||||
'firstName',
|
||||
'lastName',
|
||||
'email',
|
||||
'active',
|
||||
'phoneNumber',
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs activate system user.
|
||||
* @param {ITenantUserInactivatedPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.tenantUser.onActivated)
|
||||
async syncSystemUserOnceActivated({
|
||||
tenantUser,
|
||||
}: ITenantUserInactivatedPayload) {
|
||||
await this.systemUserModel
|
||||
.query()
|
||||
.where('id', tenantUser.systemUserId)
|
||||
.patch({
|
||||
active: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs inactivate system user.
|
||||
* @param {ITenantUserActivatedPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.tenantUser.onInactivated)
|
||||
async syncSystemUserOnceInactivated({
|
||||
tenantUser,
|
||||
}: ITenantUserActivatedPayload) {
|
||||
await this.systemUserModel
|
||||
.query()
|
||||
.where('id', tenantUser.systemUserId)
|
||||
.patch({
|
||||
active: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user