214 lines
7.2 KiB
PL/PgSQL
214 lines
7.2 KiB
PL/PgSQL
-- Administrators are management-plane identities only. Remove any legacy
|
|
-- execution bindings and reject every future database write that would make
|
|
-- an administrator a task creator, assignee, channel owner, browser worker,
|
|
-- or business-route grantee.
|
|
|
|
UPDATE tasks task
|
|
SET assigned_user_id = NULL,
|
|
lease_owner = NULL,
|
|
lease_expires_at = NULL,
|
|
updated_at = now()
|
|
FROM users account
|
|
WHERE account.organization_id = task.organization_id
|
|
AND account.id = task.assigned_user_id
|
|
AND account.role = 'admin';
|
|
|
|
UPDATE user_channels channel
|
|
SET owner_user_id = NULL,
|
|
enabled = false,
|
|
status = 'disabled',
|
|
last_error = '管理员账号已与任务执行面隔离,渠道绑定已解除。',
|
|
updated_at = now()
|
|
FROM users account
|
|
WHERE account.organization_id = channel.organization_id
|
|
AND account.id = channel.owner_user_id
|
|
AND account.role = 'admin';
|
|
|
|
UPDATE browser_connections connection
|
|
SET status = 'superseded',
|
|
erp_account_verified = false
|
|
FROM users account
|
|
WHERE account.organization_id = connection.organization_id
|
|
AND account.id = connection.user_id
|
|
AND account.role = 'admin'
|
|
AND connection.status = 'connected';
|
|
|
|
DELETE FROM user_business_route_authorizations route_grant
|
|
USING users account
|
|
WHERE account.organization_id = route_grant.organization_id
|
|
AND account.id = route_grant.user_id
|
|
AND account.role = 'admin';
|
|
|
|
UPDATE leader_task_summary_subscriptions subscription
|
|
SET enabled = false,
|
|
target_verified_at = NULL,
|
|
revision = revision + 1,
|
|
updated_at = now()
|
|
FROM users account
|
|
WHERE account.organization_id = subscription.organization_id
|
|
AND account.id = subscription.leader_user_id
|
|
AND account.role = 'admin';
|
|
|
|
UPDATE leader_task_summary_deliveries delivery
|
|
SET delivery_status = 'cancelled',
|
|
last_error = '管理员账号已与任务数据面隔离,组长任务摘要投递已取消。',
|
|
updated_at = now()
|
|
FROM users account
|
|
WHERE account.organization_id = delivery.organization_id
|
|
AND account.id = delivery.leader_user_id
|
|
AND account.role = 'admin'
|
|
AND delivery.delivery_status IN ('pending', 'sending', 'failed');
|
|
|
|
CREATE OR REPLACE FUNCTION reject_admin_task_principal()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
principal_id uuid;
|
|
principal_role text;
|
|
BEGIN
|
|
principal_id := NULLIF(to_jsonb(NEW) ->> TG_ARGV[0], '')::uuid;
|
|
IF principal_id IS NULL THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
SELECT role
|
|
INTO principal_role
|
|
FROM users
|
|
WHERE organization_id = NEW.organization_id
|
|
AND id = principal_id
|
|
FOR SHARE;
|
|
|
|
IF principal_role = 'admin' THEN
|
|
RAISE EXCEPTION USING
|
|
ERRCODE = '23514',
|
|
CONSTRAINT = TG_ARGV[1],
|
|
MESSAGE = 'administrator identities cannot enter the task data plane';
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
DROP TRIGGER IF EXISTS tasks_admin_assignee_forbidden_trigger ON tasks;
|
|
CREATE TRIGGER tasks_admin_assignee_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, assigned_user_id ON tasks
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'assigned_user_id',
|
|
'tasks_admin_assignee_forbidden'
|
|
);
|
|
|
|
DROP TRIGGER IF EXISTS tasks_admin_creator_forbidden_trigger ON tasks;
|
|
CREATE TRIGGER tasks_admin_creator_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, created_by ON tasks
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'created_by',
|
|
'tasks_admin_creator_forbidden'
|
|
);
|
|
|
|
DROP TRIGGER IF EXISTS user_channels_admin_owner_forbidden_trigger ON user_channels;
|
|
CREATE TRIGGER user_channels_admin_owner_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, owner_user_id ON user_channels
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'owner_user_id',
|
|
'user_channels_admin_owner_forbidden'
|
|
);
|
|
|
|
DROP TRIGGER IF EXISTS browser_connections_admin_worker_forbidden_trigger ON browser_connections;
|
|
CREATE TRIGGER browser_connections_admin_worker_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, user_id ON browser_connections
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'user_id',
|
|
'browser_connections_admin_worker_forbidden'
|
|
);
|
|
|
|
DROP TRIGGER IF EXISTS user_business_routes_admin_grantee_forbidden_trigger
|
|
ON user_business_route_authorizations;
|
|
CREATE TRIGGER user_business_routes_admin_grantee_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, user_id ON user_business_route_authorizations
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'user_id',
|
|
'user_business_routes_admin_grantee_forbidden'
|
|
);
|
|
|
|
DROP TRIGGER IF EXISTS leader_task_summary_admin_subscriber_forbidden_trigger
|
|
ON leader_task_summary_subscriptions;
|
|
CREATE TRIGGER leader_task_summary_admin_subscriber_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, leader_user_id ON leader_task_summary_subscriptions
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'leader_user_id',
|
|
'leader_task_summary_admin_subscriber_forbidden'
|
|
);
|
|
|
|
DROP TRIGGER IF EXISTS leader_task_summary_admin_recipient_forbidden_trigger
|
|
ON leader_task_summary_deliveries;
|
|
CREATE TRIGGER leader_task_summary_admin_recipient_forbidden_trigger
|
|
BEFORE INSERT OR UPDATE OF organization_id, leader_user_id ON leader_task_summary_deliveries
|
|
FOR EACH ROW EXECUTE FUNCTION reject_admin_task_principal(
|
|
'leader_user_id',
|
|
'leader_task_summary_admin_recipient_forbidden'
|
|
);
|
|
|
|
CREATE OR REPLACE FUNCTION isolate_administrator_from_task_runtime()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF NEW.role <> 'admin' THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
UPDATE tasks
|
|
SET assigned_user_id = NULL,
|
|
lease_owner = NULL,
|
|
lease_expires_at = NULL,
|
|
updated_at = now()
|
|
WHERE organization_id = NEW.organization_id
|
|
AND assigned_user_id = NEW.id;
|
|
|
|
UPDATE user_channels
|
|
SET owner_user_id = NULL,
|
|
enabled = false,
|
|
status = 'disabled',
|
|
last_error = '绑定账号已变更为管理员,渠道已解除绑定。',
|
|
updated_at = now()
|
|
WHERE organization_id = NEW.organization_id
|
|
AND owner_user_id = NEW.id;
|
|
|
|
UPDATE browser_connections
|
|
SET status = 'superseded',
|
|
erp_account_verified = false
|
|
WHERE organization_id = NEW.organization_id
|
|
AND user_id = NEW.id
|
|
AND status = 'connected';
|
|
|
|
DELETE FROM user_business_route_authorizations
|
|
WHERE organization_id = NEW.organization_id
|
|
AND user_id = NEW.id;
|
|
|
|
UPDATE leader_task_summary_subscriptions
|
|
SET enabled = false,
|
|
target_verified_at = NULL,
|
|
revision = revision + 1,
|
|
updated_at = now()
|
|
WHERE organization_id = NEW.organization_id
|
|
AND leader_user_id = NEW.id;
|
|
|
|
UPDATE leader_task_summary_deliveries
|
|
SET delivery_status = 'cancelled',
|
|
last_error = '账号已变更为管理员,组长任务摘要投递已取消。',
|
|
updated_at = now()
|
|
WHERE organization_id = NEW.organization_id
|
|
AND leader_user_id = NEW.id
|
|
AND delivery_status IN ('pending', 'sending', 'failed');
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
DROP TRIGGER IF EXISTS users_admin_task_runtime_isolation_trigger ON users;
|
|
CREATE TRIGGER users_admin_task_runtime_isolation_trigger
|
|
AFTER UPDATE OF role ON users
|
|
FOR EACH ROW
|
|
WHEN (NEW.role = 'admin' AND OLD.role IS DISTINCT FROM NEW.role)
|
|
EXECUTE FUNCTION isolate_administrator_from_task_runtime();
|