Files
Webklar-Kundenbereich/server/routes/admin/websiteProjects.js
T
ClaudeandClaude Opus 5.5 4fc4c70b7d Archiv/Rechte: Review-Punkte
- archiviertes Projekt bleibt unter Funktionen sichtbar, solange dort eine
  Funktion bestellt/eingerichtet/aktiv ist (z. B. Terminbuchungen)
- auf archivierten Projekten nichts neu bestellen oder einschalten
- Projekttyp Vorlage nur fuer Admins; repo-readme nur fuer bekannte Projekte

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 15:11:54 +00:00

131 lines
4.5 KiB
JavaScript

import { Router } from 'express'
import {
createProjectFromTemplate,
updateWebsiteProject,
archiveRepo,
} from '../../services/giteaAdmin.js'
import { assignProject, reconcileProject } from '../../services/projectAssignment.js'
import { completeAssignment } from '../../services/projectKindAssign.js'
import { requireAppwriteTeam } from '../../middleware/appwriteStaff.js'
const router = Router()
// Projekt-Aktionen: jeder Mitarbeiter (nicht nur Admins)
router.use(requireAppwriteTeam)
router.post('/create-from-template', async (req, res) => {
const { repoName, displayName, subdomain, customerId = '', ticketId = '', owner, kind = '' } = req.body || {}
if (!repoName && !displayName) {
return res.status(400).json({ error: 'repoName oder displayName ist erforderlich' })
}
try {
const result = await createProjectFromTemplate({
repoName,
displayName,
subdomain,
customerId,
ticketId,
owner,
kind,
staffName: req.appwriteUser?.name || req.appwriteUser?.email || '',
})
return res.status(201).json({ ok: true, ...result })
} catch (err) {
const status = err.status || 500
return res.status(status).json({ error: err.message || 'Projekt konnte nicht angelegt werden' })
}
})
// Projekt bearbeiten: Name / Subdomain / Typ -> synchronisiert Git + Preview + Appwrite
router.patch('/:id', async (req, res) => {
const { projectName, subdomain, projectType } = req.body || {}
// Vorlagen bleiben Admin-Sache (im Ticketsystem nur fuer Admins sichtbar)
if (projectType === 'template' && !req.appwriteUser?.labels?.includes('admin')) {
return res.status(403).json({ error: 'Nur Admins können Vorlagen anlegen.' })
}
try {
const result = await updateWebsiteProject(req.params.id, { projectName, subdomain, projectType })
return res.json({ ok: true, ...result })
} catch (err) {
const status = err.status || 500
return res.status(status).json({ error: err.message || 'Projekt konnte nicht aktualisiert werden' })
}
})
// Repository archivieren
router.post('/:id/archive', async (req, res) => {
try {
const result = await archiveRepo(req.params.id, true)
return res.json({ ok: true, ...result })
} catch (err) {
const status = err.status || 500
return res.status(status).json({ error: err.message || 'Projekt konnte nicht archiviert werden' })
}
})
// Repository reaktivieren
router.post('/:id/unarchive', async (req, res) => {
try {
const result = await archiveRepo(req.params.id, false)
return res.json({ ok: true, ...result })
} catch (err) {
const status = err.status || 500
return res.status(status).json({ error: err.message || 'Projekt konnte nicht reaktiviert werden' })
}
})
// Projekt einem Kunden/Ticket zuweisen -> stoesst Umzug nach GITEA_ORG + Nachtragen an
router.post('/:id/assign', async (req, res) => {
const { customerId, ticketId } = req.body || {}
if (!customerId && !ticketId) {
return res.status(400).json({ error: 'customerId oder ticketId erforderlich' })
}
try {
const result = await assignProject(req.params.id, {
customerId: String(customerId || ''),
ticketId: String(ticketId || ''),
})
return res.json({ ok: true, ...result })
} catch (err) {
if (err.status === 404) {
return res.status(404).json({ error: 'Projekt nicht gefunden' })
}
const status = err.status || 500
return res.status(status).json({ error: err.message })
}
})
// Zuordnen-Flow (WOMS): Art speichern, ggf. Ticket anlegen, Kunde/Ticket zuweisen, Preview
router.post('/:id/zuordnen', async (req, res) => {
const staffName = req.appwriteUser?.name || req.appwriteUser?.email || ''
try {
const result = await completeAssignment(req.params.id, req.body || {}, { staffName })
return res.json(result)
} catch (err) {
if (err.status === 409) {
return res.status(409).json({ error: 'bereits zugeordnet', kindSetBy: err.kindSetBy || '', kindSetAt: err.kindSetAt || '' })
}
const status = err.status || 500
return res.status(status).json({ error: err.message })
}
})
// Umzug + Pushes eines bereits zugewiesenen Projekts erneut nachtragen
router.post('/:id/pushes', async (req, res) => {
try {
const result = await reconcileProject(req.params.id)
return res.json({ ok: true, ...result })
} catch (err) {
if (err.status === 404) {
return res.status(404).json({ error: 'Projekt nicht gefunden' })
}
const status = err.status || 500
return res.status(status).json({ error: err.message })
}
})
export default router