Skip to content

Commit 3ff0a7f

Browse files
authored
Merge pull request #1302 from jumpserver/dev
v4.10.0
2 parents 7feae77 + 115e60e commit 3ff0a7f

26 files changed

Lines changed: 500 additions & 233 deletions

src/app/elements/asset-tree/asset-tree.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
</span>
2121
</div>
2222
<span
23-
[hidden]="!tree.open"
23+
*ngIf="tree.open"
2424
class="tree-banner-icon-zone"
2525
>
2626
<a

src/app/elements/connect/connect-dialog/advanced-option/advanced-option.component.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,22 @@ export class ElementAdvancedOptionComponent implements OnChanges, OnInit {
9999
return !this.connectMethod || this.connectMethod.component !== 'tinker';
100100
}
101101
},
102+
{
103+
type: 'select',
104+
field: 'virtualappConnectMethod',
105+
options: [
106+
{ label: 'Web', value: 'web' },
107+
...(true ? [{ label: 'Client', value: 'client' }] : [])
108+
],
109+
label: 'Virtualapp connect method',
110+
value: this.setting.graphics.applet_connection_method,
111+
hidden: () => {
112+
if (!this._settingSvc.hasXPack()) {
113+
return true;
114+
}
115+
return !this.connectMethod || this.connectMethod.component !== 'panda';
116+
}
117+
},
102118
{
103119
type: 'select',
104120
field: 'reusable',

src/app/elements/connect/connect-dialog/connect-dialog.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ <h3>{{ "Connect" | translate }} - {{ asset.name | truncatechars:30 }}</h3>
3939

4040
<elements-connect-method
4141
(onDownloadRDPFile)="onConfirm(true)"
42+
(onGuidePage)="onConfirm()"
4243
[(connectMethod)]="connectMethod"
4344
[account]="accountSelected"
4445
[connectOption]="connectOption"

src/app/elements/connect/connect-dialog/connect-method/connect-method.component.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
class="fa fa-arrow-circle-down question"
3333
></i>
3434
</span>
35+
<span matTooltip="{{'Client Guide'| translate}}">
36+
<i (click)="ChangeToGuidePage(method)"
37+
*ngIf="CanGuide(method)"
38+
class="fa fa-book question"
39+
></i>
40+
</span>
3541
</mat-radio-button>
3642
</mat-radio-group>
3743
</mat-tab>

src/app/elements/connect/connect-dialog/connect-method/connect-method.component.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {AppService, I18nService, SettingService} from '@app/services';
1010
export class ElementConnectMethodComponent implements OnInit {
1111
@Output() connectMethodChange = new EventEmitter<ConnectMethod>();
1212
@Output() onDownloadRDPFile = new EventEmitter<ConnectMethod>();
13+
@Output() onGuidePage = new EventEmitter<ConnectMethod>();
1314
@Input() manualAuthInfo: AuthInfo;
1415
@Input() connectOption: Object;
1516
@Input() account: Account;
@@ -26,6 +27,10 @@ export class ElementConnectMethodComponent implements OnInit {
2627
return this.connectOption && this.connectOption['appletConnectMethod'] === 'client';
2728
}
2829

30+
get isVirtualAppClientMethod() {
31+
return this.connectOption && this.connectOption['virtualappConnectMethod'] === 'client';
32+
}
33+
2934
private _protocol: Protocol;
3035

3136
get protocol() {
@@ -119,4 +124,19 @@ export class ElementConnectMethodComponent implements OnInit {
119124
this.connectMethod = method;
120125
this.onDownloadRDPFile.emit(this.connectMethod);
121126
}
127+
128+
CanGuide(method) {
129+
if (method.type === 'virtual_app' && this.isVirtualAppClientMethod) {
130+
return true;
131+
}
132+
return false;
133+
}
134+
135+
ChangeToGuidePage(method) {
136+
if (method.disabled) {
137+
return;
138+
}
139+
this.connectMethod = method;
140+
this.onGuidePage.emit(this.connectMethod);
141+
}
122142
}

src/app/elements/connect/connect.component.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, EventEmitter, OnDestroy, OnInit, Output} from '@angular/core';
1+
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
22
import 'rxjs/add/operator/toPromise';
33
import {connectEvt} from '@app/globals';
44
import {MatDialog} from '@angular/material';
@@ -25,6 +25,7 @@ import {ActivatedRoute} from '@angular/router';
2525
})
2626
export class ElementConnectComponent implements OnInit, OnDestroy {
2727
@Output() onNewView: EventEmitter<View> = new EventEmitter<View>();
28+
@Input() direct: boolean = false;
2829
hasLoginTo = false;
2930

3031
constructor(private _appSvc: AppService,
@@ -132,6 +133,11 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
132133
return;
133134
}
134135

136+
if (this.direct) {
137+
this._logger.debug('Direct connect');
138+
return;
139+
}
140+
135141
this._logger.debug('Connect info: ', connectInfo);
136142

137143
const connectMethod = connectInfo.connectMethod;
@@ -144,7 +150,7 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
144150
}
145151

146152
if (connToken.protocol === 'k8s') {
147-
const url = `${window.location.protocol}//${window.location.host}/luna/k8s/${connToken.id}`;
153+
const url = `${window.location.protocol}//${window.location.host}/luna/k8s/${connToken.id}?asset=${asset.id}`;
148154
window.open(url);
149155
return;
150156
}
@@ -210,6 +216,10 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
210216
this._logger.debug('Not auto login');
211217
return false;
212218
}
219+
220+
if (this.direct) {
221+
return true;
222+
}
213223
// 验证账号是否有效
214224
const preAccount = preData.account;
215225
const account = accounts.find(item => {
@@ -250,10 +260,13 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
250260
if (isValid) {
251261
return Promise.resolve(preConnectData);
252262
}
263+
253264
if (this._i18n.getLangCode() === 'pt-br') {
254265
dialogWidth = '730px';
255266
}
267+
256268
this._appSvc.connectDialogShown = true;
269+
257270
const dialogRef = this._dialog.open(ElementConnectDialogComponent, {
258271
minHeight: '300px',
259272
height: 'auto',

src/app/elements/content/content-window/content-view/content-view.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export class ElementContentViewComponent implements OnInit {
2525
const {connectData} = view;
2626
switch (connectData.connectMethod.component) {
2727
case 'panda':
28+
if (connectData.connectOption.virtualappConnectMethod === 'client') {
29+
connector = 'nec'
30+
break;
31+
}
2832
case 'tinker':
2933
connector = 'lion';
3034
break;

src/app/elements/content/content-window/content-window.component.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Component, ElementRef, Input, OnInit, DoCheck, ViewChild, IterableDiffers} from '@angular/core';
22
import {View} from '@app/model';
33
import {User} from '@app/globals';
4+
import {getWaterMarkContent} from '@app/utils/common';
45
import {AppService, HttpService, SettingService, ViewService} from '@app/services';
56
import {ActivatedRoute} from '@angular/router';
67

@@ -20,14 +21,15 @@ export class ElementContentWindowComponent implements OnInit, DoCheck {
2021
private _http: HttpService,
2122
public viewSrv: ViewService,
2223
private iterableDiffers: IterableDiffers,
23-
private _route: ActivatedRoute
24+
private _route: ActivatedRoute,
2425
) {
2526
this.iterableDiffer = this.iterableDiffers.find([]).create();
2627
}
2728

28-
get subViews () {
29+
get subViews() {
2930
return this.view.subViews;
3031
}
32+
3133
async ngOnInit() {
3234
try {
3335
this.id = 'window-' + Math.random().toString(36).substr(2);
@@ -53,9 +55,14 @@ export class ElementContentWindowComponent implements OnInit, DoCheck {
5355
}
5456

5557
createWaterMark() {
56-
this._settingSvc.createWaterMarkIfNeed(
57-
this.windowRef.nativeElement,
58-
`${User.name}(${User.username})\n${this.view.asset.name}`
59-
);
58+
try {
59+
const content = getWaterMarkContent(User, this.view.asset, this._settingSvc);
60+
this._settingSvc.createWaterMarkIfNeed(
61+
this.windowRef.nativeElement,
62+
content
63+
);
64+
} catch (e) {
65+
console.error('Error creating watermark:', e);
66+
}
6067
}
6168
}

src/app/elements/content/content-window/nec/nec.component.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export class ElementConnectorNecComponent implements OnInit {
3030
token: ConnectionToken;
3131
showSetReusable: boolean;
3232
commands: Array<Command> = [];
33+
isVirtualApp: boolean = false;
34+
connectMethod: any;
3335

3436
constructor(private _http: HttpService,
3537
private _i18n: I18nService,
@@ -42,12 +44,24 @@ export class ElementConnectorNecComponent implements OnInit {
4244
}
4345

4446
async ngOnInit() {
45-
const {asset, account, protocol, smartEndpoint, connectToken} = this.view;
47+
const {asset, account, protocol, smartEndpoint, connectToken, connectMethod} = this.view;
4648
this.token = connectToken;
4749
this.asset = asset;
4850
this.account = account;
4951
this.protocol = protocol;
5052
this.endpoint = smartEndpoint;
53+
this.connectMethod = connectMethod;
54+
55+
// 处理 panda nec connect method
56+
switch (this.connectMethod['component']) {
57+
case 'panda':
58+
this.protocol = 'vnc';
59+
this.isVirtualApp = true;
60+
break;
61+
default:
62+
break;
63+
}
64+
5165

5266
const oriHost = this.asset.address;
5367
this.name = `${this.asset.name}(${oriHost})`;
@@ -101,20 +115,23 @@ export class ElementConnectorNecComponent implements OnInit {
101115

102116
this.commands = [
103117
{
104-
title: this._i18n.instant('Connect command line') + ' (' + this._i18n.instant('Using token') + ')',
105-
value: cliValue,
106-
safeValue: cliSafe,
107-
helpText: this._i18n.instant('Password is token password on the table'),
108-
callClient: false
109-
},
110-
{
118+
title: this._i18n.instant('Connect command line') + ' (' + this._i18n.instant('Using token') + ')',
119+
value: cliValue,
120+
safeValue: cliSafe,
121+
helpText: this._i18n.instant('Password is token password on the table'),
122+
callClient: false
123+
},
124+
];
125+
126+
if (!this.isVirtualApp) {
127+
this.commands.push({
111128
title: this._i18n.instant('Connect command line') + ' (' + this._i18n.instant('Directly') + ')',
112129
value: cliDirect,
113130
safeValue: cliDirect,
114131
helpText: this._i18n.instant('Password is your password login to system'),
115132
callClient: false
116-
}
117-
];
133+
});
134+
}
118135
}
119136

120137
async reconnect() {

src/app/elements/iframe/iframe.component.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
2222
@Input() origin: string;
2323
@ViewChild('iFrame', {static: false}) iframeRef: ElementRef;
2424
@Output() onLoad: EventEmitter<Boolean> = new EventEmitter<Boolean>();
25-
@Output() socketCloseEvent: EventEmitter<Boolean> = new EventEmitter<Boolean>();
2625
@Output() createFileConnectToken: EventEmitter<Boolean> = new EventEmitter<Boolean>();
2726
eventHandler: EventListenerOrEventListenerObject;
2827
private renewalTrigger = new Subject<void>();
@@ -47,6 +46,7 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
4746
private iframeCommunicationService: IframeCommunicationService
4847
) {
4948
}
49+
5050
ngOnInit() {
5151
this._logger.info(`IFrame URL: ${this.src}`);
5252

@@ -68,7 +68,9 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
6868
this.eventHandler = function (e: any) {
6969
const msg = e.data;
7070

71-
if (msg.id !== this.id) { return; }
71+
if (msg.id !== this.id) {
72+
return;
73+
}
7274

7375
switch (msg.name) {
7476
case 'PING': {
@@ -88,11 +90,10 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
8890
if (this.view && this.view.connected) {
8991
this.view.connected = false;
9092
}
91-
this.socketCloseEvent.emit(true);
9293
if (this.view && this.view.connectToken && this.view.connectToken.face_monitor_token) {
9394
this.faceService.removeMonitoringTab(this.view.id);
9495
}
95-
this.iframeCommunicationService.sendMessage({ name: 'CLOSE' })
96+
this.iframeCommunicationService.sendMessage({name: 'CLOSE'});
9697
break;
9798
case 'CONNECTED':
9899
this.view.connected = true;
@@ -144,7 +145,7 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
144145
// @ts-ignore
145146
this.ping = setInterval(() => {
146147
this._logger.info(`[Luna] Send PING to: ${this.id}`);
147-
this.iframeWindow.postMessage({name: 'PING', id: this.id}, '*');
148+
this.iframeWindow.postMessage({name: 'PING', id: this.id, protocol: this.view.protocol}, '*');
148149
}, 500);
149150

150151
this.subscription = this.iframeCommunicationService.message$.subscribe((message) => {
@@ -169,7 +170,7 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
169170
if (event.data && typeof event.data === 'object') {
170171
this.termComp = event.data;
171172
}
172-
}
173+
};
173174

174175
async reconnect() {
175176
const oldConnectToken = this.view.connectToken;
@@ -180,10 +181,10 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
180181
}
181182

182183
// 更新当前 view 的 connectToken
183-
this.src = 'about:blank';
184184
this.view.connectToken = newConnectToken;
185185

186186
const url = this.src.replace(oldConnectToken.id, newConnectToken.id);
187+
this.src = 'about:blank';
187188

188189
setTimeout(() => {
189190
this.src = url;

0 commit comments

Comments
 (0)