99 lines
3.9 KiB
HTML
99 lines
3.9 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Вход — InfoUser Monitor{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-4">
|
|
<div class="card shadow">
|
|
<div class="card-body">
|
|
<h4 class="card-title text-center mb-4">InfoUser Monitor</h4>
|
|
<form id="login-form">
|
|
<div class="mb-3">
|
|
<label class="form-label">Логин</label>
|
|
<input type="text" class="form-control" id="username" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Пароль</label>
|
|
<input type="password" class="form-control" id="password" required>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary w-100">Войти</button>
|
|
</form>
|
|
{% if error %}
|
|
<div class="alert alert-danger mt-3">{{ error }}</div>
|
|
{% endif %}
|
|
<div id="login-error" class="alert alert-danger mt-3 d-none"></div>
|
|
|
|
{% if registration_open %}
|
|
<hr>
|
|
<h6 class="text-center">Или создайте первого администратора</h6>
|
|
<form id="register-form">
|
|
<div class="mb-3">
|
|
<input type="text" class="form-control" id="reg-username" placeholder="Логин" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<input type="password" class="form-control" id="reg-password" placeholder="Пароль" required>
|
|
</div>
|
|
<button type="submit" class="btn btn-outline-secondary w-100">Зарегистрироваться</button>
|
|
</form>
|
|
<div id="register-error" class="alert alert-danger mt-3 d-none"></div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="text-center mt-3 text-muted small">
|
|
По умолчанию: admin / admin
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
document.getElementById('login-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const err = document.getElementById('login-error');
|
|
err.classList.add('d-none');
|
|
const form = new FormData();
|
|
form.append('username', document.getElementById('username').value);
|
|
form.append('password', document.getElementById('password').value);
|
|
try {
|
|
const res = await fetch('/api/auth/login', { method: 'POST', body: form, credentials: 'include' });
|
|
if (res.ok) {
|
|
window.location.href = '/';
|
|
} else {
|
|
const data = await res.json();
|
|
err.textContent = data.detail || 'Ошибка входа';
|
|
err.classList.remove('d-none');
|
|
}
|
|
} catch (e) {
|
|
err.textContent = 'Сервер недоступен';
|
|
err.classList.remove('d-none');
|
|
}
|
|
});
|
|
|
|
{% if registration_open %}
|
|
document.getElementById('register-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const err = document.getElementById('register-error');
|
|
err.classList.add('d-none');
|
|
const res = await fetch('/api/auth/register', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
credentials: 'include',
|
|
body: JSON.stringify({
|
|
username: document.getElementById('reg-username').value,
|
|
password: document.getElementById('reg-password').value,
|
|
}),
|
|
});
|
|
if (res.ok) {
|
|
window.location.href = '/';
|
|
} else {
|
|
const data = await res.json();
|
|
err.textContent = data.detail || 'Ошибка регистрации';
|
|
err.classList.remove('d-none');
|
|
}
|
|
});
|
|
{% endif %}
|
|
</script>
|
|
{% endblock %}
|