Changes: 1. Fixed create_user_handler to properly initialize modules JSON for new users 2. Fixed edit_user_handler to manage module assignments instead of non-existent email field 3. Updated settings_handler to select modules column instead of email from users table 4. Added validate_and_repair_user_modules function in setup_complete_database.py to ensure all users have correct module assignments 5. Added create_app_license function to create development license file during database setup 6. Added ensure_app_license function to docker-entrypoint.sh for license creation on container startup 7. Added user modules validation on Flask app startup to repair any malformed modules 8. License file is automatically created with 1-year validity on deployment This ensures: - New users created via UI get proper module assignments - Existing users are validated/repaired on app startup - Non-superadmin users can login after license check passes - All deployments have a valid development license by default
166 lines
6.6 KiB
Python
166 lines
6.6 KiB
Python
from flask import Flask
|
|
from datetime import datetime
|
|
|
|
def create_app():
|
|
app = Flask(__name__)
|
|
app.config['SECRET_KEY'] = 'your_secret_key'
|
|
|
|
# Configure session persistence
|
|
from datetime import timedelta
|
|
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
|
|
app.config['SESSION_COOKIE_SECURE'] = False # Set to True in production with HTTPS
|
|
app.config['SESSION_COOKIE_HTTPONLY'] = True
|
|
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
|
|
|
|
# Set max upload size to 10GB for large database backups
|
|
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 * 1024 # 10GB
|
|
|
|
# Application uses direct MariaDB connections via external_server.conf
|
|
# No SQLAlchemy ORM needed - all database operations use raw SQL
|
|
|
|
from app.routes import bp as main_bp, warehouse_bp
|
|
from app.daily_mirror import daily_mirror_bp
|
|
app.register_blueprint(main_bp, url_prefix='/')
|
|
app.register_blueprint(warehouse_bp, url_prefix='/warehouse')
|
|
app.register_blueprint(daily_mirror_bp)
|
|
|
|
# Add 'now' function to Jinja2 globals
|
|
app.jinja_env.globals['now'] = datetime.now
|
|
|
|
# Add license check middleware
|
|
@app.before_request
|
|
def check_license_middleware():
|
|
from flask import session, request, redirect, url_for, flash, render_template
|
|
import os
|
|
import json
|
|
from datetime import datetime
|
|
|
|
# Skip license check for static files, login page, and superadmin users
|
|
if request.endpoint and (
|
|
request.endpoint == 'static' or
|
|
request.endpoint == 'main.login' or
|
|
request.path.startswith('/static/')
|
|
):
|
|
return None
|
|
|
|
# Skip if user is not logged in (will be redirected to login by other means)
|
|
if 'user' not in session:
|
|
return None
|
|
|
|
# Skip license check for superadmin
|
|
if session.get('role') == 'superadmin':
|
|
return None
|
|
|
|
# Check license validity
|
|
license_path = os.path.join(app.instance_path, 'app_license.json')
|
|
|
|
if not os.path.exists(license_path):
|
|
session.clear()
|
|
flash('⚠️ Application License Missing - Please contact your superadmin to generate a license key.', 'danger')
|
|
return redirect(url_for('main.login'))
|
|
|
|
try:
|
|
with open(license_path, 'r') as f:
|
|
license_data = json.load(f)
|
|
|
|
valid_until = datetime.strptime(license_data['valid_until'], '%Y-%m-%d')
|
|
|
|
if datetime.utcnow().date() > valid_until.date():
|
|
session.clear()
|
|
flash(f'⚠️ Application License Expired on {license_data["valid_until"]} - Please contact your superadmin to renew the license.', 'danger')
|
|
return redirect(url_for('main.login'))
|
|
except Exception as e:
|
|
session.clear()
|
|
flash('⚠️ License Validation Error - Please contact your superadmin.', 'danger')
|
|
return redirect(url_for('main.login'))
|
|
|
|
return None
|
|
|
|
# Initialize user modules validation and repair on app startup
|
|
def validate_user_modules_on_startup():
|
|
"""Validate and repair user modules during app startup"""
|
|
try:
|
|
import mariadb
|
|
import json
|
|
import os
|
|
|
|
# Get database config from instance folder
|
|
instance_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../instance'))
|
|
config_path = os.path.join(instance_path, 'external_server.conf')
|
|
|
|
if not os.path.exists(config_path):
|
|
print("⚠️ Database config not found, skipping user modules validation")
|
|
return
|
|
|
|
# Parse config
|
|
db_config = {}
|
|
try:
|
|
with open(config_path, 'r') as f:
|
|
for line in f:
|
|
if '=' in line:
|
|
key, value = line.strip().split('=', 1)
|
|
db_config[key] = value
|
|
|
|
db_config = {
|
|
'user': db_config.get('username', 'trasabilitate'),
|
|
'password': db_config.get('password', 'Initial01!'),
|
|
'host': db_config.get('server_domain', 'localhost'),
|
|
'port': int(db_config.get('port', 3306)),
|
|
'database': db_config.get('database_name', 'trasabilitate')
|
|
}
|
|
except Exception as e:
|
|
print(f"⚠️ Could not parse database config: {e}")
|
|
return
|
|
|
|
# Connect and validate users
|
|
conn = mariadb.connect(**db_config)
|
|
cursor = conn.cursor()
|
|
|
|
# Check if users table exists
|
|
cursor.execute("SHOW TABLES LIKE 'users'")
|
|
if not cursor.fetchone():
|
|
print("⚠️ Users table not found, skipping validation")
|
|
conn.close()
|
|
return
|
|
|
|
# Get all users and validate/repair modules
|
|
cursor.execute("SELECT id, username, role, modules FROM users")
|
|
users = cursor.fetchall()
|
|
|
|
users_repaired = 0
|
|
for user_id, username, role, modules in users:
|
|
# Determine correct modules
|
|
if role == 'superadmin':
|
|
correct_modules = None
|
|
elif role == 'admin':
|
|
correct_modules = json.dumps(['quality', 'warehouse', 'labels', 'daily_mirror'])
|
|
elif role in ['manager', 'quality_manager', 'warehouse_manager']:
|
|
correct_modules = json.dumps(['quality', 'warehouse'])
|
|
else:
|
|
correct_modules = json.dumps([])
|
|
|
|
# Repair if needed
|
|
if modules != correct_modules:
|
|
cursor.execute("UPDATE users SET modules = %s WHERE id = %s", (correct_modules, user_id))
|
|
users_repaired += 1
|
|
|
|
if users_repaired > 0:
|
|
conn.commit()
|
|
print(f"✅ User modules validation complete: {users_repaired} users repaired")
|
|
|
|
cursor.close()
|
|
conn.close()
|
|
|
|
except Exception as e:
|
|
print(f"⚠️ Error during user modules validation: {e}")
|
|
|
|
# Run validation on startup
|
|
with app.app_context():
|
|
validate_user_modules_on_startup()
|
|
|
|
# Initialize automatic backup scheduler
|
|
from app.backup_scheduler import init_backup_scheduler
|
|
init_backup_scheduler(app)
|
|
print("✅ Automatic backup scheduler initialized")
|
|
|
|
return app |