From ff5768b2245d55442b7cc235fc075871e2156162 Mon Sep 17 00:00:00 2001 From: "a.bouhuolia" Date: Thu, 17 Dec 2020 20:01:43 +0200 Subject: [PATCH] fix: user invite check api. --- server/src/api/controllers/InviteUsers.ts | 59 ++++++++++++----------- server/src/models/index.js | 2 + server/src/services/InviteUsers/index.ts | 32 ++++++++---- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/server/src/api/controllers/InviteUsers.ts b/server/src/api/controllers/InviteUsers.ts index 55a83113c..831f995a6 100644 --- a/server/src/api/controllers/InviteUsers.ts +++ b/server/src/api/controllers/InviteUsers.ts @@ -21,7 +21,8 @@ export default class InviteUsersController extends BaseController { '/send', [body('email').exists().trim().escape()], this.validationResult, - asyncMiddleware(this.sendInvite.bind(this)) + asyncMiddleware(this.sendInvite.bind(this)), + this.handleServicesError, ); return router; } @@ -36,13 +37,15 @@ export default class InviteUsersController extends BaseController { '/accept/:token', [...this.inviteUserDTO], this.validationResult, - asyncMiddleware(this.accept.bind(this)) + asyncMiddleware(this.accept.bind(this)), + this.handleServicesError, ); router.get( '/invited/:token', [param('token').exists().trim().escape()], this.validationResult, - asyncMiddleware(this.invited.bind(this)) + asyncMiddleware(this.invited.bind(this)), + this.handleServicesError, ); return router; @@ -81,13 +84,6 @@ export default class InviteUsersController extends BaseController { message: 'The invite has been sent to the given email.', }); } catch (error) { - if (error instanceof ServiceError) { - if (error.errorType === 'email_already_invited') { - return res.status(400).send({ - errors: [{ type: 'EMAIL.ALREADY.INVITED' }], - }); - } - } next(error); } return res.status(200).send(); @@ -114,18 +110,6 @@ export default class InviteUsersController extends BaseController { message: 'User invite has been accepted successfully.', }); } catch (error) { - if (error instanceof ServiceError) { - if (error.errorType === 'phone_number_exists') { - return res.status(400).send({ - errors: [{ type: 'PHONE_NUMBER.EXISTS' }], - }); - } - if (error.errorType === 'invite_token_invalid') { - return res.status(400).send({ - errors: [{ type: 'INVITE.TOKEN.INVALID' }], - }); - } - } next(error); } } @@ -151,14 +135,31 @@ export default class InviteUsersController extends BaseController { organizationName: orgName?.value, }); } catch (error) { - if (error instanceof ServiceError) { - if (error.errorType === 'invite_token_invalid') { - return res.status(400).send({ - errors: [{ type: 'INVITE.TOKEN.INVALID' }], - }); - } - } next(error); } } + + /** + * Handles the service error. + */ + handleServicesError(error, req: Request, res: Response, next: Function) { + if (error instanceof ServiceError) { + if (error.errorType === 'EMAIL_ALREADY_INVITED') { + return res.status(400).send({ + errors: [{ type: 'EMAIL.ALREADY.INVITED' }], + }); + } + if (error.errorType === 'INVITE_TOKEN_INVALID') { + return res.status(400).send({ + errors: [{ type: 'INVITE.TOKEN.INVALID' }], + }); + } + if (error.errorType === 'PHONE_NUMBER_EXISTS') { + return res.status(400).send({ + errors: [{ type: 'PHONE_NUMBER.EXISTS' }], + }); + } + } + next(error); + } } diff --git a/server/src/models/index.js b/server/src/models/index.js index 8f8d065f2..77cfc23af 100644 --- a/server/src/models/index.js +++ b/server/src/models/index.js @@ -1,4 +1,5 @@ import Option from './Option'; +import Setting from './Setting'; import SaleEstimate from './SaleEstimate'; import SaleEstimateEntry from './SaleEstimateEntry'; import SaleReceipt from './SaleReceipt'; @@ -52,4 +53,5 @@ export { ManualJournal, Customer, Vendor, + Setting }; \ No newline at end of file diff --git a/server/src/services/InviteUsers/index.ts b/server/src/services/InviteUsers/index.ts index 92cb226fb..b44ae3204 100644 --- a/server/src/services/InviteUsers/index.ts +++ b/server/src/services/InviteUsers/index.ts @@ -7,13 +7,19 @@ import { } from 'decorators/eventDispatcher'; import { ServiceError } from 'exceptions'; import { Invite, Tenant } from 'system/models'; -import { Option } from 'models'; +import { Setting } from 'models'; import { hashPassword } from 'utils'; import TenancyService from 'services/Tenancy/TenancyService'; import InviteUsersMailMessages from 'services/InviteUsers/InviteUsersMailMessages'; import events from 'subscribers/events'; import { ISystemUser, IInviteUserInput } from 'interfaces'; +import TenantsManagerService from 'services/Tenancy/TenantsManager'; +const ERRORS = { + EMAIL_ALREADY_INVITED: 'EMAIL_ALREADY_INVITED', + INVITE_TOKEN_INVALID: 'INVITE_TOKEN_INVALID', + PHONE_NUMBER_EXISTS: 'PHONE_NUMBER_EXISTS' +}; @Service() export default class InviteUserService { @EventDispatcher() @@ -31,6 +37,9 @@ export default class InviteUserService { @Inject('repositories') sysRepositories: any; + @Inject() + tenantsManager: TenantsManagerService; + /** * Accept the received invite. * @param {string} token @@ -135,13 +144,17 @@ export default class InviteUserService { const inviteToken = await this.getInviteOrThrowError(token); // Find the tenant that associated to the given token. - const tenant = await Tenant.query().findOne('id', inviteToken.tenantId); + const tenant = await Tenant.query().findById(inviteToken.tenantId); - const tenantDb = this.tenantsManager.knexInstance(tenant.organizationId); + // Setup the knex instance. + this.tenantsManager.setupKnexInstance(tenant); - const orgName = await Option.bindKnex(tenantDb) + // Retrieve the knex instance of the given tenant. + const tenantKnexInstance = this.tenantsManager.getKnexInstance(tenant.id); + + const orgName = await Setting.bindKnex(tenantKnexInstance) .query() - .findOne('key', 'organization_name'); + .findOne({ key: 'name', group: 'organization' }); // Triggers `onUserCheckInvite` event. this.eventDispatcher.dispatch(events.inviteUser.checkInvite, { @@ -162,7 +175,7 @@ export default class InviteUserService { const foundUser = await systemUserRepository.findOneByEmail(email); if (foundUser) { - throw new ServiceError('email_already_invited'); + throw new ServiceError(ERRORS.EMAIL_ALREADY_INVITED); } return foundUser; } @@ -178,7 +191,7 @@ export default class InviteUserService { if (!inviteToken) { this.logger.info('[aceept_invite] the invite token is invalid.'); - throw new ServiceError('invite_token_invalid'); + throw new ServiceError(ERRORS.INVITE_TOKEN_INVALID); } return inviteToken; } @@ -189,14 +202,13 @@ export default class InviteUserService { */ private async validateUserPhoneNumber( inviteUserInput: IInviteUserInput - ): Promise { + ): Promise { const { systemUserRepository } = this.sysRepositories; const foundUser = await systemUserRepository.findOneByPhoneNumber( inviteUserInput.phoneNumber ); - if (foundUser) { - throw new ServiceError('phone_number_exists'); + throw new ServiceError(ERRORS.PHONE_NUMBER_EXISTS); } } }