forked from wrenn/wrenn
Seed minimal template in DB and protect it from deletion
Insert a minimal template row (all-zeros UUID) so it appears in both team and admin template listings. Guard delete endpoints to prevent removal of the minimal template.
This commit is contained in:
@ -12,6 +12,7 @@ ALTER TABLE templates ADD CONSTRAINT uq_templates_team_name UNIQUE (team_id, nam
|
|||||||
|
|
||||||
-- 3. Prevent team templates from using names that belong to global (platform) templates.
|
-- 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.
|
-- A team template insert/update with a name matching any platform template is rejected.
|
||||||
|
-- +goose StatementBegin
|
||||||
CREATE OR REPLACE FUNCTION check_global_template_name_collision()
|
CREATE OR REPLACE FUNCTION check_global_template_name_collision()
|
||||||
RETURNS TRIGGER AS $$
|
RETURNS TRIGGER AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -28,13 +29,27 @@ BEGIN
|
|||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$$ LANGUAGE plpgsql;
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
CREATE TRIGGER trg_check_global_template_name
|
CREATE TRIGGER trg_check_global_template_name
|
||||||
BEFORE INSERT OR UPDATE ON templates
|
BEFORE INSERT OR UPDATE ON templates
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
EXECUTE FUNCTION check_global_template_name_collision();
|
EXECUTE FUNCTION check_global_template_name_collision();
|
||||||
|
|
||||||
-- 4. Add template UUID references to template_builds.
|
-- 4. Seed the built-in "minimal" template so it appears in all listings.
|
||||||
|
-- Both id and team_id are the all-zeros UUID (platform sentinel).
|
||||||
|
INSERT INTO templates (id, name, type, vcpus, memory_mb, size_bytes, team_id)
|
||||||
|
VALUES (
|
||||||
|
'00000000-0000-0000-0000-000000000000',
|
||||||
|
'minimal',
|
||||||
|
'base',
|
||||||
|
1,
|
||||||
|
512,
|
||||||
|
0,
|
||||||
|
'00000000-0000-0000-0000-000000000000'
|
||||||
|
) ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
|
-- 5. Add template UUID references to template_builds.
|
||||||
ALTER TABLE template_builds
|
ALTER TABLE template_builds
|
||||||
ADD COLUMN template_id UUID,
|
ADD COLUMN template_id UUID,
|
||||||
ADD COLUMN team_id UUID;
|
ADD COLUMN team_id UUID;
|
||||||
@ -54,6 +69,9 @@ ALTER TABLE template_builds
|
|||||||
DROP COLUMN IF EXISTS team_id,
|
DROP COLUMN IF EXISTS team_id,
|
||||||
DROP COLUMN IF EXISTS template_id;
|
DROP COLUMN IF EXISTS template_id;
|
||||||
|
|
||||||
|
-- Remove the seeded minimal template.
|
||||||
|
DELETE FROM templates WHERE id = '00000000-0000-0000-0000-000000000000';
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS trg_check_global_template_name ON templates;
|
DROP TRIGGER IF EXISTS trg_check_global_template_name ON templates;
|
||||||
DROP FUNCTION IF EXISTS check_global_template_name_collision();
|
DROP FUNCTION IF EXISTS check_global_template_name_collision();
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/db"
|
"git.omukk.dev/wrenn/sandbox/internal/db"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/id"
|
"git.omukk.dev/wrenn/sandbox/internal/id"
|
||||||
|
"git.omukk.dev/wrenn/sandbox/internal/layout"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/lifecycle"
|
"git.omukk.dev/wrenn/sandbox/internal/lifecycle"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/service"
|
"git.omukk.dev/wrenn/sandbox/internal/service"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/validate"
|
"git.omukk.dev/wrenn/sandbox/internal/validate"
|
||||||
@ -221,6 +222,10 @@ func (h *buildHandler) DeleteTemplate(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeError(w, http.StatusNotFound, "not_found", "template not found")
|
writeError(w, http.StatusNotFound, "not_found", "template not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if layout.IsMinimal(tmpl.TeamID, tmpl.ID) {
|
||||||
|
writeError(w, http.StatusForbidden, "forbidden", "the minimal template cannot be deleted")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Broadcast delete to all online hosts.
|
// Broadcast delete to all online hosts.
|
||||||
hosts, _ := h.db.ListActiveHosts(ctx)
|
hosts, _ := h.db.ListActiveHosts(ctx)
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import (
|
|||||||
"git.omukk.dev/wrenn/sandbox/internal/auth"
|
"git.omukk.dev/wrenn/sandbox/internal/auth"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/db"
|
"git.omukk.dev/wrenn/sandbox/internal/db"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/id"
|
"git.omukk.dev/wrenn/sandbox/internal/id"
|
||||||
|
"git.omukk.dev/wrenn/sandbox/internal/layout"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/lifecycle"
|
"git.omukk.dev/wrenn/sandbox/internal/lifecycle"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/service"
|
"git.omukk.dev/wrenn/sandbox/internal/service"
|
||||||
"git.omukk.dev/wrenn/sandbox/internal/validate"
|
"git.omukk.dev/wrenn/sandbox/internal/validate"
|
||||||
@ -271,6 +272,10 @@ func (h *snapshotHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeError(w, http.StatusForbidden, "forbidden", "platform templates cannot be deleted here")
|
writeError(w, http.StatusForbidden, "forbidden", "platform templates cannot be deleted here")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if layout.IsMinimal(tmpl.TeamID, tmpl.ID) {
|
||||||
|
writeError(w, http.StatusForbidden, "forbidden", "the minimal template cannot be deleted")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := h.deleteSnapshotBroadcast(ctx, tmpl.TeamID, tmpl.ID); err != nil {
|
if err := h.deleteSnapshotBroadcast(ctx, tmpl.TeamID, tmpl.ID); err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, "agent_error", "failed to delete snapshot files")
|
writeError(w, http.StatusInternalServerError, "agent_error", "failed to delete snapshot files")
|
||||||
|
|||||||
Reference in New Issue
Block a user