Add docs CMS: blog authoring, access policies, sharing, version history, templates, metadata, search, Gitea auto-setup

7 documentation system features:
- Blog authoring: frontmatter panel, new post wizard, authors management
- Access policies: per-file/directory edit restrictions with role/user granularity
- Public sharing: share links with collaborative editing via dual JWT auth
- Version history: Gitea auto-commit on save, diff viewer, restore
- Document templates: 8 built-in templates (blog, guide, API ref, ADR, FAQ, etc.)
- Metadata dashboard: overview of all docs with warnings (no-tags, stale, etc.)
- Content search: in-file text search with line-level matches

Gitea auto-setup: one-click configuration of API token, repos, labels, OAuth app
- Backend service + startup hook (auto-configures if GITEA_ADMIN_PASSWORD set)
- Admin GUI wizard at /app/services/gitea/setup
- config.sh now prompts for Gitea admin password

Backend: 10 new files, 5 modified (3 models, 1 enum, 2 migrations, 30+ API endpoints)
Frontend: 13 new files, 3 modified (hooks, components, pages)

Bunker Admin
This commit is contained in:
2026-03-27 13:28:52 -06:00
parent 0fc9ea80bf
commit 8b9ab93856
37 changed files with 6273 additions and 61 deletions

View File

@@ -0,0 +1,76 @@
-- CreateEnum
CREATE TYPE "DocShareLinkStatus" AS ENUM ('ACTIVE', 'REVOKED', 'EXPIRED');
-- AlterEnum
ALTER TYPE "ContactActivityType" ADD VALUE IF NOT EXISTS 'POLL_VOTED';
-- CreateTable
CREATE TABLE "doc_access_policies" (
"id" TEXT NOT NULL,
"document_path" TEXT NOT NULL,
"is_directory" BOOLEAN NOT NULL DEFAULT false,
"allowed_editors" JSONB NOT NULL DEFAULT '[]',
"created_by_id" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "doc_access_policies_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "doc_share_links" (
"id" TEXT NOT NULL,
"document_path" TEXT NOT NULL,
"share_token" TEXT NOT NULL,
"status" "DocShareLinkStatus" NOT NULL DEFAULT 'ACTIVE',
"can_edit" BOOLEAN NOT NULL DEFAULT true,
"expires_at" TIMESTAMP(3),
"max_uses" INTEGER,
"use_count" INTEGER NOT NULL DEFAULT 0,
"guest_name" TEXT,
"created_by_id" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "doc_share_links_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "doc_watches" (
"id" TEXT NOT NULL,
"user_id" TEXT NOT NULL,
"file_path" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "doc_watches_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "doc_access_policies_document_path_key" ON "doc_access_policies"("document_path");
-- CreateIndex
CREATE INDEX "doc_access_policies_created_by_id_idx" ON "doc_access_policies"("created_by_id");
-- CreateIndex
CREATE UNIQUE INDEX "doc_share_links_share_token_key" ON "doc_share_links"("share_token");
-- CreateIndex
CREATE INDEX "doc_share_links_document_path_idx" ON "doc_share_links"("document_path");
-- CreateIndex
CREATE INDEX "doc_share_links_created_by_id_idx" ON "doc_share_links"("created_by_id");
-- CreateIndex
CREATE INDEX "doc_watches_file_path_idx" ON "doc_watches"("file_path");
-- CreateIndex
CREATE UNIQUE INDEX "doc_watches_user_id_file_path_key" ON "doc_watches"("user_id", "file_path");
-- AddForeignKey
ALTER TABLE "doc_access_policies" ADD CONSTRAINT "doc_access_policies_created_by_id_fkey" FOREIGN KEY ("created_by_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "doc_share_links" ADD CONSTRAINT "doc_share_links_created_by_id_fkey" FOREIGN KEY ("created_by_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "doc_watches" ADD CONSTRAINT "doc_watches_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "site_settings" ADD COLUMN "gitea_setup_complete" BOOLEAN NOT NULL DEFAULT false;