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 startTime = Date.now();
|
||||
var connectTimes = [];
|
||||
var isConnected = false;
|
||||
|
||||
var TelebitRemote = require('../lib/daemon/index.js').TelebitRemote;
|
||||
|
||||
|
@ -628,17 +629,17 @@ function handleApi(req, res) {
|
|||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify(
|
||||
{ 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
|
||||
, 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)
|
||||
, uptime: now - startTime
|
||||
, runtime: connectTimes.length && (now - connectTimes[0]) || 0
|
||||
, runtime: isConnected && connectTimes.length && (now - connectTimes[0]) || 0
|
||||
, reconnects: connectTimes.length
|
||||
, servernames: state.servernames
|
||||
}
|
||||
));
|
||||
}
|
||||
|
@ -707,7 +708,8 @@ function handleApi(req, res) {
|
|||
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();
|
||||
return;
|
||||
}
|
||||
|
@ -1042,6 +1044,7 @@ function rawStartTelebitRemote(keepAlive) {
|
|||
}
|
||||
|
||||
function onConnect() {
|
||||
isConnected = true;
|
||||
connectTimes.unshift(Date.now());
|
||||
console.info('[connect] relay established');
|
||||
myRemote.removeListener('error', onConnectError);
|
||||
|
@ -1060,6 +1063,7 @@ function rawStartTelebitRemote(keepAlive) {
|
|||
|
||||
function onConnectError(err) {
|
||||
myRemote = null;
|
||||
isConnected = false;
|
||||
if (handleError(err, 'onConnectError')) {
|
||||
if (!keepAlive.state) {
|
||||
reject(err);
|
||||
|
@ -1075,6 +1079,7 @@ function rawStartTelebitRemote(keepAlive) {
|
|||
}
|
||||
|
||||
function retryLoop() {
|
||||
isConnected = false;
|
||||
console.warn('[Warn] disconnected. Will retry?', keepAlive.state);
|
||||
if (keepAlive.state) {
|
||||
safeReload(10 * 1000).then(resolve).catch(reject);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<script>document.body.hidden = true;</script>
|
||||
|
||||
<div class="v-app">
|
||||
<h1>Telebit (Remote) Setup</h1>
|
||||
<h1>Telebit (Remote) Setup v{{ config.version }}</h1>
|
||||
|
||||
<section v-if="views.flash.error">
|
||||
{{ views.flash.error }}
|
||||
|
@ -115,6 +115,19 @@
|
|||
</section>
|
||||
|
||||
<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>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -37,14 +37,26 @@ api.status = function apiStatus() {
|
|||
return json;
|
||||
});
|
||||
};
|
||||
api.initialize = function apiInitialize() {
|
||||
api.enable = function apiEnable() {
|
||||
var opts = {
|
||||
url: "/api/xxinitxx"
|
||||
url: "/api/enable"
|
||||
, method: "POST"
|
||||
, headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
, body: JSON.stringify(telebitState.config)
|
||||
//, headers: { 'Content-Type': 'application/json' }
|
||||
};
|
||||
return Telebit.reqLocalAsync(opts).then(function (resp) {
|
||||
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) {
|
||||
var json = resp.body;
|
||||
|
@ -107,8 +119,8 @@ var TELEBIT_RELAYS = [
|
|||
var PRODUCTION_ACME = 'https://acme-v02.api.letsencrypt.org/directory';
|
||||
var STAGING_ACME = 'https://acme-staging-v02.api.letsencrypt.org/directory';
|
||||
var appData = {
|
||||
config: null
|
||||
, status: null
|
||||
config: {}
|
||||
, status: {}
|
||||
, init: {
|
||||
teletos: true
|
||||
, letos: true
|
||||
|
@ -181,11 +193,11 @@ var appMethods = {
|
|||
, betaRelay: function () {
|
||||
appData.init.relay = BETA_RELAY;
|
||||
}
|
||||
, defaultRhubarb: function () {
|
||||
appData.init.rhubarb = DEFAULT_RELAY;
|
||||
, enable: function () {
|
||||
api.enable();
|
||||
}
|
||||
, betaRhubarb: function () {
|
||||
appData.init.rhubarb = BETA_RELAY;
|
||||
, disable: function () {
|
||||
api.disable();
|
||||
}
|
||||
};
|
||||
var appStates = {
|
||||
|
@ -200,9 +212,15 @@ var appStates = {
|
|||
}
|
||||
, status: function () {
|
||||
appData.views.section = { status: true };
|
||||
return api.status().then(function (status) {
|
||||
appData.status = status;
|
||||
});
|
||||
var tok = setInterval(function () {
|
||||
api.status().then(function (status) {
|
||||
appData.status = status;
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
return function cancelState() {
|
||||
clearInterval(tok);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -216,23 +234,72 @@ function changeState(newstate) {
|
|||
}
|
||||
location.hash = newhash;
|
||||
}
|
||||
/*globals Promise*/
|
||||
window.addEventListener('hashchange', setState, false);
|
||||
function setState(/*ev*/) {
|
||||
//ev.oldURL
|
||||
//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 fn = appStates;
|
||||
parts.forEach(function (s) {
|
||||
console.log("state:", s);
|
||||
fn = fn[s];
|
||||
});
|
||||
fn();
|
||||
appData.exit = Promise.resolve(fn());
|
||||
//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({
|
||||
el: ".v-app"
|
||||
, 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
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue