Skip to content

Commit 51b0c69

Browse files
committed
chore: 🤖 add rdp client launch functionality in target details
✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17881
1 parent 199c56f commit 51b0c69

File tree

3 files changed

+124
-11
lines changed

3 files changed

+124
-11
lines changed

‎ui/desktop/app/controllers/scopes/scope/projects/targets/target.js‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default class ScopesScopeProjectsTargetsTargetController extends Controll
1515

1616
@service store;
1717
@service confirm;
18+
@service rdp;
1819

1920
// =attributes
2021

@@ -48,4 +49,27 @@ export default class ScopesScopeProjectsTargetsTargetController extends Controll
4849
});
4950
}
5051
}
52+
53+
/**
54+
* Launch method that calls parent quickConnectAndLaunchRdp method and handles
55+
* connection errors unique to this route
56+
* @param {TargetModel} target
57+
*/
58+
@action
59+
async connectAndLaunchRdp(target) {
60+
try {
61+
await this.targets.quickConnectAndLaunchRdp(target);
62+
} catch (error) {
63+
this.isConnectionError = true;
64+
this.confirm
65+
.confirm(error.message)
66+
// Retry
67+
.then(() => this.connectAndLaunchRdp(target))
68+
.catch(() => {
69+
// Reset the flag as this was user initiated and we're not
70+
// in a transition
71+
this.isConnectionError = false;
72+
});
73+
}
74+
}
5175
}

‎ui/desktop/app/templates/scopes/scope/projects/targets/target.hbs‎

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,27 @@
1515
</PH.Title>
1616
{{#if (can 'connect target' @model.target)}}
1717
<PH.Actions>
18-
<Hds::Button
19-
data-test-target-detail-connect-button
20-
@text={{if
21-
(gt @model.hosts.length 1)
22-
(t 'resources.session.actions.quick-connect')
23-
(t 'resources.session.actions.connect')
24-
}}
25-
@icon='entry-point'
26-
@iconPosition='trailing'
27-
{{on 'click' (fn this.connect @model.target)}}
28-
/>
18+
{{#if (and @model.target.isRDP this.rdp.isPreferredRdpClientSet)}}
19+
<Hds::Button
20+
data-test-target-detail-open-button
21+
@text={{t 'actions.open'}}
22+
@icon='external-link'
23+
@iconPosition='trailing'
24+
{{on 'click' (fn this.connectAndLaunchRdp @model.target)}}
25+
/>
26+
{{else}}
27+
<Hds::Button
28+
data-test-target-detail-connect-button
29+
@text={{if
30+
(gt @model.hosts.length 1)
31+
(t 'resources.session.actions.quick-connect')
32+
(t 'resources.session.actions.connect')
33+
}}
34+
@icon='entry-point'
35+
@iconPosition='trailing'
36+
{{on 'click' (fn this.connect @model.target)}}
37+
/>
38+
{{/if}}
2939
</PH.Actions>
3040
{{/if}}
3141
</Hds::PageHeader>

‎ui/desktop/tests/acceptance/projects/targets/target-test.js‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { authenticateSession } from 'ember-simple-auth/test-support';
1919
import WindowMockIPC from '../../../helpers/window-mock-ipc';
2020
import setupStubs from 'api/test-support/handlers/cache-daemon-search';
2121
import { setRunOptions } from 'ember-a11y-testing/test-support';
22+
import { TYPE_TARGET_RDP } from 'api/models/target';
2223

2324
module('Acceptance | projects | targets | target', function (hooks) {
2425
setupApplicationTest(hooks);
@@ -28,6 +29,7 @@ module('Acceptance | projects | targets | target', function (hooks) {
2829
const TARGET_RESOURCE_LINK = (id) => `[data-test-visit-target="${id}"]`;
2930
const TARGET_TABLE_CONNECT_BUTTON = (id) =>
3031
`[data-test-targets-connect-button="${id}"]`;
32+
const TARGET_TABLE_DETAILS_OPEN_BUTTON = `[data-test-target-detail-open-button]`;
3133
const TARGET_CONNECT_BUTTON = '[data-test-target-detail-connect-button]';
3234
const TARGET_HOST_SOURCE_CONNECT_BUTTON = (id) =>
3335
`[data-test-target-connect-button=${id}]`;
@@ -576,6 +578,7 @@ module('Acceptance | projects | targets | target', function (hooks) {
576578
assert.strictEqual(currentURL(), urls.targetWithOneHost);
577579
assert.dom('.aliases').exists();
578580
});
581+
579582
test('user can connect to a target without read permissions for host-set', async function (assert) {
580583
setRunOptions({
581584
rules: {
@@ -631,4 +634,80 @@ module('Acceptance | projects | targets | target', function (hooks) {
631634

632635
assert.dom(APP_STATE_TITLE).hasText('Connected');
633636
});
637+
638+
test('shows "Open" button for RDP target with preferred client', async function (assert) {
639+
let rdpService = this.owner.lookup('service:rdp');
640+
rdpService.preferredRdpClient = 'windows-app';
641+
instances.target.update({ type: TYPE_TARGET_RDP });
642+
643+
this.stubCacheDaemonSearch();
644+
645+
await visit(urls.target);
646+
647+
assert.dom(TARGET_TABLE_DETAILS_OPEN_BUTTON).exists();
648+
assert.dom(TARGET_TABLE_DETAILS_OPEN_BUTTON).hasText('Open');
649+
assert.dom('[data-test-icon=external-link]').exists();
650+
});
651+
652+
test('shows "Connect" button for RDP target without preferred client', async function (assert) {
653+
let rdpService = this.owner.lookup('service:rdp');
654+
rdpService.preferredRdpClient = null;
655+
instances.target.update({ type: TYPE_TARGET_RDP });
656+
657+
this.stubCacheDaemonSearch();
658+
659+
await visit(urls.target);
660+
661+
assert.dom(TARGET_CONNECT_BUTTON).exists();
662+
assert.dom(TARGET_CONNECT_BUTTON).hasText('Connect');
663+
});
664+
665+
test('clicking `open` button for RDP target triggers launchRdpClient', async function (assert) {
666+
let rdpService = this.owner.lookup('service:rdp');
667+
rdpService.preferredRdpClient = 'windows-app';
668+
instances.target.update({ type: TYPE_TARGET_RDP });
669+
670+
this.ipcStub.withArgs('cliExists').returns(true);
671+
this.ipcStub.withArgs('connect').returns({
672+
session_id: instances.session.id,
673+
address: 'a_123',
674+
port: 'p_123',
675+
protocol: 'rdp',
676+
});
677+
this.stubCacheDaemonSearch();
678+
this.ipcStub.withArgs('launchRdpClient').resolves();
679+
680+
const confirmService = this.owner.lookup('service:confirm');
681+
confirmService.enabled = true;
682+
683+
await visit(urls.target);
684+
685+
await click(TARGET_TABLE_DETAILS_OPEN_BUTTON);
686+
687+
assert.ok(this.ipcStub.calledWith('launchRdpClient', instances.session.id));
688+
});
689+
690+
test('shows `Connect` button for rdp target without preferred client', async function (assert) {
691+
let rdpService = this.owner.lookup('service:rdp');
692+
rdpService.preferredRdpClient = null;
693+
instances.target.update({ type: TYPE_TARGET_RDP });
694+
695+
this.stubCacheDaemonSearch();
696+
this.ipcStub.withArgs('cliExists').returns(true);
697+
this.ipcStub.withArgs('connect').returns({
698+
session_id: instances.session.id,
699+
address: 'a_123',
700+
port: 'p_123',
701+
protocol: 'rdp',
702+
});
703+
await visit(urls.target);
704+
705+
assert.dom(TARGET_CONNECT_BUTTON).exists();
706+
assert.dom(TARGET_CONNECT_BUTTON).hasText('Connect');
707+
708+
await click(TARGET_CONNECT_BUTTON);
709+
710+
assert.ok(this.ipcStub.calledWith('connect'));
711+
assert.notOk(this.ipcStub.calledWith('launchRdpClient'));
712+
});
634713
});

0 commit comments

Comments
 (0)