mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: replace UsernameValidation mixin with helper in InvitesShowController and CreateAccount (#31330)
Follows up: https://github.com/discourse/discourse/pull/31107 This PR replaces the use of the UsernameValidation mixin with the helper class for the InvitesShowController and CreateAccount modal component, and deletes the mixin.
This commit is contained in:
@@ -15,17 +15,16 @@ import discourseDebounce from "discourse/lib/debounce";
|
||||
import discourseComputed, { bind } from "discourse/lib/decorators";
|
||||
import NameValidationHelper from "discourse/lib/name-validation-helper";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import UsernameValidationHelper from "discourse/lib/username-validation-helper";
|
||||
import { emailValid } from "discourse/lib/utilities";
|
||||
import PasswordValidation from "discourse/mixins/password-validation";
|
||||
import UserFieldsValidation from "discourse/mixins/user-fields-validation";
|
||||
import UsernameValidation from "discourse/mixins/username-validation";
|
||||
import { findAll } from "discourse/models/login-method";
|
||||
import User from "discourse/models/user";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class CreateAccount extends Component.extend(
|
||||
PasswordValidation,
|
||||
UsernameValidation,
|
||||
UserFieldsValidation
|
||||
) {
|
||||
@service site;
|
||||
@@ -44,15 +43,13 @@ export default class CreateAccount extends Component.extend(
|
||||
passwordValidationVisible = false;
|
||||
emailValidationVisible = false;
|
||||
nameValidationHelper = new NameValidationHelper(this);
|
||||
usernameValidationHelper = new UsernameValidationHelper(this);
|
||||
|
||||
@notEmpty("model.authOptions") hasAuthOptions;
|
||||
@setting("enable_local_logins") canCreateLocal;
|
||||
@setting("require_invite_code") requireInviteCode;
|
||||
// For NameValidation mixin
|
||||
@alias("model.accountName") accountName;
|
||||
// For UsernameValidation mixin
|
||||
@alias("model.authOptions") authOptions;
|
||||
@alias("model.accountEmail") accountEmail;
|
||||
|
||||
init() {
|
||||
super.init(...arguments);
|
||||
@@ -75,6 +72,21 @@ export default class CreateAccount extends Component.extend(
|
||||
this.accountUsername = event.target.value;
|
||||
}
|
||||
|
||||
@dependentKeyCompat
|
||||
get accountEmail() {
|
||||
return this.model?.accountEmail;
|
||||
}
|
||||
|
||||
@dependentKeyCompat
|
||||
get authOptions() {
|
||||
return this.model?.authOptions;
|
||||
}
|
||||
|
||||
@dependentKeyCompat
|
||||
get usernameValidation() {
|
||||
return this.usernameValidationHelper.usernameValidation;
|
||||
}
|
||||
|
||||
get nameTitle() {
|
||||
return this.nameValidationHelper.nameTitle;
|
||||
}
|
||||
@@ -192,11 +204,10 @@ export default class CreateAccount extends Component.extend(
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed("usernameValidation.reason")
|
||||
showUsernameInstructions(usernameValidationReason) {
|
||||
get showUsernameInstructions() {
|
||||
return (
|
||||
this.siteSettings.show_signup_form_username_instructions &&
|
||||
!usernameValidationReason
|
||||
!this.usernameValidation.reason
|
||||
);
|
||||
}
|
||||
|
||||
@@ -366,7 +377,11 @@ export default class CreateAccount extends Component.extend(
|
||||
// If email is valid and username has not been entered yet,
|
||||
// or email and username were filled automatically by 3rd party auth,
|
||||
// then look for a registered username that matches the email.
|
||||
discourseDebounce(this, this.fetchExistingUsername, 500);
|
||||
discourseDebounce(
|
||||
this,
|
||||
this.usernameValidationHelper.fetchExistingUsername,
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,22 +10,22 @@ import discourseComputed from "discourse/lib/decorators";
|
||||
import getUrl from "discourse/lib/get-url";
|
||||
import NameValidationHelper from "discourse/lib/name-validation-helper";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import UsernameValidationHelper from "discourse/lib/username-validation-helper";
|
||||
import { emailValid } from "discourse/lib/utilities";
|
||||
import PasswordValidation from "discourse/mixins/password-validation";
|
||||
import UserFieldsValidation from "discourse/mixins/user-fields-validation";
|
||||
import UsernameValidation from "discourse/mixins/username-validation";
|
||||
import { findAll as findLoginMethods } from "discourse/models/login-method";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class InvitesShowController extends Controller.extend(
|
||||
PasswordValidation,
|
||||
UsernameValidation,
|
||||
UserFieldsValidation
|
||||
) {
|
||||
@tracked accountUsername;
|
||||
@tracked isDeveloper;
|
||||
queryParams = ["t"];
|
||||
nameValidationHelper = new NameValidationHelper(this);
|
||||
usernameValidationHelper = new UsernameValidationHelper(this);
|
||||
successMessage = null;
|
||||
@readOnly("model.is_invite_link") isInviteLink;
|
||||
@readOnly("model.invited_by") invitedBy;
|
||||
@@ -50,6 +50,11 @@ export default class InvitesShowController extends Controller.extend(
|
||||
this.accountUsername = event.target.value;
|
||||
}
|
||||
|
||||
@dependentKeyCompat
|
||||
get usernameValidation() {
|
||||
return this.usernameValidationHelper.usernameValidation;
|
||||
}
|
||||
|
||||
get nameTitle() {
|
||||
return this.nameValidationHelper.nameTitle;
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ export default class UsernameValidationHelper {
|
||||
}
|
||||
|
||||
async fetchExistingUsername() {
|
||||
const result = await User.checkUsername(null, this.owner.accountEmail);
|
||||
const result = await User.checkUsername(null, this.owner?.accountEmail);
|
||||
|
||||
if (
|
||||
result.suggestion &&
|
||||
|
@@ -1,131 +0,0 @@
|
||||
import EmberObject, { computed } from "@ember/object";
|
||||
import Mixin from "@ember/object/mixin";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { setting } from "discourse/lib/computed";
|
||||
import discourseDebounce from "discourse/lib/debounce";
|
||||
import User from "discourse/models/user";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
function failedResult(attrs) {
|
||||
return EmberObject.create({
|
||||
shouldCheck: false,
|
||||
failed: true,
|
||||
ok: false,
|
||||
element: document.querySelector("#new-account-username"),
|
||||
...attrs,
|
||||
});
|
||||
}
|
||||
|
||||
function validResult(attrs) {
|
||||
return EmberObject.create({ ok: true, ...attrs });
|
||||
}
|
||||
|
||||
export default Mixin.create({
|
||||
checkedUsername: null,
|
||||
usernameValidationResult: null,
|
||||
uniqueUsernameValidation: null,
|
||||
maxUsernameLength: setting("max_username_length"),
|
||||
minUsernameLength: setting("min_username_length"),
|
||||
|
||||
async fetchExistingUsername() {
|
||||
const result = await User.checkUsername(null, this.accountEmail);
|
||||
|
||||
if (
|
||||
result.suggestion &&
|
||||
(isEmpty(this.accountUsername) ||
|
||||
this.accountUsername === this.get("authOptions.username"))
|
||||
) {
|
||||
this.setProperties({
|
||||
accountUsername: result.suggestion,
|
||||
prefilledUsername: result.suggestion,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
usernameValidation: computed(
|
||||
"usernameValidationResult",
|
||||
"accountUsername",
|
||||
"forceValidationReason",
|
||||
function () {
|
||||
if (
|
||||
this.usernameValidationResult &&
|
||||
this.checkedUsername === this.accountUsername
|
||||
) {
|
||||
return this.usernameValidationResult;
|
||||
}
|
||||
|
||||
const result = this.basicUsernameValidation(this.accountUsername);
|
||||
|
||||
if (result.shouldCheck) {
|
||||
discourseDebounce(this, this.checkUsernameAvailability, 500);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
),
|
||||
|
||||
basicUsernameValidation(username) {
|
||||
if (username && username === this.prefilledUsername) {
|
||||
return validResult({ reason: i18n("user.username.prefilled") });
|
||||
}
|
||||
|
||||
if (isEmpty(username)) {
|
||||
return failedResult({
|
||||
message: i18n("user.username.required"),
|
||||
reason: this.forceValidationReason
|
||||
? i18n("user.username.required")
|
||||
: null,
|
||||
});
|
||||
}
|
||||
|
||||
if (username.length < this.siteSettings.min_username_length) {
|
||||
return failedResult({ reason: i18n("user.username.too_short") });
|
||||
}
|
||||
|
||||
if (username.length > this.maxUsernameLength) {
|
||||
return failedResult({ reason: i18n("user.username.too_long") });
|
||||
}
|
||||
|
||||
return failedResult({
|
||||
shouldCheck: true,
|
||||
reason: i18n("user.username.checking"),
|
||||
});
|
||||
},
|
||||
|
||||
async checkUsernameAvailability() {
|
||||
const result = await User.checkUsername(
|
||||
this.accountUsername,
|
||||
this.accountEmail
|
||||
);
|
||||
|
||||
if (this.isDestroying || this.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("checkedUsername", this.accountUsername);
|
||||
this.isDeveloper = !!result.is_developer;
|
||||
|
||||
if (result.available) {
|
||||
this.set(
|
||||
"usernameValidationResult",
|
||||
validResult({ reason: i18n("user.username.available") })
|
||||
);
|
||||
} else if (result.suggestion) {
|
||||
this.set(
|
||||
"usernameValidationResult",
|
||||
failedResult({
|
||||
reason: i18n("user.username.not_available", result),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.set(
|
||||
"usernameValidationResult",
|
||||
failedResult({
|
||||
reason: result.errors
|
||||
? result.errors.join(" ")
|
||||
: i18n("user.username.not_available_no_suggestion"),
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
@@ -13,7 +13,8 @@ module("Unit | Component | create-account", function (hooks) {
|
||||
.factoryFor("component:modal/create-account")
|
||||
.create({ model: { accountUsername: username } });
|
||||
|
||||
const validation = component.basicUsernameValidation(username);
|
||||
const validation =
|
||||
component.usernameValidationHelper.basicUsernameValidation(username);
|
||||
assert.true(validation.failed, `username should be invalid: ${username}`);
|
||||
assert.strictEqual(
|
||||
validation.reason,
|
||||
@@ -34,7 +35,8 @@ module("Unit | Component | create-account", function (hooks) {
|
||||
.create({ model: { accountUsername: "porkchops" } });
|
||||
component.set("prefilledUsername", "porkchops");
|
||||
|
||||
const validation = component.basicUsernameValidation("porkchops");
|
||||
const validation =
|
||||
component.usernameValidationHelper.basicUsernameValidation("porkchops");
|
||||
assert.true(validation.ok, "Prefilled username is valid");
|
||||
assert.strictEqual(
|
||||
validation.reason,
|
||||
|
Reference in New Issue
Block a user