// POST /cms/posts/:id/comments — submit a comment (public, rate-limited). // The docs `before` interceptor (comment_sanitize) escapes the body and sets // the moderation status; this endpoint just validates + writes. let post_id = ctx.request.params.id; let b = ctx.request.body; if b == () || b.body == () || b.author_name == () { return #{ statusCode: 400, body: #{ error: "author_name and body required" } }; } // the post must exist and be published let posts = docs::collection("posts"); let pd = posts.get(post_id); if pd == () || pd.data.status != "published" { return #{ statusCode: 404, body: #{ error: "post not found" } }; } // rate limit: max 10 comments / hour / IP let ip = ctx.request.headers["x-forwarded-for"]; if ip == () { ip = "local"; } let rl = kv::collection("ratelimit"); let bk = "comment:" + ip; let cur = rl.get(bk); let cnt = if cur == () { 0 } else { cur.count }; if cnt >= 10 { return #{ statusCode: 429, body: #{ error: "slow down" } }; } rl.set(bk, #{ count: cnt + 1, at: time::now() }); let comments = docs::collection("comments"); let data = #{ post_id: post_id, post_slug: pd.data.slug, post_title: pd.data.title, author_name: b.author_name, author_email: if b.author_email == () { "" } else { b.author_email }, body: b.body, status: "pending", // interceptor re-affirms/overrides created_at: time::now(), }; let id = comments.create(data); // <- interceptor sanitizes + sets status here #{ statusCode: 201, body: #{ id: id, status: "submitted" } }