forked from wrenn/wrenn
Add UUID-based template IDs and team-scoped template directory layout
Introduces internal/layout package for centralized path construction,
migrates templates from name-based TEXT primary keys to UUID PKs with
team-scoped directories (WRENN_DIR/images/teams/{team_id}/{template_id}).
The built-in minimal template uses sentinel zero UUIDs. Proto messages
carry team_id + template_id alongside deprecated template name field.
Team deletion now cleans up template files across all hosts.
This commit is contained in:
64
db/migrations/20260328162803_template_uuid_pk.sql
Normal file
64
db/migrations/20260328162803_template_uuid_pk.sql
Normal file
@ -0,0 +1,64 @@
|
||||
-- +goose Up
|
||||
|
||||
-- 1. Add UUID id column to templates and make it the primary key.
|
||||
ALTER TABLE templates ADD COLUMN id UUID DEFAULT gen_random_uuid();
|
||||
UPDATE templates SET id = gen_random_uuid() WHERE id IS NULL;
|
||||
ALTER TABLE templates ALTER COLUMN id SET NOT NULL;
|
||||
ALTER TABLE templates DROP CONSTRAINT templates_pkey;
|
||||
ALTER TABLE templates ADD PRIMARY KEY (id);
|
||||
|
||||
-- 2. Name becomes a display field with team-scoped uniqueness.
|
||||
ALTER TABLE templates ADD CONSTRAINT uq_templates_team_name UNIQUE (team_id, name);
|
||||
|
||||
-- 3. Prevent team templates from using names that belong to global (platform) templates.
|
||||
-- A team template insert/update with a name matching any platform template is rejected.
|
||||
CREATE OR REPLACE FUNCTION check_global_template_name_collision()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF NEW.team_id != '00000000-0000-0000-0000-000000000000' THEN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM templates
|
||||
WHERE name = NEW.name
|
||||
AND team_id = '00000000-0000-0000-0000-000000000000'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'template name "%" is reserved by a global template', NEW.name
|
||||
USING ERRCODE = 'unique_violation';
|
||||
END IF;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_check_global_template_name
|
||||
BEFORE INSERT OR UPDATE ON templates
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION check_global_template_name_collision();
|
||||
|
||||
-- 4. Add template UUID references to template_builds.
|
||||
ALTER TABLE template_builds
|
||||
ADD COLUMN template_id UUID,
|
||||
ADD COLUMN team_id UUID;
|
||||
|
||||
-- 5. Add template UUID references to sandboxes.
|
||||
ALTER TABLE sandboxes
|
||||
ADD COLUMN template_id UUID,
|
||||
ADD COLUMN template_team_id UUID;
|
||||
|
||||
-- +goose Down
|
||||
|
||||
ALTER TABLE sandboxes
|
||||
DROP COLUMN IF EXISTS template_team_id,
|
||||
DROP COLUMN IF EXISTS template_id;
|
||||
|
||||
ALTER TABLE template_builds
|
||||
DROP COLUMN IF EXISTS team_id,
|
||||
DROP COLUMN IF EXISTS template_id;
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_check_global_template_name ON templates;
|
||||
DROP FUNCTION IF EXISTS check_global_template_name_collision();
|
||||
|
||||
ALTER TABLE templates DROP CONSTRAINT IF EXISTS uq_templates_team_name;
|
||||
|
||||
ALTER TABLE templates DROP CONSTRAINT IF EXISTS templates_pkey;
|
||||
ALTER TABLE templates ADD PRIMARY KEY (name);
|
||||
ALTER TABLE templates DROP COLUMN IF EXISTS id;
|
||||
@ -1,6 +1,6 @@
|
||||
-- name: InsertSandbox :one
|
||||
INSERT INTO sandboxes (id, team_id, host_id, template, status, vcpus, memory_mb, timeout_sec, disk_size_mb)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
INSERT INTO sandboxes (id, team_id, host_id, template, status, vcpus, memory_mb, timeout_sec, disk_size_mb, template_id, template_team_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetSandbox :one
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
-- name: InsertTemplateBuild :one
|
||||
INSERT INTO template_builds (id, name, base_template, recipe, healthcheck, vcpus, memory_mb, status, total_steps)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, 'pending', $8)
|
||||
INSERT INTO template_builds (id, name, base_template, recipe, healthcheck, vcpus, memory_mb, status, total_steps, template_id, team_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, 'pending', $8, $9, $10)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTemplateBuild :one
|
||||
|
||||
@ -1,15 +1,23 @@
|
||||
-- name: InsertTemplate :one
|
||||
INSERT INTO templates (name, type, vcpus, memory_mb, size_bytes, team_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
INSERT INTO templates (id, name, type, vcpus, memory_mb, size_bytes, team_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTemplate :one
|
||||
SELECT * FROM templates WHERE name = $1;
|
||||
SELECT * FROM templates WHERE id = $1;
|
||||
|
||||
-- name: GetTemplateByTeam :one
|
||||
-- Platform templates (team_id = 00000000-...) are visible to all teams.
|
||||
SELECT * FROM templates WHERE name = $1 AND (team_id = $2 OR team_id = '00000000-0000-0000-0000-000000000000');
|
||||
|
||||
-- name: GetTemplateByName :one
|
||||
-- Look up a template by team_id and name (exact team match, no global fallback).
|
||||
SELECT * FROM templates WHERE team_id = $1 AND name = $2;
|
||||
|
||||
-- name: GetPlatformTemplateByName :one
|
||||
-- Check if a global (platform) template exists with the given name.
|
||||
SELECT * FROM templates WHERE team_id = '00000000-0000-0000-0000-000000000000' AND name = $1;
|
||||
|
||||
-- name: ListTemplates :many
|
||||
SELECT * FROM templates ORDER BY created_at DESC;
|
||||
|
||||
@ -25,7 +33,15 @@ SELECT * FROM templates WHERE (team_id = $1 OR team_id = '00000000-0000-0000-000
|
||||
SELECT * FROM templates WHERE (team_id = $1 OR team_id = '00000000-0000-0000-0000-000000000000') AND type = $2 ORDER BY created_at DESC;
|
||||
|
||||
-- name: DeleteTemplate :exec
|
||||
DELETE FROM templates WHERE name = $1;
|
||||
DELETE FROM templates WHERE id = $1;
|
||||
|
||||
-- name: DeleteTemplateByTeam :exec
|
||||
DELETE FROM templates WHERE name = $1 AND team_id = $2;
|
||||
|
||||
-- name: DeleteTemplatesByTeam :exec
|
||||
-- Bulk delete all templates owned by a team (for team soft-delete cleanup).
|
||||
DELETE FROM templates WHERE team_id = $1;
|
||||
|
||||
-- name: ListTemplatesByTeamOnly :many
|
||||
-- List templates owned by a specific team (NOT including platform templates).
|
||||
SELECT * FROM templates WHERE team_id = $1 ORDER BY created_at DESC;
|
||||
|
||||
Reference in New Issue
Block a user