generated from mirzaev/pot
411 lines
16 KiB
HTML
411 lines
16 KiB
HTML
{% block css %}
|
||
<link type="text/css" rel="stylesheet" href="/css/account.css">
|
||
<link type="text/css" rel="stylesheet" href="/css/icons/arrow_right.css">
|
||
<link type="text/css" rel="stylesheet" href="/css/icons/nametag.css">
|
||
<link type="text/css" rel="stylesheet" href="/css/icons/keyhole.css">
|
||
<link type="text/css" rel="stylesheet" href="/css/icons/user_add.css">
|
||
{% endblock %}
|
||
|
||
{% block body %}
|
||
<div class="column">
|
||
<section id="entry" class="panel medium">
|
||
<section class="header unselectable">
|
||
<h1>Идентификация</h1>
|
||
</section>
|
||
<section class="body">
|
||
<label id="login">
|
||
<i class="nametag"></i>
|
||
<input name="login" type="text" placeholder="Входной псевдоним"
|
||
value="{{ account.login ?? session.buffer.login ?? cookie.buffer_login }}"
|
||
onkeypress="if (event.keyCode === 13) __login()" autofocus>
|
||
<button class="accept" onclick="__login()"><i class="arrow right"></i></button>
|
||
</label>
|
||
<label id="password" class="hidden">
|
||
<i class="keyhole"></i>
|
||
<input name="password" type="password" placeholder="Пароль" autocomplete="current-password"
|
||
onkeypress="if (event.keyCode === 13) __password()">
|
||
<button class="accept" onclick="__password()"><i class="arrow right"></i></button>
|
||
</label>
|
||
<label id="invite" class="hidden">
|
||
<i class="user add"></i>
|
||
<input name="invite" type="text" placeholder="Ключ приглашения"
|
||
onkeypress="if (event.keyCode === 13) __invite()">
|
||
<button class="accept" onclick="__invite()"><i class="arrow right"></i></button>
|
||
</label>
|
||
</section>
|
||
</section>
|
||
<section id="errors" class="panel medium animation window hidden" style="--height: 300px">
|
||
<section class="body">
|
||
<dl></dl>
|
||
</section>
|
||
</section>
|
||
</div>
|
||
<section id="mnemonic" class="panel small hidden">
|
||
<section class="header unselectable">
|
||
<h2>Мнемонические</h2>
|
||
</section>
|
||
<section class="body">
|
||
<ul></ul>
|
||
</section>
|
||
</section>
|
||
<section id="classic" class="panel small hidden">
|
||
<section class="header unselectable">
|
||
<h2>Классические</h2>
|
||
</section>
|
||
<section class="body">
|
||
<ul></ul>
|
||
</section>
|
||
</section>
|
||
<script>
|
||
// Инициализация функций в глобальной области видимости
|
||
let _login, __login, _password, __password, _invite, __invite, _errors;
|
||
|
||
document.addEventListener('damper.initialized', function (e) {
|
||
// Инициализирован демпфер
|
||
|
||
// Инициализация HTML-элемента с блоком входа в аккаунт
|
||
const entry = {wrap: document.getElementById('entry')};
|
||
entry.title = entry.wrap.getElementsByTagName('h1')[0];
|
||
|
||
// Инициализация HTML-элемента с блоком мнемонических паролей
|
||
const mnemonic = {wrap: document.getElementById('mnemonic')};
|
||
mnemonic.list = mnemonic.wrap.getElementsByTagName('ul')[0];
|
||
|
||
// Инициализация HTML-элемента с блоком классических паролей
|
||
const classic = {wrap: document.getElementById('classic')};
|
||
classic.list = classic.wrap.getElementsByTagName('ul')[0];
|
||
|
||
// Инициализация HTML-элемента с блоком ошибок
|
||
const errors = {wrap: document.getElementById('errors')};
|
||
errors.list = errors.wrap.getElementsByTagName('dl')[0];
|
||
|
||
// Инициализация HTML-элементов-оболочек полей ввода
|
||
const labels = {
|
||
login: {label: document.getElementById('login')},
|
||
password: {label: document.getElementById('password')},
|
||
invite: {label: document.getElementById('invite')}
|
||
};
|
||
labels.login.input = labels.login.label.querySelector('input[name=login]');
|
||
labels.password.input = labels.password.label.querySelector('input[name=password]');
|
||
labels.invite.input = labels.invite.label.querySelector('input[name=invite]');
|
||
|
||
/**
|
||
* Отправить входной псевдоним на сервер
|
||
*
|
||
* @return {void}
|
||
*/
|
||
_login = e.detail.damper(async () => {
|
||
// Деинициализация индикатора и анимации об ошибке
|
||
labels.login.input.classList.remove('error');
|
||
|
||
// Запрос к серверу
|
||
const response = await session.login(labels.login.input.value);
|
||
|
||
if (_errors(response.errors)) {
|
||
// Сгенерированы ошибки
|
||
|
||
// Разлокировка поля ввода
|
||
labels.login.input.disabled = false;;
|
||
|
||
// Инициализация отображения ошибки
|
||
labels.login.input.classList.add('error');
|
||
|
||
// Фокусировка на поле ввода
|
||
labels.login.input.focus();
|
||
} else {
|
||
// Не сгенерированы ошибки (подразумевается их отсутствие)
|
||
|
||
if (typeof response.exist === 'boolean')
|
||
if (response.exist) {
|
||
// Найден аккаунт
|
||
|
||
// Инициализация интерфейса аутентификации
|
||
entry.title.innerText = 'Аутентификация';
|
||
labels.login.label.classList.add('hidden');
|
||
labels.password.label.classList.remove('hidden');
|
||
labels.password.input.focus();
|
||
} else {
|
||
// Не найден аккаунт
|
||
|
||
// Инициализация интерфейса регистрации
|
||
entry.title.innerText = 'Регистрация';
|
||
labels.login.label.classList.add('hidden');
|
||
labels.invite.label.classList.remove('hidden');
|
||
labels.invite.input.focus();
|
||
}
|
||
}
|
||
}, 500);
|
||
|
||
/**
|
||
* Отправить входной псевдоним на сервер с дополнительной подготовкой
|
||
*
|
||
* @return {void}
|
||
*/
|
||
__login = () => {
|
||
// Блокировка поля ввода
|
||
labels.login.input.disabled = true;
|
||
|
||
// Реинициализация блока ошибок
|
||
_errors();
|
||
|
||
// Запуск процесса отправки входного псевдонима
|
||
_login();
|
||
}
|
||
|
||
/**
|
||
* Отправить пароль на сервер
|
||
*
|
||
* @return {void}
|
||
*/
|
||
_password = e.detail.damper(async () => {
|
||
// Деинициализация индикатора и анимации об ошибке
|
||
labels.password.input.classList.remove('error');
|
||
|
||
// Запрос к серверу
|
||
const response = await session.password(labels.password.input.value);
|
||
|
||
if (_errors(response.errors)) {
|
||
// Сгенерированы ошибки
|
||
|
||
// Разлокировка поля ввода
|
||
labels.password.input.disabled = false;
|
||
|
||
// Инициализация отображения ошибки
|
||
labels.password.input.classList.add('error');
|
||
|
||
// Фокусировка на поле ввода
|
||
labels.password.input.focus();
|
||
} else {
|
||
// Не сгенерированы ошибки (подразумевается их отсутствие)
|
||
|
||
if (typeof response.verify === 'boolean')
|
||
if (response.verify) {
|
||
// Пройдена проверка пароля на соответствие требованиям
|
||
|
||
if (response.account) {
|
||
// Инициализирован аккаунт
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
}, 500);
|
||
|
||
/**
|
||
* Отправить пароль на сервер с дополнительной подготовкой
|
||
*
|
||
* @return {void}
|
||
*/
|
||
__password = () => {
|
||
// Блокировка поля ввода
|
||
labels.password.input.disabled = true;
|
||
|
||
// Реинициализация блока ошибок
|
||
_errors();
|
||
|
||
// Запуск процесса отправки входного псевдонима
|
||
_password();
|
||
}
|
||
|
||
/**
|
||
* Отправить код приглашения на сервер
|
||
*
|
||
* @return {void}
|
||
*/
|
||
_invite = e.detail.damper(async () => {
|
||
// Деинициализация индикатора и анимации об ошибке
|
||
labels.invite.input.classList.remove('error');
|
||
|
||
// Запрос к серверу
|
||
const response = await session.invite(labels.invite.input.value);
|
||
|
||
if (_errors(response.errors)) {
|
||
// Сгенерированы ошибки
|
||
|
||
// Разблокировка поля ввода
|
||
labels.invite.input.disabled = false;
|
||
|
||
// Инициализация отображения ошибки
|
||
labels.invite.input.classList.add('error');
|
||
|
||
// Фокусировка на поле ввода
|
||
labels.invite.input.focus();
|
||
} else {
|
||
// Не сгенерированы ошибки (подразумевается их отсутствие)
|
||
|
||
if (typeof response.exist === 'boolean')
|
||
if (response.exist) {
|
||
// Найдено приглашение
|
||
|
||
// Инициализация интерфейса ввода пароля
|
||
labels.invite.label.classList.add('hidden');
|
||
labels.password.input.autocomplete = 'new-password';
|
||
labels.password.label.classList.remove('hidden');
|
||
mnemonic.wrap.classList.remove('hidden');
|
||
classic.wrap.classList.remove('hidden');
|
||
|
||
for (let i = 0; i < 6; i++) {
|
||
// Генерация HTML-элементов с примерами мнемонических паролей
|
||
|
||
// Инициализация HTML-элемента
|
||
const element = document.createElement('li');
|
||
|
||
// Генерация пароля
|
||
password.generate(Math.floor(Math.random() * 3) + 2, 'mnemonic')
|
||
.then((responce) => {
|
||
if (responce.password === '') {
|
||
// Не удалось сгенерировать пароль
|
||
|
||
// Перезапуск итерации
|
||
--i;
|
||
return;
|
||
}
|
||
|
||
// Запись пароля
|
||
element.innerText = responce.password;
|
||
|
||
// Запись HTML-элемента с паролем в список
|
||
mnemonic.list.appendChild(element);
|
||
|
||
// Генерация списка с текстом ошибок
|
||
_errors(response.errors);
|
||
});
|
||
}
|
||
|
||
for (let i = 0; i < 8; i++) {
|
||
// Генерация HTML-элементов с примерами классических паролей
|
||
|
||
// Инициализация HTML-элемента
|
||
const element = document.createElement('li');
|
||
|
||
// Генерация пароля
|
||
password.generate(Math.floor(Math.random() * 14) + 4)
|
||
.then((responce) => {
|
||
if (responce.password === '') {
|
||
// Не удалось сгенерировать пароль
|
||
|
||
// Перезапуск итерации
|
||
--i;
|
||
return;
|
||
}
|
||
|
||
// Запись пароля
|
||
element.innerText = responce.password;
|
||
|
||
// Запись HTML-элемента с паролем в список
|
||
classic.list.appendChild(element);
|
||
|
||
// Генерация списка с текстом ошибок
|
||
_errors(response.errors);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}, 500);
|
||
|
||
/**
|
||
* Отправить код приглашения на сервер с дополнительной подготовкой
|
||
*
|
||
* @return {void}
|
||
*/
|
||
__invite = () => {
|
||
// Блокировка поля ввода
|
||
labels.invite.input.disabled = true;
|
||
|
||
// Реинициализация блока ошибок
|
||
_errors();
|
||
|
||
// Запуск процесса отправки входного псевдонима
|
||
_invite();
|
||
}
|
||
|
||
/**
|
||
* Сгенерировать HTML-элемент с блоком ошибок
|
||
*
|
||
* @param {object} registry Реестр ошибок
|
||
* @param {bool} reinitialization Реинициализировать?
|
||
*
|
||
* @return {bool} Сгенерированы ошибки?
|
||
*/
|
||
_errors = (registry, reinitialization = true) => {
|
||
function height() {
|
||
// Скрытие HTML-элемента
|
||
errors.wrap.style.zIndex = '-99999';
|
||
errors.wrap.style.left = '-99999px';
|
||
errors.wrap.style.top = '-99999px';
|
||
errors.wrap.style.position = 'absolute';
|
||
errors.wrap.style.display = 'var(--display, unset)';
|
||
errors.wrap.style.opacity = '0';
|
||
errors.wrap.style.animationName = 'unset';
|
||
|
||
// Реинициализация переменной с данными о высоте HTML-элемента
|
||
errors.wrap.style.setProperty('--height', errors.wrap.offsetHeight + 'px');
|
||
|
||
// Отмена скрытия HTML-элемента
|
||
errors.wrap.style.zIndex =
|
||
errors.wrap.style.left =
|
||
errors.wrap.style.top =
|
||
errors.wrap.style.position =
|
||
errors.wrap.style.display =
|
||
errors.wrap.style.opacity =
|
||
errors.wrap.style.animationName = null;
|
||
}
|
||
|
||
// Удаление ошибок из прошлой генерации
|
||
if (reinitialization) errors.list.innerHTML = null;
|
||
|
||
for (error in registry) {
|
||
// Генерация HTML-элементов с текстами ошибок
|
||
|
||
// Инициализация HTML-элемента
|
||
const element = document.createElement('dd');
|
||
|
||
if (typeof registry[error] === 'object') {
|
||
// Категория ошибок
|
||
|
||
// Проверка наличия ошибок
|
||
if (registry[error].length === 0) continue;
|
||
|
||
// Инициализация HTML-элемента
|
||
const element = document.createElement('dt');
|
||
|
||
// Запись текста категории
|
||
element.innerText = error;
|
||
|
||
// Запись HTML-элемента в список
|
||
errors.list.appendChild(element);
|
||
|
||
// Реинициализация высоты
|
||
height();
|
||
|
||
// Обработка вложенных ошибок (вход в рекурсию)
|
||
_errors(registry[error], false);
|
||
} else {
|
||
// Текст ошибки (подразумевается)
|
||
|
||
// Запись текста ошибки
|
||
element.innerText = registry[error];
|
||
|
||
// Запись HTML-элемента в список
|
||
errors.list.appendChild(element);
|
||
|
||
// Реинициализация высоты
|
||
height();
|
||
}
|
||
}
|
||
|
||
// Реинициализация HTML-элемента с текстом ошибок
|
||
if (reinitialization && errors.list.childElementCount === 0) errors.wrap.classList.add('hidden');
|
||
else errors.wrap.classList.remove('hidden');
|
||
|
||
return errors.list.childElementCount === 0 ? false : true;
|
||
};
|
||
});
|
||
</script>
|
||
{% endblock %}
|
||
|
||
{% block js %}
|
||
<script type="text/javascript" src="/js/session.js"></script>
|
||
<script type="text/javascript" src="/js/password.js"></script>
|
||
{% endblock %}
|