FIX: prevents error due to property override (#26741)
The `secondFactorMethod` property is defined as a @discourseComputed` which means it can't be overridden. Yet, we do override it in `app/assets/javascripts/discourse/app/components/security-key-form.js` and `app/assets/javascripts/discourse/app/components/second-factor-form.js` by doing `this.set("secondFactorMethod", ...)`. This commit sets a default property `secondFactorMethod` on the `email-login` controller after the model has been loaded. Given this property is no longer computed, it can be set again at other places. Followups: - Ideally we would follow DDAU pattern but this is quite a significant refactor. - The test I added is very limited, ideally we should start writing system specs for this, but it means having to deal with the email, it's a significant work.
This commit is contained in:
parent
21ef033e86
commit
9f8091abf0
|
@ -4,13 +4,16 @@ import { ajax } from "discourse/lib/ajax";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import DiscourseURL from "discourse/lib/url";
|
import DiscourseURL from "discourse/lib/url";
|
||||||
import { getWebauthnCredential } from "discourse/lib/webauthn";
|
import { getWebauthnCredential } from "discourse/lib/webauthn";
|
||||||
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
|
|
||||||
import getURL from "discourse-common/lib/get-url";
|
import getURL from "discourse-common/lib/get-url";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
router: service(),
|
router: service(),
|
||||||
|
|
||||||
|
secondFactorMethod: null,
|
||||||
|
|
||||||
|
secondFactorToken: null,
|
||||||
|
|
||||||
lockImageUrl: getURL("/images/lock.svg"),
|
lockImageUrl: getURL("/images/lock.svg"),
|
||||||
|
|
||||||
@discourseComputed("model")
|
@discourseComputed("model")
|
||||||
|
@ -18,13 +21,6 @@ export default Controller.extend({
|
||||||
return model.security_key_required || model.second_factor_required;
|
return model.security_key_required || model.second_factor_required;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("model")
|
|
||||||
secondFactorMethod(model) {
|
|
||||||
return model.security_key_required
|
|
||||||
? SECOND_FACTOR_METHODS.SECURITY_KEY
|
|
||||||
: SECOND_FACTOR_METHODS.TOTP;
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
finishLogin() {
|
finishLogin() {
|
||||||
let data = {
|
let data = {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
|
@ -10,4 +11,15 @@ export default DiscourseRoute.extend({
|
||||||
model(params) {
|
model(params) {
|
||||||
return ajax(`/session/email-login/${params.token}.json`);
|
return ajax(`/session/email-login/${params.token}.json`);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
controller.set(
|
||||||
|
"secondFactorMethod",
|
||||||
|
model.security_key_required
|
||||||
|
? SECOND_FACTOR_METHODS.SECURITY_KEY
|
||||||
|
: SECOND_FACTOR_METHODS.TOTP
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { click, fillIn, visit } from "@ember/test-helpers";
|
||||||
|
import { test } from "qunit";
|
||||||
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
|
const TOKEN = "sometoken";
|
||||||
|
|
||||||
|
acceptance("Login with email and 2FA", function (needs) {
|
||||||
|
needs.settings({
|
||||||
|
enable_local_logins_via_email: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
needs.pretender((server, helper) => {
|
||||||
|
server.post("/u/email-login", () =>
|
||||||
|
helper.response({
|
||||||
|
success: "OK",
|
||||||
|
user_found: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
server.get(`/session/email-login/${TOKEN}.json`, () =>
|
||||||
|
helper.response({
|
||||||
|
token: TOKEN,
|
||||||
|
can_login: true,
|
||||||
|
token_email: "blah@example.com",
|
||||||
|
security_key_required: true,
|
||||||
|
second_factor_required: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("You can switch from security key to 2FA", async function (assert) {
|
||||||
|
await visit("/");
|
||||||
|
await click("header .login-button");
|
||||||
|
await fillIn("#login-account-name", "blah@example.com");
|
||||||
|
await click("#email-login-link");
|
||||||
|
await visit(`/session/email-login/${TOKEN}`);
|
||||||
|
await click(".toggle-second-factor-method");
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom("#second-factor")
|
||||||
|
.containsText(I18n.t("user.second_factor.title"));
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue