Skip to content

Commit 2fcb51b

Browse files
committed
WIP - put warning in dialog flow
1 parent ab47b79 commit 2fcb51b

File tree

3 files changed

+160
-139
lines changed

3 files changed

+160
-139
lines changed

pkg/shell/hosts.jsx

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,32 @@ export class CockpitHosts extends React.Component {
7575
current_key: props.machine.key,
7676
show_modal: false,
7777
edit_machine: null,
78+
switch_machine: null,
7879
};
7980

8081
this.toggleMenu = this.toggleMenu.bind(this);
8182
this.filterHosts = this.filterHosts.bind(this);
8283
this.onAddNewHost = this.onAddNewHost.bind(this);
8384
this.onEditHosts = this.onEditHosts.bind(this);
8485
this.onHostEdit = this.onHostEdit.bind(this);
86+
this.onHostSwitch = this.onHostSwitch.bind(this);
8587
this.onRemove = this.onRemove.bind(this);
8688
}
8789

8890
componentDidMount() {
91+
console.log("DID MOUNT");
8992
cockpit.user().then(user => {
9093
this.setState({ current_user: user.name || "" });
9194
}).catch(exc => console.log(exc));
95+
96+
window.trigger_connection_flow = machine => {
97+
if (!this.state.show_modal)
98+
this.onHostSwitch(machine, machine.connection_string);
99+
};
100+
}
101+
102+
componentWillUnmount() {
103+
window.trigger_connection_flow = null;
92104
}
93105

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

139+
onHostSwitch(machine, addr) {
140+
console.log("SWITCH", addr, machine.state);
141+
if (machine.state == "connected" || machine.address == "localhost")
142+
this.props.jump(addr);
143+
else if (machine.state != "connecting")
144+
this.setState({ show_modal: true, switch_machine: machine });
145+
}
146+
127147
onEditHosts() {
128148
this.setState(s => { return { editing: !s.editing } });
129149
}
@@ -180,7 +200,7 @@ export class CockpitHosts extends React.Component {
180200
header={(m.user ? m.user : this.state.current_user) + " @"}
181201
status={m.state === "failed" ? { type: "error", title: _("Connection error") } : null}
182202
className={m.state}
183-
jump={this.props.jump}
203+
jump={addr => this.onHostSwitch(m, addr)}
184204
actions={<>
185205
<Tooltip content={_("Edit")} position="right">
186206
<Button isDisabled={m.address === "localhost"} className="nav-action" hidden={!editing} onClick={e => this.onHostEdit(e, m)} key={m.label + "edit"} variant="secondary"><EditIcon /></Button>
@@ -242,22 +262,27 @@ export class CockpitHosts extends React.Component {
242262
</div>
243263
{this.state.show_modal &&
244264
<HostModal machines_ins={this.props.machines}
245-
onClose={() => this.setState({ show_modal: false, edit_machine: null })}
246-
address={this.state.edit_machine ? this.state.edit_machine.address : null}
247-
caller_callback={this.state.edit_machine
248-
? (new_connection_string) => {
249-
const parts = this.props.machines.split_connection_string(new_connection_string);
250-
if (this.state.edit_machine == this.props.machine && parts.address != this.state.edit_machine.address) {
251-
const addr = this.props.hostAddr({ host: parts.address }, true);
265+
onClose={() => this.setState({ show_modal: false,
266+
edit_machine: null, switch_machine: null })}
267+
address={this.state.edit_machine?.address || this.state.switch_machine?.address}
268+
template={this.state.switch_machine ? "connect" : null}
269+
caller_callback={(new_connection_string) => {
270+
console.log("CALLBACK", new_connection_string);
271+
const parts = this.props.machines.split_connection_string(new_connection_string);
272+
const addr = this.props.hostAddr({ host: parts.address }, true);
273+
if (this.state.edit_machine) {
274+
if (this.state.edit_machine == this.props.machine &&
275+
parts.address != this.state.edit_machine.address) {
252276
this.props.jump(addr);
253277
}
254-
return Promise.resolve();
255-
}
256-
: (new_connection_string) => {
257-
const parts = this.props.machines.split_connection_string(new_connection_string);
278+
} else {
258279
this.props.loader.connect(parts.address);
280+
if (this.state.switch_machine)
281+
this.props.jump(addr);
259282
return Promise.resolve();
260-
}} />
283+
}
284+
}}
285+
/>
261286
}
262287
</>
263288
);

pkg/shell/hosts_dialog.jsx

Lines changed: 103 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { ModalError } from "cockpit-components-inline-notification.jsx";
4646
const _ = cockpit.gettext;
4747

4848
export const codes = {
49+
"danger": "connect",
4950
"no-cockpit": "not-supported",
5051
"not-supported": "not-supported",
5152
"protocol-error": "not-supported",
@@ -108,6 +109,61 @@ export const CrossMachineWarning = () => {
108109
title={_("Malicious pages on a remote machine may affect other connected hosts")} />;
109110
};
110111

112+
class Connect extends React.Component {
113+
constructor(props) {
114+
super(props);
115+
116+
this.state = {
117+
inProgress: false,
118+
};
119+
}
120+
121+
onConnect() {
122+
console.log("CONNECT", this.props.full_address);
123+
124+
this.setState({ inProgress: true });
125+
this.props.run(this.props.try2Connect(this.props.full_address), ex => {
126+
if (ex.problem === "no-host") {
127+
let host_id_port = address;
128+
let port = "22";
129+
const port_index = host_id_port.lastIndexOf(":");
130+
if (port_index === -1)
131+
host_id_port = address + ":22";
132+
else
133+
port = host_id_port.substr(port_index + 1);
134+
135+
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);
136+
ex.problem = "not-found";
137+
}
138+
this.setState({ inProgress: false });
139+
this.props.setError(ex);
140+
});
141+
}
142+
143+
render() {
144+
return (
145+
<Modal id="hosts_connect_server_dialog" isOpen
146+
position="top" variant="medium"
147+
onClose={this.props.onClose}
148+
title={cockpit.format(_("Connect to $0"), this.props.full_address)}
149+
footer={<>
150+
<Button variant="primary" isLoading={this.state.inProgress}
151+
onClick={() => this.onConnect()}>
152+
{_("Connect")}
153+
</Button>
154+
<Button variant="link" className="btn-cancel" onClick={this.props.onClose}>
155+
{ _("Cancel") }
156+
</Button>
157+
</>}
158+
>
159+
<Stack hasGutter>
160+
<CrossMachineWarning />
161+
</Stack>
162+
</Modal>
163+
);
164+
}
165+
}
166+
111167
class AddMachine extends React.Component {
112168
constructor(props) {
113169
super(props);
@@ -229,22 +285,24 @@ class AddMachine extends React.Component {
229285
});
230286
});
231287

232-
this.props.run(this.props.try2Connect(address), ex => {
233-
if (ex.problem === "no-host") {
234-
let host_id_port = address;
235-
let port = "22";
236-
const port_index = host_id_port.lastIndexOf(":");
237-
if (port_index === -1)
238-
host_id_port = address + ":22";
239-
else
240-
port = host_id_port.substr(port_index + 1);
241-
242-
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);
243-
ex.problem = "not-found";
244-
}
245-
this.setState({ inProgress: false });
246-
this.props.setError(ex);
247-
});
288+
this.props.setError({ problem: "danger", command: "close" });
289+
290+
// this.props.run(this.props.try2Connect(address), ex => {
291+
// if (ex.problem === "no-host") {
292+
// let host_id_port = address;
293+
// let port = "22";
294+
// const port_index = host_id_port.lastIndexOf(":");
295+
// if (port_index === -1)
296+
// host_id_port = address + ":22";
297+
// else
298+
// port = host_id_port.substr(port_index + 1);
299+
300+
// 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);
301+
// ex.problem = "not-found";
302+
// }
303+
// this.setState({ inProgress: false });
304+
// this.props.setError(ex);
305+
// });
248306
}
249307

250308
render() {
@@ -295,7 +353,6 @@ class AddMachine extends React.Component {
295353
<Stack hasGutter>
296354
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
297355
{body}
298-
<CrossMachineWarning />
299356
</Stack>
300357
</Modal>
301358
);
@@ -393,7 +450,6 @@ class MachinePort extends React.Component {
393450
<Stack hasGutter>
394451
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
395452
{body}
396-
<CrossMachineWarning />
397453
</Stack>
398454
</Modal>
399455
);
@@ -527,7 +583,6 @@ class HostKey extends React.Component {
527583
<Stack hasGutter>
528584
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
529585
{body}
530-
<CrossMachineWarning />
531586
</Stack>
532587
</Modal>
533588
);
@@ -905,13 +960,37 @@ class ChangeAuth extends React.Component {
905960
<Stack hasGutter>
906961
{ this.props.dialogError && <ModalError dialogError={this.props.dialogError} />}
907962
{body}
908-
<CrossMachineWarning />
909963
</Stack>
910964
</Modal>
911965
);
912966
}
913967
}
914968

969+
export function try2Connect(machines_ins, address, options) {
970+
return new Promise((resolve, reject) => {
971+
const conn_options = { ...options, payload: "echo", host: address };
972+
973+
conn_options["init-superuser"] = get_init_superuser_for_options(conn_options);
974+
975+
const machine = machines_ins.lookup(address);
976+
if (machine && machine.host_key && !machine.on_disk) {
977+
conn_options['temp-session'] = false; // Compatibility option
978+
conn_options.session = 'shared';
979+
conn_options['host-key'] = machine.host_key;
980+
}
981+
982+
const client = cockpit.channel(conn_options);
983+
client.send("x");
984+
client.addEventListener("message", () => {
985+
resolve();
986+
client.close();
987+
});
988+
client.addEventListener("close", (event, options) => {
989+
reject(options);
990+
});
991+
});
992+
}
993+
915994
export class HostModal extends React.Component {
916995
constructor(props) {
917996
super(props);
@@ -950,28 +1029,7 @@ export class HostModal extends React.Component {
9501029
}
9511030

9521031
try2Connect(address, options) {
953-
return new Promise((resolve, reject) => {
954-
const conn_options = { ...options, payload: "echo", host: address };
955-
956-
conn_options["init-superuser"] = get_init_superuser_for_options(conn_options);
957-
958-
const machine = this.props.machines_ins.lookup(address);
959-
if (machine && machine.host_key && !machine.on_disk) {
960-
conn_options['temp-session'] = false; // Compatibility option
961-
conn_options.session = 'shared';
962-
conn_options['host-key'] = machine.host_key;
963-
}
964-
965-
const client = cockpit.channel(conn_options);
966-
client.send("x");
967-
client.addEventListener("message", () => {
968-
resolve();
969-
client.close();
970-
});
971-
client.addEventListener("close", (event, options) => {
972-
reject(options);
973-
});
974-
});
1032+
return try2Connect(this.props.machines_ins, address, options);
9751033
}
9761034

9771035
complete() {
@@ -1060,7 +1118,9 @@ export class HostModal extends React.Component {
10601118
complete: this.complete,
10611119
};
10621120

1063-
if (template === "add-machine")
1121+
if (template === "connect")
1122+
return <Connect {...props} />;
1123+
else if (template === "add-machine")
10641124
return <AddMachine {...props} />;
10651125
else if (template === "unknown-hostkey" || template === "unknown-host" || template === "invalid-hostkey")
10661126
return <HostKey {...props} />;

0 commit comments

Comments
 (0)