@expcluster/permission-groups 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/controller.ts +434 -0
- package/dist/browser/messages.d.ts +527 -0
- package/dist/browser/messages.d.ts.map +1 -0
- package/dist/browser/messages.js +561 -0
- package/dist/browser/messages.js.map +1 -0
- package/dist/browser/package.json +49 -0
- package/dist/browser/tsconfig.browser.tsbuildinfo +1 -0
- package/dist/browser/web/components/AssignmentForm.d.ts +7 -0
- package/dist/browser/web/components/AssignmentForm.d.ts.map +1 -0
- package/dist/browser/web/components/AssignmentForm.js +29 -0
- package/dist/browser/web/components/AssignmentForm.js.map +1 -0
- package/dist/browser/web/components/AssignmentsTable.d.ts +2 -0
- package/dist/browser/web/components/AssignmentsTable.d.ts.map +1 -0
- package/dist/browser/web/components/AssignmentsTable.js +61 -0
- package/dist/browser/web/components/AssignmentsTable.js.map +1 -0
- package/dist/browser/web/components/DeleteConfirm.d.ts +6 -0
- package/dist/browser/web/components/DeleteConfirm.d.ts.map +1 -0
- package/dist/browser/web/components/DeleteConfirm.js +7 -0
- package/dist/browser/web/components/DeleteConfirm.js.map +1 -0
- package/dist/browser/web/components/GroupForm.d.ts +5 -0
- package/dist/browser/web/components/GroupForm.d.ts.map +1 -0
- package/dist/browser/web/components/GroupForm.js +22 -0
- package/dist/browser/web/components/GroupForm.js.map +1 -0
- package/dist/browser/web/components/GroupViewPage.d.ts +2 -0
- package/dist/browser/web/components/GroupViewPage.d.ts.map +1 -0
- package/dist/browser/web/components/GroupViewPage.js +161 -0
- package/dist/browser/web/components/GroupViewPage.js.map +1 -0
- package/dist/browser/web/components/GroupsTable.d.ts +2 -0
- package/dist/browser/web/components/GroupsTable.d.ts.map +1 -0
- package/dist/browser/web/components/GroupsTable.js +29 -0
- package/dist/browser/web/components/GroupsTable.js.map +1 -0
- package/dist/browser/web/components/RoleMappingForm.d.ts +7 -0
- package/dist/browser/web/components/RoleMappingForm.d.ts.map +1 -0
- package/dist/browser/web/components/RoleMappingForm.js +32 -0
- package/dist/browser/web/components/RoleMappingForm.js.map +1 -0
- package/dist/browser/web/components/RoleMappingsTable.d.ts +2 -0
- package/dist/browser/web/components/RoleMappingsTable.d.ts.map +1 -0
- package/dist/browser/web/components/RoleMappingsTable.js +64 -0
- package/dist/browser/web/components/RoleMappingsTable.js.map +1 -0
- package/dist/browser/web/index.d.ts +13 -0
- package/dist/browser/web/index.d.ts.map +1 -0
- package/dist/browser/web/index.js +60 -0
- package/dist/browser/web/index.js.map +1 -0
- package/dist/node/controller.d.ts +37 -0
- package/dist/node/controller.d.ts.map +1 -0
- package/dist/node/controller.js +372 -0
- package/dist/node/controller.js.map +1 -0
- package/dist/node/index.d.ts +10 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +196 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/instance.d.ts +40 -0
- package/dist/node/instance.d.ts.map +1 -0
- package/dist/node/instance.js +155 -0
- package/dist/node/instance.js.map +1 -0
- package/dist/node/messages.d.ts +527 -0
- package/dist/node/messages.d.ts.map +1 -0
- package/dist/node/messages.js +620 -0
- package/dist/node/messages.js.map +1 -0
- package/dist/node/tsconfig.node.tsbuildinfo +1 -0
- package/dist/web/manifest.json +10 -0
- package/dist/web/static/exp_groups.afefd90b210f7c8e0df2.js +543 -0
- package/dist/web/static/index_ts.f7d30aa0c13ff0be393a.js +22 -0
- package/dist/web/static/main.c2178975889c1c720e80.js +653 -0
- package/dist/web/static/messages_ts.65a81c17fb37953c5d68.js +22 -0
- package/dist/web/static/package_json.aab0d3f37da0567c250c.js +22 -0
- package/dist/web/static/vendors-node_modules_pnpm_ant-design_icons_6_2_3_rea_94b50600dfe79448cabf92d130d83059_node_mo-c79f54.cf768c64b40c811ce6c9.js +273 -0
- package/dist/web/static/vendors-node_modules_pnpm_sinclair_typebox_0_30_4_node_modules_sinclair_typebox_typebox_js.7fa46fac84f2e9324e54.js +22 -0
- package/dist/web/static/web_index_tsx-webpack_sharing_consume_default_react.b4766180f4d467b7b24f.js +102 -0
- package/index.ts +183 -0
- package/instance.ts +171 -0
- package/messages.ts +692 -0
- package/module/control.lua +438 -0
- package/module/globals.lua +11 -0
- package/module/module.json +12 -0
- package/module/module_exports.lua +3 -0
- package/package.json +47 -0
- package/tsconfig.browser.json +4 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +5 -0
- package/web/components/AssignmentForm.tsx +74 -0
- package/web/components/AssignmentsTable.tsx +111 -0
- package/web/components/DeleteConfirm.tsx +16 -0
- package/web/components/GroupForm.tsx +45 -0
- package/web/components/GroupViewPage.tsx +287 -0
- package/web/components/GroupsTable.tsx +49 -0
- package/web/components/RoleMappingForm.tsx +106 -0
- package/web/components/RoleMappingsTable.tsx +107 -0
- package/web/index.tsx +108 -0
- package/webpack.config.js +34 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React, { useContext, useState } from "react";
|
|
2
|
+
import { Table, Button, Space, Tag } from "antd";
|
|
3
|
+
import { EditOutlined } from "@ant-design/icons";
|
|
4
|
+
|
|
5
|
+
import { ControlContext, useAccount, useRoles } from "@clusterio/web_ui";
|
|
6
|
+
import { RoleMappingRecord, RoleMappingDeleteRequest } from "../../messages";
|
|
7
|
+
import type { WebPlugin } from "..";
|
|
8
|
+
|
|
9
|
+
import RoleMappingForm from "./RoleMappingForm";
|
|
10
|
+
import DeletedConfirm from "./DeleteConfirm";
|
|
11
|
+
|
|
12
|
+
export default function RoleMappingsTable() {
|
|
13
|
+
const control = useContext(ControlContext);
|
|
14
|
+
const plugin = control.plugins.get("exp_groups") as WebPlugin;
|
|
15
|
+
const account = useAccount();
|
|
16
|
+
|
|
17
|
+
const [roleMappings, roleMappingsSynced] = plugin.useRoleMappings();
|
|
18
|
+
const [groups, groupsSynced] = plugin.useGroups();
|
|
19
|
+
const [roles, rolesSynced] = useRoles();
|
|
20
|
+
|
|
21
|
+
const [editing, setEditing] = useState<RoleMappingRecord | undefined>();
|
|
22
|
+
const [open, setOpen] = useState(false);
|
|
23
|
+
|
|
24
|
+
const roleMappingArray = [...roleMappings.values()];
|
|
25
|
+
|
|
26
|
+
const roleFilters = [...roles.values()]
|
|
27
|
+
.filter(role => roleMappingArray.some(mapping => mapping.roleIds.has(role.id)))
|
|
28
|
+
.map(role => ({ text: role.name, value: role.id }));
|
|
29
|
+
|
|
30
|
+
const groupFilters = [...groups.values()]
|
|
31
|
+
.filter(group => roleMappingArray.some(mapping => mapping.groupId === group.id))
|
|
32
|
+
.map(group => ({ text: group.name, value: group.id }))
|
|
33
|
+
|
|
34
|
+
return <>
|
|
35
|
+
<Table
|
|
36
|
+
columns={[
|
|
37
|
+
{
|
|
38
|
+
title: "Priority",
|
|
39
|
+
dataIndex: "priority",
|
|
40
|
+
width: "10%",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: "Roles",
|
|
44
|
+
filters: roleFilters,
|
|
45
|
+
onFilter: (value, record: RoleMappingRecord) => (
|
|
46
|
+
record.roleIds.has(value as number)
|
|
47
|
+
),
|
|
48
|
+
render: (_: any, record: RoleMappingRecord) => (
|
|
49
|
+
[...record.roleIds].map(id => <Tag key={id}>{roles.get(id)?.name ?? id}</Tag>)
|
|
50
|
+
),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: "Group",
|
|
54
|
+
width: "30%",
|
|
55
|
+
filters: groupFilters,
|
|
56
|
+
onFilter: (value, record: RoleMappingRecord) => (
|
|
57
|
+
record.groupId === value
|
|
58
|
+
),
|
|
59
|
+
render: (_: any, record: RoleMappingRecord) => (
|
|
60
|
+
groups.get(record.groupId)?.name ?? record.groupId
|
|
61
|
+
),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
title: "Enabled",
|
|
65
|
+
width: "10%",
|
|
66
|
+
filters: [
|
|
67
|
+
{ text: "Enabled", value: true },
|
|
68
|
+
{ text: "Disabled", value: false },
|
|
69
|
+
],
|
|
70
|
+
onFilter: (value, record: RoleMappingRecord) => (
|
|
71
|
+
record.enabled === value
|
|
72
|
+
),
|
|
73
|
+
render: (_: any, record: RoleMappingRecord) => (
|
|
74
|
+
record.enabled ? "Yes" : "No"
|
|
75
|
+
),
|
|
76
|
+
},
|
|
77
|
+
...(account.hasAnyPermission(
|
|
78
|
+
"exp_groups.role_mapping.update",
|
|
79
|
+
"exp_groups.role_mapping.delete",
|
|
80
|
+
) ? [{
|
|
81
|
+
title: "Actions",
|
|
82
|
+
width: "10%",
|
|
83
|
+
render: (_: any, record: any) => (
|
|
84
|
+
<Space>
|
|
85
|
+
{account.hasPermission("exp_groups.role_mapping.update") && <Button
|
|
86
|
+
icon={<EditOutlined />}
|
|
87
|
+
onClick={() => {
|
|
88
|
+
setEditing(record);
|
|
89
|
+
setOpen(true);
|
|
90
|
+
}}
|
|
91
|
+
/>}
|
|
92
|
+
{account.hasPermission("exp_groups.role_mapping.delete") && <DeletedConfirm
|
|
93
|
+
onConfirm={() => control.send(new RoleMappingDeleteRequest(record.id))}
|
|
94
|
+
/>}
|
|
95
|
+
</Space>
|
|
96
|
+
),
|
|
97
|
+
}] : []),
|
|
98
|
+
]}
|
|
99
|
+
dataSource={roleMappingArray.sort((a, b) => b.priority - a.priority)}
|
|
100
|
+
loading={!roleMappingsSynced || !groupsSynced || !rolesSynced}
|
|
101
|
+
rowKey={(m) => m.id}
|
|
102
|
+
pagination={false}
|
|
103
|
+
/>
|
|
104
|
+
|
|
105
|
+
<RoleMappingForm open={open} setOpen={setOpen} initial={editing} />
|
|
106
|
+
</>;
|
|
107
|
+
}
|
package/web/index.tsx
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React, { useState, useCallback, useSyncExternalStore } from "react";
|
|
2
|
+
import { BaseWebPlugin, PageLayout, PageHeader, useAccount, SectionHeader } from "@clusterio/web_ui";
|
|
3
|
+
import { Button } from "antd";
|
|
4
|
+
|
|
5
|
+
import * as messages from "../messages";
|
|
6
|
+
import * as lib from "@clusterio/lib";
|
|
7
|
+
|
|
8
|
+
import GroupsTable from "./components/GroupsTable";
|
|
9
|
+
import AssignmentsTable from "./components/AssignmentsTable";
|
|
10
|
+
import RoleMappingsTable from "./components/RoleMappingsTable";
|
|
11
|
+
import GroupViewPage from "./components/GroupViewPage";
|
|
12
|
+
import GroupForm from "./components/GroupForm";
|
|
13
|
+
import RoleMappingForm from "./components/RoleMappingForm";
|
|
14
|
+
import AssignmentForm from "./components/AssignmentForm";
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
function ExpGroupsPage() {
|
|
18
|
+
const account = useAccount();
|
|
19
|
+
|
|
20
|
+
const [groupOpen, setGroupOpen] = useState(false);
|
|
21
|
+
const [assignmentOpen, setAssignmentOpen] = useState(false);
|
|
22
|
+
const [roleMappingOpen, setRoleMappingOpen] = useState(false);
|
|
23
|
+
|
|
24
|
+
return <PageLayout nav={[{ name: "Permission Groups" }]}>
|
|
25
|
+
<PageHeader title="Permission Groups" />
|
|
26
|
+
|
|
27
|
+
{account.hasPermission("exp_groups.group.list") && <>
|
|
28
|
+
<SectionHeader
|
|
29
|
+
title="Groups"
|
|
30
|
+
extra={
|
|
31
|
+
account.hasPermission("exp_groups.group.create")
|
|
32
|
+
? <Button type="primary" onClick={() => setGroupOpen(true)}>Create</Button>
|
|
33
|
+
: undefined
|
|
34
|
+
}
|
|
35
|
+
/>
|
|
36
|
+
<GroupsTable />
|
|
37
|
+
<GroupForm open={groupOpen} setOpen={setGroupOpen} />
|
|
38
|
+
</>}
|
|
39
|
+
|
|
40
|
+
{account.hasPermission("exp_groups.role_mapping.list") && <>
|
|
41
|
+
<SectionHeader
|
|
42
|
+
title="Role Mappings"
|
|
43
|
+
extra={
|
|
44
|
+
account.hasPermission("exp_groups.role_mapping.create")
|
|
45
|
+
? <Button type="primary" onClick={() => setRoleMappingOpen(true)}>Create</Button>
|
|
46
|
+
: undefined
|
|
47
|
+
}
|
|
48
|
+
/>
|
|
49
|
+
<RoleMappingsTable />
|
|
50
|
+
<RoleMappingForm open={roleMappingOpen} setOpen={setRoleMappingOpen} />
|
|
51
|
+
</>}
|
|
52
|
+
|
|
53
|
+
{account.hasPermission("exp_groups.assignment.list") && <>
|
|
54
|
+
<SectionHeader
|
|
55
|
+
title="Assignments"
|
|
56
|
+
extra={
|
|
57
|
+
account.hasPermission("exp_groups.assignment.create")
|
|
58
|
+
? <Button type="primary" onClick={() => setAssignmentOpen(true)}>Create</Button>
|
|
59
|
+
: undefined
|
|
60
|
+
}
|
|
61
|
+
/>
|
|
62
|
+
<AssignmentsTable />
|
|
63
|
+
<AssignmentForm open={assignmentOpen} setOpen={setAssignmentOpen} />
|
|
64
|
+
</>}
|
|
65
|
+
</PageLayout>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class WebPlugin extends BaseWebPlugin {
|
|
69
|
+
groups = new lib.MapSubscriber(messages.GroupUpdatedEvent, this.control);
|
|
70
|
+
assignments = new lib.MapSubscriber(messages.ManualAssignmentUpdatedEvent, this.control);
|
|
71
|
+
roleMappings = new lib.MapSubscriber(messages.RoleMappingUpdatedEvent, this.control);
|
|
72
|
+
|
|
73
|
+
async init() {
|
|
74
|
+
this.pages = [
|
|
75
|
+
{
|
|
76
|
+
path: "/permission_groups",
|
|
77
|
+
sidebarName: "Permission Groups",
|
|
78
|
+
permission: (account => account.hasAnyPermission(
|
|
79
|
+
"exp_groups.group.list",
|
|
80
|
+
"exp_groups.assignment.list",
|
|
81
|
+
"exp_groups.role_mapping.list",
|
|
82
|
+
)),
|
|
83
|
+
content: <ExpGroupsPage />,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
path: "/permission_groups/:id/view",
|
|
87
|
+
sidebarPath: "/permission_groups",
|
|
88
|
+
permission: "exp_groups.group.get",
|
|
89
|
+
content: <GroupViewPage />,
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
useGroups() {
|
|
95
|
+
const subscribe = useCallback((cb: () => void) => this.groups.subscribe(cb), []);
|
|
96
|
+
return useSyncExternalStore(subscribe, () => this.groups.getSnapshot());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
useAssignments() {
|
|
100
|
+
const subscribe = useCallback((cb: () => void) => this.assignments.subscribe(cb), []);
|
|
101
|
+
return useSyncExternalStore(subscribe, () => this.assignments.getSnapshot());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
useRoleMappings() {
|
|
105
|
+
const subscribe = useCallback((cb: () => void) => this.roleMappings.subscribe(cb), []);
|
|
106
|
+
return useSyncExternalStore(subscribe, () => this.roleMappings.getSnapshot());
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const webpack = require("webpack");
|
|
4
|
+
const { merge } = require("webpack-merge");
|
|
5
|
+
|
|
6
|
+
const common = require("@clusterio/web_ui/webpack.common");
|
|
7
|
+
|
|
8
|
+
module.exports = (env = {}) => merge(common(env), {
|
|
9
|
+
context: __dirname,
|
|
10
|
+
entry: "./web/index.tsx",
|
|
11
|
+
output: {
|
|
12
|
+
path: path.resolve(__dirname, "dist", "web"),
|
|
13
|
+
},
|
|
14
|
+
plugins: [
|
|
15
|
+
new webpack.container.ModuleFederationPlugin({
|
|
16
|
+
name: "exp_groups",
|
|
17
|
+
library: { type: "window", name: "plugin_exp_groups" },
|
|
18
|
+
exposes: {
|
|
19
|
+
"./": "./index.ts",
|
|
20
|
+
"./package.json": "./package.json",
|
|
21
|
+
"./web": "./web/index.tsx",
|
|
22
|
+
},
|
|
23
|
+
shared: {
|
|
24
|
+
"@clusterio/lib": { import: false },
|
|
25
|
+
"@clusterio/web_ui": { import: false },
|
|
26
|
+
"antd": { import: false },
|
|
27
|
+
"react": { import: false },
|
|
28
|
+
"react-dom": { import: false },
|
|
29
|
+
"react-router": { import: false },
|
|
30
|
+
"react-router-dom": { import: false },
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
],
|
|
34
|
+
});
|