(input: RegisterUserInput)
| 486 | } |
| 487 | |
| 488 | async registerUser(input: RegisterUserInput) { |
| 489 | if ( |
| 490 | input.verification_url && |
| 491 | isUrlAllowed(input.verification_url, env['USER_REGISTER_URL_ALLOW_LIST'] as string) === false |
| 492 | ) { |
| 493 | throw new InvalidPayloadError({ |
| 494 | reason: `URL "${input.verification_url}" can't be used to verify registered users`, |
| 495 | }); |
| 496 | } |
| 497 | |
| 498 | const STALL_TIME = env['REGISTER_STALL_TIME'] as number; |
| 499 | const timeStart = performance.now(); |
| 500 | const serviceOptions: AbstractServiceOptions = { accountability: this.accountability, schema: this.schema }; |
| 501 | const settingsService = new SettingsService(serviceOptions); |
| 502 | |
| 503 | const settings = await settingsService.readSingleton({ |
| 504 | fields: [ |
| 505 | 'public_registration', |
| 506 | 'public_registration_verify_email', |
| 507 | 'public_registration_role', |
| 508 | 'public_registration_email_filter', |
| 509 | ], |
| 510 | }); |
| 511 | |
| 512 | if (settings?.['public_registration'] == false) { |
| 513 | throw new ForbiddenError(); |
| 514 | } |
| 515 | |
| 516 | const publicRegistrationRole = settings?.['public_registration_role'] ?? null; |
| 517 | const hasEmailVerification = settings?.['public_registration_verify_email']; |
| 518 | const emailFilter = settings?.['public_registration_email_filter']; |
| 519 | const first_name = input.first_name ?? null; |
| 520 | const last_name = input.last_name ?? null; |
| 521 | |
| 522 | const partialUser: Partial<User> = { |
| 523 | // Required fields |
| 524 | email: input.email, |
| 525 | password: input.password, |
| 526 | role: publicRegistrationRole, |
| 527 | status: hasEmailVerification ? 'unverified' : 'active', |
| 528 | // Optional fields |
| 529 | first_name, |
| 530 | last_name, |
| 531 | }; |
| 532 | |
| 533 | if (emailFilter && validatePayload(emailFilter, { email: input.email }).length !== 0) { |
| 534 | await stall(STALL_TIME, timeStart); |
| 535 | throw new ForbiddenError(); |
| 536 | } |
| 537 | |
| 538 | const user = await this.getUserByEmail(input.email); |
| 539 | |
| 540 | if (isEmpty(user)) { |
| 541 | await this.createOne(partialUser); |
| 542 | } |
| 543 | // We want to be able to re-send the verification email |
| 544 | else if (user.status !== ('unverified' satisfies User['status'])) { |
| 545 | // To avoid giving attackers infos about registered emails we dont fail for violated unique constraints |
no test coverage detected