Add Go/Postgres admin APIs, Angular admin UI, manual build flow, asset uploads, markdown import/export, configurable slug generation, and the Yar reading theme. Exclude local docs and generated development artifacts from version control.
100 lines
4 KiB
SQL
100 lines
4 KiB
SQL
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
username TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
last_login_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS posts (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
slug TEXT NOT NULL UNIQUE,
|
|
title TEXT NOT NULL,
|
|
summary TEXT NOT NULL DEFAULT '',
|
|
body_markdown TEXT NOT NULL DEFAULT '',
|
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
cover TEXT NOT NULL DEFAULT '',
|
|
version INTEGER NOT NULL DEFAULT 1,
|
|
slug_source TEXT NOT NULL DEFAULT 'manual',
|
|
slug_locked BOOLEAN NOT NULL DEFAULT false,
|
|
published_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
deleted_at TIMESTAMPTZ,
|
|
CONSTRAINT posts_status_check CHECK (status IN ('draft', 'published', 'archived', 'deleted')),
|
|
CONSTRAINT posts_version_check CHECK (version >= 1)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_posts_status ON posts(status);
|
|
CREATE INDEX IF NOT EXISTS idx_posts_published_at ON posts(published_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_posts_updated_at ON posts(updated_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS post_versions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
post_id UUID NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
|
|
version INTEGER NOT NULL,
|
|
title TEXT NOT NULL,
|
|
summary TEXT NOT NULL,
|
|
body_markdown TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
reason TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
CONSTRAINT post_versions_status_check CHECK (status IN ('draft', 'published', 'archived', 'deleted')),
|
|
CONSTRAINT post_versions_reason_check CHECK (reason IN ('save', 'publish', 'unpublish', 'archive', 'restore', 'import', 'rollback')),
|
|
CONSTRAINT post_versions_version_check CHECK (version >= 1),
|
|
UNIQUE (post_id, version)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_post_versions_post_id_created_at ON post_versions(post_id, created_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS tags (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL UNIQUE,
|
|
slug TEXT NOT NULL UNIQUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS post_tags (
|
|
post_id UUID NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
|
|
tag_id UUID NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
|
|
PRIMARY KEY (post_id, tag_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_post_tags_tag_id ON post_tags(tag_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS build_jobs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
trigger TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'queued',
|
|
post_id UUID REFERENCES posts(id) ON DELETE SET NULL,
|
|
started_at TIMESTAMPTZ,
|
|
finished_at TIMESTAMPTZ,
|
|
log TEXT NOT NULL DEFAULT '',
|
|
error TEXT NOT NULL DEFAULT '',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
CONSTRAINT build_jobs_trigger_check CHECK (trigger IN ('publish', 'manual', 'import', 'sync')),
|
|
CONSTRAINT build_jobs_status_check CHECK (status IN ('queued', 'running', 'success', 'failed', 'cancelled'))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_build_jobs_status_created_at ON build_jobs(status, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_build_jobs_post_id_created_at ON build_jobs(post_id, created_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS assets (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
path TEXT NOT NULL UNIQUE,
|
|
original_name TEXT NOT NULL,
|
|
mime_type TEXT NOT NULL,
|
|
size_bytes BIGINT NOT NULL,
|
|
sha256 TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
CONSTRAINT assets_size_bytes_check CHECK (size_bytes >= 0)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_assets_sha256 ON assets(sha256);
|