Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class ScopesScopeProjectsTargetsTargetController extends Controll

@service store;
@service confirm;
@service rdp;

// =attributes

Expand Down Expand Up @@ -48,4 +49,27 @@ export default class ScopesScopeProjectsTargetsTargetController extends Controll
});
}
}

/**
* Launch method that calls parent quickConnectAndLaunchRdp method and handles
* connection errors unique to this route
* @param {TargetModel} target
*/
@action
async connectAndLaunchRdp(target) {
try {
await this.targets.quickConnectAndLaunchRdp(target);
} catch (error) {
this.isConnectionError = true;
this.confirm
.confirm(error.message)
// Retry
.then(() => this.connectAndLaunchRdp(target))
.catch(() => {
// Reset the flag as this was user initiated and we're not
// in a transition
this.isConnectionError = false;
});
}
}
}
32 changes: 21 additions & 11 deletions ui/desktop/app/templates/scopes/scope/projects/targets/target.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,27 @@
</PH.Title>
{{#if (can 'connect target' @model.target)}}
<PH.Actions>
<Hds::Button
data-test-target-detail-connect-button
@text={{if
(gt @model.hosts.length 1)
(t 'resources.session.actions.quick-connect')
(t 'resources.session.actions.connect')
}}
@icon='entry-point'
@iconPosition='trailing'
{{on 'click' (fn this.connect @model.target)}}
/>
{{#if (and @model.target.isRDP this.rdp.isPreferredRdpClientSet)}}
<Hds::Button
data-test-target-detail-open-button
@text={{t 'actions.open'}}
@icon='external-link'
@iconPosition='trailing'
{{on 'click' (fn this.connectAndLaunchRdp @model.target)}}
/>
{{else}}
<Hds::Button
data-test-target-detail-connect-button
@text={{if
(gt @model.hosts.length 1)
(t 'resources.session.actions.quick-connect')
(t 'resources.session.actions.connect')
}}
@icon='entry-point'
@iconPosition='trailing'
{{on 'click' (fn this.connect @model.target)}}
/>
{{/if}}
</PH.Actions>
{{/if}}
</Hds::PageHeader>
Expand Down
79 changes: 79 additions & 0 deletions ui/desktop/tests/acceptance/projects/targets/target-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { authenticateSession } from 'ember-simple-auth/test-support';
import WindowMockIPC from '../../../helpers/window-mock-ipc';
import setupStubs from 'api/test-support/handlers/cache-daemon-search';
import { setRunOptions } from 'ember-a11y-testing/test-support';
import { TYPE_TARGET_RDP } from 'api/models/target';

module('Acceptance | projects | targets | target', function (hooks) {
setupApplicationTest(hooks);
Expand All @@ -28,6 +29,7 @@ module('Acceptance | projects | targets | target', function (hooks) {
const TARGET_RESOURCE_LINK = (id) => `[data-test-visit-target="${id}"]`;
const TARGET_TABLE_CONNECT_BUTTON = (id) =>
`[data-test-targets-connect-button="${id}"]`;
const TARGET_TABLE_DETAILS_OPEN_BUTTON = `[data-test-target-detail-open-button]`;
const TARGET_CONNECT_BUTTON = '[data-test-target-detail-connect-button]';
const TARGET_HOST_SOURCE_CONNECT_BUTTON = (id) =>
`[data-test-target-connect-button=${id}]`;
Expand Down Expand Up @@ -576,6 +578,7 @@ module('Acceptance | projects | targets | target', function (hooks) {
assert.strictEqual(currentURL(), urls.targetWithOneHost);
assert.dom('.aliases').exists();
});

test('user can connect to a target without read permissions for host-set', async function (assert) {
setRunOptions({
rules: {
Expand Down Expand Up @@ -631,4 +634,80 @@ module('Acceptance | projects | targets | target', function (hooks) {

assert.dom(APP_STATE_TITLE).hasText('Connected');
});

test('shows "Open" button for RDP target with preferred client', async function (assert) {
let rdpService = this.owner.lookup('service:rdp');
rdpService.preferredRdpClient = 'windows-app';
instances.target.update({ type: TYPE_TARGET_RDP });

this.stubCacheDaemonSearch();

await visit(urls.target);

assert.dom(TARGET_TABLE_DETAILS_OPEN_BUTTON).exists();
assert.dom(TARGET_TABLE_DETAILS_OPEN_BUTTON).hasText('Open');
assert.dom('[data-test-icon=external-link]').exists();
});

test('shows "Connect" button for RDP target without preferred client', async function (assert) {
let rdpService = this.owner.lookup('service:rdp');
rdpService.preferredRdpClient = null;
instances.target.update({ type: TYPE_TARGET_RDP });

this.stubCacheDaemonSearch();

await visit(urls.target);

assert.dom(TARGET_CONNECT_BUTTON).exists();
assert.dom(TARGET_CONNECT_BUTTON).hasText('Connect');
});

test('clicking `open` button for RDP target triggers launchRdpClient', async function (assert) {
let rdpService = this.owner.lookup('service:rdp');
rdpService.preferredRdpClient = 'windows-app';
instances.target.update({ type: TYPE_TARGET_RDP });

this.ipcStub.withArgs('cliExists').returns(true);
this.ipcStub.withArgs('connect').returns({
session_id: instances.session.id,
address: 'a_123',
port: 'p_123',
protocol: 'rdp',
});
this.stubCacheDaemonSearch();
this.ipcStub.withArgs('launchRdpClient').resolves();

const confirmService = this.owner.lookup('service:confirm');
confirmService.enabled = true;

await visit(urls.target);

await click(TARGET_TABLE_DETAILS_OPEN_BUTTON);

assert.ok(this.ipcStub.calledWith('launchRdpClient', instances.session.id));
});

test('shows `Connect` button for rdp target without preferred client', async function (assert) {
let rdpService = this.owner.lookup('service:rdp');
rdpService.preferredRdpClient = null;
instances.target.update({ type: TYPE_TARGET_RDP });

this.stubCacheDaemonSearch();
this.ipcStub.withArgs('cliExists').returns(true);
this.ipcStub.withArgs('connect').returns({
session_id: instances.session.id,
address: 'a_123',
port: 'p_123',
protocol: 'rdp',
});
await visit(urls.target);

assert.dom(TARGET_CONNECT_BUTTON).exists();
assert.dom(TARGET_CONNECT_BUTTON).hasText('Connect');

await click(TARGET_CONNECT_BUTTON);

assert.ok(this.ipcStub.calledWith('connect'));
assert.notOk(this.ipcStub.calledWith('launchRdpClient'));
});
});
Loading