Unverified Commit 569ed60b authored by BaiJiangJie's avatar BaiJiangJie Committed by GitHub

Merge pull request #68 from jumpserver/dev

Dev
parents 3a3ce5df 2374e58a
...@@ -18,6 +18,11 @@ import * as UUID from 'uuid-js/lib/uuid.js'; ...@@ -18,6 +18,11 @@ import * as UUID from 'uuid-js/lib/uuid.js';
declare function unescape(s: string): string; declare function unescape(s: string): string;
class GuacObjAddResp {
code: number;
result: string;
}
@Injectable() @Injectable()
export class HttpService { export class HttpService {
headers = new HttpHeaders(); headers = new HttpHeaders();
...@@ -69,6 +74,10 @@ export class HttpService { ...@@ -69,6 +74,10 @@ export class HttpService {
return this.http.get<Array<Node>>('/api/perms/v1/user/nodes-assets/tree/?cache_policy=1'); return this.http.get<Array<Node>>('/api/perms/v1/user/nodes-assets/tree/?cache_policy=1');
} }
get_my_granted_remote_apps() {
return this.http.get<Array<Node>>('/api/perms/v1/user/remote-apps/tree/');
}
refresh_my_granted_nodes() { refresh_my_granted_nodes() {
return this.http.get<Array<Node>>('/api/perms/v1/user/nodes-assets/tree/?cache_policy=2'); return this.http.get<Array<Node>>('/api/perms/v1/user/nodes-assets/tree/?cache_policy=2');
} }
...@@ -104,7 +113,7 @@ export class HttpService { ...@@ -104,7 +113,7 @@ export class HttpService {
params = params.set('width', width).set('height', height); params = params.set('width', width).set('height', height);
} }
return this.http.get( return this.http.get<GuacObjAddResp>(
'/guacamole/api/session/ext/jumpserver/asset/add', '/guacamole/api/session/ext/jumpserver/asset/add',
{ {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'), headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
...@@ -113,6 +122,27 @@ export class HttpService { ...@@ -113,6 +122,27 @@ export class HttpService {
); );
} }
guacamole_add_remote_app(user_id: string, remote_app_id: string) {
let params = new HttpParams()
.set('user_id', user_id)
.set('remote_app_id', remote_app_id)
.set('token', DataStore.guacamole_token);
const solution = localStorage.getItem('rdpSolution') || 'Auto';
if (solution !== 'Auto') {
const width = solution.split('x')[0];
const height = solution.split('x')[1];
params = params.set('width', width).set('height', height);
}
return this.http.get<GuacObjAddResp>(
'/guacamole/api/session/ext/jumpserver/remote-app/add',
{
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
params: params
}
);
}
guacamole_token_add_asset(assetToken: string, token: string) { guacamole_token_add_asset(assetToken: string, token: string) {
let params = new HttpParams() let params = new HttpParams()
.set('asset_token', assetToken) .set('asset_token', assetToken)
......
import {Component, Input, Output, OnInit, Inject, SimpleChanges, OnChanges, ElementRef, ViewChild, EventEmitter} from '@angular/core'; import {Component, Input, Output, OnInit, Inject, SimpleChanges, OnChanges, ElementRef, ViewChild, EventEmitter} from '@angular/core';
import {NavList, View} from '../../pages/control/control/control.component'; import {NavList, View} from '../../pages/control/control/control.component';
import {AppService, LogService} from '../../app.service'; import {AppService, HttpService, LogService} from '../../app.service';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material'; import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
import {FormControl, Validators} from '@angular/forms'; import {FormControl, Validators} from '@angular/forms';
import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import {BehaviorSubject} from 'rxjs/BehaviorSubject';
...@@ -14,11 +14,10 @@ declare var $: any; ...@@ -14,11 +14,10 @@ declare var $: any;
styleUrls: ['./asset-tree.component.scss'] styleUrls: ['./asset-tree.component.scss']
}) })
export class ElementAssetTreeComponent implements OnInit, OnChanges { export class ElementAssetTreeComponent implements OnInit, OnChanges {
@Input() Data: any;
@Input() query: string; @Input() query: string;
@Input() searchEvt$: BehaviorSubject<string>; @Input() searchEvt$: BehaviorSubject<string>;
@Output() treeRefresh = new EventEmitter<boolean>();
@ViewChild('rMenu') rMenu: ElementRef; @ViewChild('rMenu') rMenu: ElementRef;
Data = [];
nodes = []; nodes = [];
setting = { setting = {
view: { view: {
...@@ -58,14 +57,30 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges { ...@@ -58,14 +57,30 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
public _dialog: MatDialog, public _dialog: MatDialog,
public _logger: LogService, public _logger: LogService,
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
private _http: HttpService
) { ) {
this.searchEvt$ = new BehaviorSubject<string>(this.query); this.searchEvt$ = new BehaviorSubject<string>(this.query);
} }
ngOnInit() { getGrantedAssetsNodes() {
if (this.Data) { this._http.get_my_granted_nodes()
.subscribe(response => {
this.Data = [...response, ...this.Data];
this.draw();
});
}
getGrantedRemoteApps() {
this._http.get_my_granted_remote_apps()
.subscribe(response => {
this.Data = [...this.Data, ...response];
this.draw(); this.draw();
});
} }
ngOnInit() {
this.getGrantedAssetsNodes();
this.getGrantedRemoteApps();
document.addEventListener('click', this.hideRMenu.bind(this), false); document.addEventListener('click', this.hideRMenu.bind(this), false);
this.searchEvt$.asObservable() this.searchEvt$.asObservable()
.debounceTime(300) .debounceTime(300)
...@@ -73,7 +88,6 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges { ...@@ -73,7 +88,6 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
.subscribe((n) => { .subscribe((n) => {
this.filter(); this.filter();
}); });
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
...@@ -85,12 +99,18 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges { ...@@ -85,12 +99,18 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
} }
} }
refreshNodes() {
this.zTree.destroy();
this.Data = [];
this.getGrantedAssetsNodes();
this.getGrantedRemoteApps();
}
draw() { draw() {
$.fn.zTree.init($('#ztree'), this.setting, this.Data); $.fn.zTree.init($('#ztree'), this.setting, this.Data);
this.zTree = $.fn.zTree.getZTreeObj('ztree'); this.zTree = $.fn.zTree.getZTreeObj('ztree');
this.rootNodeAddDom(this.zTree, () => { this.rootNodeAddDom(this.zTree, () => {
this.zTree.destroy(); this.refreshNodes();
this.treeRefresh.emit(true);
}); });
this.activatedRoute.queryParams.subscribe(params => { this.activatedRoute.queryParams.subscribe(params => {
...@@ -128,6 +148,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges { ...@@ -128,6 +148,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
} }
onRightClick(event, treeId, treeNode) { onRightClick(event, treeId, treeNode) {
if (!treeNode || treeNode.isParent ) { if (!treeNode || treeNode.isParent ) {
return null; return null;
} }
...@@ -145,7 +166,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges { ...@@ -145,7 +166,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
} }
} }
Connect(node) { connectAsset(node) {
const system_users = node.meta.system_users; const system_users = node.meta.system_users;
const host = node.meta.asset; const host = node.meta.asset;
let user: any; let user: any;
...@@ -180,6 +201,34 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges { ...@@ -180,6 +201,34 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
} }
} }
connectRemoteApp(node) {
const id = NavList.List.length - 1;
if (node) {
NavList.List[id].nick = node.name;
NavList.List[id].connected = true;
NavList.List[id].edit = false;
NavList.List[id].closed = false;
NavList.List[id].remoteApp = node.id;
NavList.List[id].type = 'rdp';
NavList.List.push(new View());
NavList.Active = id;
}
this._logger.debug(NavList);
}
Connect(node) {
switch (node.meta.type) {
case 'asset':
this.connectAsset(node);
break;
case 'remote_app':
this.connectRemoteApp(node);
break;
default:
alert('Unknown type: ' + node.meta.type);
}
}
connectFileManager() { connectFileManager() {
const host = this.rightClickSelectNode.meta.asset; const host = this.rightClickSelectNode.meta.asset;
const id = NavList.List.length - 1; const id = NavList.List.length - 1;
......
...@@ -14,56 +14,74 @@ import {NavList} from '../../pages/control/control/control.component'; ...@@ -14,56 +14,74 @@ import {NavList} from '../../pages/control/control/control.component';
export class ElementGuacamoleComponent implements OnInit { export class ElementGuacamoleComponent implements OnInit {
@Input() host: any; @Input() host: any;
@Input() userid: any; @Input() userid: any;
@Input() remoteAppId: string;
@Input() target: string; @Input() target: string;
@Input() index: number; @Input() index: number;
@ViewChild('rdp') el: ElementRef; @ViewChild('rdp') el: ElementRef;
constructor(private sanitizer: DomSanitizer, constructor(private sanitizer: DomSanitizer,
private _http: HttpService, private _http: HttpService,
private _cookie: CookieService, private _cookie: CookieService,
private _logger: LogService) { private _logger: LogService) {
} }
ngOnInit() { registerHost() {
// /guacamole/api/tokens will redirect to http://guacamole/api/tokens if (this.remoteAppId) {
if (!this.target) { this._http.guacamole_add_remote_app(User.id, this.remoteAppId).subscribe(
const base = window.btoa(this.host.id + '\0' + 'c' + '\0' + 'jumpserver');
if (environment.production) {
if (DataStore.guacamole_token) {
this._http.guacamole_add_asset(User.id, this.host.id, this.userid).subscribe(
data => { data => {
const base = data.result;
this.target = document.location.origin + '/guacamole/#/client/' + base + '?token=' + DataStore.guacamole_token; this.target = document.location.origin + '/guacamole/#/client/' + base + '?token=' + DataStore.guacamole_token;
NavList.List[this.index].Rdp = this.el.nativeElement;
}, },
error2 => { error => {
this._logger.error(error2); this._logger.error(error);
} }
); );
} else { } else {
this._http.get_guacamole_token(User.id, '').subscribe(
data => {
// /guacamole/client will redirect to http://guacamole/#/client
DataStore.guacamole_token = data['authToken'];
this._http.guacamole_add_asset(User.id, this.host.id, this.userid).subscribe( this._http.guacamole_add_asset(User.id, this.host.id, this.userid).subscribe(
data2 => { data => {
const base = data.result;
this.target = document.location.origin + '/guacamole/#/client/' + base + '?token=' + DataStore.guacamole_token; this.target = document.location.origin + '/guacamole/#/client/' + base + '?token=' + DataStore.guacamole_token;
NavList.List[this.index].Rdp = this.el.nativeElement;
}, },
error2 => { error2 => {
this._logger.error(error2); this._logger.error(error2);
} }
); );
},
error2 => {
this._logger.error(error2);
} }
);
} }
} else {
ngOnInit() {
// /guacamole/api/tokens will redirect to http://guacamole/api/tokens
if (this.target) {
NavList.List[this.index].Rdp = this.el.nativeElement;
return null;
}
if (!environment.production) {
this.target = this._cookie.get('guacamole'); this.target = this._cookie.get('guacamole');
NavList.List[this.index].Rdp = this.el.nativeElement;
return null;
} }
const now = new Date();
const nowTime = now.getTime() / 1000;
if (!DataStore.guacamole_token || nowTime - DataStore.guacamole_token_time > 3600) {
this._http.get_guacamole_token(User.id, '').subscribe(
data => {
// /guacamole/client will redirect to http://guacamole/#/client
DataStore.guacamole_token = data['authToken'];
DataStore.guacamole_token_time = nowTime;
this.registerHost();
},
error => {
this._logger.error(error);
alert(error.message);
return null;
}
);
} else {
this.registerHost();
} }
NavList.List[this.index].Rdp = this.el.nativeElement;
} }
trust(url) { trust(url) {
......
...@@ -91,6 +91,7 @@ export let DataStore: { ...@@ -91,6 +91,7 @@ export let DataStore: {
windowsize: Array<number>; windowsize: Array<number>;
autologin: boolean; autologin: boolean;
guacamole_token: string; guacamole_token: string;
guacamole_token_time: number;
} = { } = {
socket: io.connect(), socket: io.connect(),
Nav: [{}], Nav: [{}],
...@@ -102,7 +103,8 @@ export let DataStore: { ...@@ -102,7 +103,8 @@ export let DataStore: {
leftbarshow: true, leftbarshow: true,
windowsize: [], windowsize: [],
autologin: false, autologin: false,
guacamole_token: '' guacamole_token: '',
guacamole_token_time: 0
}; };
export let CSRF = ''; export let CSRF = '';
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
type="text" tabindex="1" spellcheck="false" [(ngModel)]="q"> type="text" tabindex="1" spellcheck="false" [(ngModel)]="q">
</div> </div>
<div class="overflow ngx-scroll-overlay" fxflex="1 1 90%"> <div class="overflow ngx-scroll-overlay" fxflex="1 1 90%">
<elements-asset-tree [Data]="zNodes" [query]="q" (treeRefresh)="refreshGrantNodes()"></elements-asset-tree> <elements-asset-tree [query]="q" ></elements-asset-tree>
</div> </div>
<div class="footer-version" fxflex="0 0 26px"> <div class="footer-version" fxflex="0 0 26px">
......
...@@ -42,9 +42,8 @@ export class Host { ...@@ -42,9 +42,8 @@ export class Host {
styleUrls: ['./cleftbar.component.scss'], styleUrls: ['./cleftbar.component.scss'],
providers: [SearchComponent, ElementServerMenuComponent] providers: [SearchComponent, ElementServerMenuComponent]
}) })
export class CleftbarComponent implements OnInit { export class CleftbarComponent {
DataStore = DataStore; DataStore = DataStore;
zNodes: any;
version = version; version = version;
q: string; q: string;
event: MouseEvent; event: MouseEvent;
...@@ -97,24 +96,10 @@ export class CleftbarComponent implements OnInit { ...@@ -97,24 +96,10 @@ export class CleftbarComponent implements OnInit {
this._logger.log('nav.ts:NavComponent'); this._logger.log('nav.ts:NavComponent');
} }
ngOnInit() {
this._http.get_my_granted_nodes()
.subscribe(response => {
this.zNodes = response;
});
}
Search(q) { Search(q) {
this._search.Search(q); this._search.Search(q);
} }
refreshGrantNodes() {
this._http.refresh_my_granted_nodes()
.subscribe(response => {
this.zNodes = response;
});
}
onRightClick(event: MouseEvent): void { onRightClick(event: MouseEvent): void {
this.clientX = event.clientX; this.clientX = event.clientX;
this.clientY = event.clientY; this.clientY = event.clientY;
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
</elements-ssh-term> </elements-ssh-term>
<elements-guacamole [index]="i" <elements-guacamole [index]="i"
[host]="m.host" [host]="m.host"
[userid]="m.user.id" [userid]="m.user?.id"
[remoteAppId]="m.remoteApp"
*ngIf="m.type=='rdp'"> *ngIf="m.type=='rdp'">
</elements-guacamole> </elements-guacamole>
<app-sftp *ngIf="m.type=='sftp'" [host]="m.host"> <app-sftp *ngIf="m.type=='sftp'" [host]="m.host">
......
...@@ -19,6 +19,7 @@ export class View { ...@@ -19,6 +19,7 @@ export class View {
closed: boolean; closed: boolean;
host: any; host: any;
user: any; user: any;
remoteApp: string;
room: string; room: string;
Rdp: any; Rdp: any;
Term: any; Term: any;
......
<!--<tree-root [nodes]="nodes" [options]="options"></tree-root>--> <!--<tree-root [nodes]="nodes" [options]="options"></tree-root>-->
<!--<app-replay-mp4></app-replay-mp4>--> <!--<app-replay-mp4></app-replay-mp4>-->
<!--<elements-tree [TreeData]="nodes1"></elements-tree>--> <!--<elements-tree [TreeData]="nodes1"></elements-tree>-->
<elements-asset-tree [Data]="zNodes"></elements-asset-tree> <elements-asset-tree></elements-asset-tree>
...@@ -2,5 +2,5 @@ export const environment = { ...@@ -2,5 +2,5 @@ export const environment = {
production: true production: true
}; };
// export const version = '1.3.0-{{BUILD_NUMBER}} GPLv2.'; // export const version = '1.3.0-{{BUILD_NUMBER}} GPLv2.';
export const version = '1.4.10-101 GPLv2.'; export const version = '1.5.0-101 GPLv2.';
// export const version = '1.4.1-{{BUILD_NUMBER}} GPLv2.'; // export const version = '1.4.1-{{BUILD_NUMBER}} GPLv2.';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment