Services (daynivo-kiosk-*, daynivo-network-guard, daynivo-boot-import), programs in /usr/lib/daynivo-kiosk, folders /etc, /var/lib, /var/log and /var/cache daynivo-kiosk*, the system user daynivo, DAYNIVO_* settings, the plymouth theme, network profiles daynivo-eth0/wlan0, the image stage and its first user daynivoadmin. install.sh moves a kiosk installed up to 1.2.x over once: old services stopped and removed, folders moved (configuration, password, browser profile, logs) with symlinks under the old names, the voxip user renamed with the same uid, network profiles renamed unless a change awaits confirmation, and old leftovers removed. Tested by upgrading a configured 1.2.0 installation in a container, and running the install a second time. Old names keep working where people type or place them: voxip-config.json, voxip-authorized_keys, voxip-network-reset, voxip-kiosk-ctl, and VOXIP_DEFAULT_URL / VOXIP_DEVICE_NAME for image builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
74 lines
2.0 KiB
Python
74 lines
2.0 KiB
Python
"""Daynivo Kiosk Manager — Flask application factory."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import secrets
|
|
from dataclasses import dataclass
|
|
from datetime import timedelta
|
|
from typing import Any
|
|
|
|
from flask import Flask
|
|
|
|
from ..cdp import CDP
|
|
from ..config import load_config
|
|
from ..helper_client import HelperClient
|
|
from ..paths import Paths, load_paths, read_version
|
|
from .auth import CredentialStore, LoginThrottle
|
|
|
|
|
|
@dataclass
|
|
class Services:
|
|
paths: Paths
|
|
credentials: CredentialStore
|
|
throttle: LoginThrottle
|
|
helper: Any
|
|
cdp: Any
|
|
version: str
|
|
|
|
|
|
def _secret_key(paths: Paths) -> bytes:
|
|
path = paths.secret_key_file
|
|
try:
|
|
key = path.read_bytes()
|
|
if len(key) >= 32:
|
|
return key
|
|
except FileNotFoundError:
|
|
pass
|
|
key = secrets.token_bytes(64)
|
|
fd = os.open(str(path), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
|
|
with os.fdopen(fd, "wb") as fh:
|
|
fh.write(key)
|
|
return key
|
|
|
|
|
|
def create_app(paths: Paths | None = None, *, helper: Any = None, cdp: Any = None) -> Flask:
|
|
paths = paths or load_paths()
|
|
config = load_config(paths.config_file)
|
|
app = Flask(__name__)
|
|
app.secret_key = _secret_key(paths)
|
|
app.config.update(
|
|
SESSION_COOKIE_NAME="daynivo_session",
|
|
SESSION_COOKIE_HTTPONLY=True,
|
|
SESSION_COOKIE_SAMESITE="Strict",
|
|
SESSION_COOKIE_SECURE=config["admin_https"],
|
|
PERMANENT_SESSION_LIFETIME=timedelta(hours=12),
|
|
MAX_CONTENT_LENGTH=64 * 1024,
|
|
TEMPLATES_AUTO_RELOAD=False,
|
|
)
|
|
credentials = CredentialStore(paths.admin_file, paths.setup_code_file)
|
|
credentials.ensure_setup_code()
|
|
app.extensions["daynivo"] = Services(
|
|
paths=paths,
|
|
credentials=credentials,
|
|
throttle=LoginThrottle(),
|
|
helper=helper or HelperClient(paths.helper),
|
|
cdp=cdp or CDP(timeout=5),
|
|
version=read_version(paths),
|
|
)
|
|
|
|
from .views import bp
|
|
|
|
app.register_blueprint(bp)
|
|
return app
|