From 5077dd5a20f5b5958871270755c2e455b6c7d205 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 3 Oct 2026 11:10:09 +0000 Subject: [PATCH] Mitarbeiter-Zugang: --ohne-buckets (Server-Key ohne buckets-Scope, Buckets dann in der Konsole) Co-Authored-By: Claude Opus 5.5 --- scripts/mitarbeiter-zugang.mjs | 7 +++++-- server/services/staffAccessAdmin.js | 8 +++++--- test/staffAccess.test.js | 5 +++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/scripts/mitarbeiter-zugang.mjs b/scripts/mitarbeiter-zugang.mjs index a369b82..d86e6ab 100644 --- a/scripts/mitarbeiter-zugang.mjs +++ b/scripts/mitarbeiter-zugang.mjs @@ -7,6 +7,7 @@ * ... --label [,...] [--yes] Label "mitarbeiter" vergeben (nur ausdrueckliche Konten) * ... --eintrag-loeschen [--yes] employees-Eintrag eines Kunden loeschen (Konto bleibt) * ... --rechte [--offen-lassen [,...]] Probelauf: welche Rechte sich aendern (IDs bleiben offen) + * [--ohne-buckets] Buckets auslassen (Key ohne buckets-Scope, dann in der Konsole) * ... --rechte --anwenden [--sicherung ] [--yes] Rechte umstellen, vorher Sicherung als JSON * ... --rechte --zurueck [--yes] Rechte aus einer Sicherung wiederherstellen */ @@ -100,9 +101,11 @@ async function permissions() { } const keep = (flag('--offen-lassen') || '').split(',').map((id) => id.trim()).filter(Boolean) - const { changes, errors } = await planPermissionChanges(undefined, { keep }) + const buckets = !args.includes('--ohne-buckets') + const { changes, errors } = await planPermissionChanges(undefined, { keep, buckets }) for (const e of errors) console.log(`NICHT LESBAR ${e.path}: ${e.error}`) if (keep.length) console.log(`Bleiben offen: ${keep.join(', ')}`) + if (!buckets) console.log('Buckets übersprungen – deren Rechte bitte in der Appwrite-Konsole umstellen.') if (!changes.length) return console.log('Keine offenen Rechte (any/guests/users) gefunden.') printChanges(changes) if (!args.includes('--anwenden')) return console.log(`Probelauf: ${changes.length} Stellen. Mit --anwenden umstellen.`) @@ -123,7 +126,7 @@ async function main() { const employeeId = flag('--eintrag-loeschen') if (employeeId) return removeEntry(employeeId) if (args.includes('--rechte')) return permissions() - console.log('Usage: --status | --label [,...] | --eintrag-loeschen | --rechte [--offen-lassen ,...] [--anwenden [--sicherung ] | --zurueck ] [--yes]') + console.log('Usage: --status | --label [,...] | --eintrag-loeschen | --rechte [--offen-lassen ,...] [--ohne-buckets] [--anwenden [--sicherung ] | --zurueck ] [--yes]') } main().catch((err) => { diff --git a/server/services/staffAccessAdmin.js b/server/services/staffAccessAdmin.js index dd30036..996bd39 100644 --- a/server/services/staffAccessAdmin.js +++ b/server/services/staffAccessAdmin.js @@ -107,10 +107,11 @@ export async function removeEmployeeEntry(employeeId, request = appwriteAdminReq /** * Alle Stellen mit offenen Rechten: Collections und Buckets, bei Dokument- bzw. Datei-Sicherheit auch einzelne * Dokumente und Dateien. Jede Aenderung traegt before/after, damit sie sich zuruecknehmen laesst. keep = IDs von - * Collections/Buckets, die bewusst offen bleiben (samt ihrer Dokumente/Dateien). Eine Liste, die sich nicht lesen + * Collections/Buckets, die bewusst offen bleiben (samt ihrer Dokumente/Dateien), buckets false laesst alle Buckets + * aus. Eine Liste, die sich nicht lesen * laesst (z. B. fehlender Key-Scope), landet in errors statt den ganzen Lauf abzubrechen. */ -export async function planPermissionChanges(request = appwriteAdminRequest, { keep = [] } = {}) { +export async function planPermissionChanges(request = appwriteAdminRequest, { keep = [], buckets = true } = {}) { const changes = [] const errors = [] const kept = new Set(keep) @@ -148,7 +149,8 @@ export async function planPermissionChanges(request = appwriteAdminRequest, { ke } } - for (const bucket of await tryList('/storage/buckets', 'buckets')) { + // buckets: false -> Buckets bleiben aussen vor (Key ohne buckets-Scope; dann von Hand in der Konsole) + for (const bucket of buckets ? await tryList('/storage/buckets', 'buckets') : []) { if (kept.has(bucket.$id)) continue add( { diff --git a/test/staffAccess.test.js b/test/staffAccess.test.js index 4c668a4..6f85060 100644 --- a/test/staffAccess.test.js +++ b/test/staffAccess.test.js @@ -120,6 +120,11 @@ test('planPermissionChanges: liest ueber 100 Dokumente seitenweise, offen-lassen const partial = await planPermissionChanges(failing) assert.deepEqual(partial.errors, [{ path: '/storage/buckets', error: 'missing scope (buckets.read)' }]) assert.ok(partial.changes.some((c) => c.id === 'workorders')) + + // --ohne-buckets: Buckets gar nicht erst lesen -> kein Fehler, nur Collections und Dokumente + const noBuckets = await planPermissionChanges(failing, { buckets: false }) + assert.deepEqual(noBuckets.errors, []) + assert.deepEqual(noBuckets.changes.map((c) => c.kind).filter((k) => k === 'bucket'), []) }) test('applyPermissionChanges: schreibt mit allen Einstellungen, meldet Fehler je Stelle, Ruecknahme schreibt before', async () => {