From fc08438164597b986c0df6b6ab18094d78dda56c Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Tue, 15 Jun 2021 14:35:24 +0200 Subject: [PATCH] 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. --- packages/ctl/ctl.js | 5 +- packages/lib/link/messages.js | 2 +- packages/master/src/ControlConnection.js | 6 +- packages/web_ui/src/components/SlavesPage.jsx | 72 ++++++++++++++++++- test/integration/clusterio.js | 3 + 5 files changed, 81 insertions(+), 7 deletions(-) diff --git a/packages/ctl/ctl.js b/packages/ctl/ctl.js index 6ddc1d09..7d15d6e5 100755 --- a/packages/ctl/ctl.js +++ b/packages/ctl/ctl.js @@ -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); }, })); diff --git a/packages/lib/link/messages.js b/packages/lib/link/messages.js index 6ba0a8a4..dbb84455 100644 --- a/packages/lib/link/messages.js +++ b/packages/lib/link/messages.js @@ -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" }, diff --git a/packages/master/src/ControlConnection.js b/packages/master/src/ControlConnection.js index ddf42e83..2792774b 100644 --- a/packages/master/src/ControlConnection.js +++ b/packages/master/src/ControlConnection.js @@ -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) { diff --git a/packages/web_ui/src/components/SlavesPage.jsx b/packages/web_ui/src/components/SlavesPage.jsx index 0283c8bb..74af789a 100644 --- a/packages/web_ui/src/components/SlavesPage.jsx +++ b/packages/web_ui/src/components/SlavesPage.jsx @@ -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 <> + + { + setVisible(false); + setToken(null); + form.resetFields(); + }} + > +
+ + + + + + + + + + +
+
+ ; +} export default function SlavesPage() { @@ -13,7 +75,11 @@ export default function SlavesPage() { let [slaveList] = useSlaveList(); return -

Slaves

+ + />