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

Improve taken username warning in registration for when request fails #7621

Merged
merged 1 commit into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions src/components/views/auth/RegistrationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ enum RegistrationField {
PasswordConfirm = "field_password_confirm",
}

enum UsernameAvailableStatus {
Unknown,
Available,
Unavailable,
Error,
}

export const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario.

interface IProps {
Expand Down Expand Up @@ -348,13 +355,25 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
return result;
};

private validateUsernameRules = withValidation({
private validateUsernameRules = withValidation<this, UsernameAvailableStatus>({
description: (_, results) => {
// omit the description if the only failing result is the `available` one as it makes no sense for it.
if (results.every(({ key, valid }) => key === "available" || valid)) return;
return _t("Use lowercase letters, numbers, dashes and underscores only");
},
hideDescriptionIfValid: true,
async deriveData(this: RegistrationForm, { value }) {
if (!value) {
return UsernameAvailableStatus.Unknown;
}

try {
const available = await this.props.matrixClient.isUsernameAvailable(value);
return available ? UsernameAvailableStatus.Available : UsernameAvailableStatus.Unavailable;
} catch (err) {
return UsernameAvailableStatus.Error;
}
},
rules: [
{
key: "required",
Expand All @@ -369,19 +388,16 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
{
key: "available",
final: true,
test: async ({ value }) => {
test: async ({ value }, usernameAvailable) => {
if (!value) {
return true;
}

try {
await this.props.matrixClient.isUsernameAvailable(value);
return true;
} catch (err) {
return false;
}
return usernameAvailable === UsernameAvailableStatus.Available;
},
invalid: () => _t("Someone already has that username. Try another or if it is you, sign in below."),
invalid: (usernameAvailable) => usernameAvailable === UsernameAvailableStatus.Error
? _t("Unable to check if username has been taken. Try again later.")
: _t("Someone already has that username. Try another or if it is you, sign in below."),
},
],
});
Expand Down
6 changes: 3 additions & 3 deletions src/components/views/elements/Validation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default function withValidation<T = undefined, D = void>({
}

const data = { value, allowEmpty };
const derivedData = deriveData ? await deriveData(data) : undefined;
const derivedData: D | undefined = deriveData ? await deriveData.call(this, data) : undefined;

const results: IResult[] = [];
let valid = true;
Expand All @@ -106,13 +106,13 @@ export default function withValidation<T = undefined, D = void>({
continue;
}

if (rule.skip && rule.skip.call(this, data, derivedData)) {
if (rule.skip?.call(this, data, derivedData)) {
continue;
}

// We're setting `this` to whichever component holds the validation
// function. That allows rules to access the state of the component.
const ruleValid = await rule.test.call(this, data, derivedData);
const ruleValid: boolean = await rule.test.call(this, data, derivedData);
valid = valid && ruleValid;
if (ruleValid && rule.valid) {
// If the rule's result is valid and has text to show for
Expand Down
1 change: 1 addition & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2941,6 +2941,7 @@
"Other users can invite you to rooms using your contact details": "Other users can invite you to rooms using your contact details",
"Enter phone number (required on this homeserver)": "Enter phone number (required on this homeserver)",
"Use lowercase letters, numbers, dashes and underscores only": "Use lowercase letters, numbers, dashes and underscores only",
"Unable to check if username has been taken. Try again later.": "Unable to check if username has been taken. Try again later.",
"Someone already has that username. Try another or if it is you, sign in below.": "Someone already has that username. Try another or if it is you, sign in below.",
"Phone (optional)": "Phone (optional)",
"Register": "Register",
Expand Down