import random from flask import Flask, send_from_directory, jsonify from flask_migrate import Migrate from dotenv import load_dotenv import os from models import User, SiteSettings from flask_wtf.csrf import generate_csrf from routes.room_files import room_files_bp from routes.room_members import room_members_bp from routes.trash import trash_bp from routes.admin_api import admin_api from tasks import cleanup_trash import click from utils import timeago from extensions import db, login_manager, csrf from utils.email_templates import create_default_templates from datetime import datetime from sqlalchemy import text from utils.asset_utils import get_asset_version # Load environment variables load_dotenv() print("Environment variables after loading .env:") print(f"MASTER: {os.getenv('MASTER')}") print(f"ISMASTER: {os.getenv('ISMASTER')}") def create_app(): app = Flask(__name__) # Configure the database app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'postgresql://postgres:1253@localhost:5432/docupulse') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secure-secret-key-here') app.config['UPLOAD_FOLDER'] = os.path.join(app.root_path, 'static', 'uploads') app.config['CSS_VERSION'] = os.getenv('CSS_VERSION', '1.0.3') # Add CSS version for cache busting app.config['SERVER_NAME'] = os.getenv('SERVER_NAME', '127.0.0.1:5000') app.config['PREFERRED_URL_SCHEME'] = os.getenv('PREFERRED_URL_SCHEME', 'http') # Initialize extensions db.init_app(app) migrate = Migrate(app, db) login_manager.init_app(app) login_manager.login_view = 'auth.login' csrf.init_app(app) @app.context_processor def inject_csrf_token(): return dict(csrf_token=generate_csrf()) @app.context_processor def inject_config(): site_settings = SiteSettings.query.first() if not site_settings: site_settings = SiteSettings() db.session.add(site_settings) db.session.commit() return dict(config=app.config, site_settings=site_settings) @app.context_processor def inject_unread_notifications(): from flask_login import current_user from utils import get_unread_count if current_user.is_authenticated: unread_count = get_unread_count(current_user.id) return {'unread_notifications': unread_count} return {'unread_notifications': 0} @app.template_filter('asset_version') def asset_version_filter(filename): """Template filter to get version hash for static assets""" return get_asset_version(filename) or '' # User loader for Flask-Login @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # Health check endpoint @app.route('/health') def health_check(): try: # Check database connection with a timeout db.session.execute(text('SELECT 1')) db.session.commit() return jsonify({ 'status': 'healthy', 'database': 'connected', 'timestamp': datetime.utcnow().isoformat() }), 200 except Exception as e: app.logger.error(f"Health check failed: {str(e)}") return jsonify({ 'status': 'unhealthy', 'error': str(e), 'timestamp': datetime.utcnow().isoformat() }), 500 # Initialize routes from routes import init_app init_app(app) app.register_blueprint(room_files_bp, url_prefix='/api/rooms') app.register_blueprint(room_members_bp, url_prefix='/api/rooms') app.register_blueprint(trash_bp, url_prefix='/api/trash') app.register_blueprint(admin_api, url_prefix='/api/admin') @app.cli.command("cleanup-trash") def cleanup_trash_command(): """Clean up files that have been in trash for more than 30 days.""" cleanup_trash() click.echo("Trash cleanup completed.") @app.cli.command("create-admin") def create_admin(): """Create the default administrator user.""" admin = User.query.filter_by(email='administrator@docupulse.com').first() if admin: click.echo("Admin user already exists.") return admin = User( username='administrator', email='administrator@docupulse.com', last_name='Administrator', company='DocuPulse', position='System Administrator', is_admin=True, is_active=True, preferred_view='grid' ) admin.set_password('changeme') db.session.add(admin) db.session.commit() click.echo("Default administrator user created successfully.") click.echo("Admin credentials:") click.echo("Email: administrator@docupulse.com") click.echo("Password: changeme") # Register custom filters app.jinja_env.filters['timeago'] = timeago # Create default email templates if they don't exist with app.app_context(): try: # Ensure database tables exist db.create_all() # Create admin user first admin = User.query.filter_by(email='administrator@docupulse.com').first() if not admin: admin = User( username='administrator', email='administrator@docupulse.com', last_name='Administrator', company='DocuPulse', position='System Administrator', is_admin=True, is_active=True, preferred_view='grid' ) admin.set_password('changeme') db.session.add(admin) db.session.commit() print("Default administrator user created successfully.") print("Admin credentials:") print("Email: administrator@docupulse.com") print("Password: changeme") # Then create default templates create_default_templates() except Exception as e: print(f"Warning: Could not create default templates: {e}") return app app = create_app() @app.errorhandler(404) def page_not_found(e): from flask import render_template return render_template('common/404.html'), 404 @app.errorhandler(403) def forbidden(e): from flask import render_template return render_template('common/403.html'), 403 @app.errorhandler(401) def unauthorized(e): from flask import render_template return render_template('common/401.html'), 401 @app.errorhandler(400) def bad_request(e): from flask import render_template return render_template('common/400.html'), 400 @app.errorhandler(500) def internal_server_error(e): from flask import render_template import traceback error_details = f"{str(e)}\n\n{traceback.format_exc()}" app.logger.error(f"500 error: {error_details}") return render_template('common/500.html', error=error_details), 500 @app.route('/uploads/profile_pics/') def profile_pic(filename): return send_from_directory('/app/uploads/profile_pics', filename) if __name__ == '__main__': app.run(debug=True)