Development
This commit is contained in:
parent
33ec9e7f1c
commit
0cec7d69c9
12 changed files with 124 additions and 92 deletions
|
|
@ -839,10 +839,10 @@ def load_datasource(spec):
|
|||
|
||||
|
||||
def collect_layout_tokens(cfg):
|
||||
import license
|
||||
import settings as settings
|
||||
net = cfg.get('network_interfaces', {})
|
||||
return {
|
||||
'GENERAL_LAN_INTERFACE': str(net.get('lan_interface', '-')),
|
||||
'VPN_VLAN_COUNT': str(sum(1 for v in cfg.get('vlans', []) if v.get('is_vpn'))),
|
||||
'PRO_LICENSE_JS': 'true' if license.is_pro() else 'false',
|
||||
'PRO_LICENSE_JS': 'true' if settings.is_pro() else 'false',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,19 @@ from config_utils import (
|
|||
_is_locked, _lock_mtime, _entry_ts_from_queue,
|
||||
)
|
||||
|
||||
PAGES_DIR = os.path.join(APP_DIR, 'pages')
|
||||
NAVBAR_FILE = os.path.join(APP_DIR, 'navbar.json')
|
||||
CSS_FILE = os.path.join(DATA_DIR, 'styles.css')
|
||||
COMMON_JS_FILE = os.path.join(DATA_DIR, 'common.js')
|
||||
import settings as settings
|
||||
|
||||
PAGES_DIR = os.path.join(APP_DIR, 'pages')
|
||||
NAVBAR_FILE = os.path.join(APP_DIR, 'navbar.json')
|
||||
CSS_FILE = os.path.join(WWW_DIR, 'styles.css')
|
||||
COMMON_JS_FILE = os.path.join(WWW_DIR, 'common.js')
|
||||
|
||||
|
||||
def _file_version(path):
|
||||
try:
|
||||
return int(os.path.getmtime(path))
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
# Constants ===========================================================
|
||||
|
||||
|
|
@ -91,21 +100,20 @@ def load_icon(name):
|
|||
return ''
|
||||
|
||||
def inline_js(page_name=None):
|
||||
big_validate_js = build_big_validate()
|
||||
try:
|
||||
with open(COMMON_JS_FILE) as f:
|
||||
app_js = f.read()
|
||||
except Exception:
|
||||
app_js = ''
|
||||
page_js = ''
|
||||
if page_name:
|
||||
page_js_path = os.path.join(PAGES_DIR, page_name, 'page.js')
|
||||
parts = [build_big_validate()]
|
||||
if not settings.is_production():
|
||||
try:
|
||||
with open(page_js_path) as f:
|
||||
page_js = f.read()
|
||||
with open(COMMON_JS_FILE) as f:
|
||||
parts.append(f.read())
|
||||
except Exception:
|
||||
pass
|
||||
return big_validate_js + '\n' + app_js + ('\n' + page_js if page_js else '')
|
||||
if page_name:
|
||||
try:
|
||||
with open(os.path.join(PAGES_DIR, page_name, 'page.js')) as f:
|
||||
parts.append(f.read())
|
||||
except Exception:
|
||||
pass
|
||||
return '\n'.join(parts)
|
||||
|
||||
# Utilities ===========================================================
|
||||
|
||||
|
|
@ -1512,7 +1520,6 @@ def build_item(item, tokens, inherited_req=None):
|
|||
# Layout renderer =====================================================
|
||||
|
||||
def render_layout(view_id, content_html, tokens, page_name=None):
|
||||
css = load_css()
|
||||
level = client_level()
|
||||
has_pending_alert = not _apply_changes_immediately() and bool(get_dashboard_pending())
|
||||
titlebar_html = f'<div class="titlebar"><span class="titlebar-brand">{WEB_APP_DISPLAY_NAME}</span></div>'
|
||||
|
|
@ -1636,17 +1643,27 @@ def render_layout(view_id, content_html, tokens, page_name=None):
|
|||
'</div>\n'
|
||||
)
|
||||
|
||||
if settings.is_production():
|
||||
css_ver = _file_version(CSS_FILE)
|
||||
js_ver = _file_version(COMMON_JS_FILE)
|
||||
css_tag = f' <link rel="stylesheet" href="/www/styles.css?v={css_ver}">\n'
|
||||
common_js = f'<script src="/www/common.js?v={js_ver}"></script>\n'
|
||||
else:
|
||||
css_tag = f' <style>{load_css()}</style>\n'
|
||||
common_js = ''
|
||||
|
||||
return (
|
||||
'<!DOCTYPE html>\n<html lang="en">\n<head>\n'
|
||||
' <meta charset="UTF-8"/>\n'
|
||||
' <meta name="viewport" content="width=device-width, initial-scale=1.0"/>\n'
|
||||
f' <title>{WEB_APP_DISPLAY_NAME}</title>\n'
|
||||
f' <style>{css}</style>\n'
|
||||
f'{css_tag}'
|
||||
'</head>\n<body>\n'
|
||||
f'{titlebar_html}\n'
|
||||
f'{navbar_html}\n'
|
||||
f'<main class="main-content">\n{pending_bar}{problem_bars}{other_bars}{content_html}\n</main>\n'
|
||||
f'{footer_html}\n'
|
||||
f'{common_js}'
|
||||
f'<script>var CONFIG_HASH="{page_hash}";var LAN_IFACE="{lan_iface}";var VPN_VLAN_COUNT={vpn_count};var APPLY_UUID={json.dumps(my_uuid)};</script>\n'
|
||||
f'<script>{inline_js(page_name)}</script>\n'
|
||||
'</body>\n</html>'
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
def is_pro():
|
||||
return True
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
import os, json, sys, importlib.util as _importlib_util
|
||||
from flask import Flask, Blueprint, session, redirect, get_flashed_messages
|
||||
from flask import Flask, Blueprint, session, redirect, get_flashed_messages, send_from_directory
|
||||
from markupsafe import Markup
|
||||
from config_utils import (
|
||||
ACCOUNTS_FILE, APP_DIR, CONFIGS_DIR, HEALTH_FILE,
|
||||
ACCOUNTS_FILE, APP_DIR, CONFIGS_DIR, HEALTH_FILE, WWW_DIR,
|
||||
load_config, queue_command, _find_cmd_in_queues,
|
||||
)
|
||||
from factory import (
|
||||
LEVEL_RANK, PAGES_DIR, e, client_level, passes, build_items,
|
||||
load_json, render_layout,
|
||||
)
|
||||
import settings as settings
|
||||
from pages.actions.action import bp as actions_bp
|
||||
from pages.bannedips.action import bp as bannedips_bp
|
||||
from pages.ddns.action import bp as ddns_bp
|
||||
|
|
@ -35,6 +36,16 @@ from api_apply_health import bp as api_apply_health_bp
|
|||
app = Flask(__name__)
|
||||
app.secret_key = os.environ.get('SECRET_KEY', os.urandom(24))
|
||||
|
||||
# Static www/ serving =================================================
|
||||
|
||||
@app.route('/www/<path:filename>')
|
||||
def serve_www(filename):
|
||||
response = send_from_directory(WWW_DIR, filename)
|
||||
if settings.is_production():
|
||||
response.cache_control.max_age = 86400
|
||||
response.cache_control.public = True
|
||||
return response
|
||||
|
||||
# View blueprint ======================================================
|
||||
|
||||
bp = Blueprint('view_page', __name__)
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ from auth import require_level
|
|||
from config_utils import load_config, record_group, diff_fields, verify_config_hash
|
||||
import sanitize
|
||||
import mod_validation as validate
|
||||
import license
|
||||
import settings as settings
|
||||
|
||||
_PAGE = Path(__file__).parent.name
|
||||
|
||||
PRO_LICENSE = license.is_pro()
|
||||
PRO_LICENSE = settings.is_pro()
|
||||
|
||||
bp = Blueprint(_PAGE, __name__)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import json
|
||||
from config_utils import collect_layout_tokens, load_datasource
|
||||
from factory import load_json, build_table, table_token_key, iter_table_items, PAGES_DIR
|
||||
import license
|
||||
import settings as settings
|
||||
|
||||
PRO_LICENSE = license.is_pro()
|
||||
PRO_LICENSE = settings.is_pro()
|
||||
|
||||
|
||||
def collect_tokens(cfg):
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ from flask import Blueprint, request, redirect, flash, send_file, abort, jsonify
|
|||
from auth import require_level
|
||||
from config_utils import CONFIGS_DIR, load_config, record_group, diff_fields
|
||||
import mod_validation as validate
|
||||
import license
|
||||
import settings as settings
|
||||
|
||||
_PAGE = Path(__file__).parent.name
|
||||
|
||||
PRO_LICENSE = license.is_pro()
|
||||
PRO_LICENSE = settings.is_pro()
|
||||
|
||||
bp = Blueprint(_PAGE, __name__)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import json
|
||||
import os
|
||||
from config_utils import collect_layout_tokens, CONFIGS_DIR
|
||||
import license
|
||||
import settings as settings
|
||||
|
||||
PRO_LICENSE = license.is_pro()
|
||||
PRO_LICENSE = settings.is_pro()
|
||||
|
||||
RADIUS_LOG_MAX = 50
|
||||
RADIUS_LOG_FILE = '/var/log/freeradius/radius.log'
|
||||
|
|
|
|||
9
docker/routlin-dash/app/settings.py
Normal file
9
docker/routlin-dash/app/settings.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import os
|
||||
|
||||
|
||||
def is_production():
|
||||
return os.environ.get('PRODUCTION_MODE', '').lower() in ('1', 'true', 'yes')
|
||||
|
||||
|
||||
def is_pro():
|
||||
return bool(os.environ.get('LICENSE', '').strip())
|
||||
Loading…
Add table
Add a link
Reference in a new issue