126 lines
6.4 KiB
PL/PgSQL
126 lines
6.4 KiB
PL/PgSQL
-- Migration 053: Issues rework
|
|
-- 1. Fix update trigger bug (uses wrong column name)
|
|
-- 2. Dynamic issue types table (issue_typen)
|
|
-- 3. Migrate issues.typ → issues.typ_id
|
|
-- 4. Permission rework: replace issues:manage with granular permissions
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- 1. Fix update trigger
|
|
-- The old trigger calls update_aktualisiert_am() which sets NEW.aktualisiert_am,
|
|
-- but issues table uses updated_at → crashes every UPDATE.
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
DROP TRIGGER IF EXISTS trg_issues_updated ON issues;
|
|
|
|
CREATE OR REPLACE FUNCTION update_issues_updated_at()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_issues_updated BEFORE UPDATE ON issues
|
|
FOR EACH ROW EXECUTE FUNCTION update_issues_updated_at();
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- 2. Dynamic types table
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
CREATE TABLE IF NOT EXISTS issue_typen (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(100) NOT NULL,
|
|
parent_id INT REFERENCES issue_typen(id) ON DELETE CASCADE,
|
|
icon VARCHAR(50) DEFAULT NULL,
|
|
farbe VARCHAR(20) DEFAULT NULL,
|
|
erlaubt_abgelehnt BOOLEAN NOT NULL DEFAULT true,
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
aktiv BOOLEAN NOT NULL DEFAULT true,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_issue_typen_parent ON issue_typen(parent_id);
|
|
|
|
-- Seed default types
|
|
INSERT INTO issue_typen (id, name, parent_id, icon, farbe, erlaubt_abgelehnt, sort_order) VALUES
|
|
(1, 'Bug', NULL, 'BugReport', 'error', false, 1),
|
|
(2, 'Funktionsanfrage', NULL, 'FiberNew', 'info', true, 2),
|
|
(3, 'Sonstiges', NULL, 'HelpOutline', 'action', true, 3)
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- Ensure sequence is past seeded IDs
|
|
SELECT setval('issue_typen_id_seq', GREATEST((SELECT MAX(id) FROM issue_typen), 3));
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- 3. Migrate issues.typ column → typ_id FK
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
ALTER TABLE issues ADD COLUMN IF NOT EXISTS typ_id INT REFERENCES issue_typen(id) ON DELETE SET NULL;
|
|
|
|
-- Migrate existing data
|
|
UPDATE issues SET typ_id = 1 WHERE typ = 'bug' AND typ_id IS NULL;
|
|
UPDATE issues SET typ_id = 2 WHERE typ = 'feature' AND typ_id IS NULL;
|
|
UPDATE issues SET typ_id = 3 WHERE typ = 'sonstiges' AND typ_id IS NULL;
|
|
-- Fallback: anything unmapped → Sonstiges
|
|
UPDATE issues SET typ_id = 3 WHERE typ_id IS NULL;
|
|
|
|
-- Drop old constraint and column
|
|
ALTER TABLE issues DROP CONSTRAINT IF EXISTS issues_typ_check;
|
|
ALTER TABLE issues DROP COLUMN IF EXISTS typ;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_issues_typ_id ON issues(typ_id);
|
|
CREATE INDEX IF NOT EXISTS idx_issues_zugewiesen_an ON issues(zugewiesen_an);
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- 4. Permission rework
|
|
-- Replace issues:manage with granular permissions
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
-- 4a. Find all groups that had issues:manage and give them the new permissions
|
|
-- We use a temp table to store the groups that had manage
|
|
CREATE TEMP TABLE IF NOT EXISTS _issues_manage_groups AS
|
|
SELECT authentik_group FROM group_permissions WHERE permission_id = 'issues:manage';
|
|
|
|
-- 4b. Insert new permissions
|
|
INSERT INTO permissions (id, feature_group_id, label, description, sort_order) VALUES
|
|
('issues:change_status', 'issues', 'Status ändern', 'Status ändern und kommentieren', 4),
|
|
('issues:edit', 'issues', 'Bearbeiten', 'Issues bearbeiten (Titel, Beschreibung, Typ, Priorität, Zuweisung)', 5),
|
|
('issues:edit_settings', 'issues', 'Einstellungen', 'Issue-Kategorien verwalten', 6),
|
|
('issues:delete', 'issues', 'Löschen', 'Issues löschen', 7)
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- 4c. Grant all new permissions to groups that had manage
|
|
INSERT INTO group_permissions (authentik_group, permission_id)
|
|
SELECT g.authentik_group, p.id
|
|
FROM _issues_manage_groups g
|
|
CROSS JOIN (VALUES
|
|
('issues:view_all'),
|
|
('issues:change_status'),
|
|
('issues:edit'),
|
|
('issues:edit_settings'),
|
|
('issues:delete')
|
|
) AS p(id)
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
-- 4d. Remove old manage permission
|
|
DELETE FROM group_permissions WHERE permission_id = 'issues:manage';
|
|
DELETE FROM permissions WHERE id = 'issues:manage';
|
|
|
|
DROP TABLE IF EXISTS _issues_manage_groups;
|
|
|
|
-- 4e. Update permission_deps in app_settings JSON
|
|
-- Remove old issues entries and add new ones
|
|
UPDATE app_settings
|
|
SET value = jsonb_strip_nulls(
|
|
(value - 'issues:view_own' - 'issues:view_all' - 'issues:manage')
|
|
|| '{
|
|
"issues:create": ["issues:view_own"],
|
|
"issues:view_all": ["issues:view_own"],
|
|
"issues:change_status": ["issues:view_all"],
|
|
"issues:edit": ["issues:view_all"],
|
|
"issues:delete": ["issues:view_all"],
|
|
"issues:edit_settings": ["issues:view_all"]
|
|
}'::jsonb
|
|
)
|
|
WHERE key = 'permission_deps';
|