MAJOR: Updates for Authenticated Web UI and CLI #30
|
@ -27,6 +27,7 @@ var snakeCopy = recase.snakeCopy.bind(recase);
|
||||||
var TPLS = TOML.parse(fs.readFileSync(path.join(__dirname, "../lib/en-us.toml"), 'utf8'));
|
var TPLS = TOML.parse(fs.readFileSync(path.join(__dirname, "../lib/en-us.toml"), 'utf8'));
|
||||||
var startTime = Date.now();
|
var startTime = Date.now();
|
||||||
var connectTimes = [];
|
var connectTimes = [];
|
||||||
|
var isConnected = false;
|
||||||
|
|
||||||
var TelebitRemote = require('../lib/daemon/index.js').TelebitRemote;
|
var TelebitRemote = require('../lib/daemon/index.js').TelebitRemote;
|
||||||
|
|
||||||
|
@ -628,17 +629,17 @@ function handleApi(req, res) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
res.end(JSON.stringify(
|
res.end(JSON.stringify(
|
||||||
{ module: 'status'
|
{ module: 'status'
|
||||||
, port: (state.config.ipc && state.config.ipc.port || state._ipc.port || undefined)
|
|
||||||
, status: (state.config.disable ? 'disabled' : 'enabled')
|
|
||||||
, ready: ((state.config.relay && (state.config.token || state.config.agreeTos)) ? true : false)
|
|
||||||
, active: !!myRemote
|
|
||||||
, connected: 'maybe (todo)'
|
|
||||||
, version: pkg.version
|
, version: pkg.version
|
||||||
, servernames: state.servernames
|
, port: (state.config.ipc && state.config.ipc.port || state._ipc.port || undefined)
|
||||||
|
, enabled: !state.config.disable
|
||||||
|
, active: !!myRemote
|
||||||
|
, initialized: (state.config.relay && state.config.token && state.config.agreeTos) ? true : false
|
||||||
|
, connected: isConnected
|
||||||
, proctime: Math.round(process.uptime() * 1000)
|
, proctime: Math.round(process.uptime() * 1000)
|
||||||
, uptime: now - startTime
|
, uptime: now - startTime
|
||||||
, runtime: connectTimes.length && (now - connectTimes[0]) || 0
|
, runtime: isConnected && connectTimes.length && (now - connectTimes[0]) || 0
|
||||||
, reconnects: connectTimes.length
|
, reconnects: connectTimes.length
|
||||||
|
, servernames: state.servernames
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -707,7 +708,8 @@ function handleApi(req, res) {
|
||||||
res.end(JSON.stringify({"error":{"message":"unrecognized rpc"}}));
|
res.end(JSON.stringify({"error":{"message":"unrecognized rpc"}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!req.headers['content-length'] && !req.headers['content-type']) {
|
var hasLength = req.headers['content-length'] > 0;
|
||||||
|
if (!hasLength && !req.headers['content-type']) {
|
||||||
route();
|
route();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1042,6 +1044,7 @@ function rawStartTelebitRemote(keepAlive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onConnect() {
|
function onConnect() {
|
||||||
|
isConnected = true;
|
||||||
connectTimes.unshift(Date.now());
|
connectTimes.unshift(Date.now());
|
||||||
console.info('[connect] relay established');
|
console.info('[connect] relay established');
|
||||||
myRemote.removeListener('error', onConnectError);
|
myRemote.removeListener('error', onConnectError);
|
||||||
|
@ -1060,6 +1063,7 @@ function rawStartTelebitRemote(keepAlive) {
|
||||||
|
|
||||||
function onConnectError(err) {
|
function onConnectError(err) {
|
||||||
myRemote = null;
|
myRemote = null;
|
||||||
|
isConnected = false;
|
||||||
if (handleError(err, 'onConnectError')) {
|
if (handleError(err, 'onConnectError')) {
|
||||||
if (!keepAlive.state) {
|
if (!keepAlive.state) {
|
||||||
reject(err);
|
reject(err);
|
||||||
|
@ -1075,6 +1079,7 @@ function rawStartTelebitRemote(keepAlive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function retryLoop() {
|
function retryLoop() {
|
||||||
|
isConnected = false;
|
||||||
console.warn('[Warn] disconnected. Will retry?', keepAlive.state);
|
console.warn('[Warn] disconnected. Will retry?', keepAlive.state);
|
||||||
if (keepAlive.state) {
|
if (keepAlive.state) {
|
||||||
safeReload(10 * 1000).then(resolve).catch(reject);
|
safeReload(10 * 1000).then(resolve).catch(reject);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<script>document.body.hidden = true;</script>
|
<script>document.body.hidden = true;</script>
|
||||||
|
|
||||||
<div class="v-app">
|
<div class="v-app">
|
||||||
<h1>Telebit (Remote) Setup</h1>
|
<h1>Telebit (Remote) Setup v{{ config.version }}</h1>
|
||||||
|
|
||||||
<section v-if="views.flash.error">
|
<section v-if="views.flash.error">
|
||||||
{{ views.flash.error }}
|
{{ views.flash.error }}
|
||||||
|
@ -115,6 +115,19 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section v-if="views.section.status">
|
<section v-if="views.section.status">
|
||||||
|
<button v-if="!status.enabled" v-on:click="enable">Enable</button>
|
||||||
|
<button v-if="status.enabled" v-on:click="disable">Disable</button>
|
||||||
|
<br>
|
||||||
|
http://localhost:{{ status.port }}
|
||||||
|
<br>
|
||||||
|
Proctime: {{ statusProctime }}
|
||||||
|
<br>
|
||||||
|
Uptime: {{ statusUptime }}
|
||||||
|
<br>
|
||||||
|
Runtime: {{ statusRuntime }}
|
||||||
|
<br>
|
||||||
|
Reconnects: {{ status.reconnects }}
|
||||||
|
<br>
|
||||||
<pre><code>{{ status }}</code></pre>
|
<pre><code>{{ status }}</code></pre>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,26 @@ api.status = function apiStatus() {
|
||||||
return json;
|
return json;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
api.initialize = function apiInitialize() {
|
api.enable = function apiEnable() {
|
||||||
var opts = {
|
var opts = {
|
||||||
url: "/api/xxinitxx"
|
url: "/api/enable"
|
||||||
, method: "POST"
|
, method: "POST"
|
||||||
, headers: {
|
//, headers: { 'Content-Type': 'application/json' }
|
||||||
'Content-Type': 'application/json'
|
};
|
||||||
}
|
return Telebit.reqLocalAsync(opts).then(function (resp) {
|
||||||
, body: JSON.stringify(telebitState.config)
|
var json = resp.body;
|
||||||
|
appData.initResult = json;
|
||||||
|
window.alert("Error: [success] " + JSON.stringify(json, null, 2));
|
||||||
|
return json;
|
||||||
|
}).catch(function (err) {
|
||||||
|
window.alert("Error: [init] " + (err.message || JSON.stringify(err, null, 2)));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
api.disable = function apiDisable() {
|
||||||
|
var opts = {
|
||||||
|
url: "/api/disable"
|
||||||
|
, method: "POST"
|
||||||
|
//, headers: { 'Content-Type': 'application/json' }
|
||||||
};
|
};
|
||||||
return Telebit.reqLocalAsync(opts).then(function (resp) {
|
return Telebit.reqLocalAsync(opts).then(function (resp) {
|
||||||
var json = resp.body;
|
var json = resp.body;
|
||||||
|
@ -107,8 +119,8 @@ var TELEBIT_RELAYS = [
|
||||||
var PRODUCTION_ACME = 'https://acme-v02.api.letsencrypt.org/directory';
|
var PRODUCTION_ACME = 'https://acme-v02.api.letsencrypt.org/directory';
|
||||||
var STAGING_ACME = 'https://acme-staging-v02.api.letsencrypt.org/directory';
|
var STAGING_ACME = 'https://acme-staging-v02.api.letsencrypt.org/directory';
|
||||||
var appData = {
|
var appData = {
|
||||||
config: null
|
config: {}
|
||||||
, status: null
|
, status: {}
|
||||||
, init: {
|
, init: {
|
||||||
teletos: true
|
teletos: true
|
||||||
, letos: true
|
, letos: true
|
||||||
|
@ -181,11 +193,11 @@ var appMethods = {
|
||||||
, betaRelay: function () {
|
, betaRelay: function () {
|
||||||
appData.init.relay = BETA_RELAY;
|
appData.init.relay = BETA_RELAY;
|
||||||
}
|
}
|
||||||
, defaultRhubarb: function () {
|
, enable: function () {
|
||||||
appData.init.rhubarb = DEFAULT_RELAY;
|
api.enable();
|
||||||
}
|
}
|
||||||
, betaRhubarb: function () {
|
, disable: function () {
|
||||||
appData.init.rhubarb = BETA_RELAY;
|
api.disable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var appStates = {
|
var appStates = {
|
||||||
|
@ -200,9 +212,15 @@ var appStates = {
|
||||||
}
|
}
|
||||||
, status: function () {
|
, status: function () {
|
||||||
appData.views.section = { status: true };
|
appData.views.section = { status: true };
|
||||||
return api.status().then(function (status) {
|
var tok = setInterval(function () {
|
||||||
appData.status = status;
|
api.status().then(function (status) {
|
||||||
});
|
appData.status = status;
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
return function cancelState() {
|
||||||
|
clearInterval(tok);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,23 +234,72 @@ function changeState(newstate) {
|
||||||
}
|
}
|
||||||
location.hash = newhash;
|
location.hash = newhash;
|
||||||
}
|
}
|
||||||
|
/*globals Promise*/
|
||||||
window.addEventListener('hashchange', setState, false);
|
window.addEventListener('hashchange', setState, false);
|
||||||
function setState(/*ev*/) {
|
function setState(/*ev*/) {
|
||||||
//ev.oldURL
|
//ev.oldURL
|
||||||
//ev.newURL
|
//ev.newURL
|
||||||
|
if (appData.exit) {
|
||||||
|
appData.exit.then(function (exit) {
|
||||||
|
if ('function' === typeof appData.exit) {
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
var parts = location.hash.substr(1).replace(/^\//, '').replace(/\/$/, '').split('/');
|
var parts = location.hash.substr(1).replace(/^\//, '').replace(/\/$/, '').split('/');
|
||||||
var fn = appStates;
|
var fn = appStates;
|
||||||
parts.forEach(function (s) {
|
parts.forEach(function (s) {
|
||||||
console.log("state:", s);
|
console.log("state:", s);
|
||||||
fn = fn[s];
|
fn = fn[s];
|
||||||
});
|
});
|
||||||
fn();
|
appData.exit = Promise.resolve(fn());
|
||||||
//appMethods.states[newstate]();
|
//appMethods.states[newstate]();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function msToHumanReadable(ms) {
|
||||||
|
var uptime = ms;
|
||||||
|
var uptimed = uptime / 1000;
|
||||||
|
var minute = 60;
|
||||||
|
var hour = 60 * minute;
|
||||||
|
var day = 24 * hour;
|
||||||
|
var days = 0;
|
||||||
|
var times = [];
|
||||||
|
while (uptimed > day) {
|
||||||
|
uptimed -= day;
|
||||||
|
days += 1;
|
||||||
|
}
|
||||||
|
times.push(days + " days ");
|
||||||
|
var hours = 0;
|
||||||
|
while (uptimed > hour) {
|
||||||
|
uptimed -= hour;
|
||||||
|
hours += 1;
|
||||||
|
}
|
||||||
|
times.push(hours.toString().padStart(2, "0") + " h ");
|
||||||
|
var minutes = 0;
|
||||||
|
while (uptimed > minute) {
|
||||||
|
uptimed -= minute;
|
||||||
|
minutes += 1;
|
||||||
|
}
|
||||||
|
times.push(minutes.toString().padStart(2, "0") + " m ");
|
||||||
|
var seconds = Math.round(uptimed);
|
||||||
|
times.push(seconds.toString().padStart(2, "0") + " s ");
|
||||||
|
return times.join('');
|
||||||
|
}
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: ".v-app"
|
el: ".v-app"
|
||||||
, data: appData
|
, data: appData
|
||||||
|
, computed: {
|
||||||
|
statusProctime: function () {
|
||||||
|
return msToHumanReadable(this.status.proctime);
|
||||||
|
}
|
||||||
|
, statusRuntime: function () {
|
||||||
|
return msToHumanReadable(this.status.runtime);
|
||||||
|
}
|
||||||
|
, statusUptime: function () {
|
||||||
|
return msToHumanReadable(this.status.uptime);
|
||||||
|
}
|
||||||
|
}
|
||||||
, methods: appMethods
|
, methods: appMethods
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue