Files
ldap-auth-service/auth.html
2025-10-17 00:02:40 +05:00

497 lines
18 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>LDAP Authentication - school25.ru</title>
<meta charset="UTF-8">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
max-width: 700px;
width: 100%;
}
h2 {
color: #333;
margin-bottom: 30px;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 12px 15px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 16px;
transition: border-color 0.3s;
}
input[type="text"]:focus, input[type="password"]:focus {
border-color: #667eea;
outline: none;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px 30px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
width: 100%;
transition: transform 0.2s;
margin-top: 10px;
}
button:hover {
transform: translateY(-2px);
}
.result {
margin-top: 25px;
padding: 20px;
border-radius: 6px;
display: none;
}
.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.user-info {
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
margin-top: 15px;
}
.user-info p {
margin: 8px 0;
color: #333;
}
.loading {
display: none;
text-align: center;
color: #667eea;
margin: 10px 0;
font-size: 16px;
}
.test-users {
margin-top: 25px;
padding-top: 20px;
border-top: 1px solid #eee;
}
.test-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: 10px;
}
.test-button {
background: #28a745;
padding: 12px;
font-size: 14px;
border: none;
border-radius: 6px;
color: white;
cursor: pointer;
transition: background-color 0.2s;
}
.test-button:hover {
background: #218838;
}
.api-info {
margin-top: 25px;
padding: 20px;
background: #e9ecef;
border-radius: 6px;
font-size: 14px;
}
.api-info h4 {
margin-bottom: 15px;
color: #495057;
}
.api-info code {
background: #343a40;
color: #f8f9fa;
padding: 3px 8px;
border-radius: 4px;
font-family: 'Courier New', monospace;
display: inline-block;
margin: 2px 0;
}
.api-endpoints {
display: grid;
gap: 10px;
margin: 15px 0;
}
.endpoint {
background: white;
padding: 12px;
border-radius: 4px;
border-left: 4px solid #667eea;
}
.mode-selector {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
margin: 15px 0;
}
.mode-option {
display: flex;
align-items: center;
gap: 8px;
padding: 10px;
background: #f8f9fa;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
}
.mode-option:hover {
background: #e9ecef;
}
.mode-option.active {
background: #667eea;
color: white;
}
.mode-option input[type="radio"] {
margin: 0;
}
.json-preview {
background: #2d3748;
color: #e2e8f0;
padding: 15px;
border-radius: 6px;
margin-top: 10px;
font-family: 'Courier New', monospace;
font-size: 12px;
overflow-x: auto;
white-space: pre-wrap;
max-height: 300px;
overflow-y: auto;
}
.password-warning {
color: #dc3545;
font-size: 14px;
margin-top: 5px;
display: none;
}
</style>
</head>
<body>
<div class="container">
<h2>🔐 LDAP Authentication</h2>
<p style="text-align: center; color: #666; margin-bottom: 25px;">school25.ru Domain - Password Required</p>
<form id="authForm">
<div class="form-group">
<label>Username:</label>
<input type="text" id="username" name="username" placeholder="kalugin66" required>
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" id="password" name="password" placeholder="••••••••" required>
<div class="password-warning" id="passwordWarning">⚠ Password is required for all users</div>
</div>
<div class="mode-selector">
<label class="mode-option" id="modeBasic">
<input type="radio" name="mode" value="basic" checked>
<span>Basic Info</span>
</label>
<label class="mode-option" id="modeDescription">
<input type="radio" name="mode" value="description">
<span>Description Only</span>
</label>
<label class="mode-option" id="modeGroups">
<input type="radio" name="mode" value="groups">
<span>Groups Only</span>
</label>
</div>
<div class="mode-selector">
<label class="mode-option" id="modeAll">
<input type="radio" name="mode" value="all">
<span>All Information</span>
</label>
</div>
<button type="submit">Authenticate</button>
</form>
<div class="loading" id="loading">
🔄 Authenticating with Active Directory...
</div>
<div class="result" id="result">
<!-- Результат будет здесь -->
</div>
<div class="test-users">
<h4>Quick Test Users:</h4>
<div class="test-buttons">
<button type="button" class="test-button" onclick="fillCredentials('kalugin66', 'Admin624600@')">
kalugin66
</button>
<button type="button" class="test-button" onclick="fillCredentials('tv', 'Admin624600@')">
tv (with password)
</button>
</div>
<p style="font-size: 12px; color: #666; margin-top: 8px;">
Note: Password is now required for all users
</p>
</div>
<div class="api-info">
<h4>📋 REST API Endpoints:</h4>
<div class="api-endpoints">
<div class="endpoint">
<strong>Basic Information:</strong><br>
<code>POST /api/auth</code>
</div>
<div class="endpoint">
<strong>Description Only:</strong><br>
<code>POST /api/auth?description=1</code>
</div>
<div class="endpoint">
<strong>Groups Only:</strong><br>
<code>POST /api/auth?groups=1</code>
</div>
<div class="endpoint">
<strong>All Information:</strong><br>
<code>POST /api/auth?all=1</code>
</div>
</div>
<h4>🔧 cURL Examples:</h4>
<div class="json-preview" id="curlExamples">
// Basic information
curl -X POST http://localhost:8080/api/auth \
-H "Content-Type: application/json" \
-d '{"username": "tv", "password": "password123"}'
// Description only
curl -X POST "http://localhost:8080/api/auth?description=1" \
-H "Content-Type: application/json" \
-d '{"username": "tv", "password": "password123"}'
// Groups only
curl -X POST "http://localhost:8080/api/auth?groups=1" \
-H "Content-Type: application/json" \
-d '{"username": "tv", "password": "password123"}'
// All information
curl -X POST "http://localhost:8080/api/auth?all=1" \
-H "Content-Type: application/json" \
-d '{"username": "tv", "password": "password123"}'
</div>
</div>
</div>
<script>
let currentMode = 'basic';
// Initialize mode selection
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;
});
});
// Set initial active state
document.getElementById('modeBasic').classList.add('active');
function fillCredentials(username, password) {
document.getElementById('username').value = username;
document.getElementById('password').value = password;
document.getElementById('passwordWarning').style.display = 'none';
}
function showPasswordWarning() {
document.getElementById('passwordWarning').style.display = 'block';
}
function hidePasswordWarning() {
document.getElementById('passwordWarning').style.display = 'none';
}
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');
// Validate password
if (!password) {
showPasswordWarning();
resultDiv.style.display = 'none';
return;
}
hidePasswordWarning();
// Показываем загрузку
loadingDiv.style.display = 'block';
resultDiv.style.display = 'none';
try {
// Build URL based on selected mode
let url = '/api/auth';
switch(currentMode) {
case 'description':
url += '?description=1';
break;
case 'groups':
url += '?groups=1';
break;
case 'all':
url += '?all=1';
break;
default:
// basic mode, no parameters
break;
}
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
username: username,
password: password
})
});
const result = await response.json();
if (result.success) {
resultDiv.className = 'result success';
let resultHTML = `<h3>✅ Authentication Successful!</h3>`;
// Different display based on mode
switch(currentMode) {
case 'description':
resultHTML += `
<div class="user-info">
<p><strong>Description:</strong> ${result.description || 'Not set'}</p>
</div>
<div class="json-preview">${JSON.stringify(result, null, 2)}</div>
`;
break;
case 'groups':
resultHTML += `
<div class="user-info">
<p><strong>Groups (${result.groups ? result.groups.length : 0}):</strong></p>
<ul style="margin-left: 20px; margin-top: 8px;">
${result.groups && result.groups.length > 0 ?
result.groups.map(group => `<li>${group}</li>`).join('') :
'<li>No groups found</li>'
}
</ul>
</div>
<div class="json-preview">${JSON.stringify(result, null, 2)}</div>
`;
break;
case 'all':
resultHTML += `
<div class="user-info">
<p><strong>Username:</strong> ${result.username || 'N/A'}</p>
<p><strong>Full Name:</strong> ${result.full_name || 'N/A'}</p>
<p><strong>Email:</strong> ${result.email || 'N/A'}</p>
<p><strong>Description:</strong> ${result.description || 'N/A'}</p>
<p><strong>Groups (${result.groups ? result.groups.length : 0}):</strong> ${result.groups && result.groups.length > 0 ? result.groups.join(', ') : 'No groups'}</p>
</div>
<h4 style="margin-top: 15px;">All LDAP Attributes:</h4>
<div class="json-preview">${JSON.stringify(result.all_info, null, 2)}</div>
`;
break;
default: // basic
resultHTML += `
<div class="user-info">
<p><strong>Username:</strong> ${result.username || 'N/A'}</p>
<p><strong>Full Name:</strong> ${result.full_name || 'N/A'}</p>
<p><strong>Email:</strong> ${result.email || 'N/A'}</p>
<p><strong>Description:</strong> ${result.description || 'Not set'}</p>
<p><strong>Groups (${result.groups ? result.groups.length : 0}):</strong> ${result.groups && result.groups.length > 0 ? result.groups.join(', ') : 'No groups'}</p>
</div>
<div class="json-preview">${JSON.stringify(result, null, 2)}</div>
`;
}
resultDiv.innerHTML = resultHTML;
} else {
resultDiv.className = 'result error';
resultDiv.innerHTML = `
<h3>❌ Authentication Failed</h3>
<p><strong>Error:</strong> ${result.error}</p>
<div class="json-preview">${JSON.stringify(result, null, 2)}</div>
`;
}
} catch (error) {
resultDiv.className = 'result error';
resultDiv.innerHTML = `
<h3>❌ Network Error</h3>
<p><strong>Error:</strong> ${error.message}</p>
<p>Please check if the server is running and try again.</p>
`;
} finally {
loadingDiv.style.display = 'none';
resultDiv.style.display = 'block';
}
});
// Password validation on input
document.getElementById('password').addEventListener('input', function() {
if (this.value) {
hidePasswordWarning();
}
});
// Show password warning on focus if empty
document.getElementById('password').addEventListener('focus', function() {
if (!this.value) {
showPasswordWarning();
}
});
</script>
</body>
</html>