refactor(config): Konfigurationsdateien nach config/ verschoben (closes #3)

- config.yaml, nina.yaml, scheduler.yaml aus Root → config/ verschoben
- conf/ (env.example, nina.yaml, scheduler.yaml, config.yaml) gelöscht
- meshbot/config.py, nina.py, scheduler.py: Pfade auf config/ aktualisiert
- .gitignore: config/.env und .forgejo_token ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ppfeiffer 2026-02-20 21:37:11 +01:00
parent 3bcb44afe3
commit 4b9dd45f05
13 changed files with 61 additions and 73 deletions

View file

@ -6,48 +6,77 @@
- Changelog format: `## [x.y.z] - YYYY-MM-DD` with `### Added/Changed/Removed` sections - Changelog format: `## [x.y.z] - YYYY-MM-DD` with `### Added/Changed/Removed` sections
## Project Structure ## Project Structure
- Config: `config.yaml` (live-reloaded via file watcher in `meshbot/config.py`) - Config: `config/config.yaml` (live-reloaded via file watcher in `meshbot/config.py`)
- Bot: `meshbot/bot.py` - Meshtastic TCP, commands use `config.get("bot.command_prefix")` - Bot: `meshbot/bot.py` - Meshtastic TCP, commands use `config.get("bot.command_prefix")`
- Auth: `meshbot/auth.py` - Session-Middleware, Passwort-Hashing, Auth-Routen, Admin-API, Email - Auth: `meshbot/auth.py` - Session-Middleware, Passwort-Hashing, Auth-Routen, Admin-API, Email
- Web: `meshbot/webserver.py` - aiohttp + WebSocket + Auth-Integration - Web: `meshbot/webserver.py` - aiohttp + WebSocket + Auth-Integration
- DB: `meshbot/database.py` - SQLite via aiosqlite (nodes, messages, commands, users, tokens, email_logs) - DB: `meshbot/database.py` - SQLite via aiosqlite (nodes, messages, commands, users, tokens, email_logs)
- Scheduler: `meshbot/scheduler.py` - Cron-based job scheduler - Scheduler: `meshbot/scheduler.py` - Cron-based job scheduler
- Frontend: `static/` - Bootstrap 5.3 dark/light theme, AdminLTE-style layout - NINA: `meshbot/nina.py` - NINA-Warnmeldungen (Polling + WebSocket-Broadcast)
- Frontend: `static/` - Tabler CSS + Bootstrap 5.3 dark/light theme
- Shared JS: `static/js/app.js` - `initPage()`, Sidebar-Injection, Navbar, Theme, Auth-Check
- Entry: `main.py` - Entry: `main.py`
## Pages & Routes ## Pages & Routes
- `/` - Dashboard (`static/index.html`, `static/js/dashboard.js`) - `/` - Dashboard (`static/index.html`, `static/js/dashboard.js`) - Public
- `/scheduler` - Scheduler (`static/scheduler.html`, `static/js/scheduler.js`) - Admin only - `/scheduler` - Scheduler (`static/scheduler.html`, `static/js/scheduler.js`) - Admin only
- `/nina` - NINA-Warnungen (`static/nina.html`, `static/js/nina.js`) - Admin only (Sidebar)
- `/map` - Leaflet map (`static/map.html`, `static/js/map.js`) - Public - `/map` - Leaflet map (`static/map.html`, `static/js/map.js`) - Public
- `/packets` - Paket-Log (`static/packets.html`, `static/js/packets.js`) - Public
- `/messages` - Nachrichtenverlauf (`static/messages.html`, `static/js/messages.js`) - Public
- `/settings` - Node config (`static/settings.html`, `static/js/settings.js`) - Admin only - `/settings` - Node config (`static/settings.html`, `static/js/settings.js`) - Admin only
- `/login` + `/register` - Auth (`static/login.html`, `static/js/login.js`) - `/login` + `/register` - Auth (`static/login.html`, `static/js/login.js`)
- `/admin` - User management (`static/admin.html`, `static/js/admin.js`) - Admin only - `/admin` - User management (`static/admin.html`, `static/js/admin.js`) - Admin only
- `/ws` - WebSocket endpoint - `/ws` - WebSocket endpoint
- Auth: `/auth/login`, `/auth/register`, `/auth/logout`, `/auth/verify`, `/auth/set-password`, `/auth/forgot-password`, `/auth/reset-password`
- API: `/api/nodes`, `/api/messages`, `/api/stats`, `/api/send` (user), `/api/node/config` (admin), `/api/scheduler/jobs` (admin) ### Auth-Routen
- API Auth: `/api/auth/me`, `/api/admin/users`, `/api/admin/users/{id}/role`, `/api/admin/users/{id}/verify` `/auth/login`, `/auth/register`, `/auth/logout`, `/auth/verify`, `/auth/set-password`, `/auth/forgot-password`, `/auth/reset-password`
### API-Routen
| Endpunkt | Methode | Auth |
|----------|---------|------|
| `/api/nodes` | GET | Public |
| `/api/messages` | GET | Public |
| `/api/packets` | GET | Public |
| `/api/stats` | GET | Public |
| `/api/links` | GET | Public |
| `/api/send` | POST | User |
| `/api/node/config` | GET | Admin |
| `/api/scheduler/jobs` | GET | Public |
| `/api/scheduler/jobs` | POST | Admin |
| `/api/scheduler/jobs/{name}` | PUT/DELETE | Admin |
| `/api/nina/config` | GET/PUT | Admin |
| `/api/nina/alerts` | GET | Admin |
| `/api/auth/me` | GET | - |
| `/api/admin/users` | GET | Admin |
| `/api/admin/users/{id}/role` | PUT | Admin |
| `/api/admin/users/{id}/verify` | PUT | Admin |
## Rollen & Zugriffsrechte ## Rollen & Zugriffsrechte
| Bereich | Public | User | Admin | | Bereich | Public | User | Admin |
|---------|--------|------|-------| |---------|--------|------|-------|
| `/map`, `/` (Nodes, Stats) | Ja | Ja | Ja | | `/`, `/map`, `/packets`, `/messages` | Ja | Ja | Ja |
| Dashboard Nachrichten + Senden | Nein | Ja | Ja | | Dashboard Nachrichten senden (`/api/send`) | Nein | Ja | Ja |
| `/scheduler`, `/settings` | Nein | Nein | Ja | | `/scheduler`, `/settings`, `/nina` | Nein | Nein | Ja |
| `/admin` | Nein | Nein | Ja | | `/admin` | Nein | Nein | Ja |
## Frontend Layout Pattern ## Frontend Layout Pattern
- All pages use consistent AdminLTE-style: top-navbar (46px), sidebar (200px), content-wrapper - Alle Seiten: Tabler CSS + Bootstrap 5.3, AdminLTE-Style (top-navbar 46px, sidebar 200px, content-wrapper)
- Sidebar nav with active state, 5 entries: Dashboard, Scheduler, Karte, Einstellungen, Benutzer - Sidebar wird per `app.js` (`_injectSidebar()`) dynamisch generiert 8 Einträge:
- Admin-only sidebar entries use class `sidebar-admin` (hidden via JS if not admin) Dashboard, Scheduler (admin), NINA (admin), Karte, Pakete, Nachrichten (user), Einstellungen (admin), Benutzer (admin)
- Navbar: User-Name + Logout button (logged in) or Login button (not logged in) - Zugriffsklassen: `.sidebar-admin` (nur Admin), `.sidebar-user` (jeder eingeloggte User)
- Each JS file has: auth check (`/api/auth/me`), updateNavbar(), updateSidebar(), theme toggle, sidebar toggle - Sichtbarkeit wird in `_updateSidebar(user)` per `style.display` gesteuert
- Jede Seite ruft `initPage({ onAuth })` aus `app.js` auf übernimmt Auth-Check, Navbar, Sidebar, Theme
- Shared styles in `static/css/style.css` - Shared styles in `static/css/style.css`
## Key Details ## Key Details
- Meshtastic host configured in config.yaml, not env vars - Meshtastic host configured in config.yaml, not env vars
- Bot start: `/home/peter/meshdd-bot/venv/bin/python main.py` - Bot start: `/home/peter/meshdd-bot/venv/bin/python main.py`
- Web port: 8081 (konfigurierbar via `web.port`)
- Forgejo remote with token in URL - Forgejo remote with token in URL
- Current version: 0.5.0 - Current version: 0.08.15
- Protobuf objects converted via `google.protobuf.json_format.MessageToDict()` - Protobuf objects converted via `google.protobuf.json_format.MessageToDict()`
- Auth: bcrypt (12 rounds), aiohttp-session EncryptedCookieStorage, aiosmtplib for emails - Auth: bcrypt (12 rounds), aiohttp-session EncryptedCookieStorage, aiosmtplib for emails
- SMTP fallback: if no smtp.host configured, verification links logged to console - SMTP fallback: if no smtp.host configured, verification links logged to console
- `web.online_threshold` (Default: 900 s): Online-Schwellwert für Nodes, zentral konfigurierbar
- `links:` in config.yaml: Liste mit `url` + `label`, wird über `/api/links` und Dashboard-Links-Card angezeigt

2
.gitignore vendored
View file

@ -11,6 +11,7 @@ venv/
.venv/ .venv/
env/ env/
.env .env
config/.env
*.db *.db
*.sqlite *.sqlite
*.sqlite3 *.sqlite3
@ -21,3 +22,4 @@ env/
*~ *~
.DS_Store .DS_Store
.claude/settings.local.json .claude/settings.local.json
.forgejo_token

View file

@ -1,5 +1,15 @@
# Changelog # Changelog
## [0.08.16] - 2026-02-20
### Changed
- **Konfigurationsdateien in `config/` verschoben** (closes #3):
`config.yaml`, `nina.yaml`, `scheduler.yaml` und `env.example` liegen jetzt im
Unterverzeichnis `config/` statt im Root-Verzeichnis bzw. `conf/`.
- **`conf/` entfernt**: Das alte Verzeichnis `conf/` wurde vollständig gelöscht.
- **Python-Pfade aktualisiert**: `meshbot/config.py`, `meshbot/nina.py` und
`meshbot/scheduler.py` referenzieren jetzt das neue `config/`-Verzeichnis.
## [0.08.15] - 2026-02-20 ## [0.08.15] - 2026-02-20
### Added ### Added

View file

@ -1,19 +0,0 @@
version: "0.7.0"
bot:
name: "MeshDD-Bot"
command_prefix: "?"
meshtastic:
host: "192.168.11.4"
port: 4403
web:
host: "0.0.0.0"
port: 8081
database:
path: "data/meshdd.db"
auth:
session_max_age: 86400

View file

@ -1,15 +0,0 @@
jobs:
- name: Wetterbericht
enabled: true
cron: 0 6,12,18 * * *
command: /weather
channel: 0
description: Taeglicher Wetterbericht
type: command
- name: Mesh-Status
enabled: true
cron: 30 18 * * *
command: /mesh
channel: 0
description: Mesh-Netzwerk Uebersicht
type: command

View file

@ -1,4 +1,4 @@
version: "0.08.15" version: "0.08.16"
bot: bot:
name: "MeshDD-Bot" name: "MeshDD-Bot"

View file

@ -6,8 +6,8 @@ import yaml
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
CONFIG_PATH = os.environ.get("CONFIG_PATH", os.path.join(os.path.dirname(os.path.dirname(__file__)), "config.yaml")) CONFIG_PATH = os.environ.get("CONFIG_PATH", os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "config.yaml"))
ENV_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env") ENV_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", ".env")
_config = {} _config = {}
_mtime = 0.0 _mtime = 0.0

View file

@ -10,7 +10,7 @@ import yaml
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
NINA_API_BASE = "https://warnung.bund.de/api31" NINA_API_BASE = "https://warnung.bund.de/api31"
NINA_CONFIG_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "nina.yaml") NINA_CONFIG_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "nina.yaml")
SEVERITY_ORDER = { SEVERITY_ORDER = {
"Unknown": -1, "Unknown": -1,

View file

@ -9,7 +9,7 @@ from meshbot import config
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
SCHEDULER_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "scheduler.yaml") SCHEDULER_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "scheduler.yaml")
class Scheduler: class Scheduler:

View file

@ -1,19 +0,0 @@
enabled: false
send_to_mesh: false # true = ins Mesh senden | false = nur Weboberfläche (Monitor-Modus)
poll_interval: 300
resend_interval: 3600 # Aktive Warnungen alle N Sekunden erneut ins Mesh senden
channel: 0
min_severity: Severe
ags_codes:
- "146120000000" # Stadt Dresden
- "146270000000" # Landkreis Meißen
- "146280000000" # LK Sächsische Schweiz-Osterzgebirge
- "146250000000" # Landkreis Bautzen
- "146260000000" # Landkreis Görlitz
sources:
katwarn: true
biwapp: true
mowas: true
dwd: true
lhp: true
police: false