Add in proper passord check lib, show results in form
This commit is contained in:
@@ -1,15 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Enhanced SME Server Password Change Application - Python 3.6.8 Compatible
|
||||
Corrected SME Server Password Change Application - Python 3.6.8 Compatible
|
||||
|
||||
A Flask web application for changing user passwords on SME Server,
|
||||
with configurable password strength validation and password visibility toggles.
|
||||
with correct database structure and external password validation library.
|
||||
|
||||
Database Structure:
|
||||
passwordstrength=configuration
|
||||
Admin=strong
|
||||
Ibays=strong
|
||||
Users=strong
|
||||
|
||||
Features:
|
||||
- Configurable password strength (None/Normal/Strong)
|
||||
- Correct SME Server database integration
|
||||
- External zxcvbn password validation library
|
||||
- Password visibility toggles
|
||||
- Enhanced validation with crypto testing
|
||||
- Real-time password strength feedback
|
||||
- Admin configuration panel
|
||||
|
||||
Compatible with Python 3.6.8 and Flask 2.0.3
|
||||
"""
|
||||
@@ -20,7 +27,7 @@ from flask_cors import CORS
|
||||
from smeserver_utils import SMEPasswordManager, SMESystemInfo, SMEConfigDB
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = os.environ.get('SECRET_KEY', 'sme-server-password-change-enhanced-key')
|
||||
app.secret_key = os.environ.get('SECRET_KEY', 'sme-server-password-change-corrected-key')
|
||||
CORS(app)
|
||||
|
||||
# Initialize SME Server utilities
|
||||
@@ -30,10 +37,10 @@ config_db = SMEConfigDB()
|
||||
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
def password_change():
|
||||
"""Main password change form handler with enhanced validation"""
|
||||
"""Main password change form handler with corrected validation"""
|
||||
|
||||
# Get current password requirements for display
|
||||
password_requirements = password_manager.get_password_strength_info()
|
||||
password_requirements = password_manager.get_password_strength_info('Users')
|
||||
|
||||
if request.method == 'POST':
|
||||
# Get form data
|
||||
@@ -71,9 +78,9 @@ def password_change():
|
||||
if not password_manager.verify_current_password(username, old_password):
|
||||
errors.append("Current password is incorrect")
|
||||
|
||||
# Enhanced password strength validation
|
||||
# Enhanced password strength validation with zxcvbn
|
||||
if new_password:
|
||||
strength_errors = password_manager.validate_password_strength(new_password)
|
||||
strength_errors = password_manager.validate_password_strength(new_password, username)
|
||||
errors.extend(strength_errors)
|
||||
|
||||
if errors:
|
||||
@@ -100,41 +107,58 @@ def password_change():
|
||||
|
||||
@app.route('/api/password-strength', methods=['POST'])
|
||||
def check_password_strength():
|
||||
"""API endpoint for real-time password strength checking"""
|
||||
"""API endpoint for real-time password strength checking with zxcvbn"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
password = data.get('password', '')
|
||||
username = data.get('username', '')
|
||||
|
||||
if not password:
|
||||
return jsonify({'errors': ['Password cannot be empty']})
|
||||
|
||||
# Get validation errors
|
||||
errors = password_manager.validate_password_strength(password)
|
||||
# Get validation errors using zxcvbn
|
||||
errors = password_manager.validate_password_strength(password, username)
|
||||
|
||||
# Calculate strength score
|
||||
strength_score = 0
|
||||
max_score = 5
|
||||
# Calculate basic strength score for UI feedback
|
||||
# strength_score = 0
|
||||
# if len(password) >= 12:
|
||||
# strength_score += 1
|
||||
# if any(c.isupper() for c in password):
|
||||
# strength_score += 1
|
||||
# if any(c.islower() for c in password):
|
||||
# strength_score += 1
|
||||
# if any(c.isdigit() for c in password):
|
||||
# strength_score += 1
|
||||
# if any(not c.isalnum() for c in password):
|
||||
# strength_score += 1
|
||||
|
||||
if len(password) >= 12:
|
||||
strength_score += 1
|
||||
if any(c.isupper() for c in password):
|
||||
strength_score += 1
|
||||
if any(c.islower() for c in password):
|
||||
strength_score += 1
|
||||
if any(c.isdigit() for c in password):
|
||||
strength_score += 1
|
||||
if any(not c.isalnum() for c in password):
|
||||
strength_score += 1
|
||||
# Get zxcvbn score if available
|
||||
zxcvbn_score = None
|
||||
zxcvbn_feedback = None
|
||||
|
||||
strength_levels = ['Very Weak', 'Weak', 'Fair', 'Good', 'Strong']
|
||||
strength_level = strength_levels[min(strength_score, len(strength_levels) - 1)]
|
||||
if password_manager.external_validator:
|
||||
try:
|
||||
user_inputs = [username] if username else []
|
||||
result = password_manager.external_validator.zxcvbn(password, user_inputs)
|
||||
zxcvbn_score = result['score']
|
||||
zxcvbn_feedback = result.get('feedback', {})
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
strength_levels = ["Very Weak", "Weak", "Fair", "Good", "Strong"]
|
||||
|
||||
# Map zxcvbn score (0-4) to strength_levels (0-4)
|
||||
display_score = zxcvbn_score if password_manager.external_validator else 0
|
||||
strength_level = strength_levels[min(display_score, len(strength_levels) - 1)]
|
||||
|
||||
return jsonify({
|
||||
'errors': errors,
|
||||
'strength_score': strength_score,
|
||||
'max_score': max_score,
|
||||
'strength_score': display_score,
|
||||
'max_score': 4 if zxcvbn_score is not None else 5,
|
||||
'strength_level': strength_level,
|
||||
'is_valid': len(errors) == 0
|
||||
'is_valid': len(errors) == 0,
|
||||
'using_zxcvbn': password_manager.external_validator is not None,
|
||||
'zxcvbn_feedback': zxcvbn_feedback
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
@@ -144,39 +168,40 @@ def check_password_strength():
|
||||
def password_config():
|
||||
"""API endpoint for managing password strength configuration"""
|
||||
if request.method == 'GET':
|
||||
# Get current configuration
|
||||
# Get current configuration for all account types
|
||||
try:
|
||||
strength_setting = config_db.get_password_strength_setting()
|
||||
requirements = password_manager.get_password_strength_info()
|
||||
all_settings = config_db.get_all_password_strength_settings()
|
||||
|
||||
return jsonify({
|
||||
'current_setting': strength_setting,
|
||||
'requirements': requirements,
|
||||
'current_settings': all_settings,
|
||||
'available_levels': {
|
||||
'none': 'No specific password requirements',
|
||||
'normal': 'Minimum 12 characters with complexity requirements',
|
||||
'strong': 'Normal requirements plus protection against common passwords'
|
||||
}
|
||||
'strong': 'Normal requirements plus zxcvbn advanced validation' if password_manager.external_validator else 'Normal requirements plus basic pattern protection'
|
||||
},
|
||||
'using_zxcvbn': password_manager.external_validator is not None
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({'error': 'Failed to get password configuration'}), 500
|
||||
|
||||
elif request.method == 'POST':
|
||||
# Update configuration (admin only)
|
||||
# Update configuration
|
||||
try:
|
||||
data = request.get_json()
|
||||
new_strength = data.get('strength', '').lower()
|
||||
account_type = data.get('account_type', 'Users')
|
||||
|
||||
if new_strength not in ['none', 'normal', 'strong']:
|
||||
return jsonify({'error': 'Invalid strength level'}), 400
|
||||
if account_type not in ['Users', 'Admin', 'Ibays']:
|
||||
return jsonify({'error': 'Invalid account type'}), 400
|
||||
|
||||
success, message = config_db.set_password_strength_setting(new_strength)
|
||||
success, message = config_db.set_password_strength_setting(new_strength, account_type)
|
||||
|
||||
if success:
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Password strength setting updated to: {}'.format(new_strength),
|
||||
'new_setting': new_strength
|
||||
'message': 'Password strength setting updated for {}: {}'.format(account_type, new_strength),
|
||||
'new_setting': new_strength,
|
||||
'account_type': account_type
|
||||
})
|
||||
else:
|
||||
return jsonify({'error': message}), 500
|
||||
@@ -186,15 +211,14 @@ def password_config():
|
||||
|
||||
@app.route('/admin')
|
||||
def admin_panel():
|
||||
"""Simple admin panel for password strength configuration"""
|
||||
"""Admin panel for password strength configuration"""
|
||||
try:
|
||||
current_setting = config_db.get_password_strength_setting()
|
||||
requirements = password_manager.get_password_strength_info()
|
||||
all_settings = config_db.get_all_password_strength_settings()
|
||||
|
||||
return render_template('admin_panel.html',
|
||||
current_setting=current_setting,
|
||||
requirements=requirements,
|
||||
version=system_info.get_version())
|
||||
current_settings=all_settings,
|
||||
version=system_info.get_version(),
|
||||
using_zxcvbn=password_manager.external_validator is not None)
|
||||
except Exception as e:
|
||||
flash('Error loading admin panel: {}'.format(str(e)), 'error')
|
||||
return redirect(url_for('password_change'))
|
||||
@@ -204,13 +228,14 @@ def health_check():
|
||||
"""Health check endpoint"""
|
||||
try:
|
||||
# Test database connectivity
|
||||
strength_setting = config_db.get_password_strength_setting()
|
||||
all_settings = config_db.get_all_password_strength_settings()
|
||||
|
||||
return jsonify({
|
||||
'status': 'healthy',
|
||||
'service': 'sme-server-password-change-enhanced',
|
||||
'password_strength_setting': strength_setting,
|
||||
'features': ['configurable_strength', 'password_visibility', 'crypto_validation']
|
||||
'service': 'sme-server-password-change-corrected',
|
||||
'password_strength_settings': all_settings,
|
||||
'features': ['corrected_db_structure', 'zxcvbn_validation', 'password_visibility', 'admin_panel'],
|
||||
'using_zxcvbn': password_manager.external_validator is not None
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
@@ -221,7 +246,7 @@ def health_check():
|
||||
@app.errorhandler(404)
|
||||
def not_found(error):
|
||||
"""Handle 404 errors"""
|
||||
password_requirements = password_manager.get_password_strength_info()
|
||||
password_requirements = password_manager.get_password_strength_info('Users')
|
||||
return render_template('password_change.html',
|
||||
error="Page not found",
|
||||
password_requirements=password_requirements), 404
|
||||
@@ -229,32 +254,34 @@ def not_found(error):
|
||||
@app.errorhandler(500)
|
||||
def internal_error(error):
|
||||
"""Handle 500 errors"""
|
||||
password_requirements = password_manager.get_password_strength_info()
|
||||
password_requirements = password_manager.get_password_strength_info('Users')
|
||||
return render_template('password_change.html',
|
||||
error="Internal server error",
|
||||
password_requirements=password_requirements), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Starting Enhanced SME Server Password Change Application")
|
||||
print("Starting Corrected SME Server Password Change Application")
|
||||
print("Features:")
|
||||
print(" - Configurable password strength validation")
|
||||
print(" - Correct SME Server database structure (Users/Admin/Ibays)")
|
||||
print(" - External zxcvbn password validation library")
|
||||
print(" - Password visibility toggles")
|
||||
print(" - Real-time strength checking")
|
||||
print(" - Crypto validation for strong passwords")
|
||||
print(" - Admin configuration panel")
|
||||
print("")
|
||||
|
||||
try:
|
||||
current_strength = config_db.get_password_strength_setting()
|
||||
print("Current password strength setting: {}".format(current_strength.upper()))
|
||||
all_settings = config_db.get_all_password_strength_settings()
|
||||
print("Current password strength settings:")
|
||||
for account_type, strength in all_settings.items():
|
||||
print(" {}: {}".format(account_type, strength.upper()))
|
||||
except:
|
||||
print("Password strength setting: NORMAL (default)")
|
||||
print("Password strength settings: Using defaults")
|
||||
|
||||
print("")
|
||||
print("Using zxcvbn library: {}".format("Yes" if password_manager.external_validator else "No (fallback to basic validation)"))
|
||||
print("")
|
||||
print("Access the application at: http://localhost:5000")
|
||||
print("Admin panel at: http://localhost:5000/admin")
|
||||
print("API endpoints:")
|
||||
print(" - GET/POST /api/password-config")
|
||||
print(" - POST /api/password-strength")
|
||||
|
||||
# Run the application
|
||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
||||
|
Reference in New Issue
Block a user