Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Owners demoted on their own roster before tbu_team_roster existed. The
-- rebalancing GUC keeps the roster cap trigger out of a role-only update.
SELECT set_config('fivestack.rebalancing', 'true', true);

UPDATE public.team_roster tr
SET role = 'Admin'
FROM public.teams t
WHERE t.id = tr.team_id
AND tr.player_steam_id = t.owner_steam_id
AND tr.role <> 'Admin';

SELECT set_config('fivestack.rebalancing', 'false', true);
36 changes: 36 additions & 0 deletions hasura/triggers/team_roster.sql
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,32 @@ $$;
DROP TRIGGER IF EXISTS tbd_team_roster ON public.team_roster;
CREATE TRIGGER tbd_team_roster BEFORE DELETE ON public.team_roster FOR EACH ROW EXECUTE FUNCTION public.tbd_team_roster();

-- Same reasoning as tbd_team_roster: the roster update permission is granted by
-- the Admin role, so an owner demoted by another Admin could no longer manage
-- their own team. Staff are held to it too; ownership moves first.
CREATE OR REPLACE FUNCTION public.tbu_team_roster() RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.role IS DISTINCT FROM OLD.role
AND NEW.role <> 'Admin'
AND EXISTS (
SELECT 1
FROM teams t
WHERE t.id = NEW.team_id
AND t.owner_steam_id = NEW.player_steam_id
) THEN
RAISE EXCEPTION USING ERRCODE = '22000',
MESSAGE = 'The team owner must stay an Admin; transfer ownership first';
END IF;

RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS tbu_team_roster ON public.team_roster;
CREATE TRIGGER tbu_team_roster BEFORE UPDATE ON public.team_roster FOR EACH ROW EXECUTE FUNCTION public.tbu_team_roster();

CREATE OR REPLACE FUNCTION public.tad_team_roster() RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
Expand Down Expand Up @@ -128,6 +154,16 @@ BEGIN
RETURN NEW;
END IF;

-- The caps count rows by status alone (coaches included), so an update that
-- keeps the row's status and team cannot change any tier's count. Skipping
-- it keeps role and coach edits working on a roster that is already over a
-- cap, e.g. after team_max_subs() was lowered.
IF TG_OP = 'UPDATE'
AND NEW.status IS NOT DISTINCT FROM OLD.status
AND NEW.team_id = OLD.team_id THEN
RETURN NEW;
END IF;

IF NEW.status = 'Starter' THEN
_max := 5;
SELECT COUNT(*) INTO _count FROM public.team_roster
Expand Down
52 changes: 52 additions & 0 deletions hasura/triggers/teams.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,16 @@ $$;
DROP TRIGGER IF EXISTS tai_teams ON public.teams;
CREATE TRIGGER tai_teams AFTER INSERT ON public.teams FOR EACH ROW EXECUTE FUNCTION public.tai_teams();

-- The user update permission on teams lets any roster Admin write
-- owner_steam_id, so ownership transfer is gated here: only the current owner
-- or staff may hand it over. A session with no role is an internal write and
-- stays unrestricted.
CREATE OR REPLACE FUNCTION public.tbu_teams() RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
DECLARE
_session json;
_role text;
BEGIN
IF NEW.captain_steam_id IS NOT NULL
AND NEW.captain_steam_id IS DISTINCT FROM OLD.captain_steam_id
Expand All @@ -29,9 +36,54 @@ BEGIN
RAISE EXCEPTION 'Team captain must be a team member' USING ERRCODE = '22000';
END IF;

IF NEW.owner_steam_id IS DISTINCT FROM OLD.owner_steam_id THEN
_session := nullif(current_setting('hasura.user', true), '')::json;
_role := _session ->> 'x-hasura-role';

IF _role IS NOT NULL
AND _role NOT IN ('admin', 'administrator', 'tournament_organizer')
AND nullif(_session ->> 'x-hasura-user-id', '')::bigint IS DISTINCT FROM OLD.owner_steam_id THEN
RAISE EXCEPTION USING ERRCODE = '22000',
MESSAGE = 'Only the team owner can transfer ownership';
END IF;

IF NEW.owner_steam_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM team_roster tr
WHERE tr.team_id = NEW.id
AND tr.player_steam_id = NEW.owner_steam_id
) THEN
RAISE EXCEPTION USING ERRCODE = '22000',
MESSAGE = 'The new team owner must be a team member';
END IF;
END IF;

RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS tbu_teams ON public.teams;
CREATE TRIGGER tbu_teams BEFORE UPDATE ON public.teams FOR EACH ROW EXECUTE FUNCTION public.tbu_teams();

-- can_change_team_role trusts owner_steam_id, but the roster write permission
-- trusts the roster role, so a new owner is made an Admin on the roster too.
CREATE OR REPLACE FUNCTION public.tau_teams() RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE team_roster
SET role = 'Admin'
WHERE team_id = NEW.id
AND player_steam_id = NEW.owner_steam_id
AND role <> 'Admin';

RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS tau_teams ON public.teams;
CREATE TRIGGER tau_teams AFTER UPDATE ON public.teams
FOR EACH ROW
WHEN (NEW.owner_steam_id IS DISTINCT FROM OLD.owner_steam_id)
EXECUTE FUNCTION public.tau_teams();
Loading
Loading