mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-05-08 14:34:27 +02:00
Honor seeded Buildroot setup config
This commit is contained in:
@@ -776,6 +776,7 @@ security = repeater.setdefault("security", {})
|
||||
radio = data.setdefault("radio", {})
|
||||
|
||||
repeater["node_name"] = node_name
|
||||
repeater["setup_complete"] = True
|
||||
security["admin_password"] = admin_password
|
||||
security["jwt_secret"] = jwt_secret
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ repeater:
|
||||
# Node name for logging and identification
|
||||
node_name: "mesh-repeater-01"
|
||||
|
||||
# Set true once initial provisioning is complete so the web UI can skip /setup
|
||||
setup_complete: false
|
||||
|
||||
# TX mode: forward | monitor | no_tx (default: forward)
|
||||
# forward = repeat on; monitor = no repeat but companions/tenants can send; no_tx = all TX off
|
||||
# mode: forward
|
||||
|
||||
@@ -7,6 +7,7 @@ from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
import cherrypy
|
||||
import yaml
|
||||
from pymc_core.protocol import CryptoUtils
|
||||
|
||||
from repeater import __version__
|
||||
@@ -196,6 +197,14 @@ class APIEndpoints:
|
||||
def _is_cors_enabled(self):
|
||||
return self.config.get("web", {}).get("cors_enabled", False)
|
||||
|
||||
def _load_live_config(self):
|
||||
"""Prefer the on-disk config when checking first-boot/setup state."""
|
||||
try:
|
||||
with open(self._config_path, "r", encoding="utf-8") as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
except Exception:
|
||||
return self.config or {}
|
||||
|
||||
def _set_cors_headers(self):
|
||||
if self._is_cors_enabled():
|
||||
cherrypy.response.headers["Access-Control-Allow-Origin"] = "*"
|
||||
@@ -302,24 +311,27 @@ class APIEndpoints:
|
||||
def needs_setup(self):
|
||||
"""Check if the repeater needs initial setup configuration"""
|
||||
try:
|
||||
config = self.config
|
||||
config = self._load_live_config()
|
||||
|
||||
# Check for default values that indicate first-time setup
|
||||
node_name = config.get("repeater", {}).get("node_name", "")
|
||||
repeater_config = config.get("repeater", {})
|
||||
node_name = repeater_config.get("node_name", "")
|
||||
has_default_name = node_name in ["mesh-repeater-01", ""]
|
||||
|
||||
admin_password = (
|
||||
config.get("repeater", {}).get("security", {}).get("admin_password", "")
|
||||
)
|
||||
admin_password = repeater_config.get("security", {}).get("admin_password", "")
|
||||
has_default_password = admin_password in ["admin123", ""]
|
||||
setup_complete = bool(repeater_config.get("setup_complete", False))
|
||||
|
||||
needs_setup = has_default_name or has_default_password
|
||||
needs_setup = (has_default_name or has_default_password) and not (
|
||||
setup_complete and not has_default_name and not has_default_password
|
||||
)
|
||||
|
||||
return {
|
||||
"needs_setup": needs_setup,
|
||||
"reasons": {
|
||||
"default_name": has_default_name,
|
||||
"default_password": has_default_password,
|
||||
"setup_complete": setup_complete,
|
||||
},
|
||||
}
|
||||
except Exception as e:
|
||||
@@ -478,6 +490,7 @@ class APIEndpoints:
|
||||
if "repeater" not in config_yaml:
|
||||
config_yaml["repeater"] = {}
|
||||
config_yaml["repeater"]["node_name"] = node_name
|
||||
config_yaml["repeater"]["setup_complete"] = True
|
||||
|
||||
if "security" not in config_yaml["repeater"]:
|
||||
config_yaml["repeater"]["security"] = {}
|
||||
@@ -561,6 +574,10 @@ class APIEndpoints:
|
||||
with open(self._config_path, "w") as f:
|
||||
yaml.dump(config_yaml, f, default_flow_style=False, sort_keys=False)
|
||||
|
||||
# Keep in-memory config aligned until the restart lands.
|
||||
self.config.clear()
|
||||
self.config.update(config_yaml)
|
||||
|
||||
logger.info(
|
||||
f"Setup wizard completed: node_name={node_name}, hardware={hardware_key}, freq={freq_mhz}MHz"
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ Authentication endpoints for login and token management
|
||||
"""
|
||||
import cherrypy
|
||||
import logging
|
||||
import yaml
|
||||
from .auth.middleware import require_auth
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -152,6 +153,16 @@ class AuthEndpoints:
|
||||
self.jwt_handler = jwt_handler
|
||||
self.token_manager = token_manager
|
||||
self.config_manager = config_manager
|
||||
|
||||
def _load_live_config(self):
|
||||
config_path = getattr(self.config_manager, "config_path", None)
|
||||
if not config_path:
|
||||
return self.config
|
||||
try:
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
except Exception:
|
||||
return self.config
|
||||
|
||||
@cherrypy.expose
|
||||
def login(self, **kwargs):
|
||||
@@ -185,7 +196,8 @@ class AuthEndpoints:
|
||||
|
||||
# Validate credentials against config
|
||||
# Check if username is 'admin' and password matches config
|
||||
repeater_config = self.config.get('repeater', {})
|
||||
live_config = self._load_live_config()
|
||||
repeater_config = live_config.get('repeater', {})
|
||||
security_config = repeater_config.get('security', {})
|
||||
config_password = security_config.get('admin_password', '')
|
||||
|
||||
@@ -460,4 +472,4 @@ class AuthEndpoints:
|
||||
return json.dumps({
|
||||
'success': False,
|
||||
'error': 'Failed to change password'
|
||||
}).encode('utf-8')
|
||||
}).encode('utf-8')
|
||||
|
||||
Reference in New Issue
Block a user