-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Overview
Implement a self-contained config_module/ directory that adds a gear icon (⚙) to the dashboard for editing station and display settings via the web. The module is designed to be fully removable: deleting config_module/ disables the feature completely with no residual errors.
Design Principles
- Secrets only in
.env: callsign, grid, and display settings move out of.envand intosettings.jsonmanaged by this module - Modular: all feature code in
config_module/; existing files minimally touched - Removable:
rm -rf config_module/is sufficient to disable the feature entirely ("ultimate security")
Settings Managed
- Admin username, receiver callsign, receiver grid square
- Default last interval, highlight threshold, contest bands
- Map initial view (lat/lon) and zoom level
Security Layers
- Filesystem lockfile (
config.lock, SSH-only): hard-disables all web config changes regardless of auth state —touch config.lockto lock,rm config.lockto unlock - Flask-Login session auth: single admin account, hashed password in
.env - CSRF protection on all POST forms (manual token, no extra dependency)
- HTTPS required in production (
SESSION_COOKIE_SECURE)
What Lives Where
| Data | Location |
|---|---|
| MongoDB credentials | .env |
| Flask secret key | .env |
| Admin password hash | .env |
| Admin username | settings.json |
| Receiver callsign | settings.json |
| Receiver grid square | settings.json |
| Display defaults, bands, map view | settings.json |
| Band colors, freq ranges, zone maps | config.js (dev edit only) |
Module Structure
config_module/
├── __init__.py ← register(app) — called optionally via try/except in app.py
├── routes.py ← Blueprint: GET/POST /settings, GET/POST /login, GET /logout
├── auth.py ← Flask-Login setup, AdminUser model (no DB)
├── storage.py ← settings.json R/W, config.lock check
├── templates/config_module/
│ ├── gear_icon.html ← included by main templates via {% include ... ignore missing %}
│ └── login.html
└── static/
├── config_module.js
└── config_module.css
Minimal Changes to Existing Files
app.py: onetry/except ImportErrorblock to optionally load module- Each template: one line —
{% include 'config_module/gear_icon.html' ignore missing %} requirements.txt: addflask-login>=0.6.0.env/.env.example: removeRECEIVER_CALLSIGN/RECEIVER_GRIDSQUARE; addFLASK_SECRET_KEY,ADMIN_PASSWORD_HASH.gitignore: addconfig.lock,settings.json- No changes to existing API or view routes
Acceptance Criteria
-
rm -rf config_module/leaves app fully functional with default values, no errors -
config.lockpresent →POST /settingsreturns 423; modal is read-only with lock message - Unauthenticated gear click → redirect to
/login - Authenticated → editable modal; save writes
settings.json; updates live without restart -
RECEIVER_CALLSIGNandRECEIVER_GRIDSQUAREremoved from.env -
settings.jsonandconfig.lockin.gitignore -
set_password.pyhelper script included for generating password hash - Only one new line added to each existing template (
ignore missinginclude) - No changes to existing API or view routes
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
Status
Ready