Handle M_INVALID_USERNAME on /register/available (#9237)
* Handle M_INVALID_USERNAME on /register/available * Add tests * Make typescript check happierpull/28788/head^2
parent
a215027c6b
commit
c76cc9aee1
|
@ -85,4 +85,48 @@ describe("Registration", () => {
|
||||||
cy.get(".mx_DevicesPanel_myDevice .mx_DevicesPanel_deviceTrust .mx_E2EIcon")
|
cy.get(".mx_DevicesPanel_myDevice .mx_DevicesPanel_deviceTrust .mx_E2EIcon")
|
||||||
.should("have.class", "mx_E2EIcon_verified");
|
.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");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { MatrixError } from 'matrix-js-sdk/src/matrix';
|
||||||
|
|
||||||
import * as Email from '../../../email';
|
import * as Email from '../../../email';
|
||||||
import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
|
import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
|
||||||
|
@ -48,6 +49,7 @@ enum UsernameAvailableStatus {
|
||||||
Available,
|
Available,
|
||||||
Unavailable,
|
Unavailable,
|
||||||
Error,
|
Error,
|
||||||
|
Invalid,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario.
|
export const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario.
|
||||||
|
@ -363,6 +365,9 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
|
||||||
const available = await this.props.matrixClient.isUsernameAvailable(value);
|
const available = await this.props.matrixClient.isUsernameAvailable(value);
|
||||||
return available ? UsernameAvailableStatus.Available : UsernameAvailableStatus.Unavailable;
|
return available ? UsernameAvailableStatus.Available : UsernameAvailableStatus.Unavailable;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
if (err instanceof MatrixError && err.errcode === "M_INVALID_USERNAME") {
|
||||||
|
return UsernameAvailableStatus.Invalid;
|
||||||
|
}
|
||||||
return UsernameAvailableStatus.Error;
|
return UsernameAvailableStatus.Error;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -374,7 +379,8 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "safeLocalpart",
|
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"),
|
invalid: () => _t("Some characters not allowed"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue