feat(rust): the permission manager — the site owns the whole store (D160-D163, D188-D198)
PLAN_REDESIGNS section 1. - Every sync reads the store (perm.inventory), reconciles it against the site's record and its ledger, and pushes. A change made in the game is settled by the server's policy (D161): auto-adopt (default), adopt, or revoke. The first read of a server imports everything (D198). - Groups belong to one server unless an admin shares them (D189), in new id-keyed tables; the old ones are copied once at boot and left unread. Holders may be a Steam account nobody linked (D188). - An in-game change affects that server only (D190): a grant that reaches further gains an exception, a shared group is split. - Never judged: a permission the server does not register right now (an unloaded plugin is not a revocation), and a pair an event lease holds. - A new admin API (server view, grant/revoke with everywhere-or-here, groups by id, share/split, members, drift answers) and a screen on PermissionsManager's flow with a state on every toggle (D162, D163, U-1). - The announcement voice names a group by id; old name settings still read. Walked on both rigs against the walk core: import on an existing install, auto-adopt of a grant and a revoke, a fleet grant's exception, Kits unloaded without loss, a shared group split, adopt and revoke policies. Server 420/420, client 58/58, swagger, imports and route manifest current. Refs #21 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -1011,3 +1011,155 @@ ALTER TABLE rust_perm_pushed ADD COLUMN IF NOT EXISTS value VARCHAR(255) NULL;
|
||||
-- The value a changed field holds in the game, for a `chat-field` drift row.
|
||||
-- NULL on every other kind: a foreign grant is its own description.
|
||||
ALTER TABLE rust_perm_drift ADD COLUMN IF NOT EXISTS detail VARCHAR(255) NULL;
|
||||
|
||||
-- ── The permission manager, rebuilt (PLAN_REDESIGNS §1) ────────────────────
|
||||
--
|
||||
-- The site owns EVERY permission and group on a server now (D160), read from
|
||||
-- the plugin's inventory and imported on first contact (D198). Three things the
|
||||
-- tables above cannot hold made new ones necessary:
|
||||
--
|
||||
-- • A group belongs to ONE server unless an admin shares it (D189). The old
|
||||
-- `rust_perm_groups` is keyed by name fleet-wide, so two servers' `vip`
|
||||
-- groups with different contents could not both exist. A group is now a row
|
||||
-- with its own id; the servers it is on are rows beside it.
|
||||
-- • A holder may be a Steam account nobody has linked (D188). The authored
|
||||
-- tables above are keyed by website user (D28), and most of a real store's
|
||||
-- holders never link.
|
||||
-- • An in-game change affects that server only (D190), even to a row that
|
||||
-- reaches more servers — so a fleet-wide grant can carry exceptions.
|
||||
--
|
||||
-- The old group tables stay, unread: `permissions.db.migrateGroups` copies them
|
||||
-- here once, and a downgrade still finds them as they were.
|
||||
CREATE TABLE IF NOT EXISTS rust_permgroups (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL,
|
||||
-- Verbatim, never trimmed: Carbon's own titles end in a space ("Default "),
|
||||
-- and a trimmed copy would be "changed" by every sync.
|
||||
title VARCHAR(120) NOT NULL DEFAULT '',
|
||||
`rank` INT NOT NULL DEFAULT 0,
|
||||
-- A group NAME on the same server, or ''. Both frameworks store it by name.
|
||||
parent VARCHAR(64) NOT NULL DEFAULT '',
|
||||
-- 1: on every server, including servers added later, except those
|
||||
-- `rust_permgroup_servers` excludes. 0: on exactly the servers it includes.
|
||||
all_servers TINYINT(1) NOT NULL DEFAULT 0,
|
||||
-- `admin` (made on the site), `imported` (the first inventory, D198),
|
||||
-- `adopted` (a later in-game change, D190), `split` (D190's copy),
|
||||
-- `migrated` (copied from the old tables).
|
||||
source VARCHAR(32) NOT NULL DEFAULT 'admin',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY idx_rust_permgroups_name (name)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Which servers a group is on. `included` 1 names a server a group is on; 0
|
||||
-- takes one server out of an all-servers group — the split D190 makes when that
|
||||
-- server's copy changed in the game. The model refuses two groups of one name on
|
||||
-- one server; a unique key cannot say it across `all_servers`.
|
||||
CREATE TABLE IF NOT EXISTS rust_permgroup_servers (
|
||||
group_id INT UNSIGNED NOT NULL,
|
||||
server_id VARCHAR(64) NOT NULL,
|
||||
included TINYINT(1) NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (group_id, server_id),
|
||||
KEY idx_rust_permgroup_servers_server (server_id),
|
||||
CONSTRAINT fk_rust_permgroup_servers_group
|
||||
FOREIGN KEY (group_id) REFERENCES rust_permgroups (id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_rust_permgroup_servers_server
|
||||
FOREIGN KEY (server_id) REFERENCES rust_servers (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- What a group carries, the same on every server it is on.
|
||||
CREATE TABLE IF NOT EXISTS rust_permgroup_permissions (
|
||||
group_id INT UNSIGNED NOT NULL,
|
||||
permission VARCHAR(128) NOT NULL,
|
||||
PRIMARY KEY (group_id, permission),
|
||||
CONSTRAINT fk_rust_permgroup_permissions_group
|
||||
FOREIGN KEY (group_id) REFERENCES rust_permgroups (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Members who are website accounts, reaching every Steam account they link (D28).
|
||||
CREATE TABLE IF NOT EXISTS rust_permgroup_members (
|
||||
group_id INT UNSIGNED NOT NULL,
|
||||
user_id INT NOT NULL,
|
||||
added_by INT NULL,
|
||||
added_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (group_id, user_id),
|
||||
KEY idx_rust_permgroup_members_user (user_id),
|
||||
CONSTRAINT fk_rust_permgroup_members_group
|
||||
FOREIGN KEY (group_id) REFERENCES rust_permgroups (id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_rust_permgroup_members_user
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Members who are one Steam account, linked or not (D188).
|
||||
CREATE TABLE IF NOT EXISTS rust_permgroup_steam_members (
|
||||
group_id INT UNSIGNED NOT NULL,
|
||||
steam_id VARCHAR(32) NOT NULL,
|
||||
source VARCHAR(32) NOT NULL DEFAULT 'admin',
|
||||
added_by INT NULL,
|
||||
added_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (group_id, steam_id),
|
||||
KEY idx_rust_permgroup_steam_members_steam (steam_id),
|
||||
CONSTRAINT fk_rust_permgroup_steam_members_group
|
||||
FOREIGN KEY (group_id) REFERENCES rust_permgroups (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- A group's BetterChat style (D138), per group row rather than per name: one
|
||||
-- server's own `vip` may be styled differently from another server's.
|
||||
CREATE TABLE IF NOT EXISTS rust_permgroup_chat (
|
||||
group_id INT UNSIGNED NOT NULL,
|
||||
field VARCHAR(32) NOT NULL,
|
||||
value VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (group_id, field),
|
||||
CONSTRAINT fk_rust_permgroup_chat_group
|
||||
FOREIGN KEY (group_id) REFERENCES rust_permgroups (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- A permission held by one Steam account, linked or not (D188). The import and
|
||||
-- auto-adopt write these, and so does a site toggle for an UNLINKED player.
|
||||
CREATE TABLE IF NOT EXISTS rust_perm_steam_grants (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
steam_id VARCHAR(32) NOT NULL,
|
||||
permission VARCHAR(128) NOT NULL,
|
||||
scope VARCHAR(64) NOT NULL DEFAULT '*',
|
||||
source VARCHAR(32) NOT NULL DEFAULT 'admin',
|
||||
note VARCHAR(255) NULL,
|
||||
granted_by INT NULL,
|
||||
granted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_rust_perm_steam_grant (steam_id, permission, scope),
|
||||
KEY idx_rust_perm_steam_grant_steam (steam_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- "Everywhere except here" (D190): a grant that reaches more than one server,
|
||||
-- removed on one of them in the game, keeps reaching the others, including
|
||||
-- servers added later, which a rewrite into per-server rows would lose.
|
||||
-- `holder` says which grants table `grant_id` is in: `user` or `steam`. No
|
||||
-- foreign key can name two tables, so deleting a grant deletes its exceptions
|
||||
-- in the same model call.
|
||||
CREATE TABLE IF NOT EXISTS rust_perm_exceptions (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
holder VARCHAR(8) NOT NULL,
|
||||
grant_id INT UNSIGNED NOT NULL,
|
||||
server_id VARCHAR(64) NOT NULL,
|
||||
created_by INT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_rust_perm_exception (holder, grant_id, server_id),
|
||||
CONSTRAINT fk_rust_perm_exceptions_server
|
||||
FOREIGN KEY (server_id) REFERENCES rust_servers (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- The registering plugin (PLAN_REDESIGNS §0.1), from the inventory. NULL for a
|
||||
-- name no plugin owns; Carbon's built-in modules register theirs that way.
|
||||
ALTER TABLE rust_perm_catalogue ADD COLUMN IF NOT EXISTS owner VARCHAR(64) NULL;
|
||||
|
||||
-- When this server's store was first imported (D160, D198). NULL until the first
|
||||
-- inventory completes, and until then every sync imports.
|
||||
ALTER TABLE rust_perm_sync ADD COLUMN IF NOT EXISTS imported_at DATETIME NULL;
|
||||
|
||||
-- What a change made in the game becomes (D161): `auto-adopt` (the default),
|
||||
-- `adopt` (a person answers each one), or `revoke` (the site's set wins).
|
||||
ALTER TABLE rust_servers ADD COLUMN IF NOT EXISTS perm_policy VARCHAR(16) NOT NULL DEFAULT 'auto-adopt';
|
||||
|
||||
-- Which way a "needs a person" row went: `added` or `removed` in the game, or
|
||||
-- `split` (D190 gave a server its own copy of a shared group, and says so in
|
||||
-- case the change was meant for every server).
|
||||
ALTER TABLE rust_perm_drift ADD COLUMN IF NOT EXISTS direction VARCHAR(16) NOT NULL DEFAULT 'added';
|
||||
|
||||
Reference in New Issue
Block a user