166 lines
6.3 KiB
HTML
166 lines
6.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Password Strength Configuration - SME Server</title>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
<style>
|
|
.admin-panel {
|
|
max-width: 600px;
|
|
margin: 20px auto;
|
|
padding: 20px;
|
|
background-color: #f8f9fa;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 4px;
|
|
}
|
|
.config-option {
|
|
margin: 15px 0;
|
|
padding: 10px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 4px;
|
|
background-color: white;
|
|
}
|
|
.config-option.active {
|
|
background-color: #e8f4f8;
|
|
border-color: #007bff;
|
|
}
|
|
.config-option label {
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
}
|
|
.config-description {
|
|
font-size: 11px;
|
|
color: #666;
|
|
margin-top: 5px;
|
|
}
|
|
.update-button {
|
|
background-color: #007bff;
|
|
color: white;
|
|
border: none;
|
|
padding: 8px 16px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
margin-top: 15px;
|
|
}
|
|
.update-button:hover {
|
|
background-color: #0056b3;
|
|
}
|
|
.back-link {
|
|
display: inline-block;
|
|
margin-bottom: 20px;
|
|
color: #007bff;
|
|
text-decoration: none;
|
|
}
|
|
.back-link:hover {
|
|
text-decoration: underline;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<a href="{{ url_for('password_change') }}" class="back-link">← Back to Password Change</a>
|
|
|
|
<h1>Password Strength Configuration</h1>
|
|
|
|
<div class="admin-panel">
|
|
<p><strong>Current Setting:</strong> {{ current_setting|title }}</p>
|
|
<p><strong>Description:</strong> {{ requirements.description }}</p>
|
|
|
|
<form id="config-form">
|
|
<div class="config-option {{ 'active' if current_setting == 'none' else '' }}">
|
|
<label>
|
|
<input type="radio" name="strength" value="none" {{ 'checked' if current_setting == 'none' else '' }}>
|
|
None
|
|
</label>
|
|
<div class="config-description">
|
|
No specific password requirements. Only basic validation.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="config-option {{ 'active' if current_setting == 'normal' else '' }}">
|
|
<label>
|
|
<input type="radio" name="strength" value="normal" {{ 'checked' if current_setting == 'normal' else '' }}>
|
|
Normal
|
|
</label>
|
|
<div class="config-description">
|
|
Minimum 12 characters with at least one uppercase letter, lowercase letter, number, and special character.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="config-option {{ 'active' if current_setting == 'strong' else '' }}">
|
|
<label>
|
|
<input type="radio" name="strength" value="strong" {{ 'checked' if current_setting == 'strong' else '' }}>
|
|
Strong
|
|
</label>
|
|
<div class="config-description">
|
|
Normal requirements plus protection against common passwords, keyboard patterns, and dictionary words.
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="update-button">Update Password Strength Setting</button>
|
|
</form>
|
|
|
|
<div id="status-message" style="margin-top: 15px;"></div>
|
|
</div>
|
|
|
|
<div class="footer">
|
|
<p>{{ version if version else 'SME Server 11 (beta1)' }} - Admin Panel</p>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Handle form submission
|
|
document.getElementById('config-form').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(this);
|
|
const strength = formData.get('strength');
|
|
const statusMessage = document.getElementById('status-message');
|
|
|
|
// Update visual selection
|
|
document.querySelectorAll('.config-option').forEach(option => {
|
|
option.classList.remove('active');
|
|
});
|
|
|
|
const selectedOption = document.querySelector('input[name="strength"]:checked').closest('.config-option');
|
|
selectedOption.classList.add('active');
|
|
|
|
// Send update request
|
|
fetch('/api/password-config', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ strength: strength })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
statusMessage.innerHTML = '<div style="color: green; font-weight: bold;">✓ ' + data.message + '</div>';
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 2000);
|
|
} else {
|
|
statusMessage.innerHTML = '<div style="color: red; font-weight: bold;">✗ Error: ' + (data.error || 'Unknown error') + '</div>';
|
|
}
|
|
})
|
|
.catch(error => {
|
|
statusMessage.innerHTML = '<div style="color: red; font-weight: bold;">✗ Network error: ' + error.message + '</div>';
|
|
});
|
|
});
|
|
|
|
// Handle radio button changes for visual feedback
|
|
document.querySelectorAll('input[name="strength"]').forEach(radio => {
|
|
radio.addEventListener('change', function() {
|
|
document.querySelectorAll('.config-option').forEach(option => {
|
|
option.classList.remove('active');
|
|
});
|
|
this.closest('.config-option').classList.add('active');
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|