Skip to content

Commit

Permalink
YDA-5834: make portal config folder configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
FuHsinyu authored Jul 31, 2024
1 parent 1290716 commit f060111
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 48 deletions.
18 changes: 9 additions & 9 deletions admin/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,21 @@ def set_banner() -> Response:
:returns: Redirect to admin page with status message
"""
banner_message = request.form.get('banner', '').strip()
banner_message = escape(banner_message) # Ensure safe text
message = request.form.get('banner', '').strip()
message = escape(message) # Ensure safe text

# Message length check
error_message, is_valid = length_check(banner_message)
error_message, is_valid = length_check(message)
if not is_valid:
flash(error_message, "danger")
return redirect(url_for('admin_bp.index'))

# Update app config settings and save settings
settings = {
'banner': {
'banner_enabled': True,
'banner_importance': 'importance' in request.form,
'banner_message': banner_message
'enabled': True,
'importance': 'importance' in request.form,
'message': message
}
}
flash_msg = 'Set banner message successfully'
Expand All @@ -94,7 +94,7 @@ def remove_banner() -> Response:
"""
settings = {
'banner': {
'banner_enabled': False,
'enabled': False,
}
}
flash_msg = 'Banner removed successfully'
Expand Down Expand Up @@ -131,7 +131,7 @@ def save_settings(settings: Dict[str, Any], flash_msg: str) -> Response:
:returns: Redirect with flash message
"""
setting_file_path = path.join(app.config['APP_SHARED_FOLDER'], 'admin_settings.json')
setting_file_path = path.join(app.config['YODA_CONFIG_PATH'], 'admin_settings.json')
app.config.update(settings)

# Read existing settings
Expand Down Expand Up @@ -174,7 +174,7 @@ def set_theme_loader(app: Flask, remove_cache: Optional[bool] = False) -> None:
# Target theme path
theme_path = path.join(app.config.get('YODA_THEME_PATH'), app.config.get('YODA_THEME'))
# Secondary theme path for scanning missing templates
default_theme_path = path.join(app.config.get('YODA_MAIN_PATH'), 'general/templates/general')
default_theme_path = path.join(app.config.get('YODA_PORTAL_PATH'), 'general/templates/general')
# Create theme path list to scan templates
theme_path_lst = [theme_path, default_theme_path]

Expand Down
6 changes: 3 additions & 3 deletions admin/templates/admin/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ <h2 class="card-title">Set Maintenance Banner</h2>
<label for="banner">Banner Details:</label>
<textarea class="form-control" name="banner" id="banner" rows="2"
placeholder="Enter system maintenance details..."
required>{{config.get('banner').banner_message}}</textarea>
required>{{config.get('banner').get('message','')}}</textarea>
</div>
<!-- Checkbox to mark the banner as important -->
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="importance" name="importance" {{ 'checked' if config.get('banner', {}).get('banner_importance', False) else '' }}>
<input type="checkbox" class="form-check-input" id="importance" name="importance" {{ 'checked' if config.get('banner', {}).get('importance', False) else '' }}>
<label class="form-check-label" for="importance">Mark as Important</label>
</div>
<button type="submit" class="btn btn-primary" name="Set Banner">Set Banner</button>
Expand All @@ -51,7 +51,7 @@ <h2 class="card-title">Change Portal Theme</h2>
<!-- Add default theme option -->
{% set current_theme = config.get('YODA_THEME', 'uu') %}
{% for folder in theme_directories %}
<option value="{{ folder }}" {% if folder == current_theme %}selected{% endif %}> {{ config.YODA_THEME_MAPPING.get(folder, folder) }}</option>
<option value="{{ folder }}" {% if folder == current_theme %}selected{% endif %}> {{ config.get('YODA_THEME_MAPPING').get(folder, folder) }}</option>
{% endfor %}
</select>
</div>
Expand Down
64 changes: 36 additions & 28 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import json
from os import path
from typing import Dict, Optional
from typing import Any, Dict, Optional

from flask import Flask, g, redirect, request, Response, send_from_directory, url_for
from flask_session import Session
Expand All @@ -24,7 +24,7 @@
from search.search import search_bp
from stats.stats import stats_bp
from user.user import user_bp
from util import get_validated_static_path
from util import get_validated_static_path, log_error
from vault.vault import vault_bp


Expand All @@ -36,45 +36,53 @@
app.config.from_pyfile('flask.cfg')


def load_admin_config():
"""Load or initialize admin configurations from config file, writing defaults if no config file exists."""
config_file_path = path.join(app.config['APP_SHARED_FOLDER'], 'admin_settings.json')
default_config = {
def load_admin_setting() -> Dict[str, Any]:
"""Load or initialize admin settings from a JSON file.
If no setting file exists, it writes default loaded_settings and returns them.
If a setting file exists, it reads and returns the updated loaded_settings.
:returns: admin settings from file or default settings
"""

# configure default admin settings
config_folder = app.config['YODA_CONFIG_PATH']
settings_file_path = path.join(config_folder, 'admin_settings.json')
default_settings = {
'banner': {
'banner_enabled': False,
'banner_importance': False,
'banner_message': ''
'enabled': False,
'importance': False,
'message': ''
},
'YODA_THEME': app.config.get('YODA_THEME')
}

try:
# If file doesn't exist, create and write the default configuration
if not path.exists(config_file_path):
with open(config_file_path, 'w') as file:
json.dump(default_config, file)
return default_config

# If the file exists, read and return the configuration
with open(config_file_path, 'r') as file:
settings = json.load(file)
banner_set = settings.get('banner', default_config['banner']) # Get banner settings or use default
return {
if not path.exists(settings_file_path):
with open(settings_file_path, 'w') as file:
json.dump(default_settings, file)
return default_settings

# If the file exists, read and return the setting
with open(settings_file_path, 'r') as file:
loaded_settings = json.load(file)
merged_settings = {
'banner': {
'banner_enabled': banner_set.get('banner_enabled', default_config['banner']['banner_enabled']),
'banner_importance': banner_set.get('banner_importance', default_config['banner']['banner_importance']),
'banner_message': banner_set.get('banner_message', default_config['banner']['banner_message'])
**default_settings['banner'],
**loaded_settings.get('banner', {})
},
'YODA_THEME': settings.get('YODA_THEME', default_config['YODA_THEME'])
'YODA_THEME': loaded_settings.get('YODA_THEME', default_settings['YODA_THEME'])
}
return merged_settings
except Exception:
print("An unexpected error occurred")
return default_config

log_error("Unexpected error occurred.", True)
return default_settings

app.config['APP_SHARED_FOLDER'] = '/tmp'
app.config.update(load_admin_config())

# Load admin settings
app.config.update(load_admin_setting())
# Load theme templates
set_theme_loader(app)

Expand Down
4 changes: 4 additions & 0 deletions config/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
4 changes: 2 additions & 2 deletions general/templates/general/banner.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div name="banner head" class="non-production sticky-top text-center fw-bold lh-1 p-1 {{ 'text-bg-danger' if config.banner.banner_importance else 'text-bg-primary' }}" role="alert">
{{ config.get('banner').banner_message }}
<div name="banner head" class="non-production sticky-top text-center fw-bold lh-1 p-1 {{ 'text-bg-danger' if config.get('banner').get('importance') else 'text-bg-primary' }}" role="alert">
{{ config.get('banner').get('message') }}
</div>
2 changes: 1 addition & 1 deletion general/templates/general/base-bare.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

<body class="d-flex flex-column min-vh-100">
{% if config.get('YODA_ENVIRONMENT') != "production" %}{% include 'environment.html' %}{% endif %}
{% if config.get('banner').banner_enabled %}{% include 'banner.html' %}{% endif %}
{% if config.get('banner').get('enabled') %}{% include 'banner.html' %}{% endif %}
{% block container %}
<div class="page p-3">
<div class="container">
Expand Down
2 changes: 1 addition & 1 deletion general/templates/general/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

<body class="d-flex flex-column min-vh-100">
{% if config.get('YODA_ENVIRONMENT') != "production" %}{% include 'environment.html' %}{% endif %}
{% if config.get('banner').banner_enabled %}{% include 'banner.html' %}{% endif %}
{% if config.get('banner').get('enabled') %}{% include 'banner.html' %}{% endif %}
<header class="py-3">
<div class="container">
<div class="row">
Expand Down
8 changes: 4 additions & 4 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ def get_validated_static_path(
return static_dir, asset_name


def length_check(banner_message: str) -> Tuple[str, bool]:
def length_check(message: str) -> Tuple[str, bool]:
"""
Check banner message length.
:param banner_message: Message to validate.
:param message: Message to validate.
:returns: Error message and validity status.
"""
max_length = 256
if not banner_message:
if not message:
return "Empty banner message found.", False
elif len(banner_message) > max_length:
elif len(message) > max_length:
return "Banner message too long.", False
return None, True

Expand Down

0 comments on commit f060111

Please sign in to comment.