Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Handle M_INVALID_USERNAME on /register/available (#9237)
Browse files Browse the repository at this point in the history
* Handle M_INVALID_USERNAME on /register/available

* Add tests

* Make typescript check happier
  • Loading branch information
t3chguy committed Sep 7, 2022
1 parent a215027 commit c76cc9a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
44 changes: 44 additions & 0 deletions cypress/e2e/register/register.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,48 @@ describe("Registration", () => {
cy.get(".mx_DevicesPanel_myDevice .mx_DevicesPanel_deviceTrust .mx_E2EIcon")
.should("have.class", "mx_E2EIcon_verified");
});

it("should require username to fulfil requirements and be available", () => {
cy.get(".mx_ServerPicker_change", { timeout: 15000 }).click();
cy.get(".mx_ServerPickerDialog_continue").should("be.visible");
cy.get(".mx_ServerPickerDialog_otherHomeserver").type(synapse.baseUrl);
cy.get(".mx_ServerPickerDialog_continue").click();
// wait for the dialog to go away
cy.get('.mx_ServerPickerDialog').should('not.exist');

cy.get("#mx_RegistrationForm_username").should("be.visible");

cy.intercept("**/_matrix/client/*/register/available?username=_alice", {
statusCode: 400,
headers: {
"Content-Type": "application/json",
},
body: {
errcode: "M_INVALID_USERNAME",
error: "User ID may not begin with _",
},
});
cy.get("#mx_RegistrationForm_username").type("_alice");
cy.get(".mx_Field_tooltip")
.should("have.class", "mx_Tooltip_visible")
.should("contain.text", "Some characters not allowed");

cy.intercept("**/_matrix/client/*/register/available?username=bob", {
statusCode: 400,
headers: {
"Content-Type": "application/json",
},
body: {
errcode: "M_USER_IN_USE",
error: "The desired username is already taken",
},
});
cy.get("#mx_RegistrationForm_username").type("{selectAll}{backspace}bob");
cy.get(".mx_Field_tooltip")
.should("have.class", "mx_Tooltip_visible")
.should("contain.text", "Someone already has that username");

cy.get("#mx_RegistrationForm_username").type("{selectAll}{backspace}foobar");
cy.get(".mx_Field_tooltip").should("not.have.class", "mx_Tooltip_visible");
});
});
8 changes: 7 additions & 1 deletion src/components/views/auth/RegistrationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
import React from 'react';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixError } from 'matrix-js-sdk/src/matrix';

import * as Email from '../../../email';
import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
Expand Down Expand Up @@ -48,6 +49,7 @@ enum UsernameAvailableStatus {
Available,
Unavailable,
Error,
Invalid,
}

export const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario.
Expand Down Expand Up @@ -363,6 +365,9 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
const available = await this.props.matrixClient.isUsernameAvailable(value);
return available ? UsernameAvailableStatus.Available : UsernameAvailableStatus.Unavailable;
} catch (err) {
if (err instanceof MatrixError && err.errcode === "M_INVALID_USERNAME") {
return UsernameAvailableStatus.Invalid;
}
return UsernameAvailableStatus.Error;
}
},
Expand All @@ -374,7 +379,8 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
},
{
key: "safeLocalpart",
test: ({ value }) => !value || SAFE_LOCALPART_REGEX.test(value),
test: ({ value }, usernameAvailable) => (!value || SAFE_LOCALPART_REGEX.test(value))
&& usernameAvailable !== UsernameAvailableStatus.Invalid,
invalid: () => _t("Some characters not allowed"),
},
{
Expand Down

0 comments on commit c76cc9a

Please sign in to comment.