205 lines
7.1 KiB
JavaScript
205 lines
7.1 KiB
JavaScript
import $ from 'jquery';
|
||
import { JSONRPC } from '@/json-rpc.js';
|
||
|
||
// --- Глобальное состояние ---
|
||
let tokens = [];
|
||
|
||
/**
|
||
* @private
|
||
* Загружает текущий список токенов.
|
||
* @returns {Promise<boolean>}
|
||
*/
|
||
async function loadTokens() {
|
||
try {
|
||
// Запрос списка токенов
|
||
tokens = await JSONRPC.Auth.listTokens();
|
||
tokens = tokens || [];
|
||
return true;
|
||
} catch (e) {
|
||
console.error("Ошибка при загрузке токенов:", e);
|
||
tokens = [];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
* Рендерит список токенов и кнопки управления.
|
||
*/
|
||
function renderTokenList() {
|
||
const $listContainer = $('#api-token-container');
|
||
|
||
// Кнопка "Создать токен"
|
||
const createButtonHtml = `
|
||
<button id="create-token-btn" class="btn-primary" style="width: 200px; margin-bottom: 30px;">
|
||
Создать токен API
|
||
</button>
|
||
<div id="token-status-message" class="success-message" style="display: none;"></div>
|
||
`;
|
||
|
||
if (tokens.length === 0) {
|
||
$listContainer.html(createButtonHtml + '<p>Активных API токенов не найдено.</p>');
|
||
attachEventHandlers();
|
||
return;
|
||
}
|
||
|
||
let listHtml = tokens.map(item => {
|
||
// Мы НЕ показываем полный токен, показываем только его начало/конец для идентификации
|
||
const displayToken = item.token ?
|
||
`${item.token.substring(0, 8)}...${item.token.substring(item.token.length - 4)}` :
|
||
'Неизвестный токен';
|
||
|
||
return `
|
||
<li class="token-item" data-full-token="${item.token}">
|
||
<div class="token-description">${item.description}</div>
|
||
<div class="token-details">
|
||
<span class="token-value">Ключ: ${displayToken}</span>
|
||
<button class="delete-token-btn btn-icon" data-token="${item.token}" title="Удалить токен">
|
||
<span class="delete-icon">✖</span>
|
||
</button>
|
||
</div>
|
||
</li>
|
||
`;
|
||
}).join('');
|
||
|
||
const html = `
|
||
${createButtonHtml}
|
||
<ul class="token-list">${listHtml}</ul>
|
||
`;
|
||
|
||
$listContainer.html(html);
|
||
attachEventHandlers();
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
* Отображает модальное окно для создания токена.
|
||
*/
|
||
function showCreateTokenModal() {
|
||
// Используем простое модальное окно jQuery для минимализма
|
||
const description = prompt("Введите описание для нового API токена (например, 'Токен для Telegram бота'):");
|
||
|
||
if (description === null) {
|
||
return; // Пользователь нажал Отмена
|
||
}
|
||
|
||
if (description.trim() === "") {
|
||
alert("Описание токена не может быть пустым.");
|
||
return;
|
||
}
|
||
|
||
createToken(description.trim());
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
* Логика создания токена и обновления UI.
|
||
* @param {string} description - Описание токена.
|
||
*/
|
||
async function createToken(description) {
|
||
const $btn = $('#create-token-btn');
|
||
const $message = $('#token-status-message');
|
||
|
||
$message.hide().removeClass('error-message').addClass('success-message');
|
||
$btn.prop('disabled', true).text('Создание...');
|
||
|
||
try {
|
||
const newTokenValue = await JSONRPC.Auth.createAPIToken(description);
|
||
|
||
if (!newTokenValue) {
|
||
throw new Error("Сервер не вернул токен.");
|
||
}
|
||
|
||
// Показываем токен пользователю ОДИН раз
|
||
prompt("ВАЖНО: Ваш новый токен API. Сохраните его, он больше не будет показан!", newTokenValue);
|
||
|
||
// Перезагружаем список
|
||
await loadTokens();
|
||
renderTokenList();
|
||
|
||
$message.text(`Токен "${description}" успешно создан.`).show();
|
||
|
||
} catch (e) {
|
||
console.error('Ошибка создания токена:', e);
|
||
$message.removeClass('success-message').addClass('error-message').text('Ошибка при создании токена.').show();
|
||
} finally {
|
||
$btn.prop('disabled', false).text('Создать токен API');
|
||
setTimeout(() => $message.fadeOut(), 8000);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
* Логика удаления токена.
|
||
* @param {string} token - Токен для удаления.
|
||
*/
|
||
async function deleteToken(token) {
|
||
if (!confirm("Вы уверены, что хотите удалить этот API токен?")) {
|
||
return;
|
||
}
|
||
|
||
const $item = $(`li.token-item[data-full-token="${token}"]`);
|
||
$item.addClass('deleting').css('opacity', 0.5); // Визуальная обратная связь
|
||
|
||
try {
|
||
await JSONRPC.Auth.removeToken(token);
|
||
|
||
// Удаляем из локального состояния
|
||
tokens = tokens.filter(item => item.token !== token);
|
||
|
||
// Перерисовываем список
|
||
renderTokenList();
|
||
|
||
const $message = $('#token-status-message');
|
||
$message.text('Токен успешно удален.').addClass('success-message').show();
|
||
|
||
} catch (e) {
|
||
console.error('Ошибка удаления токена:', e);
|
||
$item.removeClass('deleting').css('opacity', 1); // Восстанавливаем, если ошибка
|
||
const $message = $('#token-status-message');
|
||
$message.removeClass('success-message').addClass('error-message').text('Ошибка при удалении токена.').show();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @private
|
||
* Прикрепление обработчиков событий.
|
||
*/
|
||
function attachEventHandlers() {
|
||
$('#create-token-btn').off('click').on('click', showCreateTokenModal);
|
||
|
||
// Делегирование для кнопок удаления (они перерисовываются)
|
||
$('#api-token-container').off('click', '.delete-token-btn').on('click', '.delete-token-btn', function() {
|
||
const tokenToDelete = $(this).data('token');
|
||
if (tokenToDelete) {
|
||
deleteToken(tokenToDelete);
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
// --- Функции для роутера ---
|
||
|
||
export const APITokensPage = {
|
||
render: () => {
|
||
return `
|
||
<h1 class="page-title">API Токены</h1>
|
||
<div id="api-token-container">
|
||
<p>Загрузка токенов...</p>
|
||
</div>
|
||
`;
|
||
},
|
||
mount: async () => {
|
||
const success = await loadTokens();
|
||
if (success) {
|
||
renderTokenList();
|
||
} else {
|
||
$('#api-token-container').html('<p class="error-message">Не удалось загрузить токены. Проверьте соединение с сервером.</p>');
|
||
}
|
||
},
|
||
unmount: () => {
|
||
tokens = [];
|
||
$('#api-token-container').off(); // Удаляем все обработчики
|
||
}
|
||
}; |