feat: a lot fix

parent 10fd9d77
......@@ -22,7 +22,6 @@
"styles": [
"../node_modules/layui-layer/dist/theme/default/layer.css",
"../node_modules/animate.css/animate.min.css",
"assets/inspinia/style.scss",
"../node_modules/xterm/dist/xterm.css",
"sass/style.scss",
"styles.css"
......
......@@ -13,53 +13,66 @@ class SSHws(Namespace):
self.clients = dict()
super().__init__(*args, **kwargs)
def ssh_with_password(self):
def ssh_with_password(self, connection):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("127.0.0.1", 22, "liuzheng", "liuzheng")
self.clients[request.sid]["chan"] = ssh.invoke_shell(term='xterm', width=self.clients[request.sid]["cols"],
height=self.clients[request.sid]["rows"])
self.clients[request.sid]["chan"][connection] = ssh.invoke_shell(term='xterm',
width=self.clients[request.sid]["cols"],
height=self.clients[request.sid]["rows"])
# self.socketio.start_background_task(self.send_data, self.clients[request.sid]["chan"])
# self.chan.settimeout(0.1)
self.socketio.start_background_task(self.sent_data, self, self.clients[request.sid]["chan"][connection],
self.clients[request.sid]["room"],
connection, request.sid)
def sent_data(self, s, chan, room, connection, sid):
while True:
if connection not in s.clients[sid]["chan"].keys():
return
try:
data = chan.recv(2048).decode('utf-8', 'replace')
s.emit(event='data', data={"data": data, "room": connection}, room=room)
except RuntimeError:
print(room, connection)
def send_data(self, s):
# Todo: 这里涉及到并发优化
while True:
for sid in self.clients:
try:
if self.clients[sid]["chan"]:
data = self.clients[sid]["chan"].recv(2048).decode('utf-8', 'replace')
s.emit(event='data', data=data, room=self.clients[sid]["room"])
except RuntimeError:
print(data)
print(self.clients)
if self.clients[sid]["chan"]:
for room, chan in self.clients[sid]["chan"]:
try:
data = chan.recv(2048).decode('utf-8', 'replace')
s.emit(event='data', data={"data": data, "room": room}, room=self.clients[sid]["room"])
except RuntimeError:
print(self.clients)
def on_connect(self):
print(request.sid)
self.clients[request.sid] = {
"cols": int(request.cookies.get('cols', 80)),
"rows": int(request.cookies.get('rows', 24)),
"room": str(uuid.uuid4()),
"chan": None
"chan": dict()
}
join_room(self.clients[request.sid]["room"])
self.socketio.start_background_task(self.send_data, self)
# self.socketio.start_background_task(self.send_data, self)
def on_data(self, message):
self.clients[request.sid]["chan"].send(message)
self.clients[request.sid]["chan"][message["room"]].send(message["data"])
def on_host(self, message):
# self.clients[request.sid]["room"] = str(uuid.uuid4())
# self.emit('room', self.clients[request.sid]["chan"]["room"])
# join_room(self.clients[request.sid]["room"])
self.ssh_with_password()
print(message, self.clients[request.sid]["room"])
connection = str(uuid.uuid4())
self.emit('room', {'room': connection, 'secret': message['secret']})
self.ssh_with_password(connection)
def on_resize(self, message):
self.clients[request.sid]["cols"] = message.get('cols', 80)
self.clients[request.sid]["rows"] = message.get('rows', 24)
self.clients[request.sid]["chan"].resize_pty(width=self.clients[request.sid]["rows"],
height=self.clients[request.sid]["rows"], width_pixels=1,
height_pixels=1)
for room in self.clients[request.sid]["chan"]:
self.clients[request.sid]["chan"][room].resize_pty(width=self.clients[request.sid]["cols"],
height=self.clients[request.sid]["rows"], width_pixels=1,
height_pixels=1)
def on_room(self, sessionid):
if sessionid not in self.clients.keys():
......@@ -73,11 +86,20 @@ class SSHws(Namespace):
def on_disconnect(self):
print("disconnect")
for connection in self.clients[request.sid]["chan"]:
self.clients[request.sid]["chan"][connection].close()
del self.clients[request.sid]["chan"]
pass
def on_leave(self):
leave_room(self.room)
def on_logout(self, connection):
print("logout", connection)
if connection:
self.clients[request.sid]["chan"][connection].close()
del self.clients[request.sid]["chan"][connection]
@app.route('/luna/<path:path>')
def send_js(path):
......@@ -155,6 +177,27 @@ def asset_groups_assets():
return jsonify(assets)
@app.route('/api/users/v1/profile/')
def user_profile():
assets = {
"id": "4fc67feb-9efa-4e7b-94b0-b73356a87b2e",
"username": "admin",
"name": "Administrator",
"email": "admin@mycomany.com",
"is_active": True,
"is_superuser": True,
"role": "Administrator",
"groups": [
"Default"
],
"wechat": "",
"phone": 13888888888,
"comment": "",
"date_expired": "2087-12-16 07:41:35"
}
return jsonify(assets)
@app.route('/api/terminal/v1/sessions/test/replay/')
def replay():
return redirect("http://jps.ilz.me/media/2017-12-24/ec87a486-0344-4f12-b27a-620321944f7f.gz")
......
This diff is collapsed.
......@@ -5,35 +5,36 @@
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build -prod --base-href=/luna/ --deploy '/luna/'",
"build": "ng build --environment prod --build-optimizer=false --base-href=/luna/ --deploy '/luna/'",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^4.2.4",
"@angular/common": "^4.2.4",
"@angular/compiler": "^4.2.4",
"@angular/core": "^4.2.4",
"@angular/forms": "^4.2.4",
"@angular/http": "^4.2.4",
"@angular/platform-browser": "^4.2.4",
"@angular/platform-browser-dynamic": "^4.2.4",
"@angular/router": "^4.2.4",
"angular2-logger": "^0.6.0",
"@angular/animations": "5.2.0",
"@angular/cdk": "^5.1.0",
"@angular/common": "5.2.0",
"@angular/compiler": "5.2.0",
"@angular/core": "5.2.0",
"@angular/forms": "5.2.0",
"@angular/http": "5.2.0",
"@angular/platform-browser": "5.2.0",
"@angular/platform-browser-dynamic": "5.2.0",
"@angular/router": "5.2.0",
"animate.css": "^3.5.2",
"body-parser": "^1.18.2",
"bootstrap": "^4.0.0-beta.3",
"clipboard": "^1.7.1",
"compass-mixins": "^0.12.10",
"core-js": "^2.4.1",
"core-js": "2.5.3",
"directory-encoder": "^0.9.2",
"filetree-css": "^1.0.0",
"font-awesome": "^4.7.0",
"font-awesome": "4.7.0",
"handlebars": "^4.0.11",
"inconsolata": "0.0.2",
"jquery": "^3.1.0",
"intl": "1.2.5",
"jquery": "3.2.1",
"jquery-slimscroll": "^1.3.8",
"jquery-sparkline": "^2.4.0",
"jvectormap": "1.2.2",
......@@ -44,42 +45,49 @@
"ng2-charts": "^1.5.0",
"ng2-cookies": "^1.0.12",
"ngx-bootstrap": "^1.6.6",
"ngx-layer": "0.0.4",
"ngx-logger": "^1.1.2",
"ngx-perfect-scrollbar": "5.2.0",
"ngx-progressbar": "^2.1.1",
"node": "^9.3.0",
"npm": "^5.6.0",
"npm-font-open-sans": "^1.1.0",
"peity": "^3.2.1",
"popper.js": "^1.12.9",
"popper.js": "1.12.9",
"roboto-fontface": "^0.8.0",
"rxjs": "^5.4.2",
"rxjs": "5.5.6",
"sass-math": "^1.0.0",
"socket.io": "^2.0.3",
"socket.io-client": "^2.0.4",
"ssh-keygen": "^0.4.1",
"term.js": "0.0.7",
"tether": "^1.4.0",
"uuid-js": "^0.7.5",
"xterm": "^2.9.2",
"zone.js": "^0.8.14"
"tslib": "1.8.1",
"zone.js": "0.8.20"
},
"devDependencies": {
"@angular/cli": "1.5.2",
"@angular/compiler-cli": "^4.2.4",
"@angular/language-service": "^4.2.4",
"@types/jasmine": "~2.5.53",
"@angular-devkit/core": "0.0.28",
"@angular-devkit/schematics": "0.0.42",
"@angular/cli": "^1.6.5",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"node-sass": "^4.7.2",
"protractor": "~5.1.2",
"ts-node": "~3.2.0",
"tslint": "~5.3.2",
"typescript": "~2.3.3"
"@angular/compiler-cli": "5.2.0",
"@angular/language-service": "5.2.0",
"@types/jasmine": "2.8.4",
"@types/node": "9.3.0",
"codelyzer": "4.0.2",
"jasmine-core": "2.8.0",
"jasmine-spec-reporter": "4.2.1",
"karma": "2.0.0",
"karma-chrome-launcher": "2.2.0",
"karma-cli": "1.0.1",
"karma-coverage-istanbul-reporter": "1.3.3",
"karma-jasmine": "1.1.1",
"karma-jasmine-html-reporter": "0.2.2",
"protractor": "5.2.2",
"ts-node": "3.3.0",
"tslint": "5.9.1",
"typescript": "2.4.2"
}
}
{
"/api": {
"target": "http://localhost:5000",
"target": "http://127.0.0.1:5000",
"secure": false
},
"/socket.io/": {
......
......@@ -6,19 +6,16 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, OnInit} from '@angular/core';
import {Logger} from 'angular2-logger/core';
import {AppService, HttpService} from '../../app.service';
import {AppService, HttpService, LogService} from '../../app.service';
import {NgForm} from '@angular/forms';
import {Router} from '@angular/router';
import {DataStore, User} from '../../globals';
import * as jQuery from 'jquery/dist/jquery.min.js';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
providers: [AppService]
})
export class LoginComponent implements OnInit {
DataStore = DataStore;
......@@ -28,7 +25,7 @@ export class LoginComponent implements OnInit {
constructor(private _appService: AppService,
private _http: HttpService,
private _router: Router,
private _logger: Logger) {
private _logger: LogService) {
this._logger.log('login.ts:LoginComponent');
DataStore.NavShow = false;
}
......@@ -47,13 +44,13 @@ export class LoginComponent implements OnInit {
DataStore.error['login'] = '';
this._logger.log(User);
if (User.username.length > 0 && User.password.length > 6 && User.password.length < 100) {
this._http.post('/api/checklogin', JSON.stringify(User)).map(res => res.json())
this._http.check_login(JSON.stringify(User))
.subscribe(
data => {
User.logined = data.logined;
User.name = data.name;
User.username = data.username;
User.logined = data.logined;
User.logined = data['logined'];
User.name = data['name'];
User.username = data['username'];
User.logined = data['logined'];
},
err => {
this._logger.error(err);
......
......@@ -9,7 +9,7 @@
<input type="checkbox" id="hostgroup-{{i}}">
<label for="hostgroup-{{i}}">{{hostGroup.name}}</label>
<ul [ngClass]="{'insearch': q }">
<li *ngFor="let host of hostGroup.assets_granted | SearchFilter: q" (click)="Connect(host)">
<li *ngFor="let host of hostGroup.assets_granted | SearchFilter: q" (click)="Connect(host)" (contextmenu)="onRightClick($event)">
<i class="fa" [ngClass]="'fa-'+(host.platform||'undefined').toLowerCase()" id="fa-{{i}}"></i>
{{host.hostname}}
</li>
......@@ -20,3 +20,4 @@
<div class="footer">
Version <strong>{{version}}</strong>
</div>
<!--<app-element-server-menu></app-element-server-menu>-->
......@@ -8,19 +8,17 @@
*/
import {Component, OnInit} from '@angular/core';
import {Logger} from 'angular2-logger/core';
import {AppService, HttpService} from '../../app.service';
import {SshComponent} from '../control/ssh/ssh.component';
import {RdpComponent} from '../control/rdp/rdp.component';
import {AppService, HttpService, LogService} from '../../app.service';
import {SearchComponent} from '../search/search.component';
import {DataStore} from '../../globals';
import {version} from '../../../environments/environment';
import * as jQuery from 'jquery/dist/jquery.min.js';
import * as layer from 'layui-layer/src/layer.js';
import {ElementServerMenuComponent} from '../../elements/server-menu/server-menu.component';
import {NavList, View} from '../control/control.component';
import {LayerService} from '../../elements/layer/layer.service';
export class HostGroup {
export interface HostGroup {
name: string;
id: string;
children: Array<Host>;
......@@ -36,13 +34,16 @@ export class Host {
selector: 'app-cleftbar',
templateUrl: './cleftbar.component.html',
styleUrls: ['./cleftbar.component.css'],
providers: [SshComponent, RdpComponent, SearchComponent]
providers: [SearchComponent, ElementServerMenuComponent]
})
export class CleftbarComponent implements OnInit {
DataStore = DataStore;
HostGroups: Array<HostGroup>;
version = version;
q: string;
event: MouseEvent;
clientX = 0;
clientY = 0;
static Reload() {
}
......@@ -78,25 +79,23 @@ export class CleftbarComponent implements OnInit {
}
constructor(private _appService: AppService,
private _term: SshComponent,
private _rdp: RdpComponent,
private _http: HttpService,
private _search: SearchComponent,
private _logger: Logger) {
private _logger: LogService,
private _menu: ElementServerMenuComponent,
private _layer: LayerService) {
this._logger.log('nav.ts:NavComponent');
// this._appService.getnav()
}
ngOnInit() {
this._http.get('/api/perms/v1/user/my/asset-groups-assets/')
.map(res => res.json())
this._http.get_my_asset_groups_assets()
.subscribe(response => {
this.HostGroups = response;
this.autologin();
});
}
autologin() {
const id = this._appService.getQueryString('id');
if (id) {
......@@ -117,17 +116,17 @@ export class CleftbarComponent implements OnInit {
Connect(host) {
// console.log(host);
let user: any;
let options = '';
const that = this;
if (host.system_users_granted.length > 1) {
let options = '';
user = this.checkPriority(host.system_users_granted);
if (user) {
this.login(host, user);
} else {
for (let u of host.system_users_granted) {
for (const u of host.system_users_granted) {
options += '<option value="' + u.id + '">' + u.username + '</option>';
}
layer.open({
this._layer.open({
title: 'Please Choose a User',
scrollbar: false,
moveOut: true,
......@@ -143,7 +142,7 @@ export class CleftbarComponent implements OnInit {
}
}
that.login(host, user);
layer.close(index);
that._layer.close(index);
},
btn2: function (index, layero) {
},
......@@ -160,38 +159,28 @@ export class CleftbarComponent implements OnInit {
}
login(host, user) {
const id = NavList.List.length - 1;
if (user) {
NavList.List[id].nick = host.hostname;
NavList.List[id].connected = true;
NavList.List[id].edit = false;
NavList.List[id].closed = false;
NavList.List[id].host = host;
NavList.List[id].user = user;
if (user.protocol === 'ssh') {
jQuery('app-ssh').show();
jQuery('app-rdp').hide();
this._term.TerminalConnect(host, user.id);
NavList.List[id].type = 'ssh';
} else if (user.protocol === 'rdp') {
jQuery('app-ssh').hide();
jQuery('app-rdp').show();
this._rdp.Connect(host, user.id);
NavList.List[id].type = 'rdp';
}
NavList.List.push(new View());
NavList.Active = id;
}
// if (host.platform) {
// if (host.platform.toLowerCase() === 'linux') {
// jQuery('app-ssh').show();
// jQuery('app-rdp').hide();
// this._term.TerminalConnect(host, user.id);
// } else if (host.platform.toLowerCase() === 'windows') {
// jQuery('app-ssh').hide();
// jQuery('app-rdp').show();
// this._rdp.Connect(host, user.id);
// } else {
// jQuery('app-ssh').show();
// jQuery('app-rdp').hide();
// this._term.TerminalConnect(host, user.id);
// }
// }
}
checkPriority(sysUsers) {
let priority: number = -1;
let user: any;
for (let u of sysUsers) {
for (const u of sysUsers) {
if (u.priority > priority) {
user = u;
priority = u.priority;
......@@ -206,4 +195,10 @@ export class CleftbarComponent implements OnInit {
this._search.Search(q);
}
onRightClick(event: MouseEvent): void {
this.clientX = event.clientX;
this.clientY = event.clientY;
// console.log(this.clientX, this.clientY);
// this._menu.contextmenu(this.clientY, this.clientX);
}
}
div, app-element-term, app-element-iframe {
height: 100%;
padding-bottom: 30px;
}
div {
display: none;
}
.active {
display: block;
}
<app-controlnav></app-controlnav>
<app-ssh></app-ssh>
<!--<app-rdp></app-rdp>-->
<div *ngFor="let m of NavList.List;let i=index"
[ngClass]="{'active':i==NavList.Active}"
>
<app-element-term [host]="m.host"
[userid]="m.user.id"
[index]="i"
*ngIf="m.type=='ssh'">
</app-element-term>
<app-element-iframe [host]="m.host"
[userid]="m.user.id"
[index]="i"
*ngIf="m.type=='rdp'">
</app-element-iframe>
</div>
......@@ -8,12 +8,13 @@
*/
import {Component, OnInit} from '@angular/core';
import {TermWS} from '../../globals';
export class Term {
machine: string;
socket: any;
term: any;
}
// export class Term {
// machine: string;
// socket: any;
// term: any;
// }
export class Rdp {
machine: string;
......@@ -28,8 +29,11 @@ export class View {
connected: boolean;
hide: boolean;
closed: boolean;
host: any;
user: any;
room: string;
Rdp: Rdp;
Term: Term;
Term: any;
}
export let NavList: {
......@@ -46,6 +50,8 @@ export let NavList: {
styleUrls: ['./control.component.css']
})
export class ControlComponent implements OnInit {
NavList = NavList;
static active(id) {
for (let i in NavList.List) {
if (id.toString() === i) {
......@@ -58,10 +64,32 @@ export class ControlComponent implements OnInit {
NavList.Active = id;
}
static TerminalDisconnect(id) {
if (NavList.List[id].connected) {
NavList.List[id].connected = false;
NavList.List[id].Term.write('\r\n\x1b[31mBye Bye!\x1b[m\r\n');
TermWS.emit('logout', NavList.List[id].room);
}
}
static RdpDisconnect(id) {
NavList.List[id].connected = false;
}
static DisconnectAll() {
alert('DisconnectAll');
for (let i = 0; i < NavList.List.length; i++) {
ControlComponent.TerminalDisconnect(i);
}
}
constructor() {
}
ngOnInit() {
}
// trackByFn(index: number, item: View) {
// return item.id;
// }
}
......@@ -32,7 +32,7 @@
.tabs ul li.active {
box-sizing: border-box;
border-bottom: 3px solid #19aa8d !important;
border-bottom: 5px solid #19aa8d !important;
}
.tabs ul li span {
......@@ -81,3 +81,28 @@
padding: 5px 20px 4px 15px;
height: 18px;
}
/*
* scrollbar
*/
.tabs::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #676a6c;
}
.tabs::-webkit-scrollbar {
height: 2px;
}
.tabs::-webkit-scrollbar-thumb {
background-color: #F5F5F5;
}
.scroll-botton {
font-size: 20px;
float: left;
height: 30px;
overflow: hidden;
background-color: #3a3333;
color: white
}
<div class="scroll-botton">
&nbsp; <a class="left" (click)="scrollleft()"><i class="fa fa-caret-left"></i></a>
&nbsp;
<a class="right" (click)="scrollright()"><i class="fa fa-caret-right"></i></a>
&nbsp;
</div>
<div class="tabs">
<ul [ngStyle]="{'width':150*NavList.List.length+'px'}">
<li *ngFor="let m of NavList.List;let i = index"
......
......@@ -8,12 +8,9 @@
*/
import {Component, OnInit} from '@angular/core';
import {NavList} from '../control.component';
import {SshComponent} from '../ssh/ssh.component';
import {RdpComponent} from '../rdp/rdp.component';
import {ControlComponent, NavList} from '../control.component';
import * as jQuery from 'jquery/dist/jquery.min.js';
@Component({
selector: 'app-controlnav',
templateUrl: './controlnav.component.html',
......@@ -44,12 +41,8 @@ export class ControlnavComponent implements OnInit {
NavList.List[index].hide = false;
NavList.Active = index;
if (NavList.List[index].type === 'ssh') {
jQuery('app-ssh').show();
jQuery('app-rdp').hide();
NavList.List[index].Term.term.focus();
NavList.List[index].Term.focus();
} else if (NavList.List[index].type === 'rdp') {
jQuery('app-ssh').hide();
jQuery('app-rdp').show();
}
}
......@@ -62,13 +55,20 @@ export class ControlnavComponent implements OnInit {
close(host, index) {
if (host.type === 'rdp') {
RdpComponent.Disconnect(host);
ControlComponent.RdpDisconnect(index);
} else if (host.type === 'ssh') {
SshComponent.TerminalDisconnect(host);
ControlComponent.TerminalDisconnect(index);
}
NavList.List.splice(index, 1);
ControlnavComponent.checkActive(index);
}
scrollleft() {
jQuery('.tabs').scrollLeft(jQuery('.tabs').scrollLeft() - 100);
}
scrollright() {
jQuery('.tabs').scrollLeft(jQuery('.tabs').scrollLeft() + 100);
}
}
<div id="rdp">
<div *ngFor="let m of NavList.List;let i=index"
[ngClass]="{'disconnected':!m.connected,'hidden': m.hide || m.type!='rdp'}" id="rdp-{{i}}">
<canvas id="canvas-{{i}}"></canvas>
</div>
</div>
/**
* RDP页面
*
* @date 2017-11-07
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, OnInit} from '@angular/core';
import {NavList, View, Rdp, ControlComponent} from '../control.component';
import {Mstsc} from 'mstsc.js/client/js/mstsc.js';
import {Client} from 'mstsc.js/client/js/client.js';
import {Canvas} from 'mstsc.js/client/js/canvas.js';
// declare let Mstsc: any;
@Component({
selector: 'app-rdp',
templateUrl: './rdp.component.html',
styleUrls: ['./rdp.component.css']
})
export class RdpComponent implements OnInit {
NavList = NavList;
static Disconnect(host) {
host.connected = false;
}
static DisconnectAll() {
}
constructor() {
}
ngOnInit() {
}
Connect(host, username) {
const id = NavList.List.length - 1;
const canvas = Mstsc.$('canvas-' + id);
// canvas.style.display = 'inline';
// canvas.width = window.innerWidth;
// canvas.height = window.innerHeight;
NavList.List[id].nick = host.name;
NavList.List[id].connected = true;
NavList.List[id].edit = false;
NavList.List[id].closed = false;
NavList.List[id].type = 'rdp';
NavList.List[id].Rdp = new Rdp;
NavList.List[id].Rdp.token = host.token;
NavList.List[id].Rdp.machine = host.uuid;
NavList.List[id].Rdp.client = new Client.Client(Mstsc.$('canvas-' + id));
NavList.List[id].Rdp.client.connect(host.token, '/rdp/socket.io');
NavList.List.push(new View());
ControlComponent.active(id);
}
}
#term {
width: 100%;
height: 100%;
padding: 15px;
}
#term > div {
height: 100%;
}
.terminal {
border: #000 solid 5px;
color: #f0f0f0;
box-shadow: rgba(0, 0, 0, 0.8) 2px 2px 20px;
white-space: nowrap;
display: inline-block;
height: 100%;
}
#term .terminal div span {
min-width: 12px;
}
.reverse-video {
color: #000;
background: #f0f0f0;
}
.termChangBar {
line-height: 1;
margin: 0 auto;
border: 1px solid #ffffff;
color: #fff;
background-color: #ffffff;
position: fixed;
right: 0;
top: 0;
}
.hidden {
display: none;
}
<div id="term">
<div *ngFor="let m of NavList.List;let i=index"
[ngClass]="{'disconnected':!m.connected,'hidden': m.hide || m.type!='ssh'}" id="term-{{i}}">
</div>
</div>
/**
* WebTerminal
*
* @date 2017-11-07
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, OnInit} from '@angular/core';
import {Logger} from 'angular2-logger/core';
import {Cookie} from 'ng2-cookies/ng2-cookies';
import {AppService} from '../../../app.service';
import {NavList, View, Term, ControlComponent} from '../control.component';
import {Terminal} from '../../../globals';
import * as io from 'socket.io-client';
import * as jQuery from 'jquery/dist/jquery.min.js';
@Component({
selector: 'app-ssh',
templateUrl: './ssh.component.html',
styleUrls: ['./ssh.component.css']
})
export class SshComponent implements OnInit {
NavList = NavList;
static TerminalDisconnect(host) {
host.connected = false;
host.Term.socket.destroy();
host.Term.term.write('\r\n\x1b[31mBye Bye!\x1b[m\r\n');
}
static TerminalDisconnectAll() {
alert('TerminalDisconnectAll');
for (let i = 0; i < NavList.List.length; i++) {
SshComponent.TerminalDisconnect(NavList.List[i]);
}
}
constructor(private _appService: AppService,
private _logger: Logger) {
this._logger.log('SshComponent.ts:SshComponent');
}
ngOnInit() {
}
TerminalConnect(host, userid) {
// console.log(host, userid);
const socket = io.connect('/ssh');
let cols = '80';
let rows = '24';
if (Cookie.get('cols')) {
cols = Cookie.get('cols');
}
if (Cookie.get('rows')) {
rows = Cookie.get('rows');
}
Cookie.set('cols', cols, 99, '/', document.domain);
Cookie.set('rows', rows, 99, '/', document.domain);
const id = NavList.List.length - 1;
NavList.List[id].nick = host.hostname;
NavList.List[id].connected = true;
NavList.List[id].edit = false;
NavList.List[id].closed = false;
NavList.List[id].type = 'ssh';
NavList.List[id].Term = new Term;
NavList.List[id].Term.machine = host.id;
NavList.List[id].Term.socket = socket;
NavList.List[id].Term.term = Terminal({
cols: cols,
rows: rows,
useStyle: true,
screenKeys: true,
});
NavList.List.push(new View());
ControlComponent.active(id);
// TermStore.term[id]['term'].on('title', function (title) {
// document.title = title;
// });
NavList.List[id].Term.term.open(document.getElementById('term-' + id), true);
NavList.List[id].Term.term.write('\x1b[31mWelcome to Jumpserver!\x1b[m\r\n');
socket.on('connect', function () {
socket.emit('host', {'uuid': host.id, 'userid': userid});
NavList.List[id].Term.term.on('data', function (data) {
socket.emit('data', data);
});
socket.on('data', function (data) {
NavList.List[id].Term.term.write(data);
});
socket.on('disconnect', function () {
SshComponent.TerminalDisconnect(NavList.List[id]);
// TermStore.term[id]["term"].destroy();
// TermStore.term[id]["connected"] = false;
});
window.onresize = function () {
let col = Math.floor(jQuery('#term').width() / jQuery('#liuzheng').width() * 8) - 3;
let row = Math.floor(jQuery('#term').height() / jQuery('#liuzheng').height()) - 5;
let rows = 24;
let cols = 80;
if (Cookie.get('rows')) {
rows = parseInt(Cookie.get('rows'), 10);
}
if (Cookie.get('cols')) {
cols = parseInt(Cookie.get('cols'), 10);
}
if (col < 80) {
col = 80;
}
if (row < 24) {
row = 24;
}
if (cols === col && row === rows) {
} else {
for (let _i = 0; _i < NavList.List.length; _i++) {
if (NavList.List[_i].connected) {
NavList.List[_i].Term.socket.emit('resize', {'cols': col, 'rows': row});
NavList.List[_i].Term.term.resize(col, row);
}
}
Cookie.set('cols', String(col), 99, '/', document.domain);
Cookie.set('rows', String(row), 99, '/', document.domain);
}
};
jQuery(window).resize();
});
}
}
......@@ -13,8 +13,6 @@ import {DataStore, User} from '../globals';
selector: 'app-controllpage',
templateUrl: './controlpage.component.html',
styleUrls: ['./controlpage.component.css'],
providers: [AppService]
})
export class ControlPageComponent implements OnInit {
DataStore = DataStore;
......
......@@ -7,9 +7,7 @@
*/
import {Component, OnChanges, Input, Pipe, PipeTransform} from '@angular/core';
import {Logger} from 'angular2-logger/core';
import {AppService, HttpService} from '../../app.service';
import {AppService, HttpService, LogService} from '../../app.service';
export let Q = '';
......@@ -25,7 +23,7 @@ export class SearchComponent implements OnChanges {
constructor(private _appService: AppService,
private _http: HttpService,
private _logger: Logger) {
private _logger: LogService) {
this._logger.log('LeftbarComponent.ts:SearchBar');
}
......@@ -41,8 +39,7 @@ export class SearchComponent implements OnChanges {
if (this.searchrequest) {
this.searchrequest.unsubscribe();
}
this.searchrequest = this._http.get('/api/search?q=' + q)
.map(res => res.json())
this.searchrequest = this._http.search(q)
.subscribe(
data => {
this._logger.log(data);
......
......@@ -6,9 +6,7 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, OnInit} from '@angular/core';
import {Logger} from 'angular2-logger/core';
import {AppService} from '../../app.service';
import {AppService, LogService} from '../../app.service';
@Component({
selector: 'app-ileftbar',
......@@ -18,7 +16,7 @@ import {AppService} from '../../app.service';
export class IleftbarComponent implements OnInit {
constructor(private _appService: AppService,
private _logger: Logger) {
private _logger: LogService) {
this._logger.log('nav.ts:NavComponent');
// this._appService.getnav()
}
......
......@@ -13,7 +13,6 @@ import {User} from '../globals';
selector: 'app-index-page',
templateUrl: './index-page.component.html',
styleUrls: ['./index-page.component.css'],
providers: [AppService]
})
export class IndexPageComponent implements OnInit {
User = User;
......
......@@ -16,13 +16,17 @@ import {ReplayPageComponent} from './replay-page/replay-page.component';
import {MonitorPageComponent} from './monitor-page/monitor-page.component';
import {RdpPageComponent} from './rdp-page/rdp-page.component';
import {TermPageComponent} from './term-page/term-page.component';
import {ElementServerMenuComponent} from './elements/server-menu/server-menu.component';
import {BlankPageComponent} from './blank-page/blank-page.component';
const appRoutes: Routes = [
{path: 'users/login', component: LoginComponent},
// {path: 'users/login', component: LoginComponent},
{path: 'rdp/:token', component: RdpPageComponent},
{path: 'term/:token', component: TermPageComponent},
{path: 'replay/:token', component: ReplayPageComponent},
{path: 'monitor/:token', component: MonitorPageComponent},
{path: 'test', component: TermPageComponent},
{path: 'undefined', component: BlankPageComponent},
{path: '', component: ControlPageComponent},
{path: '**', component: NotFoundComponent}
];
......
<ng-progress></ng-progress>
<app-element-nav *ngIf="DataStore.NavShow"></app-element-nav>
<router-outlet></router-outlet>
<!--<app-element-interactive></app-element-interactive>-->
......@@ -13,7 +13,6 @@ import {DataStore} from './globals';
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [AppService, HttpService],
// directives: [LeftbarComponent, TermComponent]
})
......
......@@ -12,27 +12,32 @@
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms'; // <-- NgModel lives here
import {Logger, Options, Level as LoggerLevel} from 'angular2-logger/core';
import {HttpModule} from '@angular/http';
import {LoggerModule, NGXLogger, NgxLoggerLevel} from 'ngx-logger';
import {HttpClientModule} from '@angular/common/http';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
// service
import {AppService, HttpService, LogService, UUIDService} from './app.service';
import {LayerService} from './elements/layer/layer.service';
// Elements
import {ElementFooterComponent} from './elements/footer/footer.component';
import {ElementTermComponent} from './elements/term/term.component';
import {ElementInteractiveComponent} from './elements/interactive/interactive.component';
import {ElementNavComponent} from './elements/nav/nav.component';
import {LoginComponent} from './BasicPage/login/login.component';
import {ElementPopupComponent} from './elements/popup/popup.component';
import {ElementRdpComponent} from './elements/rdp/rdp.component';
import {ElementServerMenuComponent} from './elements/server-menu/server-menu.component';
import {ElementIframeComponent} from './elements/iframe/iframe.component';
// pages
import {LoginComponent} from './BasicPage/login/login.component';
import {IleftbarComponent} from './IndexPage/ileftbar/ileftbar.component';
import {SearchComponent, SearchFilter} from './ControlPage/search/search.component';
import {CleftbarComponent} from './ControlPage/cleftbar/cleftbar.component';
import {ControlComponent} from './ControlPage/control/control.component';
import {ControlnavComponent} from './ControlPage/control/controlnav/controlnav.component';
import {RdpComponent} from './ControlPage/control/rdp/rdp.component';
import {SshComponent} from './ControlPage/control/ssh/ssh.component';
import {ControlPageComponent} from './ControlPage/controlpage.component';
import {IndexPageComponent} from './IndexPage/index-page.component';
import {NotFoundComponent} from './BasicPage/not-found/not-found.component';
......@@ -45,14 +50,21 @@ import {UtcDatePipe} from './app.pipe';
import {MonitorPageComponent} from './monitor-page/monitor-page.component';
import {LinuxComponent} from './monitor-page/linux/linux.component';
import {WindowsComponent} from './monitor-page/windows/windows.component';
import {ElementRdpComponent} from './elements/rdp/rdp.component';
import {NgProgressModule} from 'ngx-progressbar';
import {TestPageComponent} from './test-page/test-page.component';
import { BlankPageComponent } from './blank-page/blank-page.component';
// import {NgxLayerModule} from 'ngx-layer';
@NgModule({
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
HttpModule,
NgProgressModule,
HttpClientModule,
LoggerModule.forRoot({serverLoggingUrl: '/api/logs', level: NgxLoggerLevel.DEBUG, serverLogLevel: NgxLoggerLevel.ERROR}),
// NgxLayerModule
],
declarations: [
AppComponent,
......@@ -62,9 +74,9 @@ import {ElementRdpComponent} from './elements/rdp/rdp.component';
ElementTermComponent,
ElementInteractiveComponent,
ElementRdpComponent,
ElementServerMenuComponent,
ElementIframeComponent,
LoginComponent,
RdpComponent,
SshComponent,
SearchComponent,
SearchFilter,
IleftbarComponent,
......@@ -83,11 +95,19 @@ import {ElementRdpComponent} from './elements/rdp/rdp.component';
MonitorPageComponent,
LinuxComponent,
WindowsComponent,
TestPageComponent,
BlankPageComponent,
],
bootstrap: [AppComponent],
providers: [
{provide: Options, useValue: {store: false, level: LoggerLevel.WARN}},
Logger
// {provide: LoggerConfig, useValue: {level: LoggerLevel.WARN}},
// {provide: BrowserXhr, useClass: NgProgressBrowserXhr},
AppService,
HttpService,
LogService,
UUIDService,
LayerService,
NGXLogger
]
})
export class AppModule {
......
......@@ -6,84 +6,131 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Injectable, OnInit} from '@angular/core';
import {Http, RequestOptionsArgs, Headers} from '@angular/http';
import {Router} from '@angular/router';
import {Cookie} from 'ng2-cookies/ng2-cookies';
import {Logger} from 'angular2-logger/core';
// import {Cookie} from 'ng2-cookies/ng2-cookies';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import {DataStore, User, Browser} from './globals';
import {environment} from '../environments/environment';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {NGXLogger} from 'ngx-logger';
import {HostGroup} from './ControlPage/cleftbar/cleftbar.component';
import * as UUID from 'uuid-js/lib/uuid.js';
declare function unescape(s: string): string;
@Injectable()
export class HttpService {
headers = new Headers();
headers = new HttpHeaders();
constructor(private _http: Http) {
constructor(private http: HttpClient) {
}
// request(url: string | Request, options?: RequestOptionsArgs) {
// if (options == null) {
// options = {};
// }
// options.headers = this.headers;
// return this._http.request(url, options)
// }
get(url: string, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
}
options.headers = this.headers;
return this._http.get(url, options);
get(url: string, options?: any) {
return this.http.get(url, options);
}
post(url: string, body: any, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
}
options.headers = this.headers;
return this._http.post(url, body, options);
post(url: string, options?: any) {
return this.http.post(url, options);
}
put(url: string, options?: any) {
return this.http.put(url, options);
}
delete(url: string, options?: any) {
return this.http.delete(url, options);
}
patch(url: string, options?: any) {
return this.http.patch(url, options);
}
head(url: string, options?: any) {
return this.http.head(url, options);
}
options(url: string, options?: any) {
return this.http.options(url, options);
}
report_browser() {
return this.http.post('/api/browser', JSON.stringify(Browser));
}
check_login(user: any) {
return this.http.post('/api/checklogin', user);
}
get_user_profile() {
return this.http.get('/api/users/v1/profile/');
}
get_my_asset_groups_assets() {
return this.http.get<Array<HostGroup>>('/api/perms/v1/user/my/asset-groups-assets/');
}
put(url: string, body: any, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
get_guacamole_token(username: string, assetID: string, systemUserID: string) {
const body = new HttpParams()
.set('username', username)
.set('password', 'jumpserver')
.set('asset_id', assetID)
.set('system_user_id', systemUserID);
return this.http.post('/guacamole/api/tokens', body.toString(), {headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')});
}
search(q: string) {
return this.http.get('/api/search?q=' + q);
}
get_replay(token: string) {
return this.http.get('/api/terminal/v1/sessions/' + token + '/replay');
}
}
@Injectable()
export class LogService {
level: number;
constructor(private _logger: NGXLogger) {
// 0.- Level.OFF
// 1.- Level.ERROR
// 2.- Level.WARN
// 3.- Level.INFO
// 4.- Level.DEBUG
// 5.- Level.LOG
this.level = 4;
}
log(message: any, ...additional: any[]) {
if (this.level > 4) {
this._logger.log(message, ...additional);
}
options.headers = this.headers;
return this._http.put(url, body, options);
}
delete(url: string, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
debug(message: any, ...additional: any[]) {
if (this.level > 3) {
this._logger.debug(message, ...additional);
}
options.headers = this.headers;
return this._http.delete(url, options);
}
patch(url: string, body: any, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
info(message: any, ...additional: any[]) {
if (this.level > 2) {
this._logger.info(message, ...additional);
}
options.headers = this.headers;
return this._http.patch(url, body, options);
}
head(url: string, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
warn(message: any, ...additional: any[]) {
if (this.level > 1) {
this._logger.warn(message, ...additional);
}
options.headers = this.headers;
return this._http.head(url, options);
}
options(url: string, options?: RequestOptionsArgs) {
if (options == null) {
options = {};
error(message: any, ...additional: any[]) {
if (this.level > 0) {
this._logger.error(message, ...additional);
}
options.headers = this.headers;
return this._http.options(url, options);
}
}
......@@ -94,33 +141,36 @@ export class AppService implements OnInit {
constructor(private _http: HttpService,
private _router: Router,
private _logger: Logger) {
if (Cookie.get('loglevel')) {
// 0.- Level.OFF
// 1.- Level.ERROR
// 2.- Level.WARN
// 3.- Level.INFO
// 4.- Level.DEBUG
// 5.- Level.LOG
this._logger.level = parseInt(Cookie.get('loglevel'), 10);
// this._logger.debug('Your debug stuff');
// this._logger.info('An info');
// this._logger.warn('Take care ');
// this._logger.error('Too late !');
// this._logger.log('log !');
} else {
Cookie.set('loglevel', '0', 99, '/', document.domain);
// this._logger.level = parseInt(Cookie.getCookie('loglevel'));
this._logger.level = 0;
}
private _logger: LogService) {
// if (Cookie.get('loglevel')) {
// // 0.- Level.OFF
// // 1.- Level.ERROR
// // 2.- Level.WARN
// // 3.- Level.INFO
// // 4.- Level.DEBUG
// // 5.- Level.LOG
// this._logger.level = parseInt(Cookie.get('loglevel'), 10);
// // this._logger.debug('Your debug stuff');
// // this._logger.info('An info');
// // this._logger.warn('Take care ');
// // this._logger.error('Too late !');
// // this._logger.log('log !');
// } else {
// Cookie.set('loglevel', '0', 99, '/', document.domain);
// // this._logger.level = parseInt(Cookie.getCookie('loglevel'));
// this._logger.level = 0;
// }
// this.checklogin();
if (environment.production) {
this.checklogin();
}
// this._logger
// .debug(this._http.get_user_profile());
}
ngOnInit() {
}
checklogin() {
this._logger.log('service.ts:AppService,checklogin');
if (DataStore.Path) {
......@@ -134,33 +184,45 @@ export class AppService implements OnInit {
}
// jQuery('angular2').show();
} else {
this.browser();
this._http.get('/api/checklogin')
.map(res => res.json())
// this.browser();
this._http.get_user_profile()
.subscribe(
data => {
User.name = data.name;
User.username = data.username;
User.logined = data.logined;
User.id = data['id'];
User.name = data['name'];
User.username = data['username'];
User.email = data['email'];
User.is_active = data['is_active'];
User.is_superuser = data['is_superuser'];
User.role = data['role'];
// User.groups = data['groups'];
User.wechat = data['wechat'];
User.comment = data['comment'];
User.date_expired = data['date_expired'];
if (data['phone']) {
User.phone = data['phone'].toString();
}
User.logined = data['logined'];
this._logger.debug(User);
},
err => {
this._logger.error(err);
// this._logger.error(err);
User.logined = false;
this._router.navigate(['login']);
window.location.href = document.location.origin + '/users/login?next=' + document.location.pathname;
// this._router.navigate(['login']);
},
() => {
if (User.logined) {
if (document.location.pathname === '/login') {
this._router.navigate(['']);
} else {
this._router.navigate([document.location.pathname]);
}
} else {
this._router.navigate(['login']);
}
// jQuery('angular2').show();
}
// () => {
// if (User.logined) {
// if (document.location.pathname === '/login') {
// this._router.navigate(['']);
// } else {
// this._router.navigate([document.location.pathname]);
// }
// } else {
// this._router.navigate(['login']);
// }
// jQuery('angular2').show();
// }
);
}
}
......@@ -170,9 +232,8 @@ export class AppService implements OnInit {
}
}
browser() {
this._http.post('/api/browser', JSON.stringify(Browser)).map(res => res.json()).subscribe();
this._http.report_browser();
}
getQueryString(name) {
......@@ -302,3 +363,14 @@ export class AppService implements OnInit {
//
// }
}
@Injectable()
export class UUIDService {
constructor() {
}
gen() {
return UUID.create()['hex'];
}
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RdpComponent } from './rdp.component';
import { BlankPageComponent } from './blank-page.component';
describe('RdpComponent', () => {
let component: RdpComponent;
let fixture: ComponentFixture<RdpComponent>;
describe('BlankPageComponent', () => {
let component: BlankPageComponent;
let fixture: ComponentFixture<BlankPageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RdpComponent ]
declarations: [ BlankPageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RdpComponent);
fixture = TestBed.createComponent(BlankPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, OnInit} from '@angular/core';
import {DataStore} from '../globals';
@Component({
selector: 'app-blank-page',
templateUrl: './blank-page.component.html',
styleUrls: ['./blank-page.component.scss']
})
export class BlankPageComponent implements OnInit {
constructor() {
DataStore.NavShow = false;
}
ngOnInit() {
}
}
......@@ -6,8 +6,7 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, OnInit} from '@angular/core';
import {AppService} from '../../app.service';
import {Logger} from 'angular2-logger/core';
import {AppService, LogService} from '../../app.service';
import {DataStore, User} from '../../globals';
import {version} from '../../../environments/environment';
......@@ -22,7 +21,7 @@ export class ElementFooterComponent implements OnInit {
version = version;
constructor(private _appService: AppService,
private _logger: Logger) {
private _logger: LogService) {
this._logger.log('nav.ts:NavComponent');
// this._appService.getnav()
}
......
<iframe [src]="trust(target)"></iframe>
#rdp {
width: 100%;
height: 100%;
padding: 15px;
}
#rdp > div, iframe {
iframe {
width: 100%;
height: 100%;
}
iframe {
border: none;
background-color: white;
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementIframeComponent } from './iframe.component';
describe('ElementIframeComponent', () => {
let component: ElementIframeComponent;
let fixture: ComponentFixture<ElementIframeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ElementIframeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ElementIframeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, Input, OnInit} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
import {NavList} from '../../ControlPage/control/control.component';
import {User} from '../../globals';
import {HttpService, LogService} from '../../app.service';
@Component({
selector: 'app-element-iframe',
templateUrl: './iframe.component.html',
styleUrls: ['./iframe.component.scss']
})
export class ElementIframeComponent implements OnInit {
@Input() host: any;
@Input() userid: any;
@Input() index: number;
target: string;
constructor(private sanitizer: DomSanitizer,
private _http: HttpService,
private _logger: LogService) {
}
ngOnInit() {
// /guacamole/api/tokens will redirect to http://guacamole/api/tokens
this._http.get_guacamole_token(User.name, this.host.id, this.userid).subscribe(
data => {
const base = window.btoa(this.host.hostname + '\0' + 'c' + '\0' + 'jumpserver');
// /guacamole/client will redirect to http://guacamole/#/client
this.target = document.location.origin +
'/guacamole/#/client/' + base + '?token=' + data['authToken'];
},
error2 => {
this._logger.error(error2);
}
);
}
trust(url) {
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}
Disconnect() {
NavList.List[this.index].connected = false;
}
}
import {Injectable} from '@angular/core';
import * as layer from 'layui-layer/src/layer.js';
@Injectable()
export class LayerService {
constructor() {
}
open(options: any) {
layer.open(options);
}
dialog() {
}
confirm() {
}
tip() {
}
loading() {
}
alert() {
// alert('sss');
}
close(index: any) {
layer.close(index);
}
}
......@@ -6,13 +6,9 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, OnInit} from '@angular/core';
import {Logger} from 'angular2-logger/core';
import {AppService, HttpService} from '../../app.service';
import {AppService, HttpService, LogService} from '../../app.service';
import {CleftbarComponent} from '../../ControlPage/cleftbar/cleftbar.component';
import {SshComponent} from '../../ControlPage/control/ssh/ssh.component';
import {RdpComponent} from '../../ControlPage/control/rdp/rdp.component';
import {NavList} from '../../ControlPage/control/control.component';
import {ControlComponent, NavList} from '../../ControlPage/control/control.component';
import {DataStore} from '../../globals';
import * as jQuery from 'jquery/dist/jquery.min.js';
// import * as layer from 'layui-layer/src/layer.js';
......@@ -32,7 +28,7 @@ export class ElementNavComponent implements OnInit {
constructor(private _appService: AppService,
private _http: HttpService,
private _logger: Logger) {
private _logger: LogService) {
this._logger.log('nav.ts:NavComponent');
this.getnav();
}
......@@ -63,11 +59,11 @@ export class ElementNavComponent implements OnInit {
case'Disconnect': {
switch (NavList.List[NavList.Active].type) {
case 'ssh': {
SshComponent.TerminalDisconnect(NavList.List[NavList.Active]);
ControlComponent.TerminalDisconnect(NavList.Active);
break;
}
case 'rdp': {
RdpComponent.Disconnect(NavList.List[NavList.Active]);
ControlComponent.RdpDisconnect(NavList.Active);
break;
}
default: {
......@@ -78,8 +74,7 @@ export class ElementNavComponent implements OnInit {
break;
}
case'DisconnectAll': {
SshComponent.TerminalDisconnectAll();
RdpComponent.DisconnectAll();
ControlComponent.DisconnectAll();
break;
}
case 'Website': {
......
<div class="ES-menu" [ngStyle]="{'top':top,'left':left}">
<ul class="dropdown-content">
<li [ngClass]="m.type" *ngFor="let m of MenuList">
<a (click)="m.action" *ngIf="m.type!='line'">{{m.name}}</a>
</li>
</ul>
</div>
.ES-menu {
display: block;
width: 120px;
background-color: #2f2a2a;
position: absolute;
}
.ES-menu ul {
list-style-type: none;
line-height: 24px;
}
.ES-menu li {
display: inline-block;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown:hover {
background-color: #2d2828;
}
.dropdown-content {
position: absolute;
background-color: black;
color: #c6bcbc;
padding: 4px 0;
z-index: 999;
float: none;
list-style: none;
line-height: normal;
direction: ltr;
width: auto;
top: auto;
left: 0px;
margin-left: 0px;
margin-top: 0px;
min-width: 150px;
}
.ES-menu:hover .dropdown-content {
display: block;
}
.ES-menu .dropdown-content li {
float: left;
display: flex;
}
.ES-menu .dropdown-content li a {
padding: 6px 14px 6px 14px;
white-space: nowrap;
font-family: 'Roboto', sans-serif;
font-size: 13px;
font-weight: 300;
position: relative;
text-decoration: none;
min-width: 150px;
line-height: normal;
}
.ES-menu .dropdown-content li a span {
float: right;
}
.dropdown-content li:hover {
background-color: #3a3333;
color: black;
width: 100%;
}
.dropdown-content li.disabled:hover {
background-color: black;
}
.dropdown-content li.disabled a {
color: #c5babc;
}
.dropdown-content li.disabled a:hover {
cursor: default;
color: #c5babc;
}
.ES-menu a {
color: #f0f0f1;
text-align: center;
text-decoration: none;
padding: 6px 15px 6px 15px;
}
.ES-menu a:hover {
color: #fff;
cursor: pointer
}
.ES-menu .line {
height: 1px;
width: 100%;
background-color: white;
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementServerMenuComponent } from './server-menu.component';
describe('ElementServerMenuComponent', () => {
let component: ElementServerMenuComponent;
let fixture: ComponentFixture<ElementServerMenuComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ElementServerMenuComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ElementServerMenuComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, OnInit} from '@angular/core';
import {LayerService} from '../layer/layer.service';
export class Menu {
name: string;
type: string;
action: any;
}
@Component({
selector: 'app-element-server-menu',
templateUrl: './server-menu.component.html',
styleUrls: ['./server-menu.component.scss'],
})
export class ElementServerMenuComponent implements OnInit {
MenuList: Array<any>;
top: number;
left: number;
constructor(private ly: LayerService) {
}
ngOnInit() {
const m = new Menu();
const line = new Menu();
m.action = '';
m.name = 'test';
m.type = 'lll';
line.type = 'line';
this.MenuList = [m, m, line, m, m];
this.ly.alert();
}
public contextmenu(top: number, left: number) {
this.top = top;
this.left = left;
}
}
import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
import {AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {ElementRef} from '@angular/core';
import {term} from '../../globals';
import {term, Terminal, TermWS} from '../../globals';
import {Cookie} from 'ng2-cookies/ng2-cookies';
import {NavList} from '../../ControlPage/control/control.component';
import * as jQuery from 'jquery/dist/jquery.min.js';
import {UUIDService} from '../../app.service';
@Component({
selector: 'app-element-term',
......@@ -9,20 +12,42 @@ import * as jQuery from 'jquery/dist/jquery.min.js';
styleUrls: ['./term.component.css']
})
export class ElementTermComponent implements OnInit, AfterViewInit {
@Input() host: any;
@Input() userid: any;
@Input() index: number;
// @Input() room: string;
@ViewChild('term') el: ElementRef;
secret: string;
term: any;
constructor() {
constructor(private _uuid: UUIDService) {
}
ngOnInit() {
this.secret = this._uuid.gen();
this.term = Terminal({
cols: 80,
rows: 24,
useStyle: true,
screenKeys: true,
});
// NavList.List[this.index].room = this.room;
}
ngAfterViewInit() {
term.col = Math.floor(jQuery(this.el.nativeElement).width() / jQuery('#liuzheng').width() * 8) - 3;
term.row = Math.floor(jQuery(this.el.nativeElement).height() / jQuery('#liuzheng').height()) - 5;
term.term.open(this.el.nativeElement, true);
if (this.host) {
if (Cookie.get('cols')) {
term.col = parseInt(Cookie.get('cols'), 10);
}
if (Cookie.get('rows')) {
term.row = parseInt(Cookie.get('rows'), 10);
}
} else {
term.col = Math.floor(jQuery(this.el.nativeElement).width() / jQuery('#liuzheng').width() * 8) - 3;
term.row = Math.floor(jQuery(this.el.nativeElement).height() / jQuery('#liuzheng').height()) - 3;
term.term = this.term;
}
this.term.open(this.el.nativeElement, true);
const that = this;
window.onresize = function () {
term.col = Math.floor(jQuery(that.el.nativeElement).width() / jQuery('#liuzheng').width() * 8) - 3;
......@@ -33,9 +58,52 @@ export class ElementTermComponent implements OnInit, AfterViewInit {
if (term.row < 24) {
term.row = 24;
}
term.term.resize(term.col, term.row);
that.term.resize(term.col, term.row);
if (that.host) {
Cookie.set('cols', term.col.toString(), 99, '/', document.domain);
Cookie.set('rows', term.row.toString(), 99, '/', document.domain);
TermWS.emit('resize', {'cols': term.col, 'rows': term.row});
}
};
jQuery(window).resize();
if (this.host) {
NavList.List[this.index].Term = this.term;
// this.term.write('\x1b[31mWelcome to Jumpserver!\x1b[m\r\n');
TermWS.emit('host', {'uuid': this.host.id, 'userid': this.userid, 'secret': this.secret});
this.term.on('data', function (data) {
TermWS.emit('data', {'data': data, 'room': NavList.List[that.index].room});
});
TermWS.on('data', function (data) {
if (data['room'] === NavList.List[that.index].room) {
that.term.write(data['data']);
}
});
TermWS.on('disconnect', function () {
that.TerminalDisconnect();
});
TermWS.on('logout', function (data) {
if (data['room'] === NavList.List[that.index].room) {
NavList.List[this.index].connected = false;
this.term.write('\r\n\x1b[31mBye Bye!\x1b[m\r\n');
}
});
TermWS.on('room', function (data) {
if (data['secret'] === that.secret) {
NavList.List[that.index].room = data['room'];
}
});
}
}
TerminalDisconnect() {
NavList.List[this.index].connected = false;
this.term.write('\r\n\x1b[31mBye Bye!\x1b[m\r\n');
TermWS.emit('logout', NavList.List[this.index].room);
}
}
'use strict';
import * as terminal from 'term.js/src/term.js';
import * as terminal from 'xterm/dist/xterm';
import * as io from 'socket.io-client';
export function Terminal(xargs: any) {
return terminal(xargs);
}
export const TermWS = io.connect('/ssh');
export let term: {
term: any;
col: number;
......@@ -65,9 +66,13 @@ export let User: {
avatar: string;
role: string;
email: string;
wechat: string;
comment: string;
is_active: boolean;
is_superuser: boolean;
date_joined: string;
last_login: string;
date_expired: string;
groups: Array<Group>;
logined: boolean;
} = {
......@@ -79,9 +84,13 @@ export let User: {
avatar: '',
role: '',
email: '',
wechat: '',
comment: '',
is_active: false,
is_superuser: false,
date_joined: '',
last_login: '',
date_expired: '',
groups: [],
logined: false,
};
......
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';
import {Logger} from 'angular2-logger/core';
import {HttpService} from '../app.service';
import {HttpService, LogService} from '../app.service';
import {Video, DataStore} from '../globals';
@Component({
......@@ -14,7 +13,7 @@ export class ReplayPageComponent implements OnInit {
constructor(private activatedRoute: ActivatedRoute,
private _http: HttpService,
private _logger: Logger) {
private _logger: LogService) {
// this.video = {'type': 'none'};
DataStore.NavShow = false;
......@@ -25,8 +24,7 @@ export class ReplayPageComponent implements OnInit {
this.activatedRoute.params.subscribe((params: Params) => {
token = params['token'];
});
this._http.get('/api/terminal/v1/sessions/' + token + '/replay')
.map(res => res.json())
this._http.get_replay(token)
.subscribe(
data => {
Video.type = 'json';
......@@ -38,6 +36,7 @@ export class ReplayPageComponent implements OnInit {
Video.totalTime = Video.timelist[Video.timelist.length - 1] * 1000;
},
err => {
alert('无法下载');
this._logger.error(err);
},
);
......
<p>
test-page works!
</p>
<!--<ngx-layer></ngx-layer>-->
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SshComponent } from './ssh.component';
import { TestPageComponent } from './test-page.component';
describe('SshComponent', () => {
let component: SshComponent;
let fixture: ComponentFixture<SshComponent>;
describe('TestPageComponent', () => {
let component: TestPageComponent;
let fixture: ComponentFixture<TestPageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SshComponent ]
declarations: [ TestPageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SshComponent);
fixture = TestBed.createComponent(TestPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-test-page',
templateUrl: './test-page.component.html',
styleUrls: ['./test-page.component.scss']
})
export class TestPageComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
......@@ -9,3 +9,60 @@ $FontPathOpenSans: "~npm-font-open-sans/fonts";
@import '~npm-font-open-sans/open-sans';
$roboto-font-path: "~roboto-fontface/fonts";
@import "~roboto-fontface/css/mixins.scss";
/*
*
* INSPINIA - Responsive Admin Theme
* version 2.7.1
*
*/
$asset-path: '../static/imgs/inspinia';
// Variables, Mixins
@import "../assets/inspinia/imports/variables";
@import "../assets/inspinia/imports/mixins";
// INSPINIA Theme Elements
@import "../assets/inspinia/imports/typography";
@import "../assets/inspinia/imports/navigation";
@import "../assets/inspinia/imports/top_navigation";
@import "../assets/inspinia/imports/buttons";
@import "../assets/inspinia/imports/badges_labels";
@import "../assets/inspinia/imports/elements";
@import "../assets/inspinia/imports/sidebar";
@import "../assets/inspinia/imports/base";
@import "../assets/inspinia/imports/pages";
@import "../assets/inspinia/imports/chat";
@import "../assets/inspinia/imports/metismenu";
@import "../assets/inspinia/imports/spinners";
// Landing page styles
//@import "../assets/inspinia/imports/landing";
// RTL Support
@import "../assets/inspinia/imports/rtl";
// For demo only - config box style
@import "../assets/inspinia/imports/theme-config";
// INSPINIA Skins
@import "../assets/inspinia/imports/skins";
@import "../assets/inspinia/imports/md-skin";
// Media query style
@import "../assets/inspinia/imports/media";
// Custom style
// Your custom style to override base style
@import "../assets/inspinia/imports/custom";
// Clear layout on print mode
@media print {
nav.navbar-static-side {
display: none;
}
body { overflow: visible !important; }
#page-wrapper {
margin: 0;
}
}
......@@ -31,6 +31,7 @@ app-root {
font-size: 11px !important;
padding-bottom: 16px !important;
font-family: 'Monaco', Inconsolata !important;
color: white;
}
.terminal {
......
#!/bin/bash
set -ex
npm run-script build
rm -fr luna*
mv dist luna
tar czf luna.tar.gz luna
md5 luna.tar.gz
......@@ -7,12 +7,12 @@
set -ex
git checkout publish && \
git checkout github_dev && \
git pull github dev --rebase && \
git merge master -m "publish" && \
git merge dev -m "publish" && \
git reset --soft HEAD^ && \
git commit -m "publish" && \
git push github publish:dev && \
git push github github_dev:dev && \
echo "success"
git checkout master
git pull github dev --commit && git push origin master
git checkout dev
git pull github dev --commit && git push origin dev
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