Handle registration when user already exists (#1744)
Fixes https://github.com/webrecorder/browsertrix/issues/1743 On the backend, support adding user to new org and improved error messaging: - if user exists is not part of the org to be added to, add user to the registration org, return 201 - if user is already part of the org, return 400 with 'user_already_is_org_member' error - if user is not being added to a new org but already exists, return 'user_already_exists' frontend: - if user user same password, they will just be logged in and added to registration org (same as before) - if user uses wrong password, show alert message - handle both user_already_is_org_member and user_already_registered with alert message and link to log-in page. note: this means existing user is added to the registration org even if they provide wrong password, but they won't be able to login until they use correct password/reset/etc...
This commit is contained in:
parent
f286f04130
commit
b061a39d5f
@ -50,7 +50,7 @@ class InvitePending(BaseMongoModel):
|
||||
inviterEmail: str
|
||||
fromSuperuser: Optional[bool]
|
||||
oid: Optional[UUID]
|
||||
role: Optional[UserRole] = UserRole.VIEWER
|
||||
role: UserRole = UserRole.VIEWER
|
||||
email: Optional[str]
|
||||
|
||||
|
||||
|
@ -367,11 +367,12 @@ class OrgOps:
|
||||
await self.add_user_to_org(org, user.id, invite.role)
|
||||
return True
|
||||
|
||||
async def add_user_to_org(
|
||||
self, org: Organization, userid: UUID, role: Optional[UserRole] = None
|
||||
):
|
||||
async def add_user_to_org(self, org: Organization, userid: UUID, role: UserRole):
|
||||
"""Add user to organization with specified role"""
|
||||
org.users[str(userid)] = role or UserRole.OWNER
|
||||
if str(userid) in org.users:
|
||||
raise HTTPException(status_code=400, detail="user_already_is_org_member")
|
||||
|
||||
org.users[str(userid)] = role
|
||||
await self.update_users(org)
|
||||
|
||||
async def get_org_owners(self, org: Organization):
|
||||
|
@ -359,10 +359,17 @@ class UserManager:
|
||||
is_verified=is_verified,
|
||||
)
|
||||
|
||||
user_already_exists = False
|
||||
|
||||
try:
|
||||
await self.users.insert_one(user.dict())
|
||||
except DuplicateKeyError:
|
||||
raise HTTPException(status_code=400, detail="user_already_exists")
|
||||
maybe_user = await self.get_by_email(create.email)
|
||||
# shouldn't happen since user should exist if we have duplicate key, but just in case!
|
||||
if not maybe_user:
|
||||
raise HTTPException(status_code=400, detail="user_missing")
|
||||
user = maybe_user
|
||||
user_already_exists = True
|
||||
|
||||
add_to_org = False
|
||||
|
||||
@ -380,12 +387,16 @@ class UserManager:
|
||||
|
||||
else:
|
||||
add_to_org = True
|
||||
if not is_verified:
|
||||
if not is_verified and not user_already_exists:
|
||||
asyncio.create_task(self.request_verify(user, request))
|
||||
|
||||
# org to auto-add user to, if any
|
||||
auto_add_org: Optional[Organization] = None
|
||||
|
||||
# if user already exists, and not adding to a new org, error
|
||||
if user_already_exists and not add_to_org:
|
||||
raise HTTPException(status_code=400, detail="user_already_exists")
|
||||
|
||||
# if add to default, then get default org
|
||||
if add_to_org:
|
||||
if self.register_to_org_id:
|
||||
|
@ -44,6 +44,9 @@ export class SignUpForm extends LiteElement {
|
||||
@state()
|
||||
private pwStrengthResults: null | ZxcvbnResult = null;
|
||||
|
||||
@state()
|
||||
private showLoginLink = false;
|
||||
|
||||
protected firstUpdated() {
|
||||
void PasswordService.setOptions();
|
||||
}
|
||||
@ -55,8 +58,15 @@ export class SignUpForm extends LiteElement {
|
||||
serverError = html`
|
||||
<div class="mb-5">
|
||||
<btrix-alert id="formError" variant="danger"
|
||||
>${this.serverError}</btrix-alert
|
||||
>
|
||||
>${this.serverError}
|
||||
${this.showLoginLink
|
||||
? html` <p>
|
||||
Go to the
|
||||
<a class="underline" href="/log-in">Log-In Page</a> and try
|
||||
again.
|
||||
</p>`
|
||||
: ``}
|
||||
</btrix-alert>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@ -179,6 +189,7 @@ export class SignUpForm extends LiteElement {
|
||||
this.dispatchEvent(new CustomEvent("submit"));
|
||||
|
||||
this.serverError = undefined;
|
||||
this.showLoginLink = false;
|
||||
this.isSubmitting = true;
|
||||
|
||||
const formData = new FormData(event.target as HTMLFormElement);
|
||||
@ -229,7 +240,10 @@ export class SignUpForm extends LiteElement {
|
||||
const { detail } = (await resp.json()) as {
|
||||
detail: string & { code: string };
|
||||
};
|
||||
if (detail === "user_already_exists") {
|
||||
if (
|
||||
detail === "user_already_exists" ||
|
||||
detail === "user_already_is_org_member"
|
||||
) {
|
||||
shouldLogIn = true;
|
||||
} else if (detail.code && detail.code === "invalid_password") {
|
||||
this.serverError = msg(
|
||||
@ -254,7 +268,11 @@ export class SignUpForm extends LiteElement {
|
||||
try {
|
||||
await this.logIn({ email, password });
|
||||
} catch {
|
||||
this.dispatchEvent(new CustomEvent("unauthenticated"));
|
||||
this.serverError = msg(
|
||||
"User is already registered, but with a different password.",
|
||||
);
|
||||
this.showLoginLink = true;
|
||||
//this.dispatchEvent(new CustomEvent("unauthenticated"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user