From b0840d240e1bffda433ab7ebf94c5dad595ff2f5 Mon Sep 17 00:00:00 2001 From: Jos Rothman Date: Thu, 5 Nov 2026 23:25:42 +0100 Subject: [PATCH] Daynivo names for the files on the SD card and the command line tool - daynivo-config.json, daynivo-authorized_keys and daynivo-network-reset on the boot partition; errors go to daynivo-config.error.txt. - daynivo-kiosk-ctl, with voxip-kiosk-ctl as a symlink to it. - The voxip-* names keep working, so existing SD cards and instructions stay valid; when both config files are present the Daynivo one is applied last. - Internal names (services, /etc/voxip-kiosk, user voxip) are unchanged. Co-Authored-By: Claude Opus 5.5 --- README.md | 34 ++++++------- bin/{voxip-kiosk-ctl => daynivo-kiosk-ctl} | 0 docs/ARCHITECTURE.md | 10 ++-- docs/HARDWARE-TEST.md | 16 +++--- image/boot-README.txt | 10 ++-- ...ample.json => daynivo-config.example.json} | 0 image/stage-voxip/00-voxip/00-run.sh | 2 +- install.sh | 6 ++- src/voxip_kiosk/ctl.py | 6 +-- src/voxip_kiosk/helper.py | 49 +++++++++++-------- src/voxip_kiosk/web/templates/login.html | 2 +- src/voxip_kiosk/web/templates/network.html | 2 +- src/voxip_kiosk/web/templates/setup.html | 2 +- systemd/voxip-boot-import.service | 4 ++ tests/test_helper.py | 37 ++++++++++---- uninstall.sh | 2 +- www/setup.html | 2 +- 17 files changed, 108 insertions(+), 76 deletions(-) rename bin/{voxip-kiosk-ctl => daynivo-kiosk-ctl} (100%) rename image/{voxip-config.example.json => daynivo-config.example.json} (100%) diff --git a/README.md b/README.md index 2393672..179622c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ hardware staat in [`docs/HARDWARE-TEST.md`](docs/HARDWARE-TEST.md). 3. Optioneel, in Raspberry Pi Imager → *OS-aanpassingen*: wifi, gebruiker met wachtwoord en/of SSH-sleutel, tijdzone. Zonder aanpassingen heeft de image **geen** bruikbaar wachtwoord en staat SSH uit. -4. Optioneel: zet een `voxip-config.json` op de bootpartitie (zie +4. Optioneel: zet een `daynivo-config.json` op de bootpartitie (zie [Uitrol bij meerdere klanten](#uitrol-bij-meerdere-klanten)). 5. Start de Pi. Bij de eerste boot wordt de rootpartitie automatisch vergroot tot de hele SD-kaart. Daarna verschijnt een setupscherm met de @@ -191,14 +191,14 @@ browser blijft draaien. *Chromium herstarten* herstart alleen de browser. ### Commandoregel (via SSH) ```bash -sudo voxip-kiosk-ctl status # overzicht -sudo voxip-kiosk-ctl setup-code # setupcode voor de eerste configuratie -sudo voxip-kiosk-ctl reset-password # wachtwoord vergeten: nieuwe setupcode -sudo voxip-kiosk-ctl set-url https://… # URL wijzigen -sudo voxip-kiosk-ctl reload # pagina herladen -sudo voxip-kiosk-ctl restart-browser # Chromium herstarten -sudo voxip-kiosk-ctl health # healthcheck-rapport -sudo voxip-kiosk-ctl maintenance on|off # healthcheck tijdelijk niets laten herstellen +sudo daynivo-kiosk-ctl status # overzicht +sudo daynivo-kiosk-ctl setup-code # setupcode voor de eerste configuratie +sudo daynivo-kiosk-ctl reset-password # wachtwoord vergeten: nieuwe setupcode +sudo daynivo-kiosk-ctl set-url https://… # URL wijzigen +sudo daynivo-kiosk-ctl reload # pagina herladen +sudo daynivo-kiosk-ctl restart-browser # Chromium herstarten +sudo daynivo-kiosk-ctl health # healthcheck-rapport +sudo daynivo-kiosk-ctl maintenance on|off # healthcheck tijdelijk niets laten herstellen journalctl -u voxip-kiosk-browser -u voxip-kiosk-agent -f ``` @@ -221,7 +221,7 @@ journalctl -u voxip-kiosk-browser -u voxip-kiosk-agent -f | `admin_allow_public` | `false` | ook toegang vanaf publieke IP-adressen (afgeraden) | | `auto_update` | `false` | elke nacht een nieuwe release installeren | -Wijzigingen via de webinterface of `voxip-kiosk-ctl` worden atomair +Wijzigingen via de webinterface of `daynivo-kiosk-ctl` worden atomair opgeslagen, met een `.bak` van de vorige versie. Een URL-wijziging gaat in zonder dat Chromium herstart. Scherminstellingen gelden na een herstart van Chromium (een vinkje in de webinterface doet dat direct). @@ -231,15 +231,15 @@ Chromium (een vinkje in de webinterface doet dat direct). Eén image voor alle klanten. Per apparaat zet je na het flashen op de bootpartitie (`bootfs`, zichtbaar op Windows en macOS): -- **`voxip-config.json`**: instellingen voor deze kiosk, plus optioneel +- **`daynivo-config.json`**: instellingen voor deze kiosk, plus optioneel `hostname` en `wifi_country`. Een voorbeeld staat als - `voxip-config.example.json` op de bootpartitie. -- **`voxip-authorized_keys`**: openbare SSH-sleutels. SSH gaat dan aan, alleen + `daynivo-config.example.json` op de bootpartitie. +- **`daynivo-authorized_keys`**: openbare SSH-sleutels. SSH gaat dan aan, alleen met sleutel-login. - Wifi en een eigen gebruiker stel je in via Raspberry Pi Imager. De bestanden worden bij het opstarten verwerkt en hernoemd naar -`*.applied`, of naar `*.rejected` met de reden in `voxip-config.error.txt`. +`*.applied`, of naar `*.rejected` met de reden in `daynivo-config.error.txt`. ### Daynivo-schermen @@ -270,8 +270,8 @@ make dev # http://127.0.0.1:8080 met tijdelijke mappen in .dev/ | Symptoom | Oplossing | |---|---| -| Zwart scherm na opstarten | `sudo voxip-kiosk-ctl status`. Kijk in de journal van `voxip-kiosk-x`/`voxip-kiosk-browser`. Staat de monitor aan vóór de Pi? | -| Beheerinterface onbereikbaar na netwerkwijziging | Wacht 3 minuten (automatische rollback) of zet `voxip-network-reset` op de bootpartitie en herstart. | -| Wachtwoord vergeten | `sudo voxip-kiosk-ctl reset-password` via SSH, of verwijder `/etc/voxip-kiosk/admin.json` met de SD-kaart in een Linux-pc. | +| Zwart scherm na opstarten | `sudo daynivo-kiosk-ctl status`. Kijk in de journal van `voxip-kiosk-x`/`voxip-kiosk-browser`. Staat de monitor aan vóór de Pi? | +| Beheerinterface onbereikbaar na netwerkwijziging | Wacht 3 minuten (automatische rollback) of zet `daynivo-network-reset` op de bootpartitie en herstart. | +| Wachtwoord vergeten | `sudo daynivo-kiosk-ctl reset-password` via SSH, of verwijder `/etc/voxip-kiosk/admin.json` met de SD-kaart in een Linux-pc. | | `kiosk.local` werkt niet | Gebruik het IP-adres (staat op het setupscherm en in je router). Windows heeft soms Bonjour/mDNS nodig. Geef iedere kiosk een unieke hostname. | | Onderspanning in het dashboard | Gebruik de officiële 5,1 V/2,5 A-voeding. Onderspanning veroorzaakt crashes en SD-kaartcorruptie. | diff --git a/bin/voxip-kiosk-ctl b/bin/daynivo-kiosk-ctl similarity index 100% rename from bin/voxip-kiosk-ctl rename to bin/daynivo-kiosk-ctl diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 989da85..b2f30b6 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -12,7 +12,7 @@ samenwerken en waarom bepaalde keuzes zijn gemaakt. - Lokale webbeheerinterface (*Daynivo Kiosk Manager*) op poort 8080. - Geen klantspecifieke code: alles wat per klant verschilt staat in `/etc/voxip-kiosk/config.json` en kan bij uitrol via de bootpartitie - worden meegegeven (`voxip-config.json`). + worden meegegeven (`daynivo-config.json`). ## Overzicht @@ -104,7 +104,7 @@ Zolang er geen beheerderswachtwoord is: adressen van de beheerinterface; 3. kan een wachtwoord alleen ingesteld worden met die code. -Wie fysiek bij het scherm staat (of via SSH `voxip-kiosk-ctl setup-code` +Wie fysiek bij het scherm staat (of via SSH `daynivo-kiosk-ctl setup-code` draait) kan het apparaat dus claimen, iemand anders op het netwerk niet. ### Netwerkwijzigingen met rollback @@ -119,7 +119,7 @@ draait) kan het apparaat dus claimen, iemand anders op het netwerk niet. 5. Valt de stroom uit tijdens die periode, dan zet `voxip-network-guard.service` de snapshot terug bij het opstarten, nog vóór NetworkManager start. -6. Noodherstel: een leeg bestand `voxip-network-reset` op de bootpartitie +6. Noodherstel: een leeg bestand `daynivo-network-reset` op de bootpartitie verwijdert bij de volgende boot alle Daynivo-netwerkprofielen (terug naar DHCP). @@ -165,7 +165,7 @@ draait) kan het apparaat dus claimen, iemand anders op het netwerk niet. (toegestaan: privé, link-local, loopback, CGNAT/VPN 100.64.0.0/10). - Optioneel HTTPS (zelfondertekend certificaat, automatisch aangemaakt). - SSH staat in de image standaard uit en wordt alleen ingeschakeld met - credentials uit Raspberry Pi Imager of `voxip-authorized_keys` op de + credentials uit Raspberry Pi Imager of `daynivo-authorized_keys` op de bootpartitie (dan alleen sleutel-login). - Strikte security-headers en CSP (`default-src 'self'`). @@ -192,7 +192,7 @@ daynivo-kiosk-os/ │ ├── netinfo.py netwerkstatus (zonder rechten) │ ├── sysinfo.py CPU, temperatuur, geheugen, opslag, IP │ ├── services.py systemd- en journal-status -│ ├── ctl.py CLI voor SSH-beheer (voxip-kiosk-ctl) +│ ├── ctl.py CLI voor SSH-beheer (daynivo-kiosk-ctl) │ └── web/ Flask-app, templates, statische bestanden ├── www/ lokale kioskpagina's (start, offline, setup) ├── systemd/ unit-bestanden diff --git a/docs/HARDWARE-TEST.md b/docs/HARDWARE-TEST.md index ea66e84..4e8356c 100644 --- a/docs/HARDWARE-TEST.md +++ b/docs/HARDWARE-TEST.md @@ -47,14 +47,14 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype. (zie Logboek → Kiosk-agent). - [ ] Screenshot op de Kiosk-pagina toont wat er op het scherm staat. - [ ] Daynivo-URL met `?token=`: het token is overal gemaskeerd - (dashboard, `voxip-kiosk-ctl status`, `journalctl -u voxip-kiosk-agent`). + (dashboard, `daynivo-kiosk-ctl status`, `journalctl -u voxip-kiosk-agent`). ## 4. Herstel - [ ] `sudo pkill -9 chromium`: binnen 15 s is de pagina terug. Het logboek toont de herstart. - [ ] `sudo pkill -9 Xorg`: X en Chromium komen binnen 20 s terug. -- [ ] Crashloop: `sudo voxip-kiosk-ctl set-url https://localhost:1/` en +- [ ] Crashloop: `sudo daynivo-kiosk-ctl set-url https://localhost:1/` en daarna 7× `sudo pkill -9 chromium` binnen 2 minuten. De service komt in de fouttoestand (start-limit). De healthcheck logt een fout en start hem na ongeveer 5 minuten opnieuw. Er is geen eindeloze stille lus. @@ -82,7 +82,7 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype. - [ ] **Rollback na stroomuitval:** herhaal, trek binnen 3 minuten de stroom eruit. Na het opstarten zijn de oude instellingen actief. - [ ] **Noodreset:** stel iets onbereikbaars in en bevestig het. Zet - `voxip-network-reset` op de bootpartitie en start: weer DHCP. + `daynivo-network-reset` op de bootpartitie en start: weer DHCP. ## 6. Systeem @@ -104,7 +104,7 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype. zonder ingrijpen terug in de kiosk, zonder "herstellen"-melding. - [ ] 72 uur continu draaien met verversinterval 5 min. Daarna: geheugen < 80% (dashboard), geen onderspanning, `journalctl -p err -b` zonder - terugkerende fouten, `voxip-kiosk-ctl status` alles *Actief*. + terugkerende fouten, `daynivo-kiosk-ctl status` alles *Actief*. - [ ] SD-kaartschrijfacties: `cat /proc/diskstats | grep mmcblk0` op t=0 en na 1 uur stationair. Het verschil in geschreven sectoren (kolom 10) is minder dan 50 MB per uur. @@ -112,11 +112,11 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype. ## 8. Uitrol en updates -- [ ] Nieuwe kaart met `voxip-config.json` (url, device_name, hostname, - rotation) en `voxip-authorized_keys` op de bootpartitie: bij de eerste +- [ ] Nieuwe kaart met `daynivo-config.json` (url, device_name, hostname, + rotation) en `daynivo-authorized_keys` op de bootpartitie: bij de eerste boot toegepast, hernoemd naar `.applied`, SSH alleen met sleutel. -- [ ] Ongeldige `voxip-config.json` (http-URL): `.rejected` en - `voxip-config.error.txt` met de reden. De kiosk start met de standaardconfiguratie. +- [ ] Ongeldige `daynivo-config.json` (http-URL): `.rejected` en + `daynivo-config.error.txt` met de reden. De kiosk start met de standaardconfiguratie. - [ ] `sudo ./update.sh` vanuit een nieuwere checkout: versie in het dashboard verhoogd, configuratie en wachtwoord ongewijzigd, back-up in `/var/backups`. - [ ] Systeem → Software-updates → *Nu controleren* met een nieuwere release diff --git a/image/boot-README.txt b/image/boot-README.txt index 9414b1a..c7f7b7b 100644 --- a/image/boot-README.txt +++ b/image/boot-README.txt @@ -4,10 +4,10 @@ Daynivo Kiosk OS — bestanden op deze bootpartitie Je kunt een kiosk vooraf instellen door vóór de eerste start bestanden op deze partitie te zetten (bijvoorbeeld direct na het flashen). Ze worden bij het opstarten verwerkt en daarna hernoemd naar *.applied (of *.rejected bij -een fout; de reden staat dan in voxip-config.error.txt). +een fout; de reden staat dan in daynivo-config.error.txt). -voxip-config.json - Instellingen voor deze kiosk. Zie voxip-config.example.json. Toegestaan: +daynivo-config.json + Instellingen voor deze kiosk. Zie daynivo-config.example.json. Toegestaan: alle sleutels uit /etc/voxip-kiosk/config.json plus "hostname" en "wifi_country". Voorbeeld: @@ -18,12 +18,12 @@ voxip-config.json "rotation": 90 } -voxip-authorized_keys +daynivo-authorized_keys Openbare SSH-sleutels (één per regel). SSH wordt dan ingeschakeld, alleen met sleutel-login, voor de beheerder (voxipadmin of de gebruiker die je in Raspberry Pi Imager hebt aangemaakt). -voxip-network-reset +daynivo-network-reset Leeg bestand. Verwijdert bij de volgende start alle via de beheerinterface ingestelde netwerkprofielen (terug naar DHCP). Gebruik dit als de kiosk na een netwerkwijziging onbereikbaar is. diff --git a/image/voxip-config.example.json b/image/daynivo-config.example.json similarity index 100% rename from image/voxip-config.example.json rename to image/daynivo-config.example.json diff --git a/image/stage-voxip/00-voxip/00-run.sh b/image/stage-voxip/00-voxip/00-run.sh index b07807f..94c8beb 100755 --- a/image/stage-voxip/00-voxip/00-run.sh +++ b/image/stage-voxip/00-voxip/00-run.sh @@ -20,4 +20,4 @@ EOF_CHROOT # Instructions next to config.txt for whoever opens the boot partition. install -m 0644 files/voxip-kiosk/image/boot-README.txt "${ROOTFS_DIR}/boot/firmware/VOXIP-LEESMIJ.txt" -install -m 0644 files/voxip-kiosk/image/voxip-config.example.json "${ROOTFS_DIR}/boot/firmware/voxip-config.example.json" +install -m 0644 files/voxip-kiosk/image/daynivo-config.example.json "${ROOTFS_DIR}/boot/firmware/daynivo-config.example.json" diff --git a/install.sh b/install.sh index ab3a8b4..3ae8f9e 100755 --- a/install.sh +++ b/install.sh @@ -138,7 +138,9 @@ rm -rf "$LIB/python.old" for bin in voxip-kiosk-agent voxip-kiosk-browser voxip-kiosk-healthcheck voxip-kiosk-helper voxip-kiosk-manager voxip-kiosk-updater voxip-kiosk-x; do install -m 0755 -o root -g root "$SRC/bin/$bin" "$LIB/$bin" done -install -m 0755 -o root -g root "$SRC/bin/voxip-kiosk-ctl" /usr/local/sbin/voxip-kiosk-ctl +install -m 0755 -o root -g root "$SRC/bin/daynivo-kiosk-ctl" /usr/local/sbin/daynivo-kiosk-ctl +# The name from before the rename to Daynivo keeps working. +ln -sfn daynivo-kiosk-ctl /usr/local/sbin/voxip-kiosk-ctl rm -rf "$SHARE/www" install -d -m 0755 "$SHARE/www" @@ -340,4 +342,4 @@ if [[ ! -f $ETC/admin.json ]]; then echo " Setupcode: $(cat "$ETC/setup-code") (staat ook op het scherm)" fi fi -echo " Status: sudo voxip-kiosk-ctl status" +echo " Status: sudo daynivo-kiosk-ctl status" diff --git a/src/voxip_kiosk/ctl.py b/src/voxip_kiosk/ctl.py index 172f2d6..a80d31a 100644 --- a/src/voxip_kiosk/ctl.py +++ b/src/voxip_kiosk/ctl.py @@ -1,4 +1,4 @@ -"""voxip-kiosk-ctl — command-line management over SSH (run with sudo).""" +"""daynivo-kiosk-ctl — command-line management over SSH (run with sudo).""" from __future__ import annotations @@ -33,7 +33,7 @@ def cmd_status(args) -> int: print(f"Apparaat: {config['device_name']}") print(f"URL: {config['url'] if args.show_secrets else mask_url(config['url'])}") print(f"Beheer: {'https' if config['admin_https'] else 'http'}://{os.uname().nodename}.local:{config['admin_port']}") - print(f"Wachtwoord: {'ingesteld' if paths.admin_file.exists() else 'NOG NIET INGESTELD (setupcode: sudo voxip-kiosk-ctl setup-code)'}") + print(f"Wachtwoord: {'ingesteld' if paths.admin_file.exists() else 'NOG NIET INGESTELD (setupcode: sudo daynivo-kiosk-ctl setup-code)'}") for key, info in services.summary().items(): print(f"{info['unit']:<34} {info['label']} (herstarts: {info['restarts']})") if agent: @@ -138,7 +138,7 @@ def cmd_version(_args) -> int: def main(argv: list[str] | None = None) -> int: - parser = argparse.ArgumentParser(prog="voxip-kiosk-ctl", description="Beheer van Daynivo Kiosk OS vanaf de commandoregel.") + parser = argparse.ArgumentParser(prog="daynivo-kiosk-ctl", description="Beheer van Daynivo Kiosk OS vanaf de commandoregel.") sub = parser.add_subparsers(dest="command", required=True) p = sub.add_parser("status", help="toon de status") p.add_argument("--show-secrets", action="store_true", help="toon de volledige URL inclusief token") diff --git a/src/voxip_kiosk/helper.py b/src/voxip_kiosk/helper.py index 2b57ad6..0edb31c 100644 --- a/src/voxip_kiosk/helper.py +++ b/src/voxip_kiosk/helper.py @@ -33,9 +33,11 @@ UPDATE_UNIT = "voxip-kiosk-update-now" UPDATER_PATH = "/usr/lib/voxip-kiosk/voxip-kiosk-updater" ACTIVATE_UNIT = "voxip-network-activate" BOOT_DIRS = (Path("/boot/firmware"), Path("/boot")) -RESET_TRIGGER = "voxip-network-reset" -IMPORT_CONFIG = "voxip-config.json" -IMPORT_KEYS = "voxip-authorized_keys" +# Files on the boot partition. The voxip-* names are from before the rename to +# Daynivo and keep working, so existing SD cards and instructions stay valid. +RESET_TRIGGERS = ("daynivo-network-reset", "voxip-network-reset") +IMPORT_CONFIGS = ("voxip-config.json", "daynivo-config.json") # applied in this order: the Daynivo name wins +IMPORT_KEYS = ("voxip-authorized_keys", "daynivo-authorized_keys") SSH_KEY_TYPES = ("ssh-ed25519", "ssh-rsa", "ecdsa-sha2-", "sk-ssh-ed25519@openssh.com", "sk-ecdsa-sha2-") # Verbs the web interface may call through sudo. Everything else is only @@ -306,15 +308,16 @@ class Helper: self.network_restore(boot=True) result["rolled_back"] = True boot = self._boot_dir() - trigger = boot / RESET_TRIGGER if boot else None - if trigger and trigger.exists(): + triggers = [boot / name for name in RESET_TRIGGERS if (boot / name).exists()] if boot else [] + if triggers: stash = self.paths.network_state_dir / f"disabled-{int(time.time())}" stash.mkdir(parents=True, mode=0o700) for iface in netconfig.INTERFACES: src = self._keyfile_path(iface) if src.exists(): shutil.move(str(src), str(stash / src.name)) - trigger.unlink() + for trigger in triggers: + trigger.unlink() log(syslog.LOG_WARNING, f"Netwerk-reset uitgevoerd; Daynivo-profielen verplaatst naar {stash}") result["reset"] = True return result @@ -335,12 +338,14 @@ class Helper: if boot is None: return {"imported": []} imported = [] - conf = boot / IMPORT_CONFIG - if conf.exists(): + for name in IMPORT_CONFIGS: + conf = boot / name + if not conf.exists(): + continue try: data = json.loads(conf.read_text(encoding="utf-8-sig")) if not isinstance(data, dict): - raise HelperError("voxip-config.json moet een JSON-object zijn") + raise HelperError(f"{name} moet een JSON-object zijn") data = dict(data) host = data.pop("hostname", None) country = data.pop("wifi_country", None) @@ -351,22 +356,24 @@ class Helper: self.set_hostname(str(host)) if country: self.set_wifi_country(str(country)) - conf.rename(conf.with_name(IMPORT_CONFIG + ".applied")) - imported.append(IMPORT_CONFIG) - log(syslog.LOG_NOTICE, "Configuratie geïmporteerd vanaf de bootpartitie") + conf.rename(conf.with_name(name + ".applied")) + imported.append(name) + log(syslog.LOG_NOTICE, f"Configuratie geïmporteerd vanaf de bootpartitie ({name})") except (HelperError, cfg.ConfigError, v.ValidationError, ValueError, OSError) as exc: - (boot / "voxip-config.error.txt").write_text(f"{exc}\n", encoding="utf-8") - conf.rename(conf.with_name(IMPORT_CONFIG + ".rejected")) - log(syslog.LOG_ERR, f"voxip-config.json geweigerd: {exc}") - keys = boot / IMPORT_KEYS - if keys.exists(): + (boot / name.replace(".json", ".error.txt")).write_text(f"{exc}\n", encoding="utf-8") + conf.rename(conf.with_name(name + ".rejected")) + log(syslog.LOG_ERR, f"{name} geweigerd: {exc}") + for name in IMPORT_KEYS: + keys = boot / name + if not keys.exists(): + continue try: self._import_ssh_keys(keys.read_text(encoding="utf-8-sig")) - keys.rename(keys.with_name(IMPORT_KEYS + ".applied")) - imported.append(IMPORT_KEYS) + keys.rename(keys.with_name(name + ".applied")) + imported.append(name) except (HelperError, OSError) as exc: - keys.rename(keys.with_name(IMPORT_KEYS + ".rejected")) - log(syslog.LOG_ERR, f"SSH-sleutels geweigerd: {exc}") + keys.rename(keys.with_name(name + ".rejected")) + log(syslog.LOG_ERR, f"SSH-sleutels geweigerd ({name}): {exc}") return {"imported": imported} def _import_ssh_keys(self, text: str) -> None: diff --git a/src/voxip_kiosk/web/templates/login.html b/src/voxip_kiosk/web/templates/login.html index 594c356..6b58eae 100644 --- a/src/voxip_kiosk/web/templates/login.html +++ b/src/voxip_kiosk/web/templates/login.html @@ -12,6 +12,6 @@ -

Wachtwoord vergeten? Log via SSH in en voer sudo voxip-kiosk-ctl reset-password uit.

+

Wachtwoord vergeten? Log via SSH in en voer sudo daynivo-kiosk-ctl reset-password uit.

{% endblock %} diff --git a/src/voxip_kiosk/web/templates/network.html b/src/voxip_kiosk/web/templates/network.html index a33b7b8..794a29f 100644 --- a/src/voxip_kiosk/web/templates/network.html +++ b/src/voxip_kiosk/web/templates/network.html @@ -94,7 +94,7 @@

Herstel bij een onbereikbare kiosk

{% endblock %} diff --git a/src/voxip_kiosk/web/templates/setup.html b/src/voxip_kiosk/web/templates/setup.html index 860cd98..8527ccc 100644 --- a/src/voxip_kiosk/web/templates/setup.html +++ b/src/voxip_kiosk/web/templates/setup.html @@ -4,7 +4,7 @@

Welkom bij Daynivo Kiosk Manager

Stel eerst een uniek beheerderswachtwoord in. Je hebt daarvoor de setupcode nodig die op het - scherm van de kiosk staat (of via SSH: sudo voxip-kiosk-ctl setup-code).

+ scherm van de kiosk staat (of via SSH: sudo daynivo-kiosk-ctl setup-code).

{% if error %}{% endif %}
diff --git a/systemd/voxip-boot-import.service b/systemd/voxip-boot-import.service index b84d918..cdea75b 100644 --- a/systemd/voxip-boot-import.service +++ b/systemd/voxip-boot-import.service @@ -3,6 +3,10 @@ Description=Daynivo configuratie en SSH-sleutels importeren vanaf de bootpartiti Documentation=file:///usr/share/doc/voxip-kiosk/README.md After=local-fs.target Before=voxip-kiosk-manager.service voxip-kiosk-browser.service ssh.service +ConditionPathExistsGlob=|/boot/firmware/daynivo-config.json +ConditionPathExistsGlob=|/boot/firmware/daynivo-authorized_keys +ConditionPathExistsGlob=|/boot/daynivo-config.json +ConditionPathExistsGlob=|/boot/daynivo-authorized_keys ConditionPathExistsGlob=|/boot/firmware/voxip-config.json ConditionPathExistsGlob=|/boot/firmware/voxip-authorized_keys ConditionPathExistsGlob=|/boot/voxip-config.json diff --git a/tests/test_helper.py b/tests/test_helper.py index 638e16f..bec87d5 100644 --- a/tests/test_helper.py +++ b/tests/test_helper.py @@ -169,35 +169,54 @@ def test_boot_guard_rolls_back_and_honours_reset(helper, paths, boot): assert not any(c[0] == "nmcli" for c in helper.run.commands), "NetworkManager is not running yet at boot" (paths.nm_connections_dir / "voxip-wlan0.nmconnection").write_text("x") - (boot / "voxip-network-reset").write_text("") + (boot / "daynivo-network-reset").write_text("") assert helper.network_boot_guard() == {"reset": True} assert not (paths.nm_connections_dir / "voxip-wlan0.nmconnection").exists() - assert not (boot / "voxip-network-reset").exists() + assert not (boot / "daynivo-network-reset").exists() assert old.exists() +def test_boot_guard_still_honours_the_old_reset_name(helper, paths, boot): + (paths.nm_connections_dir / "voxip-eth0.nmconnection").write_text("x") + (boot / "voxip-network-reset").write_text("") + assert helper.network_boot_guard() == {"reset": True} + assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists() + assert not (boot / "voxip-network-reset").exists() + + def test_boot_import_applies_config(helper, paths, boot): - (boot / "voxip-config.json").write_text(json.dumps({"device_name": "Hal", "url": "https://klant.example.nl/display/hal?token=x", - "hostname": "hal", "rotation": 90})) - assert helper.boot_import() == {"imported": ["voxip-config.json"]} + (boot / "daynivo-config.json").write_text(json.dumps({"device_name": "Hal", "url": "https://klant.example.nl/display/hal?token=x", + "hostname": "hal", "rotation": 90})) + assert helper.boot_import() == {"imported": ["daynivo-config.json"]} conf = load_config(paths.config_file) assert conf["device_name"] == "Hal" and conf["rotation"] == 90 and conf["url"].startswith("https://klant") assert (helper.etc / "hostname").read_text() == "hal\n" + assert (boot / "daynivo-config.json.applied").exists() + + +def test_boot_import_still_accepts_the_old_names(helper, paths, boot): + (boot / "voxip-config.json").write_text(json.dumps({"device_name": "Oud", "rotation": 180})) + (boot / "daynivo-config.json").write_text(json.dumps({"device_name": "Nieuw"})) + assert helper.boot_import() == {"imported": ["voxip-config.json", "daynivo-config.json"]} + conf = load_config(paths.config_file) + assert conf["device_name"] == "Nieuw" and conf["rotation"] == 180 # the Daynivo file is applied last assert (boot / "voxip-config.json.applied").exists() def test_boot_import_rejects_invalid_config(helper, paths, boot): before = paths.config_file.read_text() - (boot / "voxip-config.json").write_text(json.dumps({"url": "http://onveilig.example"})) + (boot / "daynivo-config.json").write_text(json.dumps({"url": "http://onveilig.example"})) helper.boot_import() assert paths.config_file.read_text() == before - assert (boot / "voxip-config.json.rejected").exists() - assert "HTTPS" in (boot / "voxip-config.error.txt").read_text() + assert (boot / "daynivo-config.json.rejected").exists() + assert "HTTPS" in (boot / "daynivo-config.error.txt").read_text() def test_boot_import_rejects_non_key_lines(helper, boot): - (boot / "voxip-authorized_keys").write_text("dit is geen sleutel\n") + (boot / "daynivo-authorized_keys").write_text("dit is geen sleutel\n") + (boot / "voxip-authorized_keys").write_text("ook geen sleutel\n") helper.boot_import() + assert (boot / "daynivo-authorized_keys.rejected").exists() assert (boot / "voxip-authorized_keys.rejected").exists() diff --git a/uninstall.sh b/uninstall.sh index 2690587..7eb125f 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -33,7 +33,7 @@ systemctl daemon-reload echo "==> Bestanden verwijderen" rm -rf /usr/lib/voxip-kiosk /usr/share/voxip-kiosk /usr/share/doc/voxip-kiosk -rm -f /usr/local/sbin/voxip-kiosk-ctl +rm -f /usr/local/sbin/daynivo-kiosk-ctl /usr/local/sbin/voxip-kiosk-ctl rm -f /etc/sudoers.d/voxip-kiosk rm -f /etc/systemd/journald.conf.d/voxip-kiosk.conf /etc/systemd/system.conf.d/voxip-watchdog.conf rm -f /etc/logrotate.d/voxip-kiosk /etc/avahi/services/voxip-kiosk.service diff --git a/www/setup.html b/www/setup.html index 5e27bff..08be1ea 100644 --- a/www/setup.html +++ b/www/setup.html @@ -44,7 +44,7 @@ li.textContent = u; list.appendChild(li); }); - document.getElementById("code").textContent = params.get("code") || "zie: sudo voxip-kiosk-ctl setup-code"; + document.getElementById("code").textContent = params.get("code") || "zie: sudo daynivo-kiosk-ctl setup-code";