139 lines
6.0 KiB
HTML
139 lines
6.0 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||
<title>Вход в систему</title>
|
||
<link rel="stylesheet" href="/css/app.css">
|
||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||
</head>
|
||
<body>
|
||
<div class="page-wrap">
|
||
<div class="card card-mid">
|
||
<h2>Вход в систему</h2>
|
||
<p class="subtitle">Проверка учётных данных в Active Directory</p>
|
||
|
||
<form id="authForm">
|
||
<div class="form-group">
|
||
<label>Логин</label>
|
||
<input type="text" id="username" name="username" placeholder="user" autocomplete="username" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Пароль</label>
|
||
<input type="password" id="password" name="password" placeholder="••••••••" autocomplete="current-password" required>
|
||
</div>
|
||
|
||
<div class="mode-selector">
|
||
<label class="mode-option active" id="modeBasic">
|
||
<input type="radio" name="mode" value="basic" checked>
|
||
<span>Основные</span>
|
||
</label>
|
||
<label class="mode-option" id="modeDescription">
|
||
<input type="radio" name="mode" value="description">
|
||
<span>Описание</span>
|
||
</label>
|
||
<label class="mode-option" id="modeGroups">
|
||
<input type="radio" name="mode" value="groups">
|
||
<span>Группы</span>
|
||
</label>
|
||
<label class="mode-option" id="modeAll">
|
||
<input type="radio" name="mode" value="all">
|
||
<span>Всё</span>
|
||
</label>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary">Войти</button>
|
||
</form>
|
||
|
||
<div class="loading" id="loading">Проверка в Active Directory...</div>
|
||
|
||
<div class="result" id="result"></div>
|
||
|
||
<div class="auth-link">
|
||
<a href="/change-password">Забыли пароль? Сменить пароль</a>
|
||
</div>
|
||
|
||
<div class="auth-link">
|
||
<a href="/register">Регистрация</a> · <a href="/zup">ЗУП</a> · <a href="/admin">Панель администратора</a> · <a href="/help">Справка по API</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
let currentMode = 'basic';
|
||
|
||
document.querySelectorAll('.mode-option').forEach(option => {
|
||
option.addEventListener('click', function () {
|
||
document.querySelectorAll('.mode-option').forEach(opt => opt.classList.remove('active'));
|
||
this.classList.add('active');
|
||
const radio = this.querySelector('input[type="radio"]');
|
||
radio.checked = true;
|
||
currentMode = radio.value;
|
||
});
|
||
});
|
||
|
||
function escapeHtml(str) {
|
||
return String(str).replace(/[&<>"']/g, c => ({
|
||
'&': '&', '<': '<', '>': '>', '"': '"', "'": '''
|
||
}[c]));
|
||
}
|
||
|
||
document.getElementById('authForm').addEventListener('submit', async function (e) {
|
||
e.preventDefault();
|
||
|
||
const username = document.getElementById('username').value;
|
||
const password = document.getElementById('password').value;
|
||
const resultDiv = document.getElementById('result');
|
||
const loadingDiv = document.getElementById('loading');
|
||
|
||
loadingDiv.style.display = 'block';
|
||
resultDiv.style.display = 'none';
|
||
|
||
try {
|
||
let url = '/api/auth';
|
||
if (currentMode === 'description') url += '?description=1';
|
||
else if (currentMode === 'groups') url += '?groups=1';
|
||
else if (currentMode === 'all') url += '?all=1';
|
||
|
||
const response = await fetch(url, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
||
body: JSON.stringify({ username, password })
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
resultDiv.className = 'result success';
|
||
let html = '<h3>Вход выполнен</h3><div class="user-info">';
|
||
if (result.username) html += `<p><strong>Логин:</strong> ${escapeHtml(result.username)}</p>`;
|
||
if (result.full_name) html += `<p><strong>ФИО:</strong> ${escapeHtml(result.full_name)}</p>`;
|
||
if (result.email) html += `<p><strong>Email:</strong> ${escapeHtml(result.email)}</p>`;
|
||
if (result.description !== undefined) html += `<p><strong>Описание:</strong> ${escapeHtml(result.description || 'не задано')}</p>`;
|
||
if (result.groups) {
|
||
html += `<p><strong>Группы (${result.groups.length}):</strong> ${
|
||
result.groups.length > 0 ? result.groups.map(escapeHtml).join(', ') : 'нет'
|
||
}</p>`;
|
||
}
|
||
html += '</div>';
|
||
if (result.all_info) {
|
||
html += '<h4 style="margin:16px 0 0;">Все атрибуты LDAP:</h4>';
|
||
}
|
||
html += `<div class="json-preview">${escapeHtml(JSON.stringify(result, null, 2))}</div>`;
|
||
resultDiv.innerHTML = html;
|
||
} else {
|
||
resultDiv.className = 'result error';
|
||
resultDiv.innerHTML = `<h3>Ошибка входа</h3><p>${escapeHtml(result.error || 'Неизвестная ошибка')}</p>`;
|
||
}
|
||
} catch (error) {
|
||
resultDiv.className = 'result error';
|
||
resultDiv.innerHTML = `<h3>Ошибка сети</h3><p>${escapeHtml(error.message)}</p>`;
|
||
} finally {
|
||
loadingDiv.style.display = 'none';
|
||
resultDiv.style.display = 'block';
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|