221 lines
11 KiB
HTML
221 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Вход - TGLoader Admin</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
|
<style>
|
|
body {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.login-card {
|
|
border: none;
|
|
border-radius: 1rem;
|
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
|
max-width: 450px;
|
|
width: 100%;
|
|
}
|
|
.login-tabs {
|
|
border-bottom: 2px solid #dee2e6;
|
|
}
|
|
.nav-link {
|
|
color: #6c757d;
|
|
}
|
|
.nav-link.active {
|
|
color: #667eea;
|
|
border-bottom-color: #667eea;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-6">
|
|
<div class="card login-card">
|
|
<div class="card-body p-5">
|
|
<div class="text-center mb-4">
|
|
<i class="bi bi-robot" style="font-size: 3rem; color: #667eea;"></i>
|
|
<h2 class="mt-3">TGLoader</h2>
|
|
<p class="text-muted">Вход в веб-интерфейс</p>
|
|
</div>
|
|
|
|
{% if error %}
|
|
<div class="alert alert-danger" role="alert">
|
|
<i class="bi bi-exclamation-triangle me-2"></i>{{ error }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Вкладки -->
|
|
<ul class="nav nav-tabs login-tabs mb-4" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" id="otp-tab" data-bs-toggle="tab"
|
|
data-bs-target="#otp-pane" type="button" role="tab">
|
|
<i class="bi bi-key me-2"></i>По коду
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="admin-tab" data-bs-toggle="tab"
|
|
data-bs-target="#admin-pane" type="button" role="tab">
|
|
<i class="bi bi-shield-check me-2"></i>Админ (по ID)
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content">
|
|
<!-- Вход по OTP коду -->
|
|
<div class="tab-pane fade show active" id="otp-pane" role="tabpanel">
|
|
<div class="mb-3">
|
|
<label for="identifier" class="form-label">Telegram User ID или Username</label>
|
|
<input type="text" class="form-control" id="identifier"
|
|
placeholder="Введите ваш User ID или @username">
|
|
<small class="form-text text-muted">
|
|
Код будет отправлен вам в Telegram
|
|
</small>
|
|
</div>
|
|
<button type="button" class="btn btn-outline-primary w-100 mb-3"
|
|
onclick="requestOTP()">
|
|
<i class="bi bi-send me-2"></i>Получить код
|
|
</button>
|
|
|
|
<div id="otp-input-group" style="display: none;">
|
|
<div class="mb-3">
|
|
<label for="otp_code" class="form-label">Одноразовый код</label>
|
|
<input type="text" class="form-control" id="otp_code" name="otp_code"
|
|
placeholder="Введите код из Telegram" maxlength="6">
|
|
<small class="form-text text-muted">
|
|
Код действителен 10 минут
|
|
</small>
|
|
</div>
|
|
<form method="POST" action="/admin/login" id="otp-form">
|
|
{% if csrf_token %}
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
{% endif %}
|
|
<input type="hidden" name="otp_code" id="otp_code_hidden">
|
|
<button type="submit" class="btn btn-primary w-100">
|
|
<i class="bi bi-box-arrow-in-right me-2"></i>Войти
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="mt-3 text-center">
|
|
<small class="text-muted">
|
|
Или используйте команду <code>/login</code> в боте для получения кода
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Вход по User ID (альтернативный способ) -->
|
|
<div class="tab-pane fade" id="admin-pane" role="tabpanel">
|
|
<form method="POST" action="/admin/login">
|
|
{% if csrf_token %}
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
{% endif %}
|
|
<input type="hidden" name="user_id" id="admin_user_id">
|
|
<div class="mb-3">
|
|
<label for="admin_user_id_input" class="form-label">Telegram User ID</label>
|
|
<input type="number" class="form-control" id="admin_user_id_input"
|
|
placeholder="Введите ваш Telegram User ID" required>
|
|
<small class="form-text text-muted">
|
|
Альтернативный способ входа (без OTP кода)
|
|
</small>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary w-100">
|
|
<i class="bi bi-box-arrow-in-right me-2"></i>Войти
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
function showAlert(message, type = 'success') {
|
|
const alertDiv = document.createElement('div');
|
|
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
|
|
alertDiv.innerHTML = `
|
|
${message}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
`;
|
|
const cardBody = document.querySelector('.card-body');
|
|
cardBody.insertBefore(alertDiv, cardBody.firstChild);
|
|
setTimeout(() => alertDiv.remove(), 5000);
|
|
}
|
|
|
|
async function requestOTP() {
|
|
const identifier = document.getElementById('identifier').value.trim();
|
|
if (!identifier) {
|
|
showAlert('Введите User ID или username', 'danger');
|
|
return;
|
|
}
|
|
|
|
const btn = event.target;
|
|
btn.disabled = true;
|
|
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Отправка...';
|
|
|
|
try {
|
|
const formData = new FormData();
|
|
formData.append('identifier', identifier);
|
|
|
|
const response = await fetch('/admin/api/otp/request', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
showAlert(data.message, 'success');
|
|
document.getElementById('otp-input-group').style.display = 'block';
|
|
document.getElementById('otp_code').focus();
|
|
|
|
// Если код возвращен в ответе (не удалось отправить в Telegram)
|
|
if (data.code) {
|
|
document.getElementById('otp_code').value = data.code;
|
|
showAlert(`Код не был отправлен в Telegram. Используйте код: ${data.code}`, 'warning');
|
|
}
|
|
} else {
|
|
showAlert(data.message, 'danger');
|
|
}
|
|
} catch (error) {
|
|
showAlert('Ошибка при запросе кода', 'danger');
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.innerHTML = '<i class="bi bi-send me-2"></i>Получить код';
|
|
}
|
|
}
|
|
|
|
// Обработка формы OTP
|
|
document.getElementById('otp-form').addEventListener('submit', function(e) {
|
|
const code = document.getElementById('otp_code').value.trim();
|
|
if (!code) {
|
|
e.preventDefault();
|
|
showAlert('Введите код', 'danger');
|
|
return;
|
|
}
|
|
document.getElementById('otp_code_hidden').value = code;
|
|
});
|
|
|
|
// Обработка формы админа
|
|
document.getElementById('admin_user_id_input').addEventListener('input', function(e) {
|
|
document.getElementById('admin_user_id').value = e.target.value;
|
|
});
|
|
|
|
// Enter для запроса OTP
|
|
document.getElementById('identifier').addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
requestOTP();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|