Define the scenario permissions by name

With the lua side checking permission names directly there is no transform to
derive them from, so each permission is listed with its name. This was also
the chance to drop the legacy action and flag buckets, which only reflected
how the old config was written:

- exp_scenario.bypass.* for entity protection, nuke protection, the
  deconstruction log, and reports.
- exp_scenario.decon.* for the two deconstruction levels, with descriptions
  which say what they gate.
- exp_scenario.player.* for admin, spectator, instant respawn, and system
  commands.
- exp_scenario.chat.commands, and exp_scenario.gui.player_list.kick and .ban
  for the player list buttons which were never commands.

Commands derive their permission as exp_scenario.command.<name>, so
assign-role, unassign-role, and get-roles get scenario permissions rather
than the core ones they mapped to before. The in game command is bounded by
the lower role check, while core.user.update_roles is not, so granting it to
moderators would have let them change any role from the web ui.

Dropped: defer_role_changes, which priority replaced; command/give-warning,
which no role held and the player list now checks create_warning for; and
command/report, which was never defined. clear-tag/always is renamed to
tag_clear.always to match the command it belongs to. _ipc and _sudo are added
so every command has a definition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
bbassie
2026-08-19 11:36:58 +00:00
co-authored by Claude Fable 5
parent ad9a072661
commit eb715cc176
+122 -151
View File
@@ -1,160 +1,131 @@
import * as lib from "@clusterio/lib";
/**
* Convert a legacy role action into its clusterio permission name.
* Permissions checked by the scenario in game through exp_roles.
*
* The exp_roles lua module applies the same transform, so existing call sites such as
* `Roles.player_allowed(player, "gui/warp-list/add")` keep working unchanged.
*
* @param action - Legacy action such as `gui/warp-list/add` or `fast-tree-decon`.
* @returns Permission name such as `exp_scenario.gui.warp_list.add`.
* Commands are checked as `exp_scenario.command.<name>` with hyphens replaced by
* underscores, see module/commands/_authorities.lua. Everything else is checked
* by name at its call site.
*/
export function permissionFromAction(action: string) {
const body = action.replace(/-/g, "_").replace(/\//g, ".");
return `exp_scenario.${body.includes(".") ? body : `action.${body}`}`;
}
type Definition = [name: string, title: string, description: string, grantByDefault?: boolean];
/**
* Convert a legacy role flag into its clusterio permission name.
*
* @param flag - Legacy flag such as `report-immune`.
* @returns Permission name such as `exp_scenario.flag.report_immune`.
*/
export function permissionFromFlag(flag: string) {
return `exp_scenario.flag.${flag.replace(/-/g, "_")}`;
}
/** Legacy actions which map onto core clusterio permissions rather than scenario ones. */
export const coreActionPermissions: Record<string, string> = {
"command/assign-role": "core.user.update_roles",
"command/unassign-role": "core.user.update_roles",
"command/get-roles": "core.role.list",
};
/** Legacy action, user facing title, description, and whether every player gets it. */
type ActionDefinition = [action: string, title: string, description: string, grantByDefault?: boolean];
const actions: ActionDefinition[] = [
["bypass-entity-protection", "Bypass entity protection", "Remove entities that the protection filter would block."],
["bypass-nukeprotect", "Bypass nuke protection", "Use nukes without the nuke protection restrictions."],
["command/_rcon", "/_rcon", "Execute arbitrary code within a custom environment."],
["command/admin-chat", "/admin-chat", "Sends a message in chat that only admins can see."],
["command/artillery", "/artillery", "Automaticly select enemy target with artillery."],
["command/ban", "/ban", "Ban a player from the cluster via the player list."],
["command/bring", "/bring", "Teleports a player to you."],
["command/chat-commands", "Chat commands", "Use the chat command prefix to trigger auto replies."],
["command/clear-blueprints", "/clear-blueprints", "Clear all blueprints."],
["command/clear-blueprints-surface", "/clear-blueprints-surface", "Clear all blueprints on the current surface."],
["command/clear-ground-items", "/clear-ground-items", "Clear all items on the ground."],
["command/clear-inventory", "/clear-inventory", "Clear a player's inventory, moving all items to spawn."],
["command/clear-last-warnings", "/clear-last-warnings", "Clears the last warning from a player."],
["command/clear-pollution", "/clear-pollution", "Clear pollution from your current surface, or another surface."],
["command/clear-reports", "/clear-reports", "Clears all reports from a player or just the report from one player."],
["command/clear-script-warnings", "/clear-script-warnings", "Clears all script warnings from a player."],
["command/clear-tag/always", "/clear-tag (any player)", "Clear the tag of any player, not just your own."],
["command/clear-warnings", "/clear-warnings", "Clears all warnings (and script warnings) from a player."],
["command/collectdata", "/collectdata", "Collect data for RCON usage."],
["command/commands", "/commands", "List and search all commands for a keyword.", true],
["command/connect", "/connect", "Connect to another server.", true],
["command/connect-all", "/connect-all", "Connect all players to another server."],
["command/connect-player", "/connect-player", "Connect a player to a different server."],
["command/create-report", "/create-report", "Reports a player and notifies moderators.", true],
["command/create-warning", "/create-warning", "Gives a warning to a player; may lead to automatic script action."],
["command/data-preference", "/data-preference", "Allows you to set/get your data saving preference.", true],
["command/debug", "/debug", "Opens the debug gui."],
["command/follow", "/follow", "Start following a player in spectator."],
["command/get-home", "/get-home", "Returns your current home location."],
["command/get-reports", "/get-reports", "List the reports against a player, or against every player."],
["command/get-warnings", "/get-warnings", "List the warnings against a player, or against every player."],
["command/give-warning", "/give-warning", "Give a player a warning via the player list."],
["command/goto", "/goto", "Teleports you to a player."],
["command/home", "/home", "Teleports you to your home location."],
["command/jail", "/jail", "Puts a player into jail and removes all other roles."],
["command/kick", "/kick", "Kick a player from the server via the player list."],
["command/kill", "/kill", "Kills yourself or another player."],
["command/kill-enemies", "/kill-enemies", "Kill all enemy units."],
["command/kill/always", "/kill (any player)", "Kill any player, not just yourself."],
["command/lawnmower", "/lawnmower", "Clean up biter corpse, decoratives and nuclear hole."],
["command/locate", "/locate", "Opens remote view at the location of the player's last location.", true],
["command/me", "/me", "Sends an action message in the chat."],
["command/protect-area", "/protect-area", "Toggles area protection selection, hold shift to remove protection."],
["command/protect-entity", "/protect-entity", "Toggles entity protection selection, hold shift to remove protection."],
["command/protect-tag", "/protect-tag", "Toggles protected tag mode, edit and create protected map tags."],
["command/rainbow", "/rainbow", "Sends an rainbow message in the chat."],
["command/ratio", "/ratio", "Get the input and output ratios of the selected machine.", true],
["command/remove-enemies", "/remove-enemies", "Remove all enemy spawners."],
["command/remove-join-message", "/remove-join-message", "Removes you custom join message."],
["command/repair", "/repair", "Repairs entities on your force around you."],
["command/research-all", "/research-all", "Research all technology for your force, or another force."],
["command/return", "/return", "Teleports you to previous location."],
["command/save-data", "/save-data", "Writes all your player data to a file on your computer.", true],
["command/save-quickbar", "/save-quickbar", "Saves your Quickbar preset items to file."],
["command/search", "/search", "Display players sorted by the quantity of an item held and playtime."],
["command/search-amount", "/search-amount", "Display players sorted by the quantity of an item held."],
["command/search-online", "/search-online", "Display online players sorted by item count and playtime."],
["command/search-recent", "/search-recent", "Display players who hold an item sorted by join time."],
["command/server-ups", "/server-ups", "Toggle the server UPS display.", true],
["command/set-always-day", "/set-always-day", "Set always day for your current surface, or another surface."],
["command/set-bot-queue", "/set-bot-queue", "Get / Set the construction bot queue limits."],
["command/set-cheat-mode", "/set-cheat-mode", "Set cheat mode for your player, or another player."],
["command/set-friendly-fire", "/set-friendly-fire", "Set friendly fire for your force, or another force."],
["command/set-game-speed", "/set-game-speed", "Set or get the current game speed."],
["command/set-home", "/set-home", "Sets your home location to your current position."],
["command/set-join-message", "/set-join-message", "Sets / Gets your custom join message."],
["command/set-pollution-enabled", "/set-pollution-enabled", "Set polution enabled state for this game."],
["command/set-trains-to-automatic", "/set-trains-to-automatic", "Set all trains without passengers to automatic."],
["command/spawn", "/spawn", "Teleport to spawn."],
["command/spawn/always", "/spawn (any player)", "Teleport any player to spawn, not just yourself."],
["command/spectate", "/spectate", "Toggles spectator mode."],
["command/tag", "/tag", "Sets your player tag.", true],
["command/tag-clear", "/tag-clear", "Clears your tag. Or another player if you are admin.", true],
["command/tag-color", "/tag-color", "Sets your player tag color."],
["command/teleport", "/teleport", "Teleports a player to another player."],
["command/unjail", "/unjail", "Removes a player from jail and restores their previous roles."],
["command/vlayer-info", "/vlayer-info", "Print all vlayer information."],
["command/waterfill", "/waterfill", "Replace tiles with shallow water."],
["fast-tree-decon", "Fast tree deconstruction", "Deconstruct trees and rocks instantly over a large area."],
["gui/autofill", "Autofill", "Open the autofill GUI, which fills placed entities from your inventory.", true],
["gui/bonus", "Bonus", "Open the bonus GUI to adjust your personal bonuses."],
["gui/module", "Module inserter", "Open the module inserter GUI.", true],
["gui/player-list", "Player list", "Open the player list GUI.", true],
["gui/playerdata", "Player statistics", "Open the player statistics GUI."],
["gui/production", "Production statistics", "Open the production statistics GUI.", true],
["gui/readme", "Readme", "Open the server readme GUI.", true],
["gui/research", "Research milestones", "Open the research milestones GUI.", true],
["gui/rocket-info", "Rocket info", "Open the rocket info GUI.", true],
["gui/rocket-info/remote_launch", "Rocket info: remote launch", "Launch rockets remotely from the rocket info GUI."],
["gui/rocket-info/toggle-active", "Rocket info: toggle active", "Toggle whether a silo launches automatically."],
["gui/science-info", "Science production", "Open the science production GUI.", true],
["gui/surveillance", "Surveillance", "Open the surveillance GUI showing remote camera views."],
["gui/task-list", "Task list", "Open the task list GUI.", true],
["gui/task-list/add", "Task list: add", "Add new tasks to the task list."],
["gui/task-list/edit", "Task list: edit", "Edit and remove existing tasks on the task list."],
["gui/tool", "Quick actions", "Open the quick actions GUI."],
["gui/vlayer", "Virtual layer", "Open the virtual layer GUI.", true],
["gui/vlayer-edit", "Virtual layer: edit", "Use the edit controls in the virtual layer GUI."],
["gui/warp-list", "Warp list", "Open the warp list GUI and warp between locations.", true],
["gui/warp-list/add", "Warp list: add", "Add new warp points to the warp list."],
["gui/warp-list/bypass-cooldown", "Warp list: bypass cooldown", "Warp without waiting for the warp cooldown."],
["gui/warp-list/bypass-proximity", "Warp list: bypass proximity", "Warp without standing near a warp point."],
["gui/warp-list/edit", "Warp list: edit", "Edit and remove existing warp points."],
["standard-decon", "Standard deconstruction", "Deconstruct trees and rocks."],
const definitions: Definition[] = [
["exp_scenario.bypass.deconstruction_log", "Deconstruction log bypass", "Be excluded from the deconstruction log."],
["exp_scenario.bypass.entity_protection", "Bypass entity protection", "Remove entities that the protection filter would block."],
["exp_scenario.bypass.nuke_protection", "Bypass nuke protection", "Use nukes without the nuke protection restrictions."],
["exp_scenario.bypass.reports", "Report immune", "Be immune to being reported by other players."],
["exp_scenario.chat.commands", "Chat commands", "Use the chat command prefix to trigger auto replies."],
["exp_scenario.command._ipc", "/_ipc", "Send an IPC message on the selected channel."],
["exp_scenario.command._rcon", "/_rcon", "Execute arbitrary code within a custom environment."],
["exp_scenario.command._sudo", "/_sudo", "Run a command as another player."],
["exp_scenario.command.admin_chat", "/admin-chat", "Sends a message in chat that only admins can see."],
["exp_scenario.command.artillery", "/artillery", "Automaticly select enemy target with artillery."],
["exp_scenario.command.assign_role", "/assign-role", "Assigns a role lower than your own to a player."],
["exp_scenario.command.bring", "/bring", "Teleports a player to you."],
["exp_scenario.command.clear_blueprints", "/clear-blueprints", "Clear all blueprints."],
["exp_scenario.command.clear_blueprints_surface", "/clear-blueprints-surface", "Clear all blueprints on the current surface."],
["exp_scenario.command.clear_ground_items", "/clear-ground-items", "Clear all items on the ground."],
["exp_scenario.command.clear_inventory", "/clear-inventory", "Clear a player's inventory, moving all items to spawn."],
["exp_scenario.command.clear_last_warnings", "/clear-last-warnings", "Clears the last warning from a player."],
["exp_scenario.command.clear_pollution", "/clear-pollution", "Clear pollution from your current surface, or another surface."],
["exp_scenario.command.clear_reports", "/clear-reports", "Clears all reports from a player or just the report from one player."],
["exp_scenario.command.clear_script_warnings", "/clear-script-warnings", "Clears all script warnings from a player."],
["exp_scenario.command.clear_warnings", "/clear-warnings", "Clears all warnings (and script warnings) from a player."],
["exp_scenario.command.collectdata", "/collectdata", "Collect data for RCON usage."],
["exp_scenario.command.commands", "/commands", "List and search all commands for a keyword.", true],
["exp_scenario.command.connect", "/connect", "Connect to another server.", true],
["exp_scenario.command.connect_all", "/connect-all", "Connect all players to another server."],
["exp_scenario.command.connect_player", "/connect-player", "Connect a player to a different server."],
["exp_scenario.command.create_report", "/create-report", "Reports a player and notifies moderators.", true],
["exp_scenario.command.create_warning", "/create-warning", "Gives a warning to a player; may lead to automatic script action."],
["exp_scenario.command.data_preference", "/data-preference", "Allows you to set/get your data saving preference.", true],
["exp_scenario.command.debug", "/debug", "Opens the debug gui."],
["exp_scenario.command.follow", "/follow", "Start following a player in spectator."],
["exp_scenario.command.get_home", "/get-home", "Returns your current home location."],
["exp_scenario.command.get_reports", "/get-reports", "List the reports against a player, or against every player."],
["exp_scenario.command.get_roles", "/get-roles", "Get all roles that a player has, if no player provided it lists all roles.", true],
["exp_scenario.command.get_warnings", "/get-warnings", "List the warnings against a player, or against every player."],
["exp_scenario.command.goto", "/goto", "Teleports you to a player."],
["exp_scenario.command.home", "/home", "Teleports you to your home location."],
["exp_scenario.command.jail", "/jail", "Puts a player into jail, which suppresses all of their other roles."],
["exp_scenario.command.kill", "/kill", "Kills yourself or another player."],
["exp_scenario.command.kill.always", "/kill (any player)", "Kill any player, not just yourself."],
["exp_scenario.command.kill_enemies", "/kill-enemies", "Kill all enemy units."],
["exp_scenario.command.lawnmower", "/lawnmower", "Clean up biter corpse, decoratives and nuclear hole."],
["exp_scenario.command.locate", "/locate", "Opens remote view at the location of the player's last location.", true],
["exp_scenario.command.me", "/me", "Sends an action message in the chat."],
["exp_scenario.command.protect_area", "/protect-area", "Toggles area protection selection, hold shift to remove protection."],
["exp_scenario.command.protect_entity", "/protect-entity", "Toggles entity protection selection, hold shift to remove protection."],
["exp_scenario.command.protect_tag", "/protect-tag", "Toggles protected tag mode, edit and create protected map tags."],
["exp_scenario.command.rainbow", "/rainbow", "Sends an rainbow message in the chat."],
["exp_scenario.command.ratio", "/ratio", "Get the input and output ratios of the selected machine.", true],
["exp_scenario.command.remove_enemies", "/remove-enemies", "Remove all enemy spawners."],
["exp_scenario.command.remove_join_message", "/remove-join-message", "Removes you custom join message."],
["exp_scenario.command.repair", "/repair", "Repairs entities on your force around you."],
["exp_scenario.command.research_all", "/research-all", "Research all technology for your force, or another force."],
["exp_scenario.command.return", "/return", "Teleports you to previous location."],
["exp_scenario.command.save_data", "/save-data", "Writes all your player data to a file on your computer.", true],
["exp_scenario.command.save_quickbar", "/save-quickbar", "Saves your Quickbar preset items to file."],
["exp_scenario.command.search", "/search", "Display players sorted by the quantity of an item held and playtime."],
["exp_scenario.command.search_amount", "/search-amount", "Display players sorted by the quantity of an item held."],
["exp_scenario.command.search_online", "/search-online", "Display online players sorted by item count and playtime."],
["exp_scenario.command.search_recent", "/search-recent", "Display players who hold an item sorted by join time."],
["exp_scenario.command.server_ups", "/server-ups", "Toggle the server UPS display.", true],
["exp_scenario.command.set_always_day", "/set-always-day", "Set always day for your current surface, or another surface."],
["exp_scenario.command.set_bot_queue", "/set-bot-queue", "Get / Set the construction bot queue limits."],
["exp_scenario.command.set_cheat_mode", "/set-cheat-mode", "Set cheat mode for your player, or another player."],
["exp_scenario.command.set_friendly_fire", "/set-friendly-fire", "Set friendly fire for your force, or another force."],
["exp_scenario.command.set_game_speed", "/set-game-speed", "Set or get the current game speed."],
["exp_scenario.command.set_home", "/set-home", "Sets your home location to your current position."],
["exp_scenario.command.set_join_message", "/set-join-message", "Sets / Gets your custom join message."],
["exp_scenario.command.set_pollution_enabled", "/set-pollution-enabled", "Set polution enabled state for this game."],
["exp_scenario.command.set_trains_to_automatic", "/set-trains-to-automatic", "Set all trains without passengers to automatic."],
["exp_scenario.command.spawn", "/spawn", "Teleport to spawn."],
["exp_scenario.command.spawn.always", "/spawn (any player)", "Teleport any player to spawn, not just yourself."],
["exp_scenario.command.spectate", "/spectate", "Toggles spectator mode."],
["exp_scenario.command.tag", "/tag", "Sets your player tag.", true],
["exp_scenario.command.tag_clear", "/tag-clear", "Clears your tag. Or another player if you are admin.", true],
["exp_scenario.command.tag_clear.always", "/tag-clear (any player)", "Clear the tag of any player, not just your own."],
["exp_scenario.command.tag_color", "/tag-color", "Sets your player tag color."],
["exp_scenario.command.teleport", "/teleport", "Teleports a player to another player."],
["exp_scenario.command.unassign_role", "/unassign-role", "Unassigns a role lower than your own from a player."],
["exp_scenario.command.unjail", "/unjail", "Removes a player from jail, restoring their other roles."],
["exp_scenario.command.vlayer_info", "/vlayer-info", "Print all vlayer information."],
["exp_scenario.command.waterfill", "/waterfill", "Replace tiles with shallow water."],
["exp_scenario.decon.fast_trees", "Fast tree deconstruction", "Trees and rocks marked for deconstruction are removed instantly, when enabled from the toolbar."],
["exp_scenario.decon.standard", "Standard deconstruction", "Mark entities placed by other players for deconstruction."],
["exp_scenario.gui.autofill", "Autofill", "Open the autofill GUI, which fills placed entities from your inventory.", true],
["exp_scenario.gui.bonus", "Bonus", "Open the bonus GUI to adjust your personal bonuses."],
["exp_scenario.gui.module", "Module inserter", "Open the module inserter GUI.", true],
["exp_scenario.gui.player_list", "Player list", "Open the player list GUI.", true],
["exp_scenario.gui.player_list.ban", "Player list: ban", "Ban a player from the cluster via the player list."],
["exp_scenario.gui.player_list.kick", "Player list: kick", "Kick a player from the server via the player list."],
["exp_scenario.gui.playerdata", "Player statistics", "Open the player statistics GUI."],
["exp_scenario.gui.production", "Production statistics", "Open the production statistics GUI.", true],
["exp_scenario.gui.readme", "Readme", "Open the server readme GUI.", true],
["exp_scenario.gui.research", "Research milestones", "Open the research milestones GUI.", true],
["exp_scenario.gui.rocket_info", "Rocket info", "Open the rocket info GUI.", true],
["exp_scenario.gui.rocket_info.remote_launch", "Rocket info: remote launch", "Launch rockets remotely from the rocket info GUI."],
["exp_scenario.gui.rocket_info.toggle_active", "Rocket info: toggle active", "Toggle whether a silo launches automatically."],
["exp_scenario.gui.science_info", "Science production", "Open the science production GUI.", true],
["exp_scenario.gui.surveillance", "Surveillance", "Open the surveillance GUI showing remote camera views."],
["exp_scenario.gui.task_list", "Task list", "Open the task list GUI.", true],
["exp_scenario.gui.task_list.add", "Task list: add", "Add new tasks to the task list."],
["exp_scenario.gui.task_list.edit", "Task list: edit", "Edit and remove existing tasks on the task list."],
["exp_scenario.gui.tool", "Quick actions", "Open the quick actions GUI."],
["exp_scenario.gui.vlayer", "Virtual layer", "Open the virtual layer GUI.", true],
["exp_scenario.gui.vlayer_edit", "Virtual layer: edit", "Use the edit controls in the virtual layer GUI."],
["exp_scenario.gui.warp_list", "Warp list", "Open the warp list GUI and warp between locations.", true],
["exp_scenario.gui.warp_list.add", "Warp list: add", "Add new warp points to the warp list."],
["exp_scenario.gui.warp_list.bypass_cooldown", "Warp list: bypass cooldown", "Warp without waiting for the warp cooldown."],
["exp_scenario.gui.warp_list.bypass_proximity", "Warp list: bypass proximity", "Warp without standing near a warp point."],
["exp_scenario.gui.warp_list.edit", "Warp list: edit", "Edit and remove existing warp points."],
["exp_scenario.player.admin", "Factorio admin", "Be promoted to Factorio admin while holding a role with this permission."],
["exp_scenario.player.instant_respawn", "Instant respawn", "Respawn after two seconds instead of the default delay."],
["exp_scenario.player.spectator", "Spectator", "Remove the zoom to world noise effect, as Factorio does for spectators."],
["exp_scenario.player.system_commands", "System commands", "Unlock commands flagged system only, such as /_rcon and /_sudo."],
];
const flags: ActionDefinition[] = [
["deconlog-bypass", "Deconstruction log bypass", "Be excluded from the deconstruction log."],
["defer_role_changes", "Defer role changes", "Hold back role changes until this role is removed; used by Jail."],
["instant-respawn", "Instant respawn", "Respawn after two seconds instead of the default delay."],
["is_admin", "Factorio admin", "Be promoted to Factorio admin while holding a role with this flag."],
["is_spectator", "Spectator", "Be placed into Factorio spectator mode."],
["is_system", "System commands", "Unlock system commands such as /_rcon and /_sudo."],
["report-immune", "Report immune", "Be immune to being reported by other players."],
];
for (const [action, title, description, grantByDefault] of actions) {
lib.definePermission({ name: permissionFromAction(action), title, description, grantByDefault });
}
for (const [flag, title, description] of flags) {
lib.definePermission({ name: permissionFromFlag(flag), title, description });
for (const [name, title, description, grantByDefault] of definitions) {
lib.definePermission({ name, title, description, grantByDefault });
}