This commit is contained in:
2026-05-23 01:18:44 +02:00
parent 3f2572ca59
commit 3840ecf494
8 changed files with 344 additions and 44 deletions

158
scripts/portal-setup.mjs Normal file
View File

@@ -0,0 +1,158 @@
#!/usr/bin/env node
/**
* Portal-Setup: API-Key prüfen, Kunde verknüpfen, Portal-Zugang aktivieren.
*
* Usage:
* node scripts/portal-setup.mjs --check
* node scripts/portal-setup.mjs --link --email kenso@webklar.com --appwrite-user-id 6a10d87f0003f576f126
*/
import 'dotenv/config'
import { randomUUID } from 'node:crypto'
import { config, WOMS_DATABASE_ID } from '../server/config.js'
import {
getCustomerByEmail,
getPortalAccessByCustomerId,
listDocuments,
updateDocument,
Query,
verifyDatabaseAccess,
} from '../server/services/appwriteAdmin.js'
function parseArgs(argv) {
const args = { check: false, link: false, email: '', appwriteUserId: '' }
for (let i = 2; i < argv.length; i++) {
const a = argv[i]
if (a === '--check') args.check = true
else if (a === '--link') args.link = true
else if (a === '--email') args.email = argv[++i] || ''
else if (a === '--appwrite-user-id') args.appwriteUserId = argv[++i] || ''
}
return args
}
async function adminPost(collectionId, data) {
const path = `/databases/${config.appwrite.databaseId}/collections/${collectionId}/documents`
const url = `${config.appwrite.endpoint}${path}`
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': config.appwrite.projectId,
'X-Appwrite-Key': config.appwrite.apiKey,
},
body: JSON.stringify({ documentId: randomUUID(), data }),
})
const text = await response.text()
const body = text ? JSON.parse(text) : {}
if (!response.ok) throw new Error(body.message || `HTTP ${response.status}`)
return body
}
async function checkCollections() {
const names = [
config.collections.customers,
config.collections.customerPortalAccess,
config.collections.websiteProjects,
config.collections.portalFeatures,
]
const missing = []
for (const id of names) {
const url = `${config.appwrite.endpoint}/databases/${config.appwrite.databaseId}/collections/${id}`
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': config.appwrite.projectId,
'X-Appwrite-Key': config.appwrite.apiKey,
},
})
if (!response.ok) missing.push(id)
}
return missing
}
async function linkCustomer(email, appwriteUserId) {
const customer = await getCustomerByEmail(email)
if (!customer) {
throw new Error(`Kein Kunde mit E-Mail "${email}" in customers gefunden.`)
}
await updateDocument(config.collections.customers, customer.$id, {
appwriteUserId,
portalAccessEnabled: true,
customerStatus: customer.customerStatus || 'active',
updatedAt: new Date().toISOString(),
})
let portalAccess = await getPortalAccessByCustomerId(customer.$id)
if (portalAccess) {
await updateDocument(config.collections.customerPortalAccess, portalAccess.$id, {
enabled: true,
appwriteUserId,
passwordSet: true,
})
} else {
portalAccess = await adminPost(config.collections.customerPortalAccess, {
customerId: customer.$id,
enabled: true,
appwriteUserId,
passwordSet: true,
})
}
return { customerId: customer.$id, portalAccessId: portalAccess.$id }
}
async function main() {
const args = parseArgs(process.argv)
console.log(`Endpoint: ${config.appwrite.endpoint}`)
console.log(`Database: ${WOMS_DATABASE_ID}`)
console.log(`Project: ${config.appwrite.projectId}`)
console.log('')
const access = await verifyDatabaseAccess()
if (!access.ok) {
console.error('❌ APPWRITE_API_KEY: Kein Zugriff auf woms-database.')
console.error(` Appwrite: ${access.reason}`)
console.error(' Benötigt: Scopes databases.read + databases.write')
process.exit(1)
}
console.log('✅ API-Key: databases.read OK')
const sample = await listDocuments(config.collections.customers, [Query.limit(1)])
console.log(`✅ Collection "${config.collections.customers}": ${sample.length >= 0 ? 'erreichbar' : '?'}`)
const missing = await checkCollections()
if (missing.length) {
console.warn(`⚠️ Fehlende Collections: ${missing.join(', ')}`)
console.warn(' Siehe APPWRITE_SCHEMA.md im Ticketsystem/Appwrite Console anlegen.')
} else {
console.log('✅ Alle Portal-Collections vorhanden')
}
if (args.link) {
if (!args.email || !args.appwriteUserId) {
console.error('❌ --link erfordert --email und --appwrite-user-id')
process.exit(1)
}
const result = await linkCustomer(args.email.trim(), args.appwriteUserId.trim())
console.log('')
console.log('✅ Kunde verknüpft:')
console.log(` customerId: ${result.customerId}`)
console.log(` appwriteUserId: ${args.appwriteUserId}`)
console.log(` portalAccessId: ${result.portalAccessId}`)
console.log(' portalAccessEnabled: true')
console.log(' customerPortalAccess.enabled: true')
}
if (!args.check && !args.link) {
console.log('')
console.log('Nur Check ausgeführt. Für Verknüpfung:')
console.log(' node scripts/portal-setup.mjs --link --email USER@example.com --appwrite-user-id USER_ID')
}
}
main().catch((err) => {
console.error('❌', err.message)
process.exit(1)
})