Browse Source

make Prettier

master
AJ ONeal 4 years ago
parent
commit
880da4d685
  1. 18
      .jshintrc
  2. 7
      .prettierrc
  3. 208
      dump/admin.html
  4. 251
      dump/client.html
  5. 95
      html/admin/404.html
  6. 21
      html/admin/css/main.css
  7. 122
      html/admin/css/normalize.css
  8. 109
      html/admin/index.html
  9. 145
      html/admin/js/app.js
  10. 32
      html/admin/js/plugins.js
  11. 253
      html/admin/js/vendor/filter.js
  12. 175
      html/admin/partials/servers.html
  13. 64
      html/admin/partials/status.html
  14. 14
      rvpn-docker/README.md

18
.jshintrc

@ -0,0 +1,18 @@
{ "node": true
, "browser": true
, "jquery": true
, "globals": { "angular": true, "Promise": true }
, "indent": 2
, "onevar": true
, "laxcomma": true
, "laxbreak": true
, "curly": true
, "nonbsp": true
, "eqeqeq": true
, "immed": true
, "undef": true
, "unused": true
, "latedef": true
}

7
.prettierrc

@ -0,0 +1,7 @@
{
"bracketSpacing": true,
"printWidth": 120,
"tabWidth": 4,
"trailingComma": "none",
"useTabs": false
}

208
dump/admin.html

@ -1,110 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Websock VPN Instrumentation</title>
</head>
<body ng-app="vpnAdmin" ng-controller="vpnInstrumentationController">
<div class="panel panel-default panel-primary">
<div class="panel-heading">VPN Instrumentation</div>
<div class="panel-body">
<div class="panel panel-default panel-info">
<div class="panel-heading ">Control Plane</div>
<div class="panel-body">
<div class="row"> <!-- Auth -->
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="startWebSocket()">Start WebSocket</button>
</span>
<button class="btn btn-default" type="button" ng-class="conn == false && 'btn-danger' || 'btn-success'">
{[{ conn == false && 'False' || 'True' }]}
</button>
<head>
<title>Websock VPN Instrumentation</title>
</head>
<body ng-app="vpnAdmin" ng-controller="vpnInstrumentationController">
<div class="panel panel-default panel-primary">
<div class="panel-heading">VPN Instrumentation</div>
<div class="panel-body">
<div class="panel panel-default panel-info">
<div class="panel-heading">Control Plane</div>
<div class="panel-body">
<div class="row">
<!-- Auth -->
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="startWebSocket()">
Start WebSocket
</button>
</span>
<button
class="btn btn-default"
type="button"
ng-class="conn == false && 'btn-danger' || 'btn-success'"
>
{[{ conn == false && 'False' || 'True' }]}
</button>
</div>
</div>
</div>
</div>
<br>
<br />
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Auth</button>
</span>
<input type="text" class="form-control" placeholder="Enter auth data here">
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Auth</button>
</span>
<input type="text" class="form-control" placeholder="Enter auth data here" />
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default panel-info">
<div class="panel-heading">Data</div>
<div class="panel-body">
<p ng-repeat="text in log_elements">{[{text}]}</p>
<div class="panel panel-default panel-info">
<div class="panel-heading">Data</div>
<div class="panel-body">
<p ng-repeat="text in log_elements">{[{text}]}</p>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script type="text/javascript">
console.log("startup");
var vpnAdmin = angular.module('vpnAdmin',[]);
vpnAdmin.config(function($interpolateProvider) {
console.log("vpnTest Config");
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
vpnAdmin.controller('vpnInstrumentationController', function ($scope) {
console.log("vpnInstrumentationController startup");
$scope.log_elements = [];
$scope.auth_key = "";
$scope.conn = false;
$scope.webSocketStatus = function() {
if ($scope.conn == false) {
return ""
}
}
$scope.startWebSocket = function() {
console.log("Start webSocket {{$}}");
if (window["WebSocket"]) {
$scope.conn = new WebSocket("wss://{{$}}/ws/admin");
$scope.append_log("Websocket opened");
$scope.conn.onclose = function (evt) {
$scope.append_log("Connection closed.");
}
$scope.conn.onmessage = function (evt) {
$scope.append_log(evt.data)
}
}
else {
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
}
};
$scope.auth_click = function() {
$scope.append_log($scope.auth_key)
};
$scope.append_log = function(txt) {
$scope.log_elements.push(txt)
};
});
</script>
</html>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
crossorigin="anonymous"
/>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"
></script>
<script type="text/javascript">
console.log("startup");
var vpnAdmin = angular.module("vpnAdmin", []);
vpnAdmin.config(function ($interpolateProvider) {
console.log("vpnTest Config");
$interpolateProvider.startSymbol("{[{");
$interpolateProvider.endSymbol("}]}");
});
vpnAdmin.controller("vpnInstrumentationController", function ($scope) {
console.log("vpnInstrumentationController startup");
$scope.log_elements = [];
$scope.auth_key = "";
$scope.conn = false;
$scope.webSocketStatus = function () {
if ($scope.conn == false) {
return "";
}
};
$scope.startWebSocket = function () {
console.log("Start webSocket {{$}}");
if (window["WebSocket"]) {
$scope.conn = new WebSocket("wss://{{$}}/ws/admin");
$scope.append_log("Websocket opened");
$scope.conn.onclose = function (evt) {
$scope.append_log("Connection closed.");
};
$scope.conn.onmessage = function (evt) {
$scope.append_log(evt.data);
};
} else {
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"));
}
};
$scope.auth_click = function () {
$scope.append_log($scope.auth_key);
};
$scope.append_log = function (txt) {
$scope.log_elements.push(txt);
};
});
</script>
</html>

251
dump/client.html

@ -1,132 +1,151 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Websock VPN Test Client</title>
</head>
<body ng-app="vpnTest" ng-controller="vpnTestController">
<div class="panel panel-default panel-primary">
<div class="panel-heading">WebSocket Client Test</div>
<div class="panel-body">
<div class="panel panel-default panel-info">
<div class="panel-heading ">Control Plane</div>
<div class="panel-body">
<div class="row"> <!-- Auth -->
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="startWebSocket()">Start WebSocket</button>
</span>
<button class="btn btn-default" type="button" ng-class="conn == false && 'btn-danger' || 'btn-success'">
{[{ conn == false && 'False' || 'True' }]}
</button>
<head>
<title>Websock VPN Test Client</title>
</head>
<body ng-app="vpnTest" ng-controller="vpnTestController">
<div class="panel panel-default panel-primary">
<div class="panel-heading">WebSocket Client Test</div>
<div class="panel-body">
<div class="panel panel-default panel-info">
<div class="panel-heading">Control Plane</div>
<div class="panel-body">
<div class="row">
<!-- Auth -->
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="startWebSocket()">
Start WebSocket
</button>
</span>
<button
class="btn btn-default"
type="button"
ng-class="conn == false && 'btn-danger' || 'btn-success'"
>
{[{ conn == false && 'False' || 'True' }]}
</button>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Auth</button>
</span>
<input type="text" class="form-control" placeholder="Enter auth data here">
<br />
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Auth</button>
</span>
<input type="text" class="form-control" placeholder="Enter auth data here" />
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" ng-click="send_click()" type="button">Send</button>
</span>
<input ng-model="send_data" type="text" class="form-control" placeholder="Enter send data here">
<br />
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" ng-click="send_click()" type="button">
Send
</button>
</span>
<input
ng-model="send_data"
type="text"
class="form-control"
placeholder="Enter send data here"
/>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default panel-danger">
<div class="panel-heading">Messages</div>
<div class="panel-body">
<p ng-repeat="text in log_elements">{[{text}]}</p>
<div class="panel panel-default panel-danger">
<div class="panel-heading">Messages</div>
<div class="panel-body">
<p ng-repeat="text in log_elements">{[{text}]}</p>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script type="text/javascript">
console.log("startup");
var vpnTest = angular.module('vpnTest',[]);
vpnTest.config(function($interpolateProvider) {
console.log("vpnTest Config");
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
vpnTest.controller('vpnTestController', function ($scope) {
console.log("vpnTestController startup");
$scope.log_elements = [];
$scope.auth_key = "";
$scope.conn = false;
$scope.send_data = ""
$scope.webSocketStatus = function() {
if ($scope.conn == false) {
return ""
}
}
$scope.startWebSocket = function() {
console.log("Start webSocket {{$}}");
if (window["WebSocket"]) {
$scope.conn = new WebSocket("wss://{{$}}/ws/client");
$scope.append_log("Websocket opened");
$scope.conn.onclose = function (evt) {
$scope.append_log("Connection closed.");
}
$scope.conn.onmessage = function (evt) {
console.log(evt.data)
$scope.append_log(evt.data)
}
}
else {
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
}
};
$scope.auth_click = function() {
$scope.append_log($scope.auth_key)
};
$scope.send_click = function() {
console.log("send_click")
$scope.conn.send($scope.send_data)
};
$scope.append_log = function(txt) {
$scope.log_elements.push(txt)
};
});
</script>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
crossorigin="anonymous"
/>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"
></script>
<script type="text/javascript">
console.log("startup");
var vpnTest = angular.module("vpnTest", []);
vpnTest.config(function ($interpolateProvider) {
console.log("vpnTest Config");
$interpolateProvider.startSymbol("{[{");
$interpolateProvider.endSymbol("}]}");
});
vpnTest.controller("vpnTestController", function ($scope) {
console.log("vpnTestController startup");
$scope.log_elements = [];
$scope.auth_key = "";
$scope.conn = false;
$scope.send_data = "";
$scope.webSocketStatus = function () {
if ($scope.conn == false) {
return "";
}
};
$scope.startWebSocket = function () {
console.log("Start webSocket {{$}}");
if (window["WebSocket"]) {
$scope.conn = new WebSocket("wss://{{$}}/ws/client");
$scope.append_log("Websocket opened");
$scope.conn.onclose = function (evt) {
$scope.append_log("Connection closed.");
};
$scope.conn.onmessage = function (evt) {
console.log(evt.data);
$scope.append_log(evt.data);
};
} else {
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"));
}
};
$scope.auth_click = function () {
$scope.append_log($scope.auth_key);
};
$scope.send_click = function () {
console.log("send_click");
$scope.conn.send($scope.send_data);
};
$scope.append_log = function (txt) {
$scope.log_elements.push(txt);
};
});
</script>
</html>

95
html/admin/404.html

@ -1,60 +1,57 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page Not Found</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
line-height: 1.2;
margin: 0;
}
html {
color: #888;
display: table;
font-family: sans-serif;
height: 100%;
text-align: center;
width: 100%;
}
body {
display: table-cell;
vertical-align: middle;
margin: 2em auto;
}
h1 {
color: #555;
font-size: 2em;
font-weight: 400;
}
p {
margin: 0 auto;
width: 280px;
}
<head>
<meta charset="utf-8" />
<title>Page Not Found</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
* {
line-height: 1.2;
margin: 0;
}
@media only screen and (max-width: 280px) {
html {
color: #888;
display: table;
font-family: sans-serif;
height: 100%;
text-align: center;
width: 100%;
}
body, p {
width: 95%;
body {
display: table-cell;
vertical-align: middle;
margin: 2em auto;
}
h1 {
font-size: 1.5em;
margin: 0 0 0.3em;
color: #555;
font-size: 2em;
font-weight: 400;
}
}
p {
margin: 0 auto;
width: 280px;
}
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>Sorry, but the page you were trying to view does not exist.</p>
</body>
@media only screen and (max-width: 280px) {
body,
p {
width: 95%;
}
h1 {
font-size: 1.5em;
margin: 0 0 0.3em;
}
}
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>Sorry, but the page you were trying to view does not exist.</p>
</body>
</html>
<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->

21
html/admin/css/main.css

@ -95,22 +95,6 @@ textarea {
Author's custom styles
========================================================================== */
/* ==========================================================================
Helper classes
========================================================================== */
@ -195,10 +179,7 @@ textarea {
/* Style adjustments for viewports that meet the condition */
}
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 1.25dppx),
(min-resolution: 120dpi) {
@media print, (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 1.25dppx), (min-resolution: 120dpi) {
/* Style adjustments for high resolution devices */
}

122
html/admin/css/normalize.css

@ -7,9 +7,9 @@
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
@ -17,7 +17,7 @@ html {
*/
body {
margin: 0;
margin: 0;
}
/* HTML5 display definitions
@ -43,7 +43,7 @@ menu,
nav,
section,
summary {
display: block;
display: block;
}
/**
@ -55,8 +55,8 @@ audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
@ -65,8 +65,8 @@ video {
*/
audio:not([controls]) {
display: none;
height: 0;
display: none;
height: 0;
}
/**
@ -76,7 +76,7 @@ audio:not([controls]) {
[hidden],
template {
display: none;
display: none;
}
/* Links
@ -87,7 +87,7 @@ template {
*/
a {
background-color: transparent;
background-color: transparent;
}
/**
@ -97,7 +97,7 @@ a {
a:active,
a:hover {
outline: 0;
outline: 0;
}
/* Text-level semantics
@ -108,7 +108,7 @@ a:hover {
*/
abbr[title] {
border-bottom: 1px dotted;
border-bottom: 1px dotted;
}
/**
@ -117,7 +117,7 @@ abbr[title] {
b,
strong {
font-weight: bold;
font-weight: bold;
}
/**
@ -125,7 +125,7 @@ strong {
*/
dfn {
font-style: italic;
font-style: italic;
}
/**
@ -134,8 +134,8 @@ dfn {
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
font-size: 2em;
margin: 0.67em 0;
}
/**
@ -143,8 +143,8 @@ h1 {
*/
mark {
background: #ff0;
color: #000;
background: #ff0;
color: #000;
}
/**
@ -152,7 +152,7 @@ mark {
*/
small {
font-size: 80%;
font-size: 80%;
}
/**
@ -161,18 +161,18 @@ small {
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
top: -0.5em;
}
sub {
bottom: -0.25em;
bottom: -0.25em;
}
/* Embedded content
@ -183,7 +183,7 @@ sub {
*/
img {
border: 0;
border: 0;
}
/**
@ -191,7 +191,7 @@ img {
*/
svg:not(:root) {
overflow: hidden;
overflow: hidden;
}
/* Grouping content
@ -202,7 +202,7 @@ svg:not(:root) {
*/
figure {
margin: 1em 40px;
margin: 1em 40px;
}
/**
@ -210,8 +210,8 @@ figure {
*/
hr {
box-sizing: content-box;
height: 0;
box-sizing: content-box;
height: 0;
}
/**
@ -219,7 +219,7 @@ hr {
*/
pre {
overflow: auto;
overflow: auto;
}
/**
@ -230,8 +230,8 @@ code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
font-family: monospace, monospace;
font-size: 1em;
}
/* Forms
@ -254,9 +254,9 @@ input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
/**
@ -264,7 +264,7 @@ textarea {
*/
button {
overflow: visible;
overflow: visible;
}
/**
@ -276,7 +276,7 @@ button {
button,
select {
text-transform: none;
text-transform: none;
}
/**
@ -291,8 +291,8 @@ button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
@ -301,7 +301,7 @@ input[type="submit"] {
button[disabled],
html input[disabled] {
cursor: default;
cursor: default;
}
/**
@ -310,8 +310,8 @@ html input[disabled] {
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
border: 0;
padding: 0;
}
/**
@ -320,7 +320,7 @@ input::-moz-focus-inner {
*/
input {
line-height: normal;
line-height: normal;
}
/**
@ -333,8 +333,8 @@ input {
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
@ -345,7 +345,7 @@ input[type="radio"] {
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
height: auto;
}
/**
@ -354,8 +354,8 @@ input[type="number"]::-webkit-outer-spin-button {
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
box-sizing: content-box; /* 2 */
-webkit-appearance: textfield; /* 1 */
box-sizing: content-box; /* 2 */
}
/**
@ -366,7 +366,7 @@ input[type="search"] {
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
-webkit-appearance: none;
}
/**
@ -374,9 +374,9 @@ input[type="search"]::-webkit-search-decoration {
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
@ -385,8 +385,8 @@ fieldset {
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
@ -394,7 +394,7 @@ legend {
*/
textarea {
overflow: auto;
overflow: auto;
}
/**
@ -403,7 +403,7 @@ textarea {
*/
optgroup {
font-weight: bold;
font-weight: bold;
}
/* Tables
@ -414,11 +414,11 @@ optgroup {
*/
table {
border-collapse: collapse;
border-spacing: 0;
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
padding: 0;
}

109
html/admin/index.html

@ -1,76 +1,97 @@
<!doctype html>
<!DOCTYPE html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/normalize.css" />
<link rel="stylesheet" href="css/main.css" />
<script src="js/vendor/modernizr-2.8.3.min.js"></script>
<base href="/">
<base href="/" />
</head>
<body ng-app="rvpnApp">
<!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<p class="browserupgrade">
You are using an <strong>outdated</strong> browser. Please
<a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.
</p>
<![endif]-->
<!-- Admin GUI Begins Here -->
<header class="bs-docs-nav navbar navbar-static-top" id="top">
<div class="container">
<div class="navbar-header">
<a href="/admin/index.html" target="_parent" class="navbar-brand">RVPN Admin</a>
</div>
<nav class="collapse navbar-collapse" id="bs-navbar">
<ul class="nav navbar-nav">
<li> <a href="/admin/status">Status</a> </li>
<li> <a href="/admin/servers">Servers</a> </li>
<li> <a href="/admin/#domains">Domains</a> </li>
<li> <a href="/admin/#connections">Connections</a> </li>
</ul>
<div class="container">
<div class="navbar-header">
<a href="/admin/index.html" target="_parent" class="navbar-brand">RVPN Admin</a>
</div>
<nav class="collapse navbar-collapse" id="bs-navbar">
<ul class="nav navbar-nav">
<li><a href="/admin/status">Status</a></li>
<li><a href="/admin/servers">Servers</a></li>
<li><a href="/admin/#domains">Domains</a></li>
<li><a href="/admin/#connections">Connections</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Help</a></li>
<li><a href="#">Login</a></li>
</ul>
</nav>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Help</a></li>
<li><a href="#">Login</a></li>
</ul>
</nav>
</div>
</header>
<div ng-view> </div>
<div ng-view></div>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script>window.jQuery || document.write('<script src="admin/js/vendor/jquery-1.12.0.min.js"><\/script>')</script>
<script>
window.jQuery || document.write('<script src="admin/js/vendor/jquery-1.12.0.min.js"><\/script>');
</script>
<script src="admin/js/plugins.js"></script>
<script src="admin/js/main.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='https://www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','UA-XXXXX-X','auto');ga('send','pageview');
(function (b, o, i, l, e, r) {
b.GoogleAnalyticsObject = l;
b[l] ||
(b[l] = function () {
(b[l].q = b[l].q || []).push(arguments);
});
b[l].l = +new Date();
e = o.createElement(i);
r = o.getElementsByTagName(i)[0];
e.src = "https://www.google-analytics.com/analytics.js";
r.parentNode.insertBefore(e, r);
})(window, document, "script", "ga");
ga("create", "UA-XXXXX-X", "auto");
ga("send", "pageview");
</script>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-route.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
crossorigin="anonymous"
/>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"
></script>
<script src="/admin/js/vendor/filter.js"></script>
<script src="/admin/js/app.js"></script>
</html>

145
html/admin/js/app.js

@ -1,132 +1,129 @@
console.log("app.sh startup")
console.log("app.sh startup");
var app = angular.module("rvpnApp", ["ngRoute", "angular-duration-format"]);
app.config(function($routeProvider, $locationProvider) {
app.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when("/admin/status/", {
templateUrl : "admin/partials/status.html"
})
.when("/admin/index.html", {
templateUrl : "admin/partials/servers.html"
})
.when("/admin/servers/", {
templateUrl : "admin/partials/servers.html"
})
.when("/admin/#domains", {
templateUrl : "green.htm"
})
.when("/blue", {
templateUrl : "blue.htm"
});
.when("/admin/status/", {
templateUrl: "admin/partials/status.html"
})
.when("/admin/index.html", {
templateUrl: "admin/partials/servers.html"
})
.when("/admin/servers/", {
templateUrl: "admin/partials/servers.html"
})
.when("/admin/#domains", {
templateUrl: "green.htm"
})
.when("/blue", {
templateUrl: "blue.htm"
});
$locationProvider.html5Mode(true);
});
app.filter('bytes', function() {
return function(bytes, precision) {
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return '-';
if (typeof precision === 'undefined') precision = 1;
var units = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'],
number = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
}
app.filter("bytes", function () {
return function (bytes, precision) {
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return "-";
if (typeof precision === "undefined") precision = 1;
var units = ["bytes", "kB", "MB", "GB", "TB", "PB"],
number = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + " " + units[number];
};
});
app.filter('hfcduration', function() {
return function(duration, precision) {
remain = duration
duration_day = 24*60*60
duration_hour = 60*60
duration_minute = 60
duration_str = ""
app.filter("hfcduration", function () {
return function (duration, precision) {
remain = duration;
duration_day = 24 * 60 * 60;
duration_hour = 60 * 60;
duration_minute = 60;
duration_str = "";
days = Math.floor(remain / duration_day)
days = Math.floor(remain / duration_day);
if (days > 0) {
remain = remain - (days * duration_day)
duration_str = duration_str + days + 'd'
remain = remain - days * duration_day;
duration_str = duration_str + days + "d";
}
hours = Math.floor(remain / duration_hour)
hours = Math.floor(remain / duration_hour);
if (hours > 0) {
remain = remain - (hours * duration_hour)
duration_str = duration_str + hours + 'h'
remain = remain - hours * duration_hour;
duration_str = duration_str + hours + "h";
}
mins = Math.floor(remain / duration_minute)
mins = Math.floor(remain / duration_minute);
if (mins > 0) {
remain = remain - (mins * duration_minute)
duration_str = duration_str + mins + 'm'
remain = remain - mins * duration_minute;
duration_str = duration_str + mins + "m";
}
secs = Math.floor(remain)
duration_str = duration_str + secs + 's'
return (duration_str);
}
secs = Math.floor(remain);
duration_str = duration_str + secs + "s";
return duration_str;
};
});
app.controller('statusController', function ($scope, $http) {
app.controller("statusController", function ($scope, $http) {
console.log("statusController");
$scope.status_search = "";
var api = '/api/org.rootprojects.tunnel/status'
$scope.updateView = function() {
$http.get(api).then(function(response) {
var api = "/api/org.rootprojects.tunnel/status";
$scope.updateView = function () {
$http.get(api).then(function (response) {
console.log(response);
data = response.data;
if (data.error == 'ok' ){
if (data.error == "ok") {
$scope.status = data.result;
}
});
}
$scope.updateView()
};
$scope.updateView();
});
app.controller('serverController', function ($scope, $http) {
app.controller("serverController", function ($scope, $http) {
$scope.servers = [];
$scope.servers_search = "";
$scope.servers_trigger_details = [];
$scope.filtered
$scope.filtered;
var api = '/api/org.rootprojects.tunnel/servers'
$scope.updateView = function() {
$http.get(api).then(function(response) {
var api = "/api/org.rootprojects.tunnel/servers";
$scope.updateView = function () {
$http.get(api).then(function (response) {
//console.log(response);
data = response.data;
if (data.error == 'ok' ){
if (data.error == "ok") {
$scope.servers = data.result.servers;
}
});
}
};
$scope.triggerDetail = function(id) {
$scope.triggerDetail = function (id) {
//console.log("triggerDetail ", id, $scope.servers_trigger_details[id])
if ($scope.servers_trigger_details[id] == true) {
$scope.servers_trigger_details[id] = false;
} else {
$scope.servers_trigger_details[id] = true
$scope.servers_trigger_details[id] = true;
}
};
$scope.checkDetail = function(id) {
$scope.checkDetail = function (id) {
//console.log("checkDetail ", id, $scope.servers_trigger_details[id])
if ($scope.servers_trigger_details[id] == true) {
return false;
} else {
return true
return true;
}
};
$scope.updateView()
$scope.updateView();
});

32
html/admin/js/plugins.js

@ -1,12 +1,32 @@
// Avoid `console` errors in browsers that lack a console.
(function() {
(function () {
var method;
var noop = function () {};
var methods = [
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
"assert",
"clear",
"count",
"debug",
"dir",
"dirxml",
"error",
"exception",
"group",
"groupCollapsed",
"groupEnd",
"info",
"log",
"markTimeline",
"profile",
"profileEnd",
"table",
"time",
"timeEnd",
"timeline",
"timelineEnd",
"timeStamp",
"trace",
"warn"
];
var length = methods.length;
var console = (window.console = window.console || {});
@ -19,6 +39,6 @@
console[method] = noop;
}
}
}());
})();
// Place any jQuery/helper plugins in here.

253
html/admin/js/vendor/filter.js

@ -1,148 +1,165 @@
// ### filter.js >>
angular
.module('angular-duration-format.filter', [ ])
.filter('duration', function() {
angular.module("angular-duration-format.filter", []).filter("duration", function () {
var DURATION_FORMATS_SPLIT = /((?:[^ydhms']+)|(?:'(?:[^']|'')*')|(?:y+|d+|h+|m+|s+))(.*)/;
var DURATION_FORMATS = {
y: { // years
// "longer" years are not supported
value: 365 * 24 * 60 * 60 * 1000,
},
yy: {
value: 'y',
pad: 2,
},
d: { // days
value: 24 * 60 * 60 * 1000,
},
dd: {
value: 'd',
pad: 2,
},
h: { // hours
value: 60 * 60 * 1000,
},
hh: { // padded hours
value: 'h',
pad: 2,
},
m: { // minutes
value: 60 * 1000,
},
mm: { // padded minutes
value: 'm',
pad: 2,
},
s: { // seconds
value: 1000,
},
ss: { // padded seconds
value: 's',
pad: 2,
},
sss: { // milliseconds
value: 1,
},
ssss: { // padded milliseconds
value: 'sss',
pad: 4,
},
y: {
// years
// "longer" years are not supported
value: 365 * 24 * 60 * 60 * 1000
},
yy: {
value: "y",
pad: 2
},
d: {
// days
value: 24 * 60 * 60 * 1000
},
dd: {
value: "d",
pad: 2
},
h: {
// hours
value: 60 * 60 * 1000
},
hh: {
// padded hours
value: "h",
pad: 2
},
m: {
// minutes
value: 60 * 1000
},
mm: {
// padded minutes
value: "m",
pad: 2
},
s: {
// seconds
value: 1000
},
ss: {
// padded seconds
value: "s",
pad: 2
},
sss: {
// milliseconds
value: 1
},
ssss: {
// padded milliseconds
value: "sss",
pad: 4
}
};
function _parseFormat(string) {
// @inspiration AngularJS date filter
var parts = [];
var format = string ? string.toString() : '';
// @inspiration AngularJS date filter
var parts = [];
var format = string ? string.toString() : "";
while (format) {
var match = DURATION_FORMATS_SPLIT.exec(format);
while (format) {
var match = DURATION_FORMATS_SPLIT.exec(format);
if (match) {
parts = parts.concat(match.slice(1));
if (match) {
parts = parts.concat(match.slice(1));
format = parts.pop();
} else {
parts.push(format);
format = parts.pop();
} else {
parts.push(format);
format = null;
format = null;
}
}
}
return parts;
return parts;
}
function _formatDuration(timestamp, format) {
var text = '';
var values = { };
format.filter(function(format) { // filter only value parts of format
return DURATION_FORMATS.hasOwnProperty(format);
}).map(function(format) { // get formats with values only
var config = DURATION_FORMATS[format];
if (config.hasOwnProperty('pad')) {
return config.value;
} else {
return format;
}
}).filter(function(format, index, arr) { // remove duplicates
return (arr.indexOf(format) === index);
}).map(function(format) { // get format configurations with values
return angular.extend({
name: format,
}, DURATION_FORMATS[format]);
}).sort(function(a, b) { // sort formats descending by value
return b.value - a.value;
}).forEach(function(format) { // create values for format parts
var value = values[format.name] = Math.floor(timestamp / format.value);
timestamp = timestamp - (value * format.value);
});
format.forEach(function(part) {
var format = DURATION_FORMATS[part];
if (format) {
var value = values[format.value];
text += (format.hasOwnProperty('pad') ? _padNumber(value, Math.max(format.pad, value.toString().length)) : values[part]);
} else {
text += part.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
}
});
return text;
var text = "";
var values = {};
format
.filter(function (format) {
// filter only value parts of format
return DURATION_FORMATS.hasOwnProperty(format);
})
.map(function (format) {
// get formats with values only
var config = DURATION_FORMATS[format];
if (config.hasOwnProperty("pad")) {
return config.value;
} else {
return format;
}
})
.filter(function (format, index, arr) {
// remove duplicates
return arr.indexOf(format) === index;
})
.map(function (format) {
// get format configurations with values
return angular.extend(
{
name: format
},
DURATION_FORMATS[format]
);
})
.sort(function (a, b) {
// sort formats descending by value
return b.value - a.value;
})
.forEach(function (format) {
// create values for format parts
var value = (values[format.name] = Math.floor(timestamp / format.value));
timestamp = timestamp - value * format.value;
});
format.forEach(function (part) {
var format = DURATION_FORMATS[part];
if (format) {
var value = values[format.value];
text += format.hasOwnProperty("pad")
? _padNumber(value, Math.max(format.pad, value.toString().length))
: values[part];
} else {
text += part.replace(/(^'|'$)/g, "").replace(/''/g, "'");
}
});
return text;
}
function _padNumber(number, len) {
return ((new Array(len + 1)).join('0') + number).slice(-len);
return (new Array(len + 1).join("0") + number).slice(-len);
}
return function(value, format) {
var parsedValue = parseFloat(value, 10);
var parsedFormat = _parseFormat(format);
return function (value, format) {
var parsedValue = parseFloat(value, 10);
var parsedFormat = _parseFormat(format);
if (isNaN(parsedValue) || (parsedFormat.length === 0)) {
return value;
} else {
return _formatDuration(parsedValue, parsedFormat);
}
if (isNaN(parsedValue) || parsedFormat.length === 0) {
return value;
} else {
return _formatDuration(parsedValue, parsedFormat);
}
};
});
});
// ### << filter.js
// ### main.js >>
angular
.module('angular-duration-format', [
'angular-duration-format.filter',
]);
angular.module("angular-duration-format", ["angular-duration-format.filter"]);
// ### << main.js

175
html/admin/partials/servers.html

@ -1,89 +1,98 @@
<div class="panel panel-default" data-ng-controller="serverController">
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Servers
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search">
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span class="glyphicon glyphicon-refresh" title="Refresh" aria-hidden="false" ng-click="updateView()"></span>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="panel-body">
<table class="table table-striped table-bordered">
<th width="3%">ID</th>
<th width="10%">Name</th>
<th width="10%">Address</th>
<th width="10%">Xfer (in/out)</th>
<th width="10%">Req/Resp</th>
<th width="5%">Duration</th>
<th width="5%">State</th>
<th width="5%">Idle</th>
<th width="1%"><center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center></th>
<tr ng-repeat="s in servers | filter:servers_search | orderBy:'server_id'">
<td>{{ s.server_id }}</td>
<td>{{ s.server_name }}</td>
<td>
{{ s.source_address }}
<div ng-hide="checkDetail(s.server_id)">
domains({{ s.domains.length}})
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.domain_name }}
</div>
</div>
</td>
<td>
{{ s.bytes_in | bytes }}/{{ s.bytes_out | bytes }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.bytes_in | bytes }}/{{ d.bytes_out | bytes }}
</div>
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Servers
</div>
</td>
<td>
{{ s.requests }}/{{ s.responses }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.requests }}/{{ d.responses }}
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search" />
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span
class="glyphicon glyphicon-refresh"
title="Refresh"
aria-hidden="false"
ng-click="updateView()"
></span>
</button>
</form>
</div>
</td>
<td>{{ s.duration | hfcduration }}</td>
<td>{{ s.server_state }}</td>
<td>{{ s.idle | hfcduration }}</td>
<td>
<span class="glyphicon glyphicon-zoom-in" title="Detail" aria-hidden="false" ng-click="triggerDetail(s.server_id)"></span>
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
<span class="glyphicon glyphicon-zoom-in" title="Detail" aria-hidden="false" ng-click="triggerDetail(s.server_id+d.domain_name)"></span>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="panel-body">
<table class="table table-striped table-bordered">
<th width="3%">ID</th>
<th width="10%">Name</th>
<th width="10%">Address</th>
<th width="10%">Xfer (in/out)</th>
<th width="10%">Req/Resp</th>
<th width="5%">Duration</th>
<th width="5%">State</th>
<th width="5%">Idle</th>
<th width="1%">
<center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center>
</th>
<tr ng-repeat="s in servers | filter:servers_search | orderBy:'server_id'">
<td>{{ s.server_id }}</td>
<td>{{ s.server_name }}</td>
<td>
{{ s.source_address }}
<div ng-hide="checkDetail(s.server_id)">
domains({{ s.domains.length}})
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.domain_name }}
</div>
</div>
</td>
<td>
{{ s.bytes_in | bytes }}/{{ s.bytes_out | bytes }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.bytes_in | bytes }}/{{ d.bytes_out | bytes }}
</div>
</div>
</td>
<td>
{{ s.requests }}/{{ s.responses }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.requests }}/{{ d.responses }}
</div>
</div>
</td>
</div>
</div>
<td>{{ s.duration | hfcduration }}</td>
<td>{{ s.server_state }}</td>
<td>{{ s.idle | hfcduration }}</td>
<td>
<span
class="glyphicon glyphicon-zoom-in"
title="Detail"
aria-hidden="false"
ng-click="triggerDetail(s.server_id)"
></span>
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
<span
class="glyphicon glyphicon-zoom-in"
title="Detail"
aria-hidden="false"
ng-click="triggerDetail(s.server_id+d.domain_name)"
></span>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>

64
html/admin/partials/status.html

@ -1,46 +1,52 @@
<div class="panel panel-default" data-ng-controller="statusController">
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Status
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Status
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search" />
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span
class="glyphicon glyphicon-refresh"
title="Refresh"
aria-hidden="false"
ng-click="updateView()"
></span>
</button>
</form>
</div>
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search">
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span class="glyphicon glyphicon-refresh" title="Refresh" aria-hidden="false" ng-click="updateView()"></span>
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4"> </div>
<div class="col-md-4"></div>
<div class="col-md-8">Server Name: {{ status.name }} (Uptime: {{ status.uptime | hfcduration }}</div>
</div>
<div class="row">
<div class="col-md-4"> </div>
<div class="col-md-8">Administrative Domain: {{ status.admin_domain }} </div>
<div class="col-md-4"></div>
<div class="col-md-8">Administrative Domain: {{ status.admin_domain }}</div>
</div>
<div class="row">
<div class="col-md-4"> </div>
<div class="col-md-8">Server Domain: {{ status.wss_domain }} </div>
<div class="col-md-4"></div>
<div class="col-md-8">Server Domain: {{ status.wss_domain }}</div>
</div>
<div class="row">
<div class="col-md-4"> </div>
<div class="col-md-8">Default LB Method: {{ status.loadbalance_default_method }} </div>
<div class="col-md-4"></div>
<div class="col-md-8">Default LB Method: {{ status.loadbalance_default_method }}</div>
</div>
<div class="row">
<div class="col-md-4"> </div>
<div class="col-md-8">Deadtime: dwell:{{ status.dead_time.dwell}} idle:{{ status.dead_time.idle}} cancel:{{ status.dead_time.cancel_check}}</div>
<div class="col-md-4"></div>
<div class="col-md-8">
Deadtime: dwell:{{ status.dead_time.dwell}} idle:{{ status.dead_time.idle}} cancel:{{
status.dead_time.cancel_check}}
</div>
</div>
</div>
</div>

14
rvpn-docker/README.md

@ -1,7 +1,7 @@
# Docker Deployment for RVPN
- install docker 1.13, or the latest stable CE release (Testing on MAC using 17.03.0-ce-mac1 (15583))
- validate installation
- install docker 1.13, or the latest stable CE release (Testing on MAC using 17.03.0-ce-mac1 (15583))
- validate installation
```bash
hcamacho@Hanks-MBP:rvpn-docker $ docker-compose --version
@ -10,7 +10,8 @@ docker-compose version 1.11.2, build dfed245
hcamacho@Hanks-MBP:rvpn-docker $ docker --version
Docker version 17.03.0-ce, build 60ccb22
```
- checkout code into gopath
- checkout code into gopath
```bash
cd $GOPATH/src/git.coolaj86.com/coolaj86
@ -23,7 +24,7 @@ go get
## Execute Container Deployment
- prep
- prep
```bash
cd rvpn-docker
@ -42,7 +43,7 @@ Successfully built 182aa9c814f2
```
- execute container
- execute container
```bash
hcamacho@Hanks-MBP:rvpn-docker $ docker-compose up
@ -87,6 +88,3 @@ rvpn_1 | INFO: genericlistener: 2017/03/04 18:13:02.270281 connection.go:242: W
```
The line "Connection Registration Accepted indicates a client WSS registered, was authenticated and registered its domains with the RVPN

Loading…
Cancel
Save