2025-07-20 10:13:38 +01:00
<!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 {
2025-07-20 15:46:25 +01:00
max-width: 800px;
2025-07-20 10:13:38 +01:00
margin: 20px auto;
padding: 20px;
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
}
2025-07-20 15:46:25 +01:00
.account-type-section {
margin: 20px 0;
padding: 15px;
2025-07-20 10:13:38 +01:00
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
}
2025-07-20 15:46:25 +01:00
.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;
}
2025-07-20 10:13:38 +01:00
.config-option.active {
background-color: #e8f4f8;
border-color: #007bff;
}
.config-option label {
2025-07-20 15:46:25 +01:00
font-weight: normal;
2025-07-20 10:13:38 +01:00
cursor: pointer;
2025-07-20 15:46:25 +01:00
font-size: 12px;
2025-07-20 10:13:38 +01:00
}
.config-description {
2025-07-20 15:46:25 +01:00
font-size: 10px;
2025-07-20 10:13:38 +01:00
color: #666;
2025-07-20 15:46:25 +01:00
margin-top: 3px;
2025-07-20 10:13:38 +01:00
}
.update-button {
background-color: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin-top: 15px;
2025-07-20 15:46:25 +01:00
font-size: 12px;
2025-07-20 10:13:38 +01:00
}
.update-button:hover {
background-color: #0056b3;
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: #007bff;
text-decoration: none;
2025-07-20 15:46:25 +01:00
font-size: 12px;
2025-07-20 10:13:38 +01:00
}
.back-link:hover {
text-decoration: underline;
}
2025-07-20 15:46:25 +01:00
.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;
}
2025-07-20 10:13:38 +01:00
< / 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" >
2025-07-20 15:46:25 +01:00
{% 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 >
2025-07-20 10:13:38 +01:00
2025-07-20 15:46:25 +01:00
<!-- 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 >
2025-07-20 10:13:38 +01:00
< / div >
2025-07-20 15:46:25 +01:00
< 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 >
2025-07-20 10:13:38 +01:00
< / div >
2025-07-20 15:46:25 +01:00
< 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 >
2025-07-20 10:13:38 +01:00
< / div >
2025-07-20 15:46:25 +01:00
< 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 >
2025-07-20 10:13:38 +01:00
2025-07-20 15:46:25 +01:00
<!-- 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 >
2025-07-20 10:13:38 +01:00
< / div >
< div class = "footer" >
2025-07-20 15:46:25 +01:00
< p > {{ version if version else 'SME Server 11 (beta1)' }} - Admin Panel (Corrected DB Structure)< / p >
2025-07-20 10:13:38 +01:00
< / div >
< / div >
< script >
2025-07-20 15:46:25 +01:00
// 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 > ';
});
2025-07-20 10:13:38 +01:00
});
});
// Handle radio button changes for visual feedback
document.querySelectorAll('input[name="strength"]').forEach(radio => {
radio.addEventListener('change', function() {
2025-07-20 15:46:25 +01:00
const form = this.closest('.config-form');
form.querySelectorAll('.config-option').forEach(option => {
2025-07-20 10:13:38 +01:00
option.classList.remove('active');
});
this.closest('.config-option').classList.add('active');
});
});
< / script >
< / body >
< / html >