fix(server): sending invite email

This commit is contained in:
a.bouhuolia
2023-05-05 00:28:57 +02:00
parent 4d44ce4c7f
commit 3ceb9adda2
11 changed files with 60 additions and 34 deletions

View File

@@ -4,6 +4,7 @@ import moment from 'moment';
global.__root_dir = path.join(__dirname, '..'); global.__root_dir = path.join(__dirname, '..');
global.__resources_dir = path.join(global.__root_dir, 'resources'); global.__resources_dir = path.join(global.__root_dir, 'resources');
global.__locales_dir = path.join(global.__resources_dir, 'locales'); global.__locales_dir = path.join(global.__resources_dir, 'locales');
global.__views_dir = path.join(global.__root_dir, 'views');
moment.prototype.toMySqlDateTime = function () { moment.prototype.toMySqlDateTime = function () {
return this.format('YYYY-MM-DD HH:mm:ss'); return this.format('YYYY-MM-DD HH:mm:ss');

View File

@@ -1,6 +1,7 @@
import { AnyObject } from '@casl/ability/dist/types/types'; import { AnyObject } from '@casl/ability/dist/types/types';
import { ITenant } from '@/interfaces'; import { ITenant } from '@/interfaces';
import { Model } from 'objection'; import { Model } from 'objection';
import { Tenant } from '@/system/models';
export interface ISystemUser extends Model { export interface ISystemUser extends Model {
id: number; id: number;
@@ -54,20 +55,52 @@ export interface IUserInvite {
export interface IInviteUserService { export interface IInviteUserService {
acceptInvite(token: string, inviteUserInput: IInviteUserInput): Promise<void>; acceptInvite(token: string, inviteUserInput: IInviteUserInput): Promise<void>;
/**
* Re-send user invite.
* @param {number} tenantId -
* @param {string} email -
* @return {Promise<{ invite: IUserInvite }>}
*/
resendInvite( resendInvite(
tenantId: number, tenantId: number,
userId: number, userId: number,
authorizedUser: ISystemUser authorizedUser: ISystemUser
): Promise<{ ): Promise<{
invite: IUserInvite; user: ITenantUser;
}>; }>;
/**
* Sends invite mail to the given email from the given tenant and user.
* @param {number} tenantId -
* @param {string} email -
* @param {IUser} authorizedUser -
* @return {Promise<IUserInvite>}
*/
sendInvite( sendInvite(
tenantId: number, tenantId: number,
email: string, sendInviteDTO: IUserSendInviteDTO,
authorizedUser: ISystemUser authorizedUser: ISystemUser
): Promise<{ ): Promise<{
invite: IUserInvite; invitedUser: ITenantUser;
}>; }>;
}
export interface IAcceptInviteUserService {
/**
* Accept the received invite.
* @param {string} token
* @param {IInviteUserInput} inviteUserInput
* @throws {ServiceErrors}
* @returns {Promise<void>}
*/
acceptInvite(token: string, inviteUserDTO: IInviteUserInput): Promise<void>;
/**
* Validate the given invite token.
* @param {string} token - the given token string.
* @throws {ServiceError}
*/
checkInvite( checkInvite(
token: string token: string
): Promise<{ inviteToken: IUserInvite; orgName: object }>; ): Promise<{ inviteToken: IUserInvite; orgName: object }>;
@@ -121,7 +154,7 @@ export interface IUserInvitedEventPayload {
tenantId: number; tenantId: number;
user: ITenantUser; user: ITenantUser;
} }
export interface IUserInviteTenantSyncedEventPayload{ export interface IUserInviteTenantSyncedEventPayload {
invite: IUserInvite; invite: IUserInvite;
authorizedUser: ISystemUser; authorizedUser: ISystemUser;
tenantId: number; tenantId: number;
@@ -143,7 +176,7 @@ export interface IAcceptInviteEventPayload {
export interface ICheckInviteEventPayload { export interface ICheckInviteEventPayload {
inviteToken: IUserInvite; inviteToken: IUserInvite;
tenant: ITenant tenant: Tenant;
} }
export interface IUserSendInviteDTO { export interface IUserSendInviteDTO {

View File

@@ -1,5 +1,6 @@
import { Container, Inject } from 'typedi'; import { Container, Inject } from 'typedi';
import InviteUserService from '@/services/InviteUsers/AcceptInviteUser'; import InviteUserService from '@/services/InviteUsers/AcceptInviteUser';
import SendInviteUsersMailMessage from '@/services/InviteUsers/SendInviteUsersMailMessage';
export default class UserInviteMailJob { export default class UserInviteMailJob {
/** /**
@@ -21,24 +22,17 @@ export default class UserInviteMailJob {
*/ */
public async handler(job, done: Function): Promise<void> { public async handler(job, done: Function): Promise<void> {
const { invite, authorizedUser, tenantId } = job.attrs.data; const { invite, authorizedUser, tenantId } = job.attrs.data;
const sendInviteMailMessage = Container.get(SendInviteUsersMailMessage);
const Logger = Container.get('logger');
const inviteUsersService = Container.get(InviteUserService);
Logger.info(`Send invite user mail - started: ${job.attrs.data}`);
try { try {
await inviteUsersService.mailMessages.sendInviteMail( await sendInviteMailMessage.sendInviteMail(
tenantId, tenantId,
authorizedUser, authorizedUser,
invite invite
); );
Logger.info(`Send invite user mail - finished: ${job.attrs.data}`);
done(); done();
} catch (error) { } catch (error) {
Logger.info( console.log(error);
`Send invite user mail - error: ${job.attrs.data}, error: ${error}`
);
done(error); done(error);
} }
} }

View File

@@ -109,7 +109,7 @@ export default class Mail {
* Retrieve view content from the view directory. * Retrieve view content from the view directory.
*/ */
private getViewContent(): string { private getViewContent(): string {
const filePath = path.join(global.__root_dir, `../views/${this.view}`); const filePath = path.join(global.__views_dir, `/${this.view}`);
return fs.readFileSync(filePath, 'utf8'); return fs.readFileSync(filePath, 'utf8');
} }
} }

View File

@@ -22,7 +22,7 @@ import SaleInvoiceAutoIncrementSubscriber from '@/subscribers/SaleInvoices/AutoI
import SaleInvoiceConvertFromEstimateSubscriber from '@/subscribers/SaleInvoices/ConvertFromEstimate'; import SaleInvoiceConvertFromEstimateSubscriber from '@/subscribers/SaleInvoices/ConvertFromEstimate';
import PaymentReceiveAutoSerialSubscriber from '@/subscribers/PaymentReceive/AutoSerialIncrement'; import PaymentReceiveAutoSerialSubscriber from '@/subscribers/PaymentReceive/AutoSerialIncrement';
import SyncSystemSendInvite from '@/services/InviteUsers/SyncSystemSendInvite'; import SyncSystemSendInvite from '@/services/InviteUsers/SyncSystemSendInvite';
import InviteSendMainNotification from '@/services/InviteUsers/InviteSendMailNotification'; import InviteSendMainNotification from '@/services/InviteUsers/InviteSendMailNotificationSubscribe';
import SyncTenantAcceptInvite from '@/services/InviteUsers/SyncTenantAcceptInvite'; import SyncTenantAcceptInvite from '@/services/InviteUsers/SyncTenantAcceptInvite';
import SyncTenantUserMutate from '@/services/Users/SyncTenantUserSaved'; import SyncTenantUserMutate from '@/services/Users/SyncTenantUserSaved';
import { SyncTenantUserDelete } from '@/services/Users/SyncTenantUserDeleted'; import { SyncTenantUserDelete } from '@/services/Users/SyncTenantUserDeleted';

View File

@@ -12,9 +12,12 @@ import {
} from '@/interfaces'; } from '@/interfaces';
import { ERRORS } from './constants'; import { ERRORS } from './constants';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import { IAcceptInviteUserService } from '@/interfaces';
@Service() @Service()
export default class AcceptInviteUserService { export default class AcceptInviteUserService
implements IAcceptInviteUserService
{
@Inject() @Inject()
private eventPublisher: EventPublisher; private eventPublisher: EventPublisher;

View File

@@ -1,7 +1,4 @@
import { import { IUserInviteTenantSyncedEventPayload } from '@/interfaces';
IUserInvitedEventPayload,
IUserInviteTenantSyncedEventPayload,
} from '@/interfaces';
import events from '@/subscribers/events'; import events from '@/subscribers/events';
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';

View File

@@ -1,12 +1,12 @@
import path from 'path';
import { ISystemUser } from '@/interfaces'; import { ISystemUser } from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService';
import Mail from '@/lib/Mail'; import Mail from '@/lib/Mail';
import { Service, Container } from 'typedi'; import { Service } from 'typedi';
import config from '@/config';
import { Tenant } from '@/system/models'; import { Tenant } from '@/system/models';
import config from '@/config';
@Service() @Service()
export default class InviteUsersMailMessages { export default class SendInviteUsersMailMessage {
/** /**
* Sends invite mail to the given email. * Sends invite mail to the given email.
* @param user * @param user
@@ -18,7 +18,7 @@ export default class InviteUsersMailMessages {
.findById(tenantId) .findById(tenantId)
.withGraphFetched('metadata'); .withGraphFetched('metadata');
const root = __dirname + '/../../../views/images/bigcapital.png'; const root = path.join(global.__views_dir, '/images/bigcapital.png');
const mail = new Mail() const mail = new Mail()
.setSubject(`${fromUser.firstName} has invited you to join a Bigcapital`) .setSubject(`${fromUser.firstName} has invited you to join a Bigcapital`)

View File

@@ -8,7 +8,7 @@ import { IAcceptInviteEventPayload } from '@/interfaces';
@Service() @Service()
export default class SyncTenantAcceptInvite { export default class SyncTenantAcceptInvite {
@Inject() @Inject()
tenancy: HasTenancyService; private tenancy: HasTenancyService;
/** /**
* Attaches events with handlers. * Attaches events with handlers.

View File

@@ -82,9 +82,7 @@ export default class InviteTenantUserService implements IInviteUserService {
tenantId: number, tenantId: number,
userId: number, userId: number,
authorizedUser: ISystemUser authorizedUser: ISystemUser
): Promise<{ ): Promise<{ user: ITenantUser }> {
user: ITenantUser;
}> {
// Retrieve the user by id or throw not found service error. // Retrieve the user by id or throw not found service error.
const user = await this.getUserByIdOrThrowError(tenantId, userId); const user = await this.getUserByIdOrThrowError(tenantId, userId);