Updater: über Modul-Proxy statt private Registry + echte Fehlermeldung [apk]
All checks were successful
Build APK / build-apk (push) Successful in 1m39s

Der Updater fragte die private Forgejo-Registry direkt ab -> 403/CORS ->
catch -> 'App ist aktuell'. Er hat NIE wirklich geprueft.

- updater.ts: geht jetzt ueber update.php (eigener, authentifizierter
  Endpoint, CORS-frei). checkForUpdate() verschluckt Fehler NICHT mehr,
  sondern wirft mit Klartext-Grund.
- Einstellungen: 'Auf Update pruefen' zeigt bei Fehler die echte Meldung
  ('Update-Pruefung fehlgeschlagen: <Grund>') statt falschem 'aktuell'.
- +layout: Start-Pruefung still (nur Banner bei Erfolg, kein Fehler-Toast).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-05-19 20:36:22 +02:00
parent 46226f0d78
commit 36e66693f3
4 changed files with 57 additions and 44 deletions

View file

@ -229,3 +229,16 @@ export function uploadDebugLog(payload: DebugLogUpload): Promise<{ ok: boolean;
body: JSON.stringify(payload),
});
}
/**
* Neueste verfügbare App-Version erfragen. Der Server (update.php) prüft die
* Registry die App muss die private Registry nicht selbst erreichen.
*/
export function checkAppUpdate(): Promise<{ version: string | null }> {
return request<{ version: string | null }>('update.php');
}
/** Authentifizierte Download-URL der aktuellsten APK (über den Server-Proxy) */
export function updateDownloadUrl(): string {
return `${serverUrl}${API_PATH}/update.php?download=1&jwt=${encodeURIComponent(token)}`;
}

View file

@ -1,18 +1,20 @@
/**
* Auto-Updater (Muster aus Wissensbasis KB #363).
* Auto-Updater.
*
* Prüft die Forgejo Package Registry auf eine neuere APK. Die CI lädt jede
* APK mit Versionsstempel `YYYYMMDD-HHMM` hoch; dieselbe Version steckt über
* `VITE_APP_VERSION` im Build. Stringvergleich genügt also.
* Die Forgejo-Paket-Registry ist privat die App kann sie NICHT direkt
* abfragen (403 / CORS). Darum läuft die Prüfung über das netdiag-Modul
* (update.php): der Server prüft die Registry, die App spricht nur ihren
* eigenen, authentifizierten Endpunkt an.
*
* checkForUpdate() verschluckt Fehler NICHT bei einem Problem wirft es mit
* Klartext-Grund. So kann der Aufrufer wirklich aktuell" von Prüfung
* fehlgeschlagen" unterscheiden und eine echte Meldung zeigen.
*/
import { Capacitor } from '@capacitor/core';
import { checkAppUpdate, updateDownloadUrl } from './api';
const PKG_OWNER = 'data-it';
const PKG_NAME = 'netdiag-apk';
const REGISTRY_BASE = 'https://git.data-it-solution.de';
/** Aktuelle Build-Version (von der CI injiziert, im Dev leer) */
/** Aktuelle Build-Version (von der CI injiziert, im Dev 'dev') */
export const APP_VERSION: string = import.meta.env.VITE_APP_VERSION ?? 'dev';
export interface UpdateInfo {
@ -20,43 +22,25 @@ export interface UpdateInfo {
downloadUrl: string;
}
interface ForgejoPackage {
name: string;
version: string;
}
/**
* Prüfen, ob eine neuere APK verfügbar ist.
*
* @returns UpdateInfo bei verfügbarem Update, sonst null
* @returns UpdateInfo bei verfügbarem Update, null wenn nachweislich aktuell.
* @throws ApiError mit Klartext-Grund, wenn die Prüfung selbst fehlschlägt.
*/
export async function checkForUpdate(): Promise<UpdateInfo | null> {
// Im Browser-Dev oder ohne CI-Version nicht prüfen
if (!Capacitor.isNativePlatform() || APP_VERSION === 'dev') return null;
// Browser-Dev: keine native Update-Installation möglich
if (!Capacitor.isNativePlatform()) return null;
try {
const res = await fetch(
`${REGISTRY_BASE}/api/v1/packages/${PKG_OWNER}?type=generic&q=${PKG_NAME}`,
);
if (!res.ok) return null;
const pkgs = (await res.json()) as ForgejoPackage[];
const { version } = await checkAppUpdate(); // wirft ApiError bei Serverproblem
const versions = pkgs
.filter((p) => p.name === PKG_NAME && p.version !== 'latest')
.map((p) => p.version)
.sort();
const latest = versions[versions.length - 1];
if (latest && latest > APP_VERSION) {
return {
version: latest,
downloadUrl: `${REGISTRY_BASE}/api/packages/${PKG_OWNER}/generic/${PKG_NAME}/${latest}/NetDiag-${latest}.apk`,
};
}
} catch {
// Update-Prüfung ist unkritisch — Fehler still ignorieren
if (!version) {
throw new Error('Server lieferte keine Versionsinfo');
}
return null;
if (version > APP_VERSION) {
return { version, downloadUrl: updateDownloadUrl() };
}
return null; // aktuell — nachweislich geprüft
}
/**

View file

@ -36,8 +36,12 @@
showExitHint: () => toast.show('Nochmal drücken zum Beenden'),
});
// Auf neue APK prüfen (KB #363)
updateInfo = await checkForUpdate();
// Auf neue APK prüfen — beim Start still (kein Toast), nur Banner bei Erfolg
try {
updateInfo = await checkForUpdate();
} catch (e) {
console.warn('Update-Prüfung beim Start fehlgeschlagen:', e);
}
booted = true;
});

View file

@ -24,10 +24,22 @@
async function checkUpdate() {
checking = true;
const upd = await checkForUpdate();
checking = false;
if (upd) openUpdate(upd);
else toast.show('App ist aktuell', 'success');
try {
const upd = await checkForUpdate();
if (upd) openUpdate(upd);
else toast.show('App ist aktuell', 'success');
} catch (e) {
// Echte Fehlermeldung statt stillem „aktuell"
toast.show(
e instanceof Error
? `Update-Prüfung fehlgeschlagen: ${e.message}`
: 'Update-Prüfung fehlgeschlagen',
'error',
6000,
);
} finally {
checking = false;
}
}
async function logout() {