mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-09-21 17:04:00 +00:00
Merge pull request #475 from bbassie/feature/plugin-permissions
Declare permissions on the plugin declaration
This commit is contained in:
+119
-117
@@ -12,123 +12,6 @@ declare module "@clusterio/lib" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group permissions
|
|
||||||
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.group.get",
|
|
||||||
title: "Get Groups",
|
|
||||||
description: "Retrieve a specific Factorio permission group by ID.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.group.list",
|
|
||||||
title: "List Groups",
|
|
||||||
description: "List all Factorio permission groups.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.group.subscribe",
|
|
||||||
title: "Subscribe to Group Updates",
|
|
||||||
description: "Receive updates when Factorio permission groups change.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.group.create",
|
|
||||||
title: "Create Groups",
|
|
||||||
description: "Create new Factorio permission groups.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.group.update",
|
|
||||||
title: "Update Groups",
|
|
||||||
description: "Modify existing Factorio permission groups.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.group.delete",
|
|
||||||
title: "Delete Groups",
|
|
||||||
description: "Delete Factorio permission groups.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assignment permissions
|
|
||||||
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.assignment.get",
|
|
||||||
title: "Get Assignments",
|
|
||||||
description: "Retrieve a specific manual group assignment for a player.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.assignment.list",
|
|
||||||
title: "List Assignments",
|
|
||||||
description: "List all manual group assignments.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.assignment.subscribe",
|
|
||||||
title: "Subscribe to Assignment Updates",
|
|
||||||
description: "Receive updates when manual group assignments change.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.assignment.create",
|
|
||||||
title: "Create Assignments",
|
|
||||||
description: "Manually assign players to groups, overriding role mappings.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.assignment.update",
|
|
||||||
title: "Update Assignments",
|
|
||||||
description: "Modify existing manual group assignments.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.assignment.delete",
|
|
||||||
title: "Delete Assignments",
|
|
||||||
description: "Remove manual group assignments.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Role mapping permissions
|
|
||||||
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.role_mapping.get",
|
|
||||||
title: "Get Role Mappings",
|
|
||||||
description: "Retrieve a specific role mapping rule.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.role_mapping.list",
|
|
||||||
title: "List Role Mappings",
|
|
||||||
description: "List all role mapping rules.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.role_mapping.subscribe",
|
|
||||||
title: "Subscribe to Role Mapping Updates",
|
|
||||||
description: "Receive updates when role mapping rules change.",
|
|
||||||
grantByDefault: true,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.role_mapping.create",
|
|
||||||
title: "Create Role Mappings",
|
|
||||||
description: "Create rules that map user roles to Factorio permission groups.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.role_mapping.update",
|
|
||||||
title: "Update Role Mappings",
|
|
||||||
description: "Modify existing role mapping rules.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_groups.role_mapping.delete",
|
|
||||||
title: "Delete Role Mappings",
|
|
||||||
description: "Delete role mapping rules.",
|
|
||||||
grantByDefault: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const plugin: lib.PluginDeclaration = {
|
export const plugin: lib.PluginDeclaration = {
|
||||||
name: "exp_groups",
|
name: "exp_groups",
|
||||||
title: "ExpGaming - Permission Groups",
|
title: "ExpGaming - Permission Groups",
|
||||||
@@ -164,6 +47,125 @@ export const plugin: lib.PluginDeclaration = {
|
|||||||
messages.RoleMappingListRequest,
|
messages.RoleMappingListRequest,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
permissions: [
|
||||||
|
// Group permissions
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "exp_groups.group.get",
|
||||||
|
title: "Get Groups",
|
||||||
|
description: "Retrieve a specific Factorio permission group by ID.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.group.list",
|
||||||
|
title: "List Groups",
|
||||||
|
description: "List all Factorio permission groups.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.group.subscribe",
|
||||||
|
title: "Subscribe to Group Updates",
|
||||||
|
description: "Receive updates when Factorio permission groups change.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.group.create",
|
||||||
|
title: "Create Groups",
|
||||||
|
description: "Create new Factorio permission groups.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.group.update",
|
||||||
|
title: "Update Groups",
|
||||||
|
description: "Modify existing Factorio permission groups.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.group.delete",
|
||||||
|
title: "Delete Groups",
|
||||||
|
description: "Delete Factorio permission groups.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Assignment permissions
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "exp_groups.assignment.get",
|
||||||
|
title: "Get Assignments",
|
||||||
|
description: "Retrieve a specific manual group assignment for a player.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.assignment.list",
|
||||||
|
title: "List Assignments",
|
||||||
|
description: "List all manual group assignments.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.assignment.subscribe",
|
||||||
|
title: "Subscribe to Assignment Updates",
|
||||||
|
description: "Receive updates when manual group assignments change.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.assignment.create",
|
||||||
|
title: "Create Assignments",
|
||||||
|
description: "Manually assign players to groups, overriding role mappings.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.assignment.update",
|
||||||
|
title: "Update Assignments",
|
||||||
|
description: "Modify existing manual group assignments.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.assignment.delete",
|
||||||
|
title: "Delete Assignments",
|
||||||
|
description: "Remove manual group assignments.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Role mapping permissions
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "exp_groups.role_mapping.get",
|
||||||
|
title: "Get Role Mappings",
|
||||||
|
description: "Retrieve a specific role mapping rule.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.role_mapping.list",
|
||||||
|
title: "List Role Mappings",
|
||||||
|
description: "List all role mapping rules.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.role_mapping.subscribe",
|
||||||
|
title: "Subscribe to Role Mapping Updates",
|
||||||
|
description: "Receive updates when role mapping rules change.",
|
||||||
|
grantByDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.role_mapping.create",
|
||||||
|
title: "Create Role Mappings",
|
||||||
|
description: "Create rules that map user roles to Factorio permission groups.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.role_mapping.update",
|
||||||
|
title: "Update Role Mappings",
|
||||||
|
description: "Modify existing role mapping rules.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_groups.role_mapping.delete",
|
||||||
|
title: "Delete Role Mappings",
|
||||||
|
description: "Delete role mapping rules.",
|
||||||
|
grantByDefault: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
instanceEntrypoint: "./dist/node/instance",
|
instanceEntrypoint: "./dist/node/instance",
|
||||||
instanceConfigFields: {
|
instanceConfigFields: {
|
||||||
"exp_groups.sync_mode": {
|
"exp_groups.sync_mode": {
|
||||||
|
|||||||
@@ -1,6 +1,30 @@
|
|||||||
import * as lib from "@clusterio/lib";
|
import * as lib from "@clusterio/lib";
|
||||||
import { Type, Static } from "@sinclair/typebox";
|
import { Type, Static } from "@sinclair/typebox";
|
||||||
|
|
||||||
|
// Declared here rather than in index.ts because the browser project cannot include index.ts, which re-exports controller.ts
|
||||||
|
declare module "@clusterio/lib" {
|
||||||
|
export interface Permissions {
|
||||||
|
"exp_groups.group.get": never;
|
||||||
|
"exp_groups.group.list": never;
|
||||||
|
"exp_groups.group.subscribe": never;
|
||||||
|
"exp_groups.group.create": never;
|
||||||
|
"exp_groups.group.update": never;
|
||||||
|
"exp_groups.group.delete": never;
|
||||||
|
"exp_groups.assignment.get": never;
|
||||||
|
"exp_groups.assignment.list": never;
|
||||||
|
"exp_groups.assignment.subscribe": never;
|
||||||
|
"exp_groups.assignment.create": never;
|
||||||
|
"exp_groups.assignment.update": never;
|
||||||
|
"exp_groups.assignment.delete": never;
|
||||||
|
"exp_groups.role_mapping.get": never;
|
||||||
|
"exp_groups.role_mapping.list": never;
|
||||||
|
"exp_groups.role_mapping.subscribe": never;
|
||||||
|
"exp_groups.role_mapping.create": never;
|
||||||
|
"exp_groups.role_mapping.update": never;
|
||||||
|
"exp_groups.role_mapping.delete": never;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Data records
|
Data records
|
||||||
*/
|
*/
|
||||||
|
|||||||
+26
-22
@@ -1,29 +1,14 @@
|
|||||||
import * as lib from "@clusterio/lib";
|
import * as lib from "@clusterio/lib";
|
||||||
import * as messages from "./messages";
|
import * as messages from "./messages";
|
||||||
|
import { permissions as scenarioPermissions, type ScenarioPermissionName } from "./permissions";
|
||||||
// Defines a permission for every in game action and role flag used by the scenario
|
|
||||||
import "./permissions";
|
|
||||||
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_scenario.config.view",
|
|
||||||
title: "View ExpScenario Config",
|
|
||||||
description: "View the config for all submodules of ExpScenario",
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_scenario.config.edit",
|
|
||||||
title: "Edit ExpScenario Config",
|
|
||||||
description: "Edit the config for all submodules of ExpScenario",
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.definePermission({
|
|
||||||
name: "exp_scenario.seed",
|
|
||||||
title: "Seed ExpScenario roles and groups",
|
|
||||||
description: "Create the roles and permission groups the scenario shipped with",
|
|
||||||
});
|
|
||||||
|
|
||||||
declare module "@clusterio/lib" {
|
declare module "@clusterio/lib" {
|
||||||
|
// Everything checked in game through exp_roles, plus the permissions checked on the controller
|
||||||
|
export interface Permissions extends Record<ScenarioPermissionName, never> {
|
||||||
|
"exp_scenario.config.view": never;
|
||||||
|
"exp_scenario.config.edit": never;
|
||||||
|
"exp_scenario.seed": never;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const plugin: lib.PluginDeclaration = {
|
export const plugin: lib.PluginDeclaration = {
|
||||||
@@ -37,5 +22,24 @@ export const plugin: lib.PluginDeclaration = {
|
|||||||
messages.SeedRequest,
|
messages.SeedRequest,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
permissions: [
|
||||||
|
...scenarioPermissions,
|
||||||
|
{
|
||||||
|
name: "exp_scenario.config.view",
|
||||||
|
title: "View ExpScenario Config",
|
||||||
|
description: "View the config for all submodules of ExpScenario",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_scenario.config.edit",
|
||||||
|
title: "Edit ExpScenario Config",
|
||||||
|
description: "Edit the config for all submodules of ExpScenario",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exp_scenario.seed",
|
||||||
|
title: "Seed ExpScenario roles and groups",
|
||||||
|
description: "Create the roles and permission groups the scenario shipped with",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
webEntrypoint: "./web",
|
webEntrypoint: "./web",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as lib from "@clusterio/lib";
|
import type * as lib from "@clusterio/lib";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permissions checked by the scenario in game through exp_roles.
|
* Permissions checked by the scenario in game through exp_roles.
|
||||||
@@ -7,9 +7,9 @@ import * as lib from "@clusterio/lib";
|
|||||||
* underscores, see module/commands/_authorities.lua. Everything else is checked
|
* underscores, see module/commands/_authorities.lua. Everything else is checked
|
||||||
* by name at its call site.
|
* by name at its call site.
|
||||||
*/
|
*/
|
||||||
type Definition = [name: string, title: string, description: string, grantByDefault?: boolean];
|
type Definition<Name extends string = string> = readonly [name: Name, title: string, description: string, grantByDefault?: boolean];
|
||||||
|
|
||||||
const definitions: Definition[] = [
|
const definitions = [
|
||||||
["exp_scenario.bypass.deconstruction_log", "Deconstruction log bypass", "Be excluded from the deconstruction log."],
|
["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.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.nuke_protection", "Bypass nuke protection", "Use nukes without the nuke protection restrictions."],
|
||||||
@@ -118,8 +118,12 @@ const definitions: Definition[] = [
|
|||||||
["exp_scenario.player.admin", "Factorio admin", "Be promoted to Factorio admin while holding a role with this permission."],
|
["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.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.spectator", "Spectator", "Remove the zoom to world noise effect, as Factorio does for spectators."],
|
||||||
];
|
] as const satisfies readonly Definition[];
|
||||||
|
|
||||||
for (const [name, title, description, grantByDefault] of definitions) {
|
/** Name of a permission defined by the scenario, added to lib.Permissions in index.ts. */
|
||||||
lib.definePermission({ name, title, description, grantByDefault });
|
export type ScenarioPermissionName = (typeof definitions)[number][0];
|
||||||
}
|
|
||||||
|
export const permissions = definitions.map((definition: Definition<ScenarioPermissionName>): lib.PermissionDefinition => {
|
||||||
|
const [name, title, description, grantByDefault] = definition;
|
||||||
|
return { name, title, description, grantByDefault };
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type * as lib from "@clusterio/lib";
|
||||||
import { RoleColor } from "@expcluster/roles";
|
import { RoleColor } from "@expcluster/roles";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,7 +20,7 @@ export interface SeedRole {
|
|||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
/** Name of the role whose permissions are also granted, applied recursively. */
|
/** Name of the role whose permissions are also granted, applied recursively. */
|
||||||
parent?: string;
|
parent?: string;
|
||||||
permissions: string[];
|
permissions: lib.PermissionName[];
|
||||||
/**
|
/**
|
||||||
* Name of the seed group holders are placed in by their highest role.
|
* Name of the seed group holders are placed in by their highest role.
|
||||||
* Without one the holders stay in Factorio's Default group.
|
* Without one the holders stay in Factorio's Default group.
|
||||||
@@ -329,7 +330,7 @@ export const seedGroups: SeedGroup[] = [
|
|||||||
|
|
||||||
/** The permissions a seed role grants, including those of its parents. */
|
/** The permissions a seed role grants, including those of its parents. */
|
||||||
export function flattenSeedPermissions(role: SeedRole, roles = seedRoles) {
|
export function flattenSeedPermissions(role: SeedRole, roles = seedRoles) {
|
||||||
const permissions = new Set<string>();
|
const permissions = new Set<lib.PermissionName>();
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
let current: SeedRole | undefined = role;
|
let current: SeedRole | undefined = role;
|
||||||
while (current && !seen.has(current.name)) {
|
while (current && !seen.has(current.name)) {
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ const { ControllerPlugin: RolesPlugin } = require("@expcluster/roles/dist/node/c
|
|||||||
const { ControllerPlugin: GroupsPlugin } = require("@expcluster/permission-groups/dist/node/controller");
|
const { ControllerPlugin: GroupsPlugin } = require("@expcluster/permission-groups/dist/node/controller");
|
||||||
const { GroupRecord, GroupPermissions, RoleMappingRecord } = require("@expcluster/permission-groups");
|
const { GroupRecord, GroupPermissions, RoleMappingRecord } = require("@expcluster/permission-groups");
|
||||||
|
|
||||||
// Importing this defines the permissions the seed grants
|
const { plugin } = require("../dist/node/index");
|
||||||
require("../dist/node/permissions");
|
|
||||||
|
// Registering the plugin defines the permissions the seed grants
|
||||||
|
lib.registerPluginPermissions([plugin]);
|
||||||
|
|
||||||
// The controller validates message classes against the link registry
|
// The controller validates message classes against the link registry
|
||||||
for (const Message of [messages.SeedRequest, ...roles.plugin.messages, ...groups.plugin.messages]) {
|
for (const Message of [messages.SeedRequest, ...roles.plugin.messages, ...groups.plugin.messages]) {
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ const t = require("tap");
|
|||||||
const lib = require("@clusterio/lib");
|
const lib = require("@clusterio/lib");
|
||||||
const { seedRoles, seedGroups, flattenSeedPermissions } = require("../dist/node/seed");
|
const { seedRoles, seedGroups, flattenSeedPermissions } = require("../dist/node/seed");
|
||||||
|
|
||||||
// Importing this defines the permissions the seed grants
|
const { plugin } = require("../dist/node/index");
|
||||||
require("../dist/node/permissions");
|
|
||||||
|
// Registering the plugin defines the permissions the seed grants
|
||||||
|
lib.registerPluginPermissions([plugin]);
|
||||||
|
|
||||||
t.test("seedRoles[] grant only defined permissions", t2 => {
|
t.test("seedRoles[] grant only defined permissions", t2 => {
|
||||||
for (const role of seedRoles) {
|
for (const role of seedRoles) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.browser.json",
|
"extends": "../tsconfig.browser.json",
|
||||||
"include": [ "web/**/*.tsx", "web/**/*.ts", "messages.ts", "package.json" ],
|
"include": [ "web/**/*.tsx", "web/**/*.ts", "index.ts", "messages.ts", "permissions.ts", "package.json" ],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user