Kundenansicht: News-Aenderungen mit Mitarbeiter und Titel protokollieren

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-01 19:30:47 +00:00
1 parent 25f3c1df4d
commit 7d8ba56088
3 files changed
+120

No files matched your search

+12
View File
@@ -4,6 +4,9 @@ import { assertOwnProject, getFeatureDoc } from '../services/siteFeatures.js'
import { NEWS_IMAGE_MAX_BYTES, newsImagePath, newsImageRateLimited, storeNewsImage } from '../services/newsImages.js'
import { createPost, deletePost, listPosts, updatePost } from '../services/newsPosts.js'
import { uploadSlot } from './chat.js'
import { config } from '../config.js'
import { getDocument } from '../services/appwriteAdmin.js'
import { logIfKundenansicht } from '../services/kundenansicht.js'
const router = Router()
@@ -41,6 +44,9 @@ function limitWrites(req, res, next) {
return next()
}
// Protokoll-Detail der Kundenansicht: Titel, sonst der Anfang des Textes
const postLabel = (post) => String(post?.title || '').trim() || String(post?.text || '').slice(0, 60)
const projectIdOf = (req) => {
const raw = req.query.projectId ?? req.body?.projectId
return typeof raw === 'string' ? raw : ''
@@ -78,6 +84,7 @@ router.get('/', requireSession, withProject(), async (req, res) => {
router.post('/', requireSession, withProject(), limitWrites, async (req, res) => {
try {
const post = await createPost({ customerId: getSessionCustomerId(req), projectId: req.projectId, input: req.body })
await logIfKundenansicht(req, 'news_angelegt', postLabel(post))
res.status(201).json(post)
} catch (err) {
fail(res, err)
@@ -100,6 +107,7 @@ router.post(
async (req, res) => {
try {
const image = await storeNewsImage({ customerId: getSessionCustomerId(req), projectId: req.projectId, buffer: req.body })
await logIfKundenansicht(req, 'news_bild')
res.status(201).json(image)
} catch (err) {
fail(res, err)
@@ -126,6 +134,7 @@ router.get('/image/:projectId/:file', requireSession, async (req, res) => {
router.patch('/:id', requireSession, withProject(), limitWrites, async (req, res) => {
try {
const post = await updatePost({ customerId: getSessionCustomerId(req), projectId: req.projectId, id: req.params.id, input: req.body })
await logIfKundenansicht(req, 'news_geaendert', postLabel(post))
res.json(post)
} catch (err) {
fail(res, err)
@@ -134,7 +143,10 @@ router.patch('/:id', requireSession, withProject(), limitWrites, async (req, res
router.delete('/:id', requireSession, withProject(), limitWrites, async (req, res) => {
try {
// Titel fuers Protokoll vor dem Loeschen lesen (deletePost prueft den Besitz danach selbst)
const before = req.session.viewId ? await getDocument(config.collections.newsPosts, req.params.id).catch(() => null) : null
await deletePost({ customerId: getSessionCustomerId(req), projectId: req.projectId, id: req.params.id })
await logIfKundenansicht(req, 'news_geloescht', postLabel(before))
res.status(204).end()
} catch (err) {
fail(res, err)
+13
View File
@@ -61,6 +61,19 @@ export function endKundenansicht(res) {
clearPreviewSession(res)
}
/** Aenderung in der Kundenansicht protokollieren; ausserhalb einer Kundenansicht (Kunde selbst) passiert nichts. */
export async function logIfKundenansicht(req, action, detail = '') {
const session = req.session
if (!isKundenansicht(session)) return
await logViewAction({
customerId: session.customerId,
staffUserId: session.appwriteUserId,
staffName: session.adminName,
action,
detail,
})
}
// "beendet"/"abgelaufen" je Ansicht nur einmal protokollieren (parallele Anfragen eines Tabs)
const LOGGED_TTL_MS = 3 * 60 * 60 * 1000
const logged = new Map()