UNPKG

9.97 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const common_1 = require("@nestjs/common");
5const uuidv4 = require("uuid/v4");
6const configuration_1 = require("../configuration");
7const transactional_1 = require("../datastore/transactional");
8const logging_1 = require("../gcloud/logging");
9const index_1 = require("../index");
10const invite_1 = require("../mail-templates/invite");
11const mail_sender_1 = require("../mail/mail.sender");
12const arrays_1 = require("../util/arrays");
13const auth_repository_1 = require("./auth.repository");
14const auth_service_1 = require("./auth.service");
15exports.DEFAULT_INVITE_CODE_EXPIRY = 7 * 24 * 60 * 60 * 1000;
16const DEFAULT_INVITE_CODE_EXPIRY_EMAIL_COPY = '7 days';
17const DEFAULT_INVITATION_EMAIL_COPY = 'You have been invited as a new user.';
18let InviteUserService = class InviteUserService {
19 constructor(authRepository, mailSender, configuration, userService, userInviteRepository) {
20 this.authRepository = authRepository;
21 this.mailSender = mailSender;
22 this.configuration = configuration;
23 this.userService = userService;
24 this.userInviteRepository = userInviteRepository;
25 this.getActivationExpiryInMillis = () => {
26 return this.configuration.auth.local && this.configuration.auth.local.activationExpiryInMinutes
27 ? this.configuration.auth.local.activationExpiryInMinutes * 60 * 1000
28 : exports.DEFAULT_INVITE_CODE_EXPIRY;
29 };
30 this.getActivationExpiryEmailCopy = () => !(this.configuration.auth.local && this.configuration.auth.local.activationExpiryInMinutes)
31 ? DEFAULT_INVITE_CODE_EXPIRY_EMAIL_COPY
32 : this.configuration.auth.local.activationExpiryEmailCopy;
33 this.getInvitationCopy = () => !(this.configuration.auth.local && this.configuration.auth.local.invitationEmailCopy)
34 ? DEFAULT_INVITATION_EMAIL_COPY
35 : this.configuration.auth.local.invitationEmailCopy;
36 this.logger = logging_1.createLogger('invite-user-service');
37 }
38 async inviteUserIfRequired(context, request) {
39 return this.inviteUserInternal(context, request, false);
40 }
41 async inviteUser(context, request) {
42 return this.inviteUserInternal(context, request, true);
43 }
44 async getInvitedUser(context, code) {
45 const invite = await this.userInviteRepository.get(context, code);
46 if (!invite) {
47 return;
48 }
49 const activationExpiry = this.getActivationExpiryInMillis();
50 if (Date.now() - invite.createdAt.getTime() > activationExpiry) {
51 this.logger.info(`User invite for ${invite.email} has expired. Was created ${invite.createdAt}.`);
52 throw new Error('Account activation code expired');
53 }
54 return this.userService.get(context, invite.userId);
55 }
56 async reInviteForUserId(context, userId) {
57 this.logger.info(`Re Inviting user with id: ${userId}`);
58 const existingInvite = await this.getUserInviteForUserId(context, userId);
59 if (existingInvite) {
60 return this.reInviteUser(context, existingInvite);
61 }
62 else {
63 throw new Error('No user invites found.');
64 }
65 }
66 async getUserInviteForUserId(context, userId) {
67 const [existingInvites] = await this.userInviteRepository.query(context, {
68 filters: {
69 userId,
70 },
71 limit: 1,
72 });
73 this.logger.info(`Existing Invites ${existingInvites}`);
74 if (existingInvites && existingInvites.length > 0) {
75 return existingInvites[0];
76 }
77 else {
78 return undefined;
79 }
80 }
81 async reInviteUser(context, existingInvite) {
82 const user = await this.userService.getByEmail(context, existingInvite.email);
83 if (!user) {
84 throw new Error('User not found');
85 }
86 const newInvite = await this.userInviteRepository.save(context, {
87 id: uuidv4(),
88 email: existingInvite.email,
89 createdAt: new Date(),
90 roles: existingInvite.roles,
91 userId: existingInvite.userId,
92 });
93 await this.userInviteRepository.delete(context, existingInvite.id);
94 const activateLink = await this.sendActivationEmail(context, newInvite.email, newInvite.id, false);
95 return { user, inviteId: newInvite.id, activateLink };
96 }
97 async inviteUserInternal(context, request, validateNew) {
98 const { email, roles } = request;
99 this.logger.info(`Inviting user with email: ${email}, roles: ${roles}, validateNew: ${validateNew}`);
100 if (roles.includes('super')) {
101 throw new Error('Cannot assign super role to users');
102 }
103 const auth = await this.authRepository.get(context, email);
104 if (validateNew && auth) {
105 throw new Error('Email already exists');
106 }
107 let user = await this.userService.getByEmail(context, email);
108 if (!user) {
109 user = await this.userService.create(context, {
110 email,
111 name: request.name,
112 enabled: false,
113 });
114 }
115 if (auth) {
116 this.logger.info(`User with email ${email} already has a login so does not need to be invited`);
117 const updatedUser = await this.userService.update(context, user.id, {
118 roles: arrays_1.unique(user.roles, ...roles),
119 enabled: true,
120 });
121 return { user: updatedUser };
122 }
123 else {
124 const inviteId = uuidv4();
125 await this.userInviteRepository.save(context, {
126 id: inviteId,
127 email,
128 createdAt: new Date(),
129 roles,
130 userId: user.id,
131 });
132 const activateLink = await this.sendActivationEmail(context, email, inviteId, request.skipEmail);
133 return { user, inviteId, activateLink };
134 }
135 }
136 async sendActivationEmail(context, email, inviteId, skipEmail) {
137 const activateLink = `${this.configuration.host}/activate/${inviteId}`;
138 if (skipEmail) {
139 this.logger.info('Skipping sending invitation email based on request option');
140 return activateLink;
141 }
142 this.logger.info(`Sending invitation email to ${email} with link ${activateLink}`);
143 const title = 'Activate your account';
144 await this.mailSender.send(context, {
145 to: email,
146 subject: title,
147 html: invite_1.userInviteEmail(title, activateLink, this.getInvitationCopy(), this.getActivationExpiryEmailCopy()),
148 });
149 return activateLink;
150 }
151 async checkActivationCode(context, code) {
152 const invite = await this.userInviteRepository.get(context, code);
153 return this.checkInvite(context, invite);
154 }
155 async activateAccount(context, code, name, password) {
156 const invite = await this.userInviteRepository.get(context, code);
157 const err = await this.checkInvite(context, invite);
158 if (err) {
159 throw new Error(err);
160 }
161 const user = await this.userService.update(context, invite.userId, {
162 name,
163 roles: invite.roles,
164 enabled: true,
165 });
166 this.logger.info(`Accepting invitation and activating account for email ${user.email}, code ${code}, name ${name}`);
167 await this.authRepository.save(context, {
168 id: invite.email,
169 type: 'password',
170 password: await auth_service_1.hashPassword(password),
171 userId: user.id,
172 });
173 await this.userInviteRepository.delete(context, code);
174 return user;
175 }
176 async checkInvite(context, invite) {
177 if (!invite) {
178 return 'This activation code is no longer available. Please use the \'Activate Account\' link in the most recent activation email you have received. If you\'re still experiencing problems please contact your administrator.';
179 }
180 const activationExpiry = this.getActivationExpiryInMillis();
181 if (Date.now() - invite.createdAt.getTime() > activationExpiry) {
182 return 'Sorry, your activation code has expired. Please contact your administrator';
183 }
184 const auth = await this.authRepository.get(context, invite.email);
185 if (auth) {
186 return 'Account already registered';
187 }
188 return null;
189 }
190};
191tslib_1.__decorate([
192 transactional_1.Transactional(),
193 tslib_1.__metadata("design:type", Function),
194 tslib_1.__metadata("design:paramtypes", [Object, Object]),
195 tslib_1.__metadata("design:returntype", Promise)
196], InviteUserService.prototype, "inviteUser", null);
197tslib_1.__decorate([
198 transactional_1.Transactional(),
199 tslib_1.__metadata("design:type", Function),
200 tslib_1.__metadata("design:paramtypes", [Object, Object]),
201 tslib_1.__metadata("design:returntype", Promise)
202], InviteUserService.prototype, "reInviteUser", null);
203tslib_1.__decorate([
204 transactional_1.Transactional(),
205 tslib_1.__metadata("design:type", Function),
206 tslib_1.__metadata("design:paramtypes", [Object, String, String, String]),
207 tslib_1.__metadata("design:returntype", Promise)
208], InviteUserService.prototype, "activateAccount", null);
209InviteUserService = tslib_1.__decorate([
210 common_1.Injectable(),
211 tslib_1.__param(1, common_1.Inject(mail_sender_1.MAIL_SENDER)),
212 tslib_1.__param(2, common_1.Inject(configuration_1.CONFIGURATION)),
213 tslib_1.__param(3, common_1.Inject(index_1.USER_SERVICE)),
214 tslib_1.__metadata("design:paramtypes", [auth_repository_1.CredentialRepository, Object, Object, Object, auth_repository_1.UserInviteRepository])
215], InviteUserService);
216exports.InviteUserService = InviteUserService;
217//# sourceMappingURL=invite-user.service.js.map
\No newline at end of file