DEV: Convert second-factor-backup-edit modal to component-based API (#22366)
This PR converts the `second-factor-backup-edit` modal to make use of the new component-based API
This commit is contained in:
parent
f92ed88c52
commit
c05e54e461
|
@ -0,0 +1,62 @@
|
|||
<DModal
|
||||
@title={{i18n "user.second_factor_backup.title"}}
|
||||
@closeModal={{@closeModal}}
|
||||
class="second-factor-backup-edit-modal"
|
||||
>
|
||||
<:body>
|
||||
{{#if this.successMessage}}
|
||||
<div class="alert alert-success">
|
||||
{{this.successMessage}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.errorMessage}}
|
||||
<div class="alert alert-error">
|
||||
{{this.errorMessage}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<ConditionalLoadingSection @isLoading={{this.loading}}>
|
||||
{{#if this.backupCodes}}
|
||||
<h3>{{i18n "user.second_factor_backup.codes.title"}}</h3>
|
||||
<p>{{i18n "user.second_factor_backup.codes.description"}}</p>
|
||||
<BackupCodes
|
||||
@copyBackupCode={{this.copyBackupCode}}
|
||||
@backupCodes={{this.backupCodes}}
|
||||
/>
|
||||
{{/if}}
|
||||
</ConditionalLoadingSection>
|
||||
|
||||
{{#if this.backupEnabled}}
|
||||
{{html-safe
|
||||
(i18n
|
||||
"user.second_factor_backup.remaining_codes" count=this.remainingCodes
|
||||
)
|
||||
}}
|
||||
{{else}}
|
||||
{{html-safe (i18n "user.second_factor_backup.not_enabled")}}
|
||||
{{/if}}
|
||||
</:body>
|
||||
<:footer>
|
||||
<div class="actions">
|
||||
{{#if this.backupEnabled}}
|
||||
<DButton
|
||||
class="btn-primary"
|
||||
@icon="redo"
|
||||
@action={{this.generateSecondFactorCodes}}
|
||||
@type="submit"
|
||||
@isLoading={{this.loading}}
|
||||
@label="user.second_factor_backup.regenerate"
|
||||
/>
|
||||
{{else}}
|
||||
<DButton
|
||||
class="btn-primary"
|
||||
@action={{this.generateSecondFactorCodes}}
|
||||
@type="submit"
|
||||
@disabled={{this.loading}}
|
||||
@label="user.second_factor_backup.enable"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</:footer>
|
||||
</DModal>
|
|
@ -0,0 +1,63 @@
|
|||
import Component from "@glimmer/component";
|
||||
import I18n from "I18n";
|
||||
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
|
||||
import { debounce } from "discourse-common/utils/decorators";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default class SecondFactorBackupEdit extends Component {
|
||||
@tracked loading = false;
|
||||
@tracked errorMessage;
|
||||
@tracked successMessage;
|
||||
@tracked backupEnabled =
|
||||
this.args.model.secondFactor.second_factor_backup_enabled;
|
||||
@tracked remainingCodes =
|
||||
this.args.model.secondFactor.second_factor_remaining_backup_codes;
|
||||
@tracked backupCodes;
|
||||
@tracked secondFactorMethod = SECOND_FACTOR_METHODS.TOTP;
|
||||
|
||||
@action
|
||||
copyBackupCode(successful) {
|
||||
if (successful) {
|
||||
this.successMessage = I18n.t(
|
||||
"user.second_factor_backup.copied_to_clipboard"
|
||||
);
|
||||
} else {
|
||||
this.errorMessage = I18n.t(
|
||||
"user.second_factor_backup.copy_to_clipboard_error"
|
||||
);
|
||||
}
|
||||
this._hideCopyMessage();
|
||||
}
|
||||
|
||||
@action
|
||||
generateSecondFactorCodes() {
|
||||
this.loading = true;
|
||||
this.args.model.secondFactor
|
||||
.generateSecondFactorCodes()
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
this.errorMessage = response.error;
|
||||
return;
|
||||
}
|
||||
|
||||
this.args.model.markDirty();
|
||||
this.errorMessage = null;
|
||||
this.backupCodes = response.backup_codes;
|
||||
this.args.model.setBackupEnabled(true);
|
||||
this.backupEnabled = true;
|
||||
this.remainingCodes = response.backup_codes.length;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.args.closeModal();
|
||||
this.args.model.onError(error);
|
||||
})
|
||||
.finally(() => (this.loading = false));
|
||||
}
|
||||
|
||||
@debounce(2000)
|
||||
_hideCopyMessage() {
|
||||
this.successMessage = null;
|
||||
this.errorMessage = null;
|
||||
}
|
||||
}
|
|
@ -8,13 +8,13 @@ import { alias } from "@ember/object/computed";
|
|||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { findAll } from "discourse/models/login-method";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import { inject as service } from "@ember/service";
|
||||
import SecondFactorConfirmPhrase from "discourse/components/dialog-messages/second-factor-confirm-phrase";
|
||||
import SecondFactorAddSecurityKey from "discourse/components/modal/second-factor-add-security-key";
|
||||
import SecondFactorEditSecurityKey from "discourse/components/modal/second-factor-edit-security-key";
|
||||
import SecondFactorEdit from "discourse/components/modal/second-factor-edit";
|
||||
import SecondFactorAddTotp from "discourse/components/modal/second-factor-add-totp";
|
||||
import SecondFactorBackupEdit from "discourse/components/modal/second-factor-backup-edit";
|
||||
|
||||
export default Controller.extend(CanCheckEmails, {
|
||||
dialog: service(),
|
||||
|
@ -63,6 +63,11 @@ export default Controller.extend(CanCheckEmails, {
|
|||
}
|
||||
},
|
||||
|
||||
@action
|
||||
setBackupEnabled(value) {
|
||||
this.set("backupEnabled", value);
|
||||
},
|
||||
|
||||
@action
|
||||
loadSecondFactors() {
|
||||
if (this.dirty === false) {
|
||||
|
@ -310,15 +315,14 @@ export default Controller.extend(CanCheckEmails, {
|
|||
this.loadSecondFactors();
|
||||
},
|
||||
|
||||
editSecondFactorBackup() {
|
||||
const controller = showModal("second-factor-backup-edit", {
|
||||
model: this.model,
|
||||
title: "user.second_factor_backup.title",
|
||||
});
|
||||
controller.setProperties({
|
||||
onClose: () => this.loadSecondFactors(),
|
||||
markDirty: () => this.markDirty(),
|
||||
onError: (e) => this.handleError(e),
|
||||
async editSecondFactorBackup() {
|
||||
await this.modal.show(SecondFactorBackupEdit, {
|
||||
model: {
|
||||
secondFactor: this.model,
|
||||
markDirty: () => this.markDirty(),
|
||||
onError: (e) => this.handleError(e),
|
||||
setBackupEnabled: (e) => this.setBackupEnabled(e),
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
import Controller from "@ember/controller";
|
||||
import I18n from "I18n";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import discourseLater from "discourse-common/lib/later";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
loading: false,
|
||||
errorMessage: null,
|
||||
successMessage: null,
|
||||
backupEnabled: alias("model.second_factor_backup_enabled"),
|
||||
remainingCodes: alias("model.second_factor_remaining_backup_codes"),
|
||||
backupCodes: null,
|
||||
secondFactorMethod: SECOND_FACTOR_METHODS.TOTP,
|
||||
|
||||
onShow() {
|
||||
this.setProperties({
|
||||
loading: false,
|
||||
errorMessage: null,
|
||||
successMessage: null,
|
||||
backupCodes: null,
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
copyBackupCode(successful) {
|
||||
if (successful) {
|
||||
this.set(
|
||||
"successMessage",
|
||||
I18n.t("user.second_factor_backup.copied_to_clipboard")
|
||||
);
|
||||
} else {
|
||||
this.set(
|
||||
"errorMessage",
|
||||
I18n.t("user.second_factor_backup.copy_to_clipboard_error")
|
||||
);
|
||||
}
|
||||
|
||||
this._hideCopyMessage();
|
||||
},
|
||||
|
||||
generateSecondFactorCodes() {
|
||||
this.set("loading", true);
|
||||
this.model
|
||||
.generateSecondFactorCodes()
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
this.set("errorMessage", response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
this.markDirty();
|
||||
this.setProperties({
|
||||
errorMessage: null,
|
||||
backupCodes: response.backup_codes,
|
||||
backupEnabled: true,
|
||||
remainingCodes: response.backup_codes.length,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.send("closeModal");
|
||||
this.onError(error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.setProperties({
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
_hideCopyMessage() {
|
||||
discourseLater(
|
||||
() => this.setProperties({ successMessage: null, errorMessage: null }),
|
||||
2000
|
||||
);
|
||||
},
|
||||
});
|
|
@ -1,61 +0,0 @@
|
|||
<DModalBody>
|
||||
{{#if this.successMessage}}
|
||||
<div class="alert alert-success">
|
||||
{{this.successMessage}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.errorMessage}}
|
||||
<div class="alert alert-error">
|
||||
{{this.errorMessage}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<ConditionalLoadingSection @isLoading={{this.loading}}>
|
||||
{{#if this.backupCodes}}
|
||||
<h3>{{i18n "user.second_factor_backup.codes.title"}}</h3>
|
||||
|
||||
<p>
|
||||
{{i18n "user.second_factor_backup.codes.description"}}
|
||||
</p>
|
||||
|
||||
<BackupCodes
|
||||
@copyBackupCode={{action "copyBackupCode"}}
|
||||
@backupCodes={{this.backupCodes}}
|
||||
/>
|
||||
{{/if}}
|
||||
</ConditionalLoadingSection>
|
||||
|
||||
{{#if this.backupEnabled}}
|
||||
{{html-safe
|
||||
(i18n
|
||||
"user.second_factor_backup.remaining_codes" count=this.remainingCodes
|
||||
)
|
||||
}}
|
||||
{{else}}
|
||||
{{html-safe (i18n "user.second_factor_backup.not_enabled")}}
|
||||
{{/if}}
|
||||
</DModalBody>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="actions">
|
||||
{{#if this.backupEnabled}}
|
||||
<DButton
|
||||
@class="btn-primary"
|
||||
@icon="redo"
|
||||
@action={{action "generateSecondFactorCodes"}}
|
||||
@type="submit"
|
||||
@isLoading={{this.loading}}
|
||||
@label="user.second_factor_backup.regenerate"
|
||||
/>
|
||||
{{else}}
|
||||
<DButton
|
||||
@class="btn-primary"
|
||||
@action={{action "generateSecondFactorCodes"}}
|
||||
@type="submit"
|
||||
@disabled={{this.loading}}
|
||||
@label="user.second_factor_backup.enable"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
|
@ -48,12 +48,10 @@ acceptance("User Preferences - Second Factor Backup", function (needs) {
|
|||
updateCurrentUser({ second_factor_enabled: true });
|
||||
await visit("/u/eviltrout/preferences/second-factor");
|
||||
|
||||
if (exists(".new-second-factor-backup")) {
|
||||
// if codes don't exist yet, create them
|
||||
await click(".new-second-factor-backup");
|
||||
await click(".second-factor-backup-edit-modal .btn-primary");
|
||||
await click(".modal-close");
|
||||
}
|
||||
// create backup codes
|
||||
await click(".new-second-factor-backup");
|
||||
await click(".second-factor-backup-edit-modal .btn-primary");
|
||||
await click(".second-factor-backup-edit-modal .modal-close");
|
||||
|
||||
await click(".two-factor-backup-dropdown .select-kit-header");
|
||||
await click("li[data-name='Disable'");
|
||||
|
|
Loading…
Reference in New Issue