from email.mime import image from alembic.util import obfuscate_url_pw from app import app from flask import render_template, flash, redirect, url_for, request, session from app.forms import LoginForm, SettingsForm from flask_login import login_user, current_user, logout_user, login_required import sqlalchemy as sa from app import db from app.models import User, Setting from werkzeug.datastructures import FileStorage import json from flask_babel import _ import base64 def get_setting(name) -> str: setting = db.session.scalar(sa.select(Setting).where(Setting.key == name)) return str(setting.value) def set_setting(name: str, value: str): setting = db.session.scalar(sa.select(Setting).where(Setting.key == name)) print(f"I have changed {setting.key}") setting.value = value db.session.add(setting) def dump_settings(filename: str) -> None: settings = db.session.execute(sa.select(Setting)).scalars().all() settings_dict = {s.key: s.value for s in settings} print(settings_dict) with open(filename, "w") as f: json.dump(settings_dict, f, indent=4) @app.route('/') @app.route('/index') def index(): disable_chat = get_setting("disable_chat") disable_app_store = get_setting("disable_app_store") disable_map_viewer = get_setting("disable_map_viewer") disable_file_viewer = get_setting("disable_file_viewer") service_array = [] usb_inserted = False # actual test of whether USB is inserted usb_has_maps = False # actual test of whether USB has maps folder usb_has_appstore = False # actual test of whether USB has an appstore if disable_chat == 'false': service_array.append({"name": "Message Board", "image": url_for("static", filename="images/chat-icon.png"), "url": app.config["CONVENE_INSTALL_PATH"] }) if disable_app_store == 'false' and usb_has_appstore: service_array.append({"name": "Apps", "image": url_for("static", filename="images/appstore-icon.svg")}) if disable_map_viewer == 'false' and usb_has_maps: service_array.append({"name": "Offline Maps", "image": url_for("static", filename="images/maps-icon.png")}) if disable_file_viewer == 'false': name = "Files" if not usb_inserted: name = "Insert USB to browse files" service_array.append({ "name": name, "image": url_for("static", filename="images/explore-icon.svg"), "url": url_for("usb")}) return render_template('index.html', title='Home', get_setting=get_setting, services=service_array) @app.route('/usb') def usb(): return render_template('usb-file-viewer.html', title='File Viewer') @app.route('/login', methods=['GET', 'POST']) def login(): if current_user.is_authenticated: return redirect(url_for('admin')) form = LoginForm() form.remember_me.data = False if form.validate_on_submit(): user = db.session.scalar(sa.select(User).where(User.username == form.username.data)) if user is None or not user.check_password(form.password.data): flash(_('Invalid username or password')) return redirect(url_for('login')) login_user(user) return redirect(url_for('admin')) return render_template('login.html', title='Sign in', form=form, get_setting=get_setting) @app.route('/logout') def logout(): logout_user() return redirect(url_for('index')) @app.route('/admin', methods=['GET', 'POST']) @login_required def admin(): form = SettingsForm() populate_settings = ['butterbox_name', 'wifi_password', 'disable_access_point', 'ssid', 'disable_file_viewer', 'disable_map_viewer', 'disable_app_store', 'disable_chat' ] bool_settings = ['disable_access_point','disable_file_viewer', 'disable_map_viewer', 'disable_app_store', 'disable_chat'] if not form.is_submitted(): for s in populate_settings: if s in bool_settings: getattr(form, s).data = (get_setting(s) == "true") else: getattr(form, s).data = get_setting(s) if form.validate_on_submit(): if form.submit.data: for s in populate_settings: new_value = getattr(form, s).data if s in bool_settings: new_value = str(new_value).lower() # all settings are str fow now existing_value = get_setting(s) if new_value != existing_value: print(f"New value was changed for {s}. Existing value was {existing_value}, new value was {new_value}") set_setting(s, new_value) if s in ['butterbox_name', 'wifi_password', 'ssid', 'disable_access_point']: app.config['SETTINGS_CHANGED'] = True new_logo = form.butterbox_logo.data if new_logo.filename: logo_stream = form.butterbox_logo.data.stream b64_logo = base64.b64encode(logo_stream.read()).decode('utf-8') file_mimetype = form.butterbox_logo.data.mimetype new_value = f"data:{file_mimetype};base64,{b64_logo}" existing_value = get_setting('butterbox_logo') if new_value != existing_value: print( f"New value was changed for logo") set_setting('butterbox_logo', new_value) new_admin_password = form.admin_password.data if new_admin_password: existing_admin_password = get_setting('admin_password') if new_admin_password != existing_admin_password: print( f"New value was changed for admin password") set_setting('admin_password', new_admin_password) print(get_setting('admin_password')) if app.config['SETTINGS_CHANGED']: flash(_("⚠️ Some settings won't take effect until the Butter Box restarts. Click 'Apply Changes' to restart.")) db.session.commit() if form.apply_changes.data: set_setting('apply_changes', "true") dump_settings("settings.txt") flash(_("⚠️ Changes applied! Please wait for the box to restart.")) return render_template('admin.html', get_setting=get_setting, form=form)