Add generate slave token button

Add a generate slave token button to the web interface and modify the
generateSlaveToken message and corresponding ctl command to have the
slave id be optional.  The random id is the desired behavior when adding
a slave with the installer, as it'll ask for the token for the new slave
and deduce the id from the token.
This commit is contained in:
Hornwitser committed 2021-06-15 14:46:44 +02:00
1 parent cc562a451e
commit fc08438164
5 files changed
+81 -7

No files matched your search

+3 -2
View File
@@ -137,10 +137,11 @@ slaveCommands.add(new libCommand.Command({
slaveCommands.add(new libCommand.Command({
definition: ["generate-token", "Generate token for a slave", (yargs) => {
yargs.option("id", { type: "number", nargs: 1, describe: "Slave id", demandOption: true });
yargs.option("id", { type: "number", nargs: 1, describe: "Slave id" });
}],
handler: async function(args, control) {
let response = await libLink.messages.generateSlaveToken.send(control, { slave_id: args.id });
let slaveId = typeof args.id === "number" ? args.id : null;
let response = await libLink.messages.generateSlaveToken.send(control, { slave_id: slaveId });
print(response.token);
},
}));
+1 -1
View File
@@ -422,7 +422,7 @@ messages.generateSlaveToken = new Request({
links: ["control-master"],
permission: "core.slave.generate_token",
requestProperties: {
"slave_id": { type: "integer" },
"slave_id": { type: ["integer", "null"] },
},
responseProperties: {
"token": { type: "string" },
+5 -1
View File
@@ -130,7 +130,11 @@ class ControlConnection extends BaseConnection {
}
async generateSlaveTokenRequestHandler(message) {
return { token: this.generateSlaveToken(message.data.slave_id) };
let slaveId = message.data.slave_id;
if (slaveId === null) {
slaveId = Math.random() * 2**31 | 0;
}
return { token: this.generateSlaveToken(slaveId) };
}
async createSlaveConfigRequestHandler(message) {
+69 -3
View File
@@ -1,11 +1,73 @@
import React, { useContext } from "react";
import { Table } from "antd";
import React, { useContext, useRef, useState } from "react";
import { Button, Form, Input, Modal, PageHeader, Table } from "antd";
import libLink from "@clusterio/lib/link";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import { useSlaveList } from "../model/slave";
import { notifyErrorHandler } from "../util/notify";
function GenerateSlaveTokenButton(props) {
let control = useContext(ControlContext);
let [visible, setVisible] = useState(false);
let [token, setToken] = useState(null);
let [form] = Form.useForm();
let tokenTextAreaRef = useRef(null);
async function generateToken() {
let values = form.getFieldsValue();
let slaveId = null;
if (values.slaveId) {
slaveId = Number.parseInt(values.slaveId, 10);
if (Number.isNaN(slaveId)) {
form.setFields([{ name: "slaveId", errors: ["Must be an integer"] }]);
return;
}
form.setFields([{ name: "slaveId", errors: [] }]);
}
let result = await libLink.messages.generateSlaveToken.send(control, { slave_id: slaveId });
setToken(result.token);
}
return <>
<Button
onClick={() => { setVisible(true); }}
>Generate Token</Button>
<Modal
title="Generate Slave Token"
visible={visible}
footer={null}
onCancel={() => {
setVisible(false);
setToken(null);
form.resetFields();
}}
>
<Form form={form} layout="vertical" requiredMark="optional">
<Form.Item name="slaveId" label="Slave ID">
<Input/>
</Form.Item>
<Form.Item>
<Button
onClick={() => { generateToken().catch(notifyErrorHandler("Error generating token")); }}
>Generate</Button>
</Form.Item>
<Form.Item label="Token" required>
<Input.TextArea value={token} autoSize ref={tokenTextAreaRef} />
</Form.Item>
<Button disabled={token === null} onClick={() => {
let textArea = tokenTextAreaRef.current.resizableTextArea.textArea;
textArea.select();
document.execCommand("copy");
window.getSelection().removeAllRanges();
}}>Copy</Button>
</Form>
</Modal>
</>;
}
export default function SlavesPage() {
@@ -13,7 +75,11 @@ export default function SlavesPage() {
let [slaveList] = useSlaveList();
return <PageLayout nav={[{ name: "Slaves" }]}>
<h2>Slaves</h2>
<PageHeader
className="site-page-header"
title="Slaves"
extra=<GenerateSlaveTokenButton />
/>
<Table
columns={[
{
+3
View File
@@ -167,6 +167,9 @@ describe("Integration of Clusterio", function() {
it("runs", async function() {
await execCtl("slave generate-token --id 42");
});
it("runs without an id", async function() {
await execCtl("slave generate-token");
});
});
describe("instance list", function() {
it("runs", async function() {