(email: string | string[], role: string, url: string | null, subject?: string | null)
| 406 | } |
| 407 | |
| 408 | async inviteUser(email: string | string[], role: string, url: string | null, subject?: string | null): Promise<void> { |
| 409 | const opts: MutationOptions = {}; |
| 410 | |
| 411 | try { |
| 412 | if (url && isUrlAllowed(url, env['USER_INVITE_URL_ALLOW_LIST'] as string) === false) { |
| 413 | throw new InvalidPayloadError({ reason: `URL "${url}" can't be used to invite users` }); |
| 414 | } |
| 415 | } catch (err: any) { |
| 416 | opts.preMutationError = err; |
| 417 | } |
| 418 | |
| 419 | const emails = toArray(email); |
| 420 | |
| 421 | const mailService = new MailService({ |
| 422 | schema: this.schema, |
| 423 | accountability: this.accountability, |
| 424 | }); |
| 425 | |
| 426 | for (const email of emails) { |
| 427 | // Check if user is known |
| 428 | const user = await this.getUserByEmail(email); |
| 429 | |
| 430 | // Create user first to verify uniqueness if unknown |
| 431 | if (isEmpty(user)) { |
| 432 | await this.createOne({ email, role, status: 'invited' }, opts); |
| 433 | |
| 434 | // For known users update role if changed |
| 435 | } else if (user.status === 'invited' && user.role !== role) { |
| 436 | await this.updateOne(user.id, { role }, opts); |
| 437 | } |
| 438 | |
| 439 | // Send invite for new and already invited users |
| 440 | if (isEmpty(user) || user.status === 'invited') { |
| 441 | const subjectLine = subject ?? "You've been invited"; |
| 442 | |
| 443 | mailService |
| 444 | .send({ |
| 445 | to: user?.email ?? email, |
| 446 | subject: subjectLine, |
| 447 | template: { |
| 448 | name: 'user-invitation', |
| 449 | data: { |
| 450 | url: this.inviteUrl(user?.email ?? email, url), |
| 451 | email: user?.email ?? email, |
| 452 | }, |
| 453 | }, |
| 454 | }) |
| 455 | .catch((error) => { |
| 456 | logger.error(error, `Could not send user invitation mail`); |
| 457 | }); |
| 458 | } |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | async acceptInvite(token: string, password: string): Promise<void> { |
| 463 | const { email, scope } = verifyJWT(token, getSecret()) as { |
no test coverage detected