diff --git a/src/core/common/errors.ts b/src/core/common/errors.ts index 3f5b8111d..49ae6e621 100644 --- a/src/core/common/errors.ts +++ b/src/core/common/errors.ts @@ -317,6 +317,11 @@ export enum ERROR_CODES { USER_ALREADY_PREMOD = "USER_ALREADY_PREMOD", + /** + * INVITE_INCLUDES_EXISTING_USER is returned when attempting to invite a user who already exists + */ + INVITE_INCLUDES_EXISTING_USER = "INVITE_INCLUDES_EXISTING_USER", + /** * REPEAT_POST is returned if a user attempts to post the same comment more than once * in a row within a given time frame diff --git a/src/core/server/errors/index.ts b/src/core/server/errors/index.ts index 6653aa9da..2b6924867 100644 --- a/src/core/server/errors/index.ts +++ b/src/core/server/errors/index.ts @@ -702,6 +702,17 @@ export class InviteRequiresEmailAddresses extends CoralError { } } +export class InviteIncludesExistingUser extends CoralError { + constructor(email: string) { + super({ + code: ERROR_CODES.INVITE_INCLUDES_EXISTING_USER, + context: { + pub: { email }, + }, + }); + } +} + export class LiveUpdatesDisabled extends CoralError { constructor() { super({ diff --git a/src/core/server/errors/translations.ts b/src/core/server/errors/translations.ts index 4dc296d21..2db1987b8 100644 --- a/src/core/server/errors/translations.ts +++ b/src/core/server/errors/translations.ts @@ -55,5 +55,6 @@ export const ERROR_TRANSLATIONS: Record = { PERSISTED_QUERY_NOT_FOUND: "error-persistedQueryNotFound", RAW_QUERY_NOT_AUTHORIZED: "error-rawQueryNotAuthorized", USER_ALREADY_PREMOD: "error-userAlreadyPremod", + INVITE_INCLUDES_EXISTING_USER: "error-inviteIncludesExistingUser", REPEAT_POST: "error-repeatPost", }; diff --git a/src/core/server/locales/en-US/errors.ftl b/src/core/server/locales/en-US/errors.ftl index ae0e998ff..64907b9eb 100644 --- a/src/core/server/locales/en-US/errors.ftl +++ b/src/core/server/locales/en-US/errors.ftl @@ -57,4 +57,5 @@ error-passwordIncorrect = Incorrect password. Please try again. error-usernameAlreadyUpdated = You may only change your username once every { framework-timeago-time }. error-persistedQueryNotFound = The persisted query with ID { $id } was not found. error-rawQueryNotAuthorized = You are not authorized to execute this query. +error-inviteIncludesExistingUser = A user with the email address { $email } already exists. error-repeatPost = Are you sure? This comment is very similar to your previous comment. diff --git a/src/core/server/services/users/auth/invite.ts b/src/core/server/services/users/auth/invite.ts index eb7424794..3583d60c0 100644 --- a/src/core/server/services/users/auth/invite.ts +++ b/src/core/server/services/users/auth/invite.ts @@ -31,6 +31,7 @@ import { import { constructTenantURL } from "coral-server/app/url"; import { IntegrationDisabled, + InviteIncludesExistingUser, InviteRequiresEmailAddresses, InviteTokenExpired, TokenInvalidError, @@ -192,16 +193,16 @@ export async function invite( inviteURL?: string; invitedNow?: Invite; }> = []; + + // check to make sure users have not been invited previously for (const email of uniq(emails)) { - // Check to see if the user with the specified email already has an account. const userAlready = await retrieveUserWithEmail(mongo, tenant.id, email); if (userAlready) { - payloads.push({ email }); - continue; + throw new InviteIncludesExistingUser(email); } + } - // Check to see that the user has not been invited before, if they have, - // redeem it and create a new one. + for (const email of uniq(emails)) { await redeemInviteFromEmail(mongo, tenant.id, email); // Create the User invite record.