import * as fs from 'fs';
|
import * as path from 'path';
|
import type { AbgleichErgebnis, Software } from 'bibliothek-types';
|
import { DATEIEN_ORDNER, QUELLEN_ORDNER, abgleichSpeichern } from './datenbank';
|
import { bezugsquelleFuer, type QuellenAbgleich } from './bezugsquellen';
|
import { pruefeSignatur, weichtHerausgeberAb } from './signatur';
|
import { alsUmgebung, ladeGeheimnisse } from './geheimnisse';
|
import { gitSshBefehl } from './konfiguration';
|
|
/** Größe der aktuell bereitgestellten Datei — Grundlage der Plausibilitätsprüfung. */
|
function bisherigeGroesse(software: Software): number {
|
if (!software.dateiname) {
|
return 0;
|
}
|
const pfad = path.join(DATEIEN_ORDNER, String(software.id), software.dateiname);
|
return fs.existsSync(pfad) ? fs.statSync(pfad).size : 0;
|
}
|
|
/** Unveränderten Stand zurückschreiben (bei Misserfolg oder unbekannter Quelle). */
|
function unveraendert(software: Software, meldung: string, version = software.version): AbgleichErgebnis {
|
return {
|
version,
|
dateiname: software.dateiname,
|
erfolg: false,
|
meldung,
|
geaendert: false,
|
signaturStatus: software.signaturStatus,
|
signaturHerausgeber: software.signaturHerausgeber,
|
veroeffentlichtAm: software.veroeffentlichtAm,
|
benoetigteGeheimnisse: software.benoetigteGeheimnisse,
|
};
|
}
|
|
/** Gleicht eine Software mit ihrer Bezugsquelle ab und speichert das Ergebnis zurück. */
|
export async function gleicheSoftwareAb(software: Software): Promise<void> {
|
if (software.quelleTyp === 'manuell') {
|
return; // Datei wird von Hand hinterlegt – es gibt nichts abzugleichen
|
}
|
if (!software.quelleTyp || !software.quelleWert) {
|
return; // keine Quelle gesetzt – nichts zu holen
|
}
|
const quelle = bezugsquelleFuer(software.quelleTyp);
|
if (!quelle) {
|
abgleichSpeichern(software.id, unveraendert(software, `Unbekannte Bezugsquelle: ${software.quelleTyp}`));
|
return;
|
}
|
|
const zielordner = path.join(DATEIEN_ORDNER, String(software.id));
|
const ergebnis = await quelle.gleicheAb({
|
wert: software.quelleWert,
|
aktuelleVersion: software.version,
|
zielordner,
|
arbeitsordner: path.join(QUELLEN_ORDNER, String(software.id)),
|
bauBefehl: software.bauBefehl,
|
bauErgebnis: software.bauErgebnis,
|
vorherigeGroesse: bisherigeGroesse(software),
|
geheimnisse: alsUmgebung(ladeGeheimnisse(software.id)),
|
gitSshBefehl: gitSshBefehl(),
|
});
|
|
if (!ergebnis.erfolg) {
|
abgleichSpeichern(software.id, unveraendert(software, ergebnis.meldung, ergebnis.version));
|
return;
|
}
|
|
abgleichSpeichern(software.id, await mitSignaturbefund(software, ergebnis, zielordner));
|
}
|
|
/**
|
* Ergänzt das Abgleich-Ergebnis um die Windows-Signatur der bereitgestellten Datei.
|
* Ist ein Signaturgeber erwartet und weicht der gefundene ab, wird die Datei nicht
|
* zum Download freigegeben (`dateiname` bleibt leer) — sie bleibt aber zur Ansicht liegen.
|
*/
|
async function mitSignaturbefund(software: Software, ergebnis: QuellenAbgleich, zielordner: string): Promise<AbgleichErgebnis> {
|
const befund = await pruefeSignatur(path.join(zielordner, ergebnis.dateiname));
|
const gemeinsam = {
|
version: ergebnis.version,
|
signaturStatus: befund.status,
|
signaturHerausgeber: befund.herausgeber,
|
veroeffentlichtAm: ergebnis.veroeffentlichtAm ?? software.veroeffentlichtAm,
|
benoetigteGeheimnisse: ergebnis.benoetigteGeheimnisse ?? software.benoetigteGeheimnisse,
|
};
|
if (weichtHerausgeberAb(software.erwarteterHerausgeber, befund.herausgeber)) {
|
return {
|
...gemeinsam,
|
dateiname: '', // nicht ausliefern, bis das geklärt ist
|
erfolg: false,
|
meldung: `Signatur weicht ab: erwartet „${software.erwarteterHerausgeber}", gefunden „${befund.herausgeber || 'unsigniert'}" (${befund.status}). Die Datei wird nicht zum Download angeboten.`,
|
geaendert: false,
|
};
|
}
|
return {
|
...gemeinsam,
|
dateiname: ergebnis.dateiname,
|
erfolg: true,
|
meldung: ergebnis.meldung,
|
geaendert: ergebnis.geaendert,
|
};
|
}
|
|
/** Gleicht nacheinander alle Einträge mit gesetzter Quelle ab (täglicher Auto-Check). */
|
export async function gleicheAlleAb(alle: Software[]): Promise<void> {
|
for (const software of alle) {
|
if (software.quelleTyp && software.quelleWert) {
|
await gleicheSoftwareAb(software);
|
}
|
}
|
}
|