Skip to content

Commit

Permalink
WIP - put warning in dialog flow
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Sep 2, 2024
1 parent ab47b79 commit 2fcb51b
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 139 deletions.
51 changes: 38 additions & 13 deletions pkg/shell/hosts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,32 @@ export class CockpitHosts extends React.Component {
current_key: props.machine.key,
show_modal: false,
edit_machine: null,
switch_machine: null,
};

this.toggleMenu = this.toggleMenu.bind(this);
this.filterHosts = this.filterHosts.bind(this);
this.onAddNewHost = this.onAddNewHost.bind(this);
this.onEditHosts = this.onEditHosts.bind(this);
this.onHostEdit = this.onHostEdit.bind(this);
this.onHostSwitch = this.onHostSwitch.bind(this);
this.onRemove = this.onRemove.bind(this);
}

componentDidMount() {
console.log("DID MOUNT");
cockpit.user().then(user => {
this.setState({ current_user: user.name || "" });
}).catch(exc => console.log(exc));

window.trigger_connection_flow = machine => {
if (!this.state.show_modal)
this.onHostSwitch(machine, machine.connection_string);
};
}

componentWillUnmount() {
window.trigger_connection_flow = null;
}

static getDerivedStateFromProps(nextProps, prevState) {
Expand Down Expand Up @@ -124,6 +136,14 @@ export class CockpitHosts extends React.Component {
this.setState({ show_modal: true, edit_machine: machine });
}

onHostSwitch(machine, addr) {
console.log("SWITCH", addr, machine.state);
if (machine.state == "connected" || machine.address == "localhost")
this.props.jump(addr);
else if (machine.state != "connecting")
this.setState({ show_modal: true, switch_machine: machine });
}

onEditHosts() {
this.setState(s => { return { editing: !s.editing } });
}
Expand Down Expand Up @@ -180,7 +200,7 @@ export class CockpitHosts extends React.Component {
header={(m.user ? m.user : this.state.current_user) + " @"}
status={m.state === "failed" ? { type: "error", title: _("Connection error") } : null}
className={m.state}
jump={this.props.jump}
jump={addr => this.onHostSwitch(m, addr)}
actions={<>
<Tooltip content={_("Edit")} position="right">
<Button isDisabled={m.address === "localhost"} className="nav-action" hidden={!editing} onClick={e => this.onHostEdit(e, m)} key={m.label + "edit"} variant="secondary"><EditIcon /></Button>
Expand Down Expand Up @@ -242,22 +262,27 @@ export class CockpitHosts extends React.Component {
</div>
{this.state.show_modal &&
<HostModal machines_ins={this.props.machines}
onClose={() => this.setState({ show_modal: false, edit_machine: null })}
address={this.state.edit_machine ? this.state.edit_machine.address : null}
caller_callback={this.state.edit_machine
? (new_connection_string) => {
const parts = this.props.machines.split_connection_string(new_connection_string);
if (this.state.edit_machine == this.props.machine && parts.address != this.state.edit_machine.address) {
const addr = this.props.hostAddr({ host: parts.address }, true);
onClose={() => this.setState({ show_modal: false,
edit_machine: null, switch_machine: null })}
address={this.state.edit_machine?.address || this.state.switch_machine?.address}
template={this.state.switch_machine ? "connect" : null}
caller_callback={(new_connection_string) => {
console.log("CALLBACK", new_connection_string);
const parts = this.props.machines.split_connection_string(new_connection_string);
const addr = this.props.hostAddr({ host: parts.address }, true);
if (this.state.edit_machine) {
if (this.state.edit_machine == this.props.machine &&
parts.address != this.state.edit_machine.address) {
this.props.jump(addr);
}
return Promise.resolve();
}
: (new_connection_string) => {
const parts = this.props.machines.split_connection_string(new_connection_string);
} else {
this.props.loader.connect(parts.address);
if (this.state.switch_machine)
this.props.jump(addr);
return Promise.resolve();
}} />
}
}}
/>
}
</>
);
Expand Down
146 changes: 103 additions & 43 deletions pkg/shell/hosts_dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { ModalError } from "cockpit-components-inline-notification.jsx";
const _ = cockpit.gettext;

export const codes = {
"danger": "connect",
"no-cockpit": "not-supported",
"not-supported": "not-supported",
"protocol-error": "not-supported",
Expand Down Expand Up @@ -108,6 +109,61 @@ export const CrossMachineWarning = () => {
title={_("Malicious pages on a remote machine may affect other connected hosts")} />;
};

class Connect extends React.Component {
constructor(props) {
super(props);

this.state = {
inProgress: false,
};
}

onConnect() {
console.log("CONNECT", this.props.full_address);

this.setState({ inProgress: true });
this.props.run(this.props.try2Connect(this.props.full_address), ex => {
if (ex.problem === "no-host") {
let host_id_port = address;
let port = "22";
const port_index = host_id_port.lastIndexOf(":");
if (port_index === -1)
host_id_port = address + ":22";
else
port = host_id_port.substr(port_index + 1);

ex.message = cockpit.format(_("Unable to contact the given host $0. Make sure it has ssh running on port $1, or specify another port in the address."), host_id_port, port);
ex.problem = "not-found";
}
this.setState({ inProgress: false });
this.props.setError(ex);
});
}

render() {
return (
<Modal id="hosts_connect_server_dialog" isOpen
position="top" variant="medium"
onClose={this.props.onClose}
title={cockpit.format(_("Connect to $0"), this.props.full_address)}
footer={<>
<Button variant="primary" isLoading={this.state.inProgress}
onClick={() => this.onConnect()}>
{_("Connect")}
</Button>
<Button variant="link" className="btn-cancel" onClick={this.props.onClose}>
{ _("Cancel") }
</Button>
</>}
>
<Stack hasGutter>
<CrossMachineWarning />
</Stack>
</Modal>
);
}
}

class AddMachine extends React.Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -229,22 +285,24 @@ class AddMachine extends React.Component {
});
});

this.props.run(this.props.try2Connect(address), ex => {
if (ex.problem === "no-host") {
let host_id_port = address;
let port = "22";
const port_index = host_id_port.lastIndexOf(":");
if (port_index === -1)
host_id_port = address + ":22";
else
port = host_id_port.substr(port_index + 1);

ex.message = cockpit.format(_("Unable to contact the given host $0. Make sure it has ssh running on port $1, or specify another port in the address."), host_id_port, port);
ex.problem = "not-found";
}
this.setState({ inProgress: false });
this.props.setError(ex);
});
this.props.setError({ problem: "danger", command: "close" });

// this.props.run(this.props.try2Connect(address), ex => {
// if (ex.problem === "no-host") {
// let host_id_port = address;
// let port = "22";
// const port_index = host_id_port.lastIndexOf(":");
// if (port_index === -1)
// host_id_port = address + ":22";
// else
// port = host_id_port.substr(port_index + 1);

// ex.message = cockpit.format(_("Unable to contact the given host $0. Make sure it has ssh running on port $1, or specify another port in the address."), host_id_port, port);
// ex.problem = "not-found";
// }
// this.setState({ inProgress: false });
// this.props.setError(ex);
// });
}

render() {
Expand Down Expand Up @@ -295,7 +353,6 @@ class AddMachine extends React.Component {
<Stack hasGutter>
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
{body}
<CrossMachineWarning />
</Stack>
</Modal>
);
Expand Down Expand Up @@ -393,7 +450,6 @@ class MachinePort extends React.Component {
<Stack hasGutter>
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
{body}
<CrossMachineWarning />
</Stack>
</Modal>
);
Expand Down Expand Up @@ -527,7 +583,6 @@ class HostKey extends React.Component {
<Stack hasGutter>
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
{body}
<CrossMachineWarning />
</Stack>
</Modal>
);
Expand Down Expand Up @@ -905,13 +960,37 @@ class ChangeAuth extends React.Component {
<Stack hasGutter>
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
{body}
<CrossMachineWarning />
</Stack>
</Modal>
);
}
}

export function try2Connect(machines_ins, address, options) {
return new Promise((resolve, reject) => {
const conn_options = { ...options, payload: "echo", host: address };

conn_options["init-superuser"] = get_init_superuser_for_options(conn_options);

const machine = machines_ins.lookup(address);
if (machine && machine.host_key && !machine.on_disk) {
conn_options['temp-session'] = false; // Compatibility option
conn_options.session = 'shared';
conn_options['host-key'] = machine.host_key;
}

const client = cockpit.channel(conn_options);
client.send("x");
client.addEventListener("message", () => {
resolve();
client.close();
});
client.addEventListener("close", (event, options) => {
reject(options);
});
});
}

export class HostModal extends React.Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -950,28 +1029,7 @@ export class HostModal extends React.Component {
}

try2Connect(address, options) {
return new Promise((resolve, reject) => {
const conn_options = { ...options, payload: "echo", host: address };

conn_options["init-superuser"] = get_init_superuser_for_options(conn_options);

const machine = this.props.machines_ins.lookup(address);
if (machine && machine.host_key && !machine.on_disk) {
conn_options['temp-session'] = false; // Compatibility option
conn_options.session = 'shared';
conn_options['host-key'] = machine.host_key;
}

const client = cockpit.channel(conn_options);
client.send("x");
client.addEventListener("message", () => {
resolve();
client.close();
});
client.addEventListener("close", (event, options) => {
reject(options);
});
});
return try2Connect(this.props.machines_ins, address, options);
}

complete() {
Expand Down Expand Up @@ -1060,7 +1118,9 @@ export class HostModal extends React.Component {
complete: this.complete,
};

if (template === "add-machine")
if (template === "connect")
return <Connect {...props} />;
else if (template === "add-machine")
return <AddMachine {...props} />;
else if (template === "unknown-hostkey" || template === "unknown-host" || template === "invalid-hostkey")
return <HostKey {...props} />;
Expand Down
Loading

0 comments on commit 2fcb51b

Please sign in to comment.