DEV: Convert second-factor-add-totp modal to component-based API (#22358)
This PR converts the `second-factor-add-totp` modal to make use of the new component-based API
This commit is contained in:
parent
760668dfde
commit
2a598db08a
|
@ -0,0 +1,79 @@
|
|||
<DModal
|
||||
@closeModal={{@closeModal}}
|
||||
@title={{i18n "user.second_factor.totp.add"}}
|
||||
{{did-insert this.totpRequested}}
|
||||
>
|
||||
<:body>
|
||||
<ConditionalLoadingSpinner @condition={{this.loading}}>
|
||||
{{#if this.errorMessage}}
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="alert alert-error">{{this.errorMessage}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
{{html-safe (i18n "user.second_factor.enable_description")}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="qr-code">
|
||||
<img src={{html-safe this.secondFactorImage}} />
|
||||
</div>
|
||||
<p>
|
||||
{{#if this.showSecondFactorKey}}
|
||||
{{this.secondFactorKey}}
|
||||
{{else}}
|
||||
<a href {{on "click" this.enableShowSecondFactorKey}}>{{i18n
|
||||
"user.second_factor.show_key_description"
|
||||
}}</a>
|
||||
{{/if}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label input-prepend">{{i18n
|
||||
"user.second_factor.name"
|
||||
}}</label>
|
||||
<div class="controls">
|
||||
<SecondFactorInput
|
||||
@value={{this.secondFactorName}}
|
||||
@inputId="second-factor-name"
|
||||
@placeholder={{i18n "user.second_factor.totp.default_name"}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label class="control-label input-prepend">{{i18n
|
||||
"user.second_factor.label"
|
||||
}}</label>
|
||||
<div class="controls">
|
||||
<TextField
|
||||
class="second-factor-token-input"
|
||||
maxlength={{6}}
|
||||
@value={{this.secondFactorToken}}
|
||||
@inputId="second-factor-token"
|
||||
placeholder="123456"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
autofocus="autofocus"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<DButton
|
||||
class="btn-primary add-totp"
|
||||
@action={{this.enableSecondFactor}}
|
||||
@label="enable"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ConditionalLoadingSpinner>
|
||||
</:body>
|
||||
</DModal>
|
|
@ -0,0 +1,63 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default class SecondFactorAddTotp extends Component {
|
||||
@tracked loading = false;
|
||||
@tracked secondFactorImage;
|
||||
@tracked secondFactorKey;
|
||||
@tracked showSecondFactorKey = false;
|
||||
@tracked errorMessage;
|
||||
@tracked secondFactorToken;
|
||||
|
||||
@action
|
||||
totpRequested() {
|
||||
this.args.model.secondFactor
|
||||
.createSecondFactorTotp()
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
this.errorMessage = response.error;
|
||||
return;
|
||||
}
|
||||
|
||||
this.errorMessage = null;
|
||||
this.secondFactorKey = response.key;
|
||||
this.secondFactorImage = response.qr;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.args.closeModal();
|
||||
this.args.model.onError(error);
|
||||
})
|
||||
.finally(() => (this.loading = false));
|
||||
}
|
||||
|
||||
@action
|
||||
enableShowSecondFactorKey() {
|
||||
this.showSecondFactorKey = true;
|
||||
}
|
||||
|
||||
@action
|
||||
enableSecondFactor() {
|
||||
if (!this.secondFactorToken || !this.secondFactorName) {
|
||||
this.errorMessage = I18n.t(
|
||||
"user.second_factor.totp.name_and_code_required_error"
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
this.args.model.secondFactor
|
||||
.enableSecondFactorTotp(this.secondFactorToken, this.secondFactorName)
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
this.errorMessage = response.error;
|
||||
return;
|
||||
}
|
||||
this.args.model.markDirty();
|
||||
this.errorMessage = null;
|
||||
this.args.closeModal();
|
||||
})
|
||||
.catch((error) => this.args.model.onError(error))
|
||||
.finally(() => (this.loading = false));
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import SecondFactorConfirmPhrase from "discourse/components/dialog-messages/seco
|
|||
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";
|
||||
|
||||
export default Controller.extend(CanCheckEmails, {
|
||||
dialog: service(),
|
||||
|
@ -263,16 +264,15 @@ export default Controller.extend(CanCheckEmails, {
|
|||
});
|
||||
},
|
||||
|
||||
createTotp() {
|
||||
const controller = showModal("second-factor-add-totp", {
|
||||
model: this.model,
|
||||
title: "user.second_factor.totp.add",
|
||||
});
|
||||
controller.setProperties({
|
||||
onClose: () => this.loadSecondFactors(),
|
||||
markDirty: () => this.markDirty(),
|
||||
onError: (e) => this.handleError(e),
|
||||
async createTotp() {
|
||||
await this.modal.show(SecondFactorAddTotp, {
|
||||
model: {
|
||||
secondFactor: this.model,
|
||||
markDirty: () => this.markDirty(),
|
||||
onError: (e) => this.handleError(e),
|
||||
},
|
||||
});
|
||||
this.loadSecondFactors();
|
||||
},
|
||||
|
||||
async createSecurityKey() {
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import I18n from "I18n";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
loading: false,
|
||||
secondFactorImage: null,
|
||||
secondFactorKey: null,
|
||||
showSecondFactorKey: false,
|
||||
errorMessage: null,
|
||||
|
||||
onShow() {
|
||||
this.setProperties({
|
||||
errorMessage: null,
|
||||
secondFactorKey: null,
|
||||
secondFactorName: null,
|
||||
secondFactorToken: null,
|
||||
showSecondFactorKey: false,
|
||||
secondFactorImage: null,
|
||||
loading: true,
|
||||
});
|
||||
this.model
|
||||
.createSecondFactorTotp()
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
this.set("errorMessage", response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
errorMessage: null,
|
||||
secondFactorKey: response.key,
|
||||
secondFactorImage: response.qr,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.send("closeModal");
|
||||
this.onError(error);
|
||||
})
|
||||
.finally(() => this.set("loading", false));
|
||||
},
|
||||
|
||||
@action
|
||||
enableShowSecondFactorKey(event) {
|
||||
event?.preventDefault();
|
||||
this.set("showSecondFactorKey", true);
|
||||
},
|
||||
|
||||
actions: {
|
||||
showSecondFactorKey() {
|
||||
this.enableShowSecondFactorKey();
|
||||
},
|
||||
|
||||
enableSecondFactor() {
|
||||
if (!this.secondFactorToken || !this.secondFactorName) {
|
||||
this.set(
|
||||
"errorMessage",
|
||||
I18n.t("user.second_factor.totp.name_and_code_required_error")
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.set("loading", true);
|
||||
|
||||
this.model
|
||||
.enableSecondFactorTotp(this.secondFactorToken, this.secondFactorName)
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
this.set("errorMessage", response.error);
|
||||
return;
|
||||
}
|
||||
this.markDirty();
|
||||
this.set("errorMessage", null);
|
||||
this.send("closeModal");
|
||||
})
|
||||
.catch((error) => this.onError(error))
|
||||
.finally(() => this.set("loading", false));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,73 +0,0 @@
|
|||
<DModalBody>
|
||||
<ConditionalLoadingSpinner @condition={{this.loading}}>
|
||||
{{#if this.errorMessage}}
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="alert alert-error">{{this.errorMessage}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
{{html-safe (i18n "user.second_factor.enable_description")}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="qr-code">
|
||||
<img src={{html-safe this.secondFactorImage}} />
|
||||
</div>
|
||||
<p>
|
||||
{{#if this.showSecondFactorKey}}
|
||||
{{this.secondFactorKey}}
|
||||
{{else}}
|
||||
<a href {{on "click" this.enableShowSecondFactorKey}}>{{i18n
|
||||
"user.second_factor.show_key_description"
|
||||
}}</a>
|
||||
{{/if}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label input-prepend">{{i18n
|
||||
"user.second_factor.name"
|
||||
}}</label>
|
||||
<div class="controls">
|
||||
<SecondFactorInput
|
||||
@value={{this.secondFactorName}}
|
||||
@inputId="second-factor-name"
|
||||
@placeholder={{i18n "user.second_factor.totp.default_name"}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label class="control-label input-prepend">{{i18n
|
||||
"user.second_factor.label"
|
||||
}}</label>
|
||||
<div class="controls">
|
||||
<TextField
|
||||
@class="second-factor-token-input"
|
||||
@maxlength={{6}}
|
||||
@value={{this.secondFactorToken}}
|
||||
@inputId="second-factor-token"
|
||||
@placeholder="123456"
|
||||
@autocorrect="off"
|
||||
@autocapitalize="off"
|
||||
@autofocus="autofocus"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<DButton
|
||||
@class="btn-primary add-totp"
|
||||
@action={{action "enableSecondFactor"}}
|
||||
@label="enable"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ConditionalLoadingSpinner>
|
||||
</DModalBody>
|
Loading…
Reference in New Issue