145 lines
4.7 KiB
JavaScript
145 lines
4.7 KiB
JavaScript
import { promises } from 'fs';
|
|
import path from 'path';
|
|
import { randomUUID } from 'crypto';
|
|
import { d as decryptObject, a as encryptObject } from './encryption.mjs';
|
|
|
|
const getDataPath = (filename) => {
|
|
const cwd = process.cwd();
|
|
if (cwd.endsWith(".output")) {
|
|
return path.join(cwd, "../server/data", filename);
|
|
}
|
|
return path.join(cwd, "server/data", filename);
|
|
};
|
|
const MEMBERS_FILE = getDataPath("members.json");
|
|
function getEncryptionKey() {
|
|
return process.env.ENCRYPTION_KEY || "default-key-change-in-production";
|
|
}
|
|
function isEncrypted(data) {
|
|
try {
|
|
const parsed = JSON.parse(data.trim());
|
|
if (Array.isArray(parsed)) {
|
|
return false;
|
|
}
|
|
if (typeof parsed === "object" && parsed !== null && !parsed.encryptedData) {
|
|
return false;
|
|
}
|
|
return false;
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
}
|
|
async function readMembers() {
|
|
try {
|
|
const data = await promises.readFile(MEMBERS_FILE, "utf-8");
|
|
const encrypted = isEncrypted(data);
|
|
if (encrypted) {
|
|
const encryptionKey = getEncryptionKey();
|
|
try {
|
|
return decryptObject(data, encryptionKey);
|
|
} catch (decryptError) {
|
|
console.error("Fehler beim Entschl\xFCsseln der Mitgliederdaten:", decryptError);
|
|
try {
|
|
const plainData = JSON.parse(data);
|
|
console.warn("Entschl\xFCsselung fehlgeschlagen, versuche als unverschl\xFCsseltes Format zu lesen");
|
|
return plainData;
|
|
} catch (parseError) {
|
|
console.error("Konnte Mitgliederdaten weder entschl\xFCsseln noch als JSON lesen");
|
|
return [];
|
|
}
|
|
}
|
|
} else {
|
|
const members = JSON.parse(data);
|
|
console.log("Migriere unverschl\xFCsselte Mitgliederdaten zu verschl\xFCsselter Speicherung...");
|
|
await writeMembers(members);
|
|
return members;
|
|
}
|
|
} catch (error) {
|
|
if (error.code === "ENOENT") {
|
|
return [];
|
|
}
|
|
console.error("Fehler beim Lesen der Mitgliederdaten:", error);
|
|
return [];
|
|
}
|
|
}
|
|
async function writeMembers(members) {
|
|
try {
|
|
const encryptionKey = getEncryptionKey();
|
|
const encryptedData = encryptObject(members, encryptionKey);
|
|
await promises.writeFile(MEMBERS_FILE, encryptedData, "utf-8");
|
|
return true;
|
|
} catch (error) {
|
|
console.error("Fehler beim Schreiben der Mitgliederdaten:", error);
|
|
return false;
|
|
}
|
|
}
|
|
function normalizeDate(dateString) {
|
|
if (!dateString) return "";
|
|
try {
|
|
const date = new Date(dateString);
|
|
if (isNaN(date.getTime())) return dateString.trim();
|
|
return date.toISOString().split("T")[0];
|
|
} catch (e) {
|
|
return dateString.trim();
|
|
}
|
|
}
|
|
function findDuplicateMember(members, firstName, lastName, geburtsdatum) {
|
|
const normalizedFirstName = (firstName || "").trim().toLowerCase();
|
|
const normalizedLastName = (lastName || "").trim().toLowerCase();
|
|
const normalizedDate = normalizeDate(geburtsdatum);
|
|
return members.find((m) => {
|
|
const mFirstName = (m.firstName || "").trim().toLowerCase();
|
|
const mLastName = (m.lastName || "").trim().toLowerCase();
|
|
const mDate = normalizeDate(m.geburtsdatum);
|
|
return mFirstName === normalizedFirstName && mLastName === normalizedLastName && mDate === normalizedDate && mDate !== "";
|
|
});
|
|
}
|
|
async function saveMember(memberData) {
|
|
const members = await readMembers();
|
|
if (memberData.id) {
|
|
const index = members.findIndex((m) => m.id === memberData.id);
|
|
if (index !== -1) {
|
|
const duplicate = findDuplicateMember(
|
|
members.filter((m) => m.id !== memberData.id),
|
|
memberData.firstName,
|
|
memberData.lastName,
|
|
memberData.geburtsdatum
|
|
);
|
|
if (duplicate) {
|
|
throw new Error("Ein Mitglied mit diesem Namen und Geburtsdatum existiert bereits.");
|
|
}
|
|
members[index] = { ...members[index], ...memberData };
|
|
} else {
|
|
throw new Error("Mitglied nicht gefunden");
|
|
}
|
|
} else {
|
|
if (memberData.firstName && memberData.lastName && memberData.geburtsdatum) {
|
|
const duplicate = findDuplicateMember(
|
|
members,
|
|
memberData.firstName,
|
|
memberData.lastName,
|
|
memberData.geburtsdatum
|
|
);
|
|
if (duplicate) {
|
|
throw new Error("Ein Mitglied mit diesem Namen und Geburtsdatum existiert bereits.");
|
|
}
|
|
}
|
|
const newMember = {
|
|
...memberData,
|
|
id: randomUUID()
|
|
// Cryptographically secure unique ID
|
|
};
|
|
members.push(newMember);
|
|
}
|
|
await writeMembers(members);
|
|
return true;
|
|
}
|
|
async function deleteMember(id) {
|
|
const members = await readMembers();
|
|
const filtered = members.filter((m) => m.id !== id);
|
|
await writeMembers(filtered);
|
|
return true;
|
|
}
|
|
|
|
export { deleteMember as d, normalizeDate as n, readMembers as r, saveMember as s, writeMembers as w };
|
|
//# sourceMappingURL=members.mjs.map
|