from datetime import datetime import logging import os from flask import ( Blueprint, current_app, g, redirect, request, render_template, send_file, url_for, ) from flask_login import login_required from werkzeug.wrappers.response import Response from ..exceptions import exception_handler from ...reload import reload from ...sql_migration_list import BrickSQLMigrationList from ...sql import BrickSQL from ..upload import upload_helper logger = logging.getLogger(__name__) admin_database_page = Blueprint( 'admin_database', __name__, url_prefix='/admin/database' ) # Delete the database @admin_database_page.route('/delete', methods=['GET']) @login_required @exception_handler(__file__) def delete() -> str: return render_template( 'admin.html', delete_database=True, error=request.args.get('error') ) # Actually delete the database @admin_database_page.route('/delete', methods=['POST']) @login_required @exception_handler(__file__, post_redirect='admin_database.delete') def do_delete() -> Response: BrickSQL.delete() reload() return redirect(url_for('admin.admin')) # Download the database @admin_database_page.route('/download', methods=['GET']) @login_required @exception_handler(__file__) def download() -> Response: # Create a file name with a timestamp embedded name, extension = os.path.splitext( os.path.basename(current_app.config['DATABASE_PATH']) ) # Info logger.info('The database has been downloaded') return send_file( current_app.config['DATABASE_PATH'], as_attachment=True, download_name='{name}-v{version}-{timestamp}{extension}'.format( name=name, version=BrickSQL(failsafe=True).version, timestamp=datetime.now().astimezone(g.timezone).strftime( current_app.config['DATABASE_TIMESTAMP_FORMAT'] ), extension=extension ) ) # Drop the database @admin_database_page.route('/drop', methods=['GET']) @login_required @exception_handler(__file__) def drop() -> str: return render_template( 'admin.html', drop_database=True, error=request.args.get('error') ) # Actually drop the database @admin_database_page.route('/drop', methods=['POST']) @login_required @exception_handler(__file__, post_redirect='admin_database.drop') def do_drop() -> Response: BrickSQL.drop() reload() return redirect(url_for('admin.admin')) # Actually upgrade the database @admin_database_page.route('/upgrade', methods=['POST']) @login_required @exception_handler(__file__, post_redirect='admin_database.upgrade') def do_upgrade() -> Response: BrickSQL(failsafe=True).upgrade() reload() return redirect(url_for('admin.admin')) # Import a database @admin_database_page.route('/import', methods=['GET']) @login_required @exception_handler(__file__) def upload() -> str: return render_template( 'admin.html', import_database=True, error=request.args.get('error') ) # Actually import a database @admin_database_page.route('/import', methods=['POST']) @login_required @exception_handler(__file__, post_redirect='admin_database.upload') def do_upload() -> Response: file = upload_helper( 'database', 'admin_database.upload', extensions=['.db'], ) if isinstance(file, Response): return file BrickSQL.upload(file) reload() return redirect(url_for('admin.admin')) # Upgrade the database @admin_database_page.route('/upgrade', methods=['GET']) @login_required @exception_handler(__file__, post_redirect='admin.admin') def upgrade() -> str | Response: database = BrickSQL(failsafe=True) if not database.upgrade_needed(): return redirect(url_for('admin.admin')) return render_template( 'admin.html', upgrade_database=True, migrations=BrickSQLMigrationList().pending( database.version ), error=request.args.get('error') )