Add project:manage_members, CSP frame-src, task-run member view, CreateUser tx error handling, ERR_NO_PROJECT chat gate, and creator-scoped project name/client_key uniqueness to stop duplicate creates and auth gaps. Co-authored-by: Cursor <cursoragent@cursor.com>
42 lines
1.5 KiB
SQL
42 lines
1.5 KiB
SQL
-- +goose Up
|
|
-- 创建项目幂等键 + 同创建人下项目名唯一(防双击/重试重复行)。
|
|
-- 约束粒度:同一 creator_user_id 内 name 唯一(允许不同团队同名项目)。
|
|
|
|
ALTER TABLE projects
|
|
ADD COLUMN IF NOT EXISTS client_key TEXT NULL;
|
|
|
|
COMMENT ON COLUMN projects.client_key IS
|
|
'Optional client idempotency key; same creator+key returns the existing project.';
|
|
|
|
-- Deduplicate same-creator same-name rows before unique index (keep lowest id).
|
|
WITH dups AS (
|
|
SELECT id,
|
|
ROW_NUMBER() OVER (
|
|
PARTITION BY creator_user_id, lower(trim(name))
|
|
ORDER BY id ASC
|
|
) AS rn
|
|
FROM projects
|
|
WHERE creator_user_id IS NOT NULL
|
|
AND creator_user_id > 0
|
|
AND length(trim(name)) > 0
|
|
)
|
|
UPDATE projects p
|
|
SET name = p.name || ' (dup-' || p.id || ')'
|
|
FROM dups d
|
|
WHERE p.id = d.id AND d.rn > 1;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_projects_creator_client_key
|
|
ON projects (creator_user_id, client_key)
|
|
WHERE client_key IS NOT NULL AND length(trim(client_key)) > 0
|
|
AND creator_user_id IS NOT NULL AND creator_user_id > 0;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_projects_creator_name
|
|
ON projects (creator_user_id, lower(trim(name)))
|
|
WHERE creator_user_id IS NOT NULL AND creator_user_id > 0
|
|
AND length(trim(name)) > 0;
|
|
|
|
-- +goose Down
|
|
DROP INDEX IF EXISTS uq_projects_creator_name;
|
|
DROP INDEX IF EXISTS uq_projects_creator_client_key;
|
|
ALTER TABLE projects DROP COLUMN IF EXISTS client_key;
|