docs(examples): add the CMS proof-of-concept dogfooding artifact
A WordPress-inspired CMS whose entire backend is PiCloud Rhai scripts deployed with pic apply, plus a SvelteKit frontend. Built to dogfood the project tool, CLI, and SDK; exercises docs/kv/files/users, docs+queue+cron +pubsub triggers, the transactional-outbox notification chain, a docs before-interceptor, set_if CAS, SSE, per-app CORS, env overlays, and a durable Workflow (validate -> enrich || seo -> publish -> finalize) started with workflow::start and polled with workflow::run_status, visualized live with Svelte Flow. FINDINGS.md / SECURITY.md capture every gap, surprise, and security issue found (each tagged [PiCloud] vs [CMS]); the platform fixes for the actionable ones ship in the preceding commit. Also folds in the read-only `pic` allowlist entries added to .claude/settings.json during the session (fewer-permission-prompts). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
39
examples/cms-poc/scripts/comments/comment_create.rhai
Normal file
39
examples/cms-poc/scripts/comments/comment_create.rhai
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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" } }
|
||||
Reference in New Issue
Block a user