File size: 7,258 Bytes
5486429 218d422 5486429 218d422 5486429 8843db1 5486429 8843db1 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 8843db1 218d422 5486429 218d422 5486429 218d422 80bfac4 5486429 218d422 5486429 218d422 5486429 218d422 5486429 218d422 5486429 8843db1 5486429 8843db1 5486429 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
/*
KSTools 版本管理系統 - Supabase Schema
Project 2: kstools-public (版本系統)
這個 schema 應該在第二個 Supabase Project 中執行
主要用於儲存版本資訊、下載記錄和檔案存儲
*/
-- 啟用必要的擴展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- ================================
-- 移除現有外鍵約束(如果存在)
-- ================================
-- 安全移除外鍵約束,不影響現有資料
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.table_constraints
WHERE constraint_name = 'fk_version'
AND table_name = 'download_logs'
) THEN
ALTER TABLE download_logs DROP CONSTRAINT fk_version;
END IF;
END $$;
-- ================================
-- 版本管理表(安全建立,如果不存在)
-- ================================
-- 版本表
CREATE TABLE IF NOT EXISTS versions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
version VARCHAR(20) NOT NULL UNIQUE,
title VARCHAR(255),
release_date TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
is_active BOOLEAN DEFAULT true,
download_url TEXT NOT NULL,
file_size BIGINT,
file_type VARCHAR(10) CHECK (file_type IN ('zip', 'exe', 'msi')) DEFAULT 'zip',
file_name TEXT NOT NULL,
changelog TEXT,
min_revit_version VARCHAR(10),
released_by VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 下載記錄表
CREATE TABLE IF NOT EXISTS download_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
version VARCHAR(20),
license_key VARCHAR(255),
action VARCHAR(20) CHECK (action IN ('download', 'update_check', 'install')),
user_agent TEXT,
ip_address INET,
downloaded_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- ================================
-- 索引優化
-- ================================
-- 版本表索引
CREATE INDEX IF NOT EXISTS idx_versions_version ON versions(version);
CREATE INDEX IF NOT EXISTS idx_versions_release_date ON versions(release_date DESC);
CREATE INDEX IF NOT EXISTS idx_versions_is_active ON versions(is_active);
-- 下載記錄表索引
CREATE INDEX IF NOT EXISTS idx_download_logs_version ON download_logs(version);
CREATE INDEX IF NOT EXISTS idx_download_logs_downloaded_at ON download_logs(downloaded_at DESC);
CREATE INDEX IF NOT EXISTS idx_download_logs_action ON download_logs(action);
-- ================================
-- Row Level Security (RLS) 政策
-- ================================
-- 啟用 RLS(如果尚未啟用)
DO $$
BEGIN
ALTER TABLE versions ENABLE ROW LEVEL SECURITY;
EXCEPTION
WHEN OTHERS THEN NULL;
END $$;
DO $$
BEGIN
ALTER TABLE download_logs ENABLE ROW LEVEL SECURITY;
EXCEPTION
WHEN OTHERS THEN NULL;
END $$;
-- 安全建立 RLS 政策(先刪除再建立)
DO $$
BEGIN
-- 版本表政策
DROP POLICY IF EXISTS "Public read versions" ON versions;
CREATE POLICY "Public read versions" ON versions
FOR SELECT USING (true);
DROP POLICY IF EXISTS "Service role insert versions" ON versions;
CREATE POLICY "Service role insert versions" ON versions
FOR INSERT WITH CHECK (auth.role() = 'service_role');
DROP POLICY IF EXISTS "Service role update versions" ON versions;
CREATE POLICY "Service role update versions" ON versions
FOR UPDATE USING (auth.role() = 'service_role');
-- 下載記錄表政策
DROP POLICY IF EXISTS "Service role all download_logs" ON download_logs;
CREATE POLICY "Service role all download_logs" ON download_logs
FOR ALL USING (auth.role() = 'service_role');
END $$;
-- ================================
-- Storage Bucket 設定
-- ================================
-- 安全建立 Storage Bucket(如果不存在)
DO $$
BEGIN
INSERT INTO storage.buckets (id, name, public)
VALUES ('plugin-releases', 'plugin-releases', true);
EXCEPTION
WHEN unique_violation THEN NULL; -- Bucket 已存在
END $$;
-- Storage RLS 政策設定(安全建立)
DO $$
BEGIN
-- 1. 允許公開讀取發布檔案
DROP POLICY IF EXISTS "Public read plugin releases" ON storage.objects;
CREATE POLICY "Public read plugin releases" ON storage.objects
FOR SELECT USING (bucket_id = 'plugin-releases');
-- 2. 允許 Service Role 管理檔案(上傳、更新、刪除)
DROP POLICY IF EXISTS "Service role manage plugin releases" ON storage.objects;
CREATE POLICY "Service role manage plugin releases" ON storage.objects
FOR ALL USING (auth.role() = 'service_role' AND bucket_id = 'plugin-releases');
-- 3. 允許認證用戶上傳檔案(可選,如果需要讓登入用戶上傳)
DROP POLICY IF EXISTS "Authenticated users upload plugin releases" ON storage.objects;
CREATE POLICY "Authenticated users upload plugin releases" ON storage.objects
FOR INSERT WITH CHECK (
bucket_id = 'plugin-releases' AND
auth.role() = 'authenticated'
);
END $$;
-- ================================
-- 觸發器:自動更新 updated_at
-- ================================
-- 建立更新時間觸發器函數
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- 安全建立觸發器(先刪除再建立)
DO $$
BEGIN
DROP TRIGGER IF EXISTS update_versions_updated_at ON versions;
CREATE TRIGGER update_versions_updated_at
BEFORE UPDATE ON versions
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
END $$;
-- ================================
-- 有用的查詢視圖
-- ================================
-- 安全建立視圖(先刪除再建立)
DROP VIEW IF EXISTS latest_version;
CREATE VIEW latest_version AS
SELECT *
FROM versions
WHERE is_active = true
ORDER BY release_date DESC
LIMIT 1;
DROP VIEW IF EXISTS version_stats;
CREATE VIEW version_stats AS
SELECT
v.version,
v.release_date,
COUNT(dl.id) as download_count,
COUNT(CASE WHEN dl.action = 'download' THEN 1 END) as actual_downloads,
COUNT(CASE WHEN dl.action = 'update_check' THEN 1 END) as update_checks
FROM versions v
LEFT JOIN download_logs dl ON v.version = dl.version
WHERE v.is_active = true
GROUP BY v.id, v.version, v.release_date
ORDER BY v.release_date DESC;
-- ================================
-- 資料表註解
-- ================================
COMMENT ON TABLE versions IS '插件版本資訊表';
COMMENT ON COLUMN versions.version IS '版本號,格式:x.y.z';
COMMENT ON COLUMN versions.title IS '版本標題,簡短描述版本特色';
COMMENT ON COLUMN versions.download_url IS '下載連結URL';
COMMENT ON COLUMN versions.file_size IS '檔案大小(位元組)';
COMMENT ON COLUMN versions.file_type IS '檔案類型:zip, exe, msi';
COMMENT ON COLUMN versions.file_name IS '檔案名稱,包含副檔名';
COMMENT ON COLUMN versions.changelog IS '更新日誌(Markdown格式)';
COMMENT ON COLUMN versions.min_revit_version IS '最小支援的Revit版本';
COMMENT ON TABLE download_logs IS '下載記錄表';
COMMENT ON COLUMN download_logs.action IS '操作類型:download, update_check, install'; |