Rollen Freigaben Push und Beleg Upload ueberarbeiten
All checks were successful
CI / Build (push) Successful in 2m6s
CI / Deploy (push) Successful in 2m11s

This commit is contained in:
jan
2026-05-01 15:50:37 +02:00
parent f947908f0e
commit 549c8f16c6
34 changed files with 1354 additions and 172 deletions

72
src/lib/google-drive.ts Normal file
View File

@@ -0,0 +1,72 @@
import { google } from "googleapis";
import { Readable } from "node:stream";
const DEFAULT_DRIVE_FOLDER_ID = "12zMANi_J0uvie16LUxSmfeqwGjKawEhJ";
function getDriveClient() {
const clientEmail = process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL;
const privateKey = process.env.GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY?.replace(/\\n/g, "\n");
if (!clientEmail || !privateKey) {
throw new Error("Google-Drive-Service-Account ist nicht konfiguriert.");
}
const auth = new google.auth.JWT({
email: clientEmail,
key: privateKey,
scopes: ["https://www.googleapis.com/auth/drive.file"]
});
return google.drive({ version: "v3", auth });
}
export function sanitizeDriveFileName(title: string, fallback = "beleg") {
const sanitized = title
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-zA-Z0-9._-]+/g, "-")
.replace(/^-+|-+$/g, "")
.slice(0, 80);
return sanitized || fallback;
}
export async function uploadExpenseProofToDrive(input: {
title: string;
fileName: string;
mimeType: string;
buffer: Buffer;
}) {
const drive = getDriveClient();
const folderId = process.env.GOOGLE_DRIVE_FOLDER_ID || DEFAULT_DRIVE_FOLDER_ID;
const extension = input.fileName.includes(".") ? `.${input.fileName.split(".").pop()}` : "";
const baseName = sanitizeDriveFileName(input.title);
const uniqueSuffix = new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
const name = `${baseName}-${uniqueSuffix}${extension}`;
const response = await drive.files.create({
requestBody: {
name,
parents: [folderId]
},
media: {
mimeType: input.mimeType,
body: Readable.from(input.buffer)
},
fields: "id, webViewLink"
});
if (!response.data.id) {
throw new Error("Google Drive hat keine Datei-ID zurueckgegeben.");
}
await drive.permissions.create({
fileId: response.data.id,
requestBody: {
type: "anyone",
role: "reader"
}
});
return response.data.webViewLink ?? `https://drive.google.com/file/d/${response.data.id}/view`;
}