Files
StandalonePasswordChange/python-flask/smeserver-password-app/templates/admin_panel.html

299 lines
13 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: 800px;
margin: 20px auto;
padding: 20px;
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
}
.account-type-section {
margin: 20px 0;
padding: 15px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
}
.account-type-title {
font-weight: bold;
font-size: 14px;
margin-bottom: 10px;
color: #333;
}
.config-option {
margin: 10px 0;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
}
.config-option.active {
background-color: #e8f4f8;
border-color: #007bff;
}
.config-option label {
font-weight: normal;
cursor: pointer;
font-size: 12px;
}
.config-description {
font-size: 10px;
color: #666;
margin-top: 3px;
}
.update-button {
background-color: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin-top: 15px;
font-size: 12px;
}
.update-button:hover {
background-color: #0056b3;
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: #007bff;
text-decoration: none;
font-size: 12px;
}
.back-link:hover {
text-decoration: underline;
}
.zxcvbn-info {
background-color: #e8f5e8;
border: 1px solid #4caf50;
padding: 10px;
margin: 10px 0;
border-radius: 4px;
font-size: 11px;
}
.current-settings {
background-color: #f0f8ff;
border: 1px solid #87ceeb;
padding: 10px;
margin-bottom: 20px;
border-radius: 4px;
}
</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">
{% if using_zxcvbn %}
<div class="zxcvbn-info">
✓ Using zxcvbn library for advanced password validation
</div>
{% else %}
<div class="zxcvbn-info" style="background-color: #fff3cd; border-color: #ffc107;">
⚠ zxcvbn library not available - using basic validation
</div>
{% endif %}
<div class="current-settings">
<strong>Current Settings:</strong><br>
Users: {{ current_settings.Users|title }}<br>
Admin: {{ current_settings.Admin|title }}<br>
Ibays: {{ current_settings.Ibays|title }}
</div>
<!-- Users Configuration -->
<div class="account-type-section">
<div class="account-type-title">👤 Users Password Strength</div>
<form class="config-form" data-account-type="Users">
<div class="config-option {{ 'active' if current_settings.Users == 'none' else '' }}">
<label>
<input type="radio" name="strength" value="none" {{ 'checked' if current_settings.Users == 'none' else '' }}>
None
</label>
<div class="config-description">
No specific password requirements. Only basic validation.
</div>
</div>
<div class="config-option {{ 'active' if current_settings.Users == 'normal' else '' }}">
<label>
<input type="radio" name="strength" value="normal" {{ 'checked' if current_settings.Users == '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_settings.Users == 'strong' else '' }}">
<label>
<input type="radio" name="strength" value="strong" {{ 'checked' if current_settings.Users == 'strong' else '' }}>
Strong
</label>
<div class="config-description">
Normal requirements plus {{ 'zxcvbn advanced validation against common passwords, patterns, and dictionary attacks' if using_zxcvbn else 'basic protection against common passwords and keyboard patterns' }}.
</div>
</div>
<button type="submit" class="update-button">Update Users Password Strength</button>
<div class="status-message"></div>
</form>
</div>
<!-- Admin Configuration -->
<div class="account-type-section">
<div class="account-type-title">👑 Admin Password Strength</div>
<form class="config-form" data-account-type="Admin">
<div class="config-option {{ 'active' if current_settings.Admin == 'none' else '' }}">
<label>
<input type="radio" name="strength" value="none" {{ 'checked' if current_settings.Admin == 'none' else '' }}>
None
</label>
<div class="config-description">
No specific password requirements. Only basic validation.
</div>
</div>
<div class="config-option {{ 'active' if current_settings.Admin == 'normal' else '' }}">
<label>
<input type="radio" name="strength" value="normal" {{ 'checked' if current_settings.Admin == 'normal' else '' }}>
Normal
</label>
<div class="config-description">
Minimum 12 characters with complexity requirements.
</div>
</div>
<div class="config-option {{ 'active' if current_settings.Admin == 'strong' else '' }}">
<label>
<input type="radio" name="strength" value="strong" {{ 'checked' if current_settings.Admin == 'strong' else '' }}>
Strong
</label>
<div class="config-description">
Normal requirements plus advanced validation.
</div>
</div>
<button type="submit" class="update-button">Update Admin Password Strength</button>
<div class="status-message"></div>
</form>
</div>
<!-- Ibays Configuration -->
<div class="account-type-section">
<div class="account-type-title">📁 Ibays Password Strength</div>
<form class="config-form" data-account-type="Ibays">
<div class="config-option {{ 'active' if current_settings.Ibays == 'none' else '' }}">
<label>
<input type="radio" name="strength" value="none" {{ 'checked' if current_settings.Ibays == 'none' else '' }}>
None
</label>
<div class="config-description">
No specific password requirements. Only basic validation.
</div>
</div>
<div class="config-option {{ 'active' if current_settings.Ibays == 'normal' else '' }}">
<label>
<input type="radio" name="strength" value="normal" {{ 'checked' if current_settings.Ibays == 'normal' else '' }}>
Normal
</label>
<div class="config-description">
Minimum 12 characters with complexity requirements.
</div>
</div>
<div class="config-option {{ 'active' if current_settings.Ibays == 'strong' else '' }}">
<label>
<input type="radio" name="strength" value="strong" {{ 'checked' if current_settings.Ibays == 'strong' else '' }}>
Strong
</label>
<div class="config-description">
Normal requirements plus advanced validation.
</div>
</div>
<button type="submit" class="update-button">Update Ibays Password Strength</button>
<div class="status-message"></div>
</form>
</div>
</div>
<div class="footer">
<p>{{ version if version else 'SME Server 11 (beta1)' }} - Admin Panel (Corrected DB Structure)</p>
</div>
</div>
<script>
// Handle form submissions for all account types
document.querySelectorAll('.config-form').forEach(form => {
form.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const strength = formData.get('strength');
const accountType = this.dataset.accountType;
const statusMessage = this.querySelector('.status-message');
// Update visual selection
this.querySelectorAll('.config-option').forEach(option => {
option.classList.remove('active');
});
const selectedOption = this.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,
account_type: accountType
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
statusMessage.innerHTML = '<div style="color: green; font-weight: bold; font-size: 10px;">✓ ' + data.message + '</div>';
setTimeout(() => {
statusMessage.innerHTML = '';
}, 3000);
} else {
statusMessage.innerHTML = '<div style="color: red; font-weight: bold; font-size: 10px;">✗ Error: ' + (data.error || 'Unknown error') + '</div>';
}
})
.catch(error => {
statusMessage.innerHTML = '<div style="color: red; font-weight: bold; font-size: 10px;">✗ Network error: ' + error.message + '</div>';
});
});
});
// Handle radio button changes for visual feedback
document.querySelectorAll('input[name="strength"]').forEach(radio => {
radio.addEventListener('change', function() {
const form = this.closest('.config-form');
form.querySelectorAll('.config-option').forEach(option => {
option.classList.remove('active');
});
this.closest('.config-option').classList.add('active');
});
});
</script>
</body>
</html>