150 lines
4.6 KiB
HTML
150 lines
4.6 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<title>Lendry SSO - Заглушка</title>
|
||
<style>
|
||
body {
|
||
font-family:
|
||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 100vh;
|
||
margin: 0;
|
||
background-color: #f3f4f6;
|
||
}
|
||
.login-card {
|
||
background: white;
|
||
padding: 2rem;
|
||
border-radius: 12px;
|
||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||
width: 100%;
|
||
max-width: 320px;
|
||
text-align: center;
|
||
}
|
||
h2 {
|
||
margin-top: 0;
|
||
color: #111827;
|
||
}
|
||
input {
|
||
width: 100%;
|
||
padding: 10px;
|
||
margin-bottom: 15px;
|
||
border: 1px solid #d1d5db;
|
||
border-radius: 6px;
|
||
box-sizing: border-box;
|
||
font-size: 16px;
|
||
}
|
||
button {
|
||
width: 100%;
|
||
padding: 10px;
|
||
background-color: #2563eb;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 6px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
button:hover {
|
||
background-color: #1d4ed8;
|
||
}
|
||
.error {
|
||
color: #dc2626;
|
||
font-size: 14px;
|
||
margin-top: 10px;
|
||
display: none;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="login-card">
|
||
<h2>Вход в Lendry</h2>
|
||
<p style="font-size: 12px; color: #6b7280; margin-bottom: 20px">
|
||
Frontend-заглушка для теста SSO
|
||
</p>
|
||
|
||
<form id="loginForm">
|
||
<input
|
||
type="text"
|
||
id="username"
|
||
value=""
|
||
placeholder="Логин"
|
||
required
|
||
/>
|
||
<input
|
||
type="password"
|
||
id="password"
|
||
value=""
|
||
placeholder="Пароль"
|
||
required
|
||
/>
|
||
<button type="submit">Войти и вернуться в сервис</button>
|
||
</form>
|
||
<div id="error" class="error"></div>
|
||
</div>
|
||
|
||
<script>
|
||
document
|
||
.getElementById("loginForm")
|
||
.addEventListener("submit", async (e) => {
|
||
e.preventDefault();
|
||
const errorEl = document.getElementById("error");
|
||
errorEl.style.display = "none";
|
||
|
||
let username = document.getElementById("username").value;
|
||
let password = document.getElementById("password").value;
|
||
|
||
console.log(username + password);
|
||
let json = JSON.stringify({
|
||
username,
|
||
password,
|
||
deviceId: "stub-device",
|
||
publicKey: "N6fByS7oTIOX6m7on8h6T093SOn3df67o6v6n6n6n6o=",
|
||
});
|
||
try {
|
||
// 1. Делаем реальный запрос к вашему API Gateway
|
||
const response = await fetch(
|
||
"https://docker.mvk.lpr:4000/auth/login",
|
||
{
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
// Добавил device_id и public_key (как требует ваш auth.proto)
|
||
body: json,
|
||
// КРИТИЧЕСКИ ВАЖНО: заставляет браузер сохранить куку refreshToken
|
||
credentials: "include",
|
||
},
|
||
);
|
||
|
||
const result = await response.json();
|
||
console.log(result);
|
||
|
||
if (response.ok && result.data && result.data.status === "OK") {
|
||
// 2. Ищем, куда нас просили вернуться
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const returnUrl = urlParams.get("returnUrl");
|
||
if (returnUrl) {
|
||
// 3. Перенаправляем пользователя обратно на Gateway (который перекинет в Grafana)
|
||
window.location.href = returnUrl;
|
||
} else {
|
||
alert(
|
||
"Успешный вход! Но параметр returnUrl не найден. Вы авторизованы.",
|
||
);
|
||
}
|
||
} else {
|
||
errorEl.textContent =
|
||
result.message || "Неверный логин или пароль";
|
||
errorEl.style.display = "block";
|
||
}
|
||
} catch (err) {
|
||
console.error(err);
|
||
errorEl.textContent = "Ошибка сети. Проверьте консоль.";
|
||
errorEl.style.display = "block";
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|