123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- {{define "modals/twoFactorModal"}}
- <a-modal id="two-factor-modal" v-model="twoFactorModal.visible" :title="twoFactorModal.title" :closable="true"
- :class="themeSwitcher.currentTheme">
- <template v-if="twoFactorModal.type === 'set'">
- <p>{{ i18n "pages.settings.security.twoFactorModalSteps" }}</p>
- <a-divider></a-divider>
- <p>{{ i18n "pages.settings.security.twoFactorModalFirstStep" }}</p>
- <div :style="{ display: 'flex', alignItems: 'center', flexDirection: 'column', gap: '12px' }">
- <div class="qr-bg" :style="{ width: '180px', height: '180px' }">
- <canvas @click="copy(twoFactorModal.token)" id="twofactor-qrcode" class="qr-cv"></canvas>
- </div>
- <span :style="{ fontSize: '12px', fontFamily: 'monospace' }">[[ twoFactorModal.token ]]</span>
- </div>
- <a-divider></a-divider>
- <p>{{ i18n "pages.settings.security.twoFactorModalSecondStep" }}</p>
- <a-input v-model.trim="twoFactorModal.enteredCode" :style="{ width: '100%' }"></a-input>
- </template>
- <template v-if="twoFactorModal.type === 'remove'">
- <p>{{ i18n "pages.settings.security.twoFactorModalRemoveStep" }}</p>
- <a-input v-model.trim="twoFactorModal.enteredCode" :style="{ width: '100%' }"></a-input>
- </template>
- <template slot="footer">
- <a-button @click="twoFactorModal.cancel">
- <span>{{ i18n "cancel" }}</span>
- </a-button>
- <a-button type="primary" :disabled="twoFactorModal.enteredCode.length < 6" @click="twoFactorModal.ok">
- <span>{{ i18n "confirm" }}</span>
- </a-button>
- </template>
- </a-modal>
- <script>
- const twoFactorModal = {
- title: '',
- fileName: '',
- token: '',
- enteredCode: '',
- visible: false,
- type: 'set',
- confirm: null,
- totpObject: null,
- qrImage: "",
- ok() {
- if (twoFactorModal.totpObject.generate() === twoFactorModal.enteredCode) {
- ObjectUtil.execute(twoFactorModal.confirm, true)
- twoFactorModal.close()
- switch (twoFactorModal.type) {
- case 'set':
- Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalSetSuccess" }}')
- break;
- case 'remove':
- Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalDeleteSuccess" }}')
- break;
- default:
- break;
- }
- } else {
- Vue.prototype.$message['error']('{{ i18n "pages.settings.security.twoFactorModalError" }}')
- }
- },
- cancel() {
- ObjectUtil.execute(twoFactorModal.confirm, false)
- twoFactorModal.close()
- },
- show: function ({
- title = '',
- token = '',
- type = 'set',
- confirm = (success) => { }
- }) {
- this.title = title;
- this.token = token;
- this.visible = true;
- this.confirm = confirm;
- this.type = type;
- this.totpObject = new OTPAuth.TOTP({
- issuer: "3x-ui",
- label: "Administrator",
- algorithm: "SHA1",
- digits: 6,
- period: 30,
- secret: twoFactorModal.token,
- });
- },
- close: function () {
- twoFactorModal.enteredCode = "";
- twoFactorModal.visible = false;
- },
- };
- const twoFactorModalApp = new Vue({
- delimiters: ['[[', ']]'],
- el: '#two-factor-modal',
- data: {
- twoFactorModal: twoFactorModal,
- },
- updated() {
- if (
- this.twoFactorModal.visible &&
- this.twoFactorModal.type === 'set' &&
- document.getElementById('twofactor-qrcode')
- ) {
- this.setQrCode('twofactor-qrcode', this.twoFactorModal.totpObject.toString());
- }
- },
- methods: {
- setQrCode(elementId, content) {
- new QRious({
- element: document.getElementById(elementId),
- size: 200,
- value: content,
- background: 'white',
- backgroundAlpha: 0,
- foreground: 'black',
- padding: 2,
- level: 'L'
- });
- },
- copy(content) {
- ClipboardManager
- .copyText(content)
- .then(() => {
- app.$message.success('{{ i18n "copied" }}')
- })
- },
- }
- });
- </script>
- {{end}}
|