mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-03 08:00:32 +00:00
Remove RecoveryCodeEntryView and inline UI
This commit is contained in:
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2024-present Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Component = use('util.Component');
|
||||
|
||||
export default def(class RecoveryCodeEntryView extends Component {
|
||||
static ID = 'ui.component.RecoveryCodeEntryView';
|
||||
static PROPERTIES = {
|
||||
value: {},
|
||||
length: { value: 8 },
|
||||
error: {},
|
||||
};
|
||||
|
||||
static CSS = /*css*/`
|
||||
fieldset {
|
||||
display: flex;
|
||||
}
|
||||
.recovery-code-input {
|
||||
flex-grow: 1;
|
||||
box-sizing: border-box;
|
||||
height: 50px;
|
||||
font-size: 25px;
|
||||
text-align: center;
|
||||
border-radius: 0.5rem;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
/* TODO: I'd rather not duplicate this */
|
||||
.error {
|
||||
display: none;
|
||||
color: red;
|
||||
border: 1px solid red;
|
||||
border-radius: 4px;
|
||||
padding: 9px;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
}
|
||||
.error-message {
|
||||
display: none;
|
||||
color: rgb(215 2 2);
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgb(215 2 2);
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
|
||||
create_template ({ template }) {
|
||||
$(template).html(/*html*/`
|
||||
<div class="recovery-code-entry">
|
||||
<form>
|
||||
<div class="error"></div>
|
||||
<fieldset name="recovery-code" style="border: none; padding:0;" data-recovery-code-form>
|
||||
<input type="text" class="recovery-code-input" placeholder="${i18n('login2fa_recovery_placeholder')}" maxlength="${this.get('length')}" required>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
on_focus () {
|
||||
$(this.dom_).find('input').focus();
|
||||
}
|
||||
|
||||
on_ready ({ listen }) {
|
||||
listen('error', (error) => {
|
||||
if ( ! error ) return $(this.dom_).find('.error').hide();
|
||||
$(this.dom_).find('.error').text(error).show();
|
||||
});
|
||||
|
||||
listen('value', (value) => {
|
||||
// clear input
|
||||
if ( value === undefined ) {
|
||||
$(this.dom_).find('input').val('');
|
||||
}
|
||||
});
|
||||
|
||||
const input = $(this.dom_).find('input');
|
||||
input.on('input', () => {
|
||||
if ( input.val().length === this.get('length') ) {
|
||||
this.set('value', input.val());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -22,7 +22,6 @@ import Button from './Components/Button.js';
|
||||
import CodeEntryView from './Components/CodeEntryView.js';
|
||||
import Flexer from './Components/Flexer.js';
|
||||
import JustHTML from './Components/JustHTML.js';
|
||||
import RecoveryCodeEntryView from './Components/RecoveryCodeEntryView.js';
|
||||
import StepView from './Components/StepView.js';
|
||||
import UIComponentWindow from './UIComponentWindow.js';
|
||||
import UIWindow from './UIWindow.js';
|
||||
@@ -330,52 +329,81 @@ async function UIWindowLogin (options) {
|
||||
}</p>
|
||||
`,
|
||||
}),
|
||||
new RecoveryCodeEntryView({
|
||||
_ref: me => recovery_entry = me,
|
||||
async 'property.value' (value, { component }) {
|
||||
let error_i18n_key = 'something_went_wrong';
|
||||
if ( ! value ) return;
|
||||
try {
|
||||
const resp = await fetch(`${window.api_origin}/login/recovery-code`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
token: data.otp_jwt_token,
|
||||
code: value,
|
||||
}),
|
||||
});
|
||||
|
||||
if ( resp.status === 429 ) {
|
||||
error_i18n_key = 'confirm_code_generic_too_many_requests';
|
||||
throw new Error('expected error');
|
||||
new JustHTML({
|
||||
_ref: me => {
|
||||
recovery_entry = me;
|
||||
const set_error = (msg) => {
|
||||
const err = me.dom_.querySelector('.error');
|
||||
if ( ! err ) return;
|
||||
if ( ! msg ) {
|
||||
err.style.display = 'none';
|
||||
err.textContent = '';
|
||||
} else {
|
||||
err.textContent = msg;
|
||||
err.style.display = 'block';
|
||||
}
|
||||
};
|
||||
me.clear_input = () => {
|
||||
const input = me.dom_.querySelector('.recovery-code-input');
|
||||
if ( input ) input.value = '';
|
||||
};
|
||||
me.clear_error = () => set_error(undefined);
|
||||
me.dom_.addEventListener('input', async (e) => {
|
||||
if ( ! e.target.matches('.recovery-code-input') ) return;
|
||||
const value = e.target.value;
|
||||
if ( value.length !== 8 ) return;
|
||||
let error_i18n_key = 'something_went_wrong';
|
||||
try {
|
||||
const resp = await fetch(`${window.api_origin}/login/recovery-code`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
token: data.otp_jwt_token,
|
||||
code: value,
|
||||
}),
|
||||
});
|
||||
|
||||
const next_data = await resp.json();
|
||||
if ( resp.status === 429 ) {
|
||||
error_i18n_key = 'confirm_code_generic_too_many_requests';
|
||||
throw new Error('expected error');
|
||||
}
|
||||
|
||||
if ( ! next_data.proceed ) {
|
||||
error_i18n_key = 'confirm_code_generic_incorrect';
|
||||
throw new Error('expected error');
|
||||
const next_data = await resp.json();
|
||||
|
||||
if ( ! next_data.proceed ) {
|
||||
error_i18n_key = 'confirm_code_generic_incorrect';
|
||||
throw new Error('expected error');
|
||||
}
|
||||
|
||||
data = next_data;
|
||||
|
||||
$(win).close();
|
||||
p.resolve();
|
||||
} catch (e) {
|
||||
set_error(i18n(error_i18n_key));
|
||||
}
|
||||
|
||||
data = next_data;
|
||||
|
||||
$(win).close();
|
||||
p.resolve();
|
||||
} catch (e) {
|
||||
// keeping this log; useful in screenshots
|
||||
component.set('error', i18n(error_i18n_key));
|
||||
}
|
||||
});
|
||||
},
|
||||
html: `
|
||||
<div class="recovery-code-entry">
|
||||
<form>
|
||||
<div class="error" style="display: none; color: red; border: 1px solid red; border-radius: 4px; padding: 9px; margin-bottom: 15px; text-align: center; font-size: 13px;"></div>
|
||||
<fieldset name="recovery-code" style="border: none; padding: 0; display: flex;" data-recovery-code-form>
|
||||
<input type="text" class="recovery-code-input" placeholder="${html_encode(i18n('login2fa_recovery_placeholder'))}" maxlength="8" required style="flex-grow: 1; box-sizing: border-box; height: 50px; font-size: 25px; text-align: center; border-radius: 0.5rem; font-family: 'Courier New', Courier, monospace;">
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
new Button({
|
||||
label: i18n('login2fa_recovery_back'),
|
||||
style: 'link',
|
||||
on_click: async () => {
|
||||
stepper.back();
|
||||
recovery_entry.set('value', undefined);
|
||||
recovery_entry.set('error', undefined);
|
||||
recovery_entry.clear_input();
|
||||
recovery_entry.clear_error();
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user