Compare commits
No commits in common. "c5e78110288552d77adf5f7972d7dd531e02e8ef" and "075342920d3c4c400cf7d2d1c756a61ef3194c5f" have entirely different histories.
c5e7811028
...
075342920d
@ -386,7 +386,6 @@ function handleApi(req, res) {
|
|||||||
function getConfigOnly() {
|
function getConfigOnly() {
|
||||||
var resp = JSON.parse(JSON.stringify(state.config));
|
var resp = JSON.parse(JSON.stringify(state.config));
|
||||||
resp.version = pkg.version;
|
resp.version = pkg.version;
|
||||||
resp._otp = state.otp;
|
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
res.end(JSON.stringify(resp));
|
res.end(JSON.stringify(resp));
|
||||||
}
|
}
|
||||||
@ -417,8 +416,12 @@ function handleApi(req, res) {
|
|||||||
res.end('{"error":{"message":"module \'init\' needs more arguments"}}');
|
res.end('{"error":{"message":"module \'init\' needs more arguments"}}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!Array.isArray(opts.body)) {
|
||||||
if (Array.isArray(opts.body)) {
|
// TODO
|
||||||
|
res.statusCode = 500;
|
||||||
|
res.end('{"error":{"message":"[internal error (our fault)] module \'init\' expected an array"}}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
// relay, email, agree_tos, servernames, ports
|
// relay, email, agree_tos, servernames, ports
|
||||||
//
|
//
|
||||||
opts.body.forEach(function (opt) {
|
opts.body.forEach(function (opt) {
|
||||||
@ -434,46 +437,29 @@ function handleApi(req, res) {
|
|||||||
}
|
}
|
||||||
conf[parts[0]] = parts[1];
|
conf[parts[0]] = parts[1];
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
conf = opts.body;
|
|
||||||
}
|
|
||||||
|
|
||||||
conf = camelCopy(conf);
|
// TODO camelCase query
|
||||||
|
state.config.email = conf.email || state.config.email || '';
|
||||||
// TODO deep merge
|
if ('undefined' !== typeof conf.agreeTos
|
||||||
// greenlock config
|
|| 'undefined' !== typeof conf.agreeTos ) {
|
||||||
if (!state.config.greenlock) { state.config.greenlock = {}; }
|
state.config.agreeTos = conf.agreeTos || conf.agree_tos;
|
||||||
if (conf.greenlock) {
|
|
||||||
if ('undefined' !== typeof conf.greenlock.agree) {
|
|
||||||
state.config.greenlock.agree = conf.greenlock.agree;
|
|
||||||
}
|
}
|
||||||
if (conf.greenlock.server) { state.config.greenlock.server = conf.greenlock.server; }
|
state.otp = conf._otp; // this should only be done on the client side
|
||||||
if (conf.greenlock.version) { state.config.greenlock.version = conf.greenlock.version; }
|
state.config.relay = conf.relay || state.config.relay || '';
|
||||||
}
|
|
||||||
|
|
||||||
// main config
|
|
||||||
if (conf.email) { state.config.email = conf.email; }
|
|
||||||
if (conf.relay) { state.config.relay = conf.relay; }
|
|
||||||
if (conf.token) { state.config.token = conf.token; }
|
|
||||||
if (conf.secret) { state.config.secret = conf.secret; }
|
|
||||||
if ('undefined' !== typeof conf.agreeTos) {
|
|
||||||
state.config.agreeTos = conf.agreeTos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to state
|
|
||||||
if (conf.pretoken) { state.pretoken = conf.pretoken; }
|
|
||||||
if (conf._otp) {
|
|
||||||
state.otp = conf._otp; // TODO should this only be done on the client side?
|
|
||||||
delete conf._otp;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log();
|
console.log();
|
||||||
console.log('conf.token', typeof conf.token, conf.token);
|
console.log('conf.token', typeof conf.token, conf.token);
|
||||||
console.log('state.config.token', typeof state.config.token, state.config.token);
|
console.log('state.config.token', typeof state.config.token, state.config.token);
|
||||||
|
state.config.token = conf.token || state.config.token || null;
|
||||||
if (state.secret) { console.log('state.secret'); state.token = common.signToken(state); }
|
state.config.secret = conf.secret || state.config.secret || null;
|
||||||
if (!state.token) { console.log('!state.token'); state.token = conf._token; }
|
state.pretoken = conf.pretoken || state.config.pretoken || null;
|
||||||
|
if (state.secret) {
|
||||||
|
console.log('state.secret');
|
||||||
|
state.token = common.signToken(state);
|
||||||
|
}
|
||||||
|
if (!state.token) {
|
||||||
|
console.log('!state.token');
|
||||||
|
state.token = conf._token;
|
||||||
|
}
|
||||||
console.log();
|
console.log();
|
||||||
console.log('JSON.stringify(conf)');
|
console.log('JSON.stringify(conf)');
|
||||||
console.log(JSON.stringify(conf));
|
console.log(JSON.stringify(conf));
|
||||||
@ -644,10 +630,6 @@ function handleApi(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function route() {
|
function route() {
|
||||||
if (/\b(relay)\b/.test(opts.pathname)) {
|
|
||||||
controllers.relay(req, res, opts);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (/\b(config)\b/.test(opts.pathname) && /get/i.test(req.method)) {
|
if (/\b(config)\b/.test(opts.pathname) && /get/i.test(req.method)) {
|
||||||
getConfigOnly();
|
getConfigOnly();
|
||||||
return;
|
return;
|
||||||
@ -702,6 +684,10 @@ function handleApi(req, res) {
|
|||||||
listSuccess();
|
listSuccess();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (/relay/.test(opts.pathname)) {
|
||||||
|
controllers.relay(req, res, opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
res.end(JSON.stringify({"error":{"message":"unrecognized rpc"}}));
|
res.end(JSON.stringify({"error":{"message":"unrecognized rpc"}}));
|
||||||
|
@ -4,19 +4,9 @@
|
|||||||
<title>Telebit Setup</title>
|
<title>Telebit Setup</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>document.body.hidden = true;</script>
|
|
||||||
|
|
||||||
<div class="v-app">
|
<div class="v-app">
|
||||||
<h1>Telebit (Remote) Setup</h1>
|
<h1>Telebit (Remote) Setup</h1>
|
||||||
|
|
||||||
<section v-if="views.flash.error">
|
|
||||||
{{ views.flash.error }}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section v-if="views.section.loading">
|
|
||||||
Loading...
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section v-if="views.section.setup">
|
<section v-if="views.section.setup">
|
||||||
<h2>Create Account</h2>
|
<h2>Create Account</h2>
|
||||||
<form v-on:submit.stop.prevent="initialize">
|
<form v-on:submit.stop.prevent="initialize">
|
||||||
@ -110,14 +100,6 @@
|
|||||||
<pre><code>{{ init }}</code></pre>
|
<pre><code>{{ init }}</code></pre>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section v-if="views.section.otp">
|
|
||||||
<pre><code><h2>{{ init.otp }}</h2></code></pre>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section v-if="views.section.status">
|
|
||||||
<pre><code>{{ status }}</code></pre>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/vue.js"></script>
|
<script src="/js/vue.js"></script>
|
||||||
|
@ -34,17 +34,20 @@ api.config = function apiConfig() {
|
|||||||
api.status = function apiStatus() {
|
api.status = function apiStatus() {
|
||||||
return Telebit.reqLocalAsync({ url: "/api/status", method: "GET" }).then(function (resp) {
|
return Telebit.reqLocalAsync({ url: "/api/status", method: "GET" }).then(function (resp) {
|
||||||
var json = resp.body;
|
var json = resp.body;
|
||||||
|
appData.status = json;
|
||||||
return json;
|
return json;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
api.initialize = function apiInitialize() {
|
api.initialize = function apiInitialize() {
|
||||||
var opts = {
|
var opts = {
|
||||||
url: "/api/xxinitxx"
|
url: "/api/init"
|
||||||
, method: "POST"
|
, method: "POST"
|
||||||
, headers: {
|
, headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
, body: JSON.stringify(telebitState.config)
|
, body: JSON.stringify({
|
||||||
|
foo: 'bar'
|
||||||
|
})
|
||||||
};
|
};
|
||||||
return Telebit.reqLocalAsync(opts).then(function (resp) {
|
return Telebit.reqLocalAsync(opts).then(function (resp) {
|
||||||
var json = resp.body;
|
var json = resp.body;
|
||||||
@ -56,47 +59,6 @@ api.initialize = function apiInitialize() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function showOtp(otp, pollUrl) {
|
|
||||||
localStorage.setItem('poll_url', pollUrl);
|
|
||||||
telebitState.pollUrl = pollUrl;
|
|
||||||
appData.init.otp = otp;
|
|
||||||
changeState('otp');
|
|
||||||
}
|
|
||||||
function doConfigure() {
|
|
||||||
if (telebitState.dir.pair_request) {
|
|
||||||
telebitState._can_pair = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Read config from form
|
|
||||||
//
|
|
||||||
|
|
||||||
// Create Empty Config, If Necessary
|
|
||||||
if (!telebitState.config) { telebitState.config = {}; }
|
|
||||||
if (!telebitState.config.greenlock) { telebitState.config.greenlock = {}; }
|
|
||||||
|
|
||||||
// Populate Config
|
|
||||||
if (appData.init.teletos && appData.init.letos) { telebitState.config.agreeTos = true; }
|
|
||||||
if (appData.init.relay) { telebitState.config.relay = appData.init.relay; }
|
|
||||||
if (appData.init.email) { telebitState.config.email = appData.init.email; }
|
|
||||||
if ('undefined' !== typeof appData.init.letos) { telebitState.config.greenlock.agree = appData.init.letos; }
|
|
||||||
if ('newsletter' === appData.init.notifications) {
|
|
||||||
telebitState.config.newsletter = true; telebitState.config.communityMember = true;
|
|
||||||
}
|
|
||||||
if ('important' === appData.init.notifications) { telebitState.config.communityMember = true; }
|
|
||||||
if (appData.init.acmeVersion) { telebitState.config.greenlock.version = appData.init.acmeVersion; }
|
|
||||||
if (appData.init.acmeServer) { telebitState.config.greenlock.server = appData.init.acmeServer; }
|
|
||||||
|
|
||||||
// Temporary State
|
|
||||||
telebitState._otp = Telebit.otp();
|
|
||||||
appData.init.otp = telebitState._otp;
|
|
||||||
|
|
||||||
return Telebit.authorize(telebitState, showOtp).then(function () {
|
|
||||||
console.log('1 api.init...');
|
|
||||||
return api.initialize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO test for internet connectivity (and telebit connectivity)
|
// TODO test for internet connectivity (and telebit connectivity)
|
||||||
var DEFAULT_RELAY = 'telebit.cloud';
|
var DEFAULT_RELAY = 'telebit.cloud';
|
||||||
var BETA_RELAY = 'telebit.ppl.family';
|
var BETA_RELAY = 'telebit.ppl.family';
|
||||||
@ -121,15 +83,9 @@ var appData = {
|
|||||||
, tcp: null
|
, tcp: null
|
||||||
, ssh: null
|
, ssh: null
|
||||||
, views: {
|
, views: {
|
||||||
flash: {
|
section: {
|
||||||
error: ""
|
setup: false
|
||||||
}
|
|
||||||
, section: {
|
|
||||||
loading: true
|
|
||||||
, setup: false
|
|
||||||
, advanced: false
|
, advanced: false
|
||||||
, otp: false
|
|
||||||
, status: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -142,28 +98,34 @@ var appMethods = {
|
|||||||
}
|
}
|
||||||
appData.init.relay = appData.init.relay.toLowerCase();
|
appData.init.relay = appData.init.relay.toLowerCase();
|
||||||
telebitState = { relay: appData.init.relay };
|
telebitState = { relay: appData.init.relay };
|
||||||
|
|
||||||
return Telebit.api.directory(telebitState).then(function (dir) {
|
return Telebit.api.directory(telebitState).then(function (dir) {
|
||||||
if (!dir.api_host) {
|
if (!dir.api_host) {
|
||||||
window.alert("Error: '" + telebitState.relay + "' does not appear to be a valid telebit service");
|
window.alert("Error: '" + telebitState.relay + "' does not appear to be a valid telebit service");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
telebitState.dir = dir;
|
|
||||||
|
|
||||||
// If it's one of the well-known relays
|
|
||||||
if (-1 !== TELEBIT_RELAYS.indexOf(appData.init.relay)) {
|
if (-1 !== TELEBIT_RELAYS.indexOf(appData.init.relay)) {
|
||||||
return doConfigure();
|
if (!telebitState.config) { telebitState.config = {}; }
|
||||||
|
if (!telebitState.config.relay) { telebitState.config.relay = telebitState.relay; }
|
||||||
|
telebitState.config.email = appData.init.email;
|
||||||
|
telebitState.config._otp = Telebit.otp();
|
||||||
|
return Telebit.authorize(telebitState).then(function () {
|
||||||
|
console.log('1 api.init...');
|
||||||
|
return api.initialize();
|
||||||
|
}).catch(function (err) {
|
||||||
|
console.error(err);
|
||||||
|
window.alert("Error: [authorize] " + (err.message || JSON.stringify(err, null, 2)));
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
changeState('advanced');
|
changeState('advanced');
|
||||||
}
|
}
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
window.alert("Error: [initialize] " + (err.message || JSON.stringify(err, null, 2)));
|
window.alert("Error: [directory] " + (err.message || JSON.stringify(err, null, 2)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
, advance: function () {
|
, advance: function () {
|
||||||
return doConfigure();
|
console.log('2 api.init...');
|
||||||
|
return api.initialize();
|
||||||
}
|
}
|
||||||
, productionAcme: function () {
|
, productionAcme: function () {
|
||||||
console.log("prod acme:");
|
console.log("prod acme:");
|
||||||
@ -195,26 +157,10 @@ var appStates = {
|
|||||||
, advanced: function () {
|
, advanced: function () {
|
||||||
appData.views.section = { advanced: true };
|
appData.views.section = { advanced: true };
|
||||||
}
|
}
|
||||||
, otp: function () {
|
|
||||||
appData.views.section = { otp: true };
|
|
||||||
}
|
|
||||||
, status: function () {
|
|
||||||
appData.views.section = { status: true };
|
|
||||||
return api.status().then(function (status) {
|
|
||||||
appData.status = status;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function changeState(newstate) {
|
function changeState(newstate) {
|
||||||
var newhash = '#/' + newstate + '/';
|
location.hash = '#/' + newstate + '/';
|
||||||
if (location.hash === newhash) {
|
|
||||||
if (!telebitState.firstState) {
|
|
||||||
telebitState.firstState = true;
|
|
||||||
setState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
location.hash = newhash;
|
|
||||||
}
|
}
|
||||||
window.addEventListener('hashchange', setState, false);
|
window.addEventListener('hashchange', setState, false);
|
||||||
function setState(/*ev*/) {
|
function setState(/*ev*/) {
|
||||||
@ -237,52 +183,11 @@ new Vue({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
api.config().then(function (config) {
|
api.config();
|
||||||
telebitState.config = config;
|
api.status().then(function () {
|
||||||
if (config.greenlock) {
|
|
||||||
appData.init.acmeServer = config.greenlock.server;
|
|
||||||
}
|
|
||||||
if (config.relay) {
|
|
||||||
appData.init.relay = config.relay;
|
|
||||||
}
|
|
||||||
if (config.email) {
|
|
||||||
appData.init.email = config.email;
|
|
||||||
}
|
|
||||||
if (config.agreeTos) {
|
|
||||||
appData.init.letos = config.agreeTos;
|
|
||||||
appData.init.teletos = config.agreeTos;
|
|
||||||
}
|
|
||||||
if (config._otp) {
|
|
||||||
appData.init.otp = config._otp;
|
|
||||||
}
|
|
||||||
|
|
||||||
telebitState.pollUrl = config._pollUrl || localStorage.getItem('poll_url');
|
|
||||||
|
|
||||||
if ((!config.token && !config._otp) || !config.relay || !config.email || !config.agreeTos) {
|
|
||||||
changeState('setup');
|
changeState('setup');
|
||||||
setState();
|
setState();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!config.token && config._otp) {
|
|
||||||
changeState('otp');
|
|
||||||
setState();
|
|
||||||
// this will skip ahead as necessary
|
|
||||||
return Telebit.authorize(telebitState, showOtp).then(function () {
|
|
||||||
console.log('2 api.init...');
|
|
||||||
return api.initialize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO handle default state
|
|
||||||
changeState('status');
|
|
||||||
}).catch(function (err) {
|
|
||||||
appData.views.flash.error = err.message || JSON.stringify(err, null, 2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
window.api = api;
|
window.api = api;
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
document.body.hidden = false;
|
|
||||||
}, 50);
|
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
@ -11,14 +11,19 @@ if ('undefined' !== typeof Promise) {
|
|||||||
|
|
||||||
var common = exports.TELEBIT || require('./lib/common.js');
|
var common = exports.TELEBIT || require('./lib/common.js');
|
||||||
|
|
||||||
common.authorize = common.getToken = function getToken(state, showOtp) {
|
common.authorize = common.getToken = function getToken(state) {
|
||||||
state.relay = state.config.relay;
|
state.relay = state.config.relay;
|
||||||
|
|
||||||
// { _otp, config: {} }
|
// { _otp, config: {} }
|
||||||
return common.api.token(state, {
|
return common.api.token(state, {
|
||||||
error: function (err) { console.error("[Error] common.api.token handlers.error: \n", err); return PromiseA.reject(err); }
|
error: function (err) {
|
||||||
|
console.error("[Error] common.api.token handlers.error:");
|
||||||
|
console.error(err);
|
||||||
|
return PromiseA.reject(err);
|
||||||
|
}
|
||||||
, directory: function (dir) {
|
, directory: function (dir) {
|
||||||
/*console.log('[directory] Telebit Relay Discovered:', dir);*/
|
//console.log('[directory] Telebit Relay Discovered:');
|
||||||
|
//console.log(dir);
|
||||||
state._apiDirectory = dir;
|
state._apiDirectory = dir;
|
||||||
return PromiseA.resolve();
|
return PromiseA.resolve();
|
||||||
}
|
}
|
||||||
@ -27,13 +32,12 @@ common.authorize = common.getToken = function getToken(state, showOtp) {
|
|||||||
state.wss = tunnelUrl;
|
state.wss = tunnelUrl;
|
||||||
return PromiseA.resolve();
|
return PromiseA.resolve();
|
||||||
}
|
}
|
||||||
, requested: function (authReq, pollUrl) {
|
, requested: function (authReq) {
|
||||||
console.log("[requested] Pairing Requested");
|
console.log("[requested] Pairing Requested");
|
||||||
state._otp = state._otp = authReq.otp;
|
state.config._otp = state.config._otp = authReq.otp;
|
||||||
|
|
||||||
if (!state.config.token && state._can_pair) {
|
if (!state.config.token && state._can_pair) {
|
||||||
console.info("0000".replace(/0000/g, state._otp));
|
console.info("0000".replace(/0000/g, state.config._otp));
|
||||||
showOtp(authReq.otp, pollUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PromiseA.resolve();
|
return PromiseA.resolve();
|
||||||
@ -43,9 +47,7 @@ common.authorize = common.getToken = function getToken(state, showOtp) {
|
|||||||
state.config.pretoken = pretoken;
|
state.config.pretoken = pretoken;
|
||||||
state._connecting = true;
|
state._connecting = true;
|
||||||
|
|
||||||
// This will only be saved to the session
|
return common.reqLocalAsync({ url: '/api/config', method: 'POST', body: state.config }).then(function () {
|
||||||
state.config._otp = state._otp;
|
|
||||||
return common.reqLocalAsync({ url: '/api/config', method: 'POST', body: state.config, json: true }).then(function () {
|
|
||||||
console.info("waiting...");
|
console.info("waiting...");
|
||||||
return PromiseA.resolve();
|
return PromiseA.resolve();
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
@ -57,7 +59,6 @@ common.authorize = common.getToken = function getToken(state, showOtp) {
|
|||||||
}
|
}
|
||||||
, offer: function (token) {
|
, offer: function (token) {
|
||||||
//console.log("[offer] Pairing Enabled by Relay");
|
//console.log("[offer] Pairing Enabled by Relay");
|
||||||
state.token = token;
|
|
||||||
state.config.token = token;
|
state.config.token = token;
|
||||||
if (state._error) {
|
if (state._error) {
|
||||||
return;
|
return;
|
||||||
@ -76,7 +77,7 @@ common.authorize = common.getToken = function getToken(state, showOtp) {
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.warn("[warning] could not decode token");
|
console.warn("[warning] could not decode token");
|
||||||
}
|
}
|
||||||
return common.reqLocalAsync({ url: '/api/config', method: 'POST', body: state.config, json: true }).then(function () {
|
return common.reqLocalAsync({ url: '/api/config', method: 'POST', body: state.config }).then(function () {
|
||||||
//console.log("Pairing Enabled Locally");
|
//console.log("Pairing Enabled Locally");
|
||||||
return PromiseA.resolve();
|
return PromiseA.resolve();
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
@ -86,9 +87,12 @@ common.authorize = common.getToken = function getToken(state, showOtp) {
|
|||||||
return PromiseA.reject(err);
|
return PromiseA.reject(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
, granted: function (/*_*/) { /*console.log("[grant] Pairing complete!");*/ return PromiseA.resolve(); }
|
, granted: function (/*_*/) {
|
||||||
|
//console.log("[grant] Pairing complete!");
|
||||||
|
return PromiseA.resolve();
|
||||||
|
}
|
||||||
, end: function () {
|
, end: function () {
|
||||||
return common.reqLocalAsync({ url: '/api/enable', method: 'POST', body: [], json: true }).then(function () {
|
return common.reqLocalAsync({ url: '/api/enable', method: 'POST', body: [] }).then(function () {
|
||||||
console.info("Success");
|
console.info("Success");
|
||||||
|
|
||||||
// workaround for https://github.com/nodejs/node/issues/21319
|
// workaround for https://github.com/nodejs/node/issues/21319
|
||||||
@ -108,6 +112,9 @@ common.authorize = common.getToken = function getToken(state, showOtp) {
|
|||||||
// end workaround
|
// end workaround
|
||||||
|
|
||||||
//parseCli(state);
|
//parseCli(state);
|
||||||
|
}).catch(function (err) {
|
||||||
|
console.error('[end] [error]', err);
|
||||||
|
return PromiseA.reject(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -48,15 +48,11 @@ if ('undefined' !== typeof fetch) {
|
|||||||
if (!opts) { opts = {}; }
|
if (!opts) { opts = {}; }
|
||||||
if (opts.json && true !== opts.json) {
|
if (opts.json && true !== opts.json) {
|
||||||
opts.body = opts.json;
|
opts.body = opts.json;
|
||||||
opts.json = true;
|
|
||||||
}
|
}
|
||||||
if (opts.json) {
|
if (opts.json) {
|
||||||
if (!opts.headers) { opts.headers = {}; }
|
if (!opts.headers) { opts.headers = {}; }
|
||||||
if (opts.body) {
|
if (opts.body) {
|
||||||
opts.headers['Content-Type'] = 'application/json';
|
opts.headers['Content-Type'] = 'application/json';
|
||||||
if ('string' !== typeof opts.body) {
|
|
||||||
opts.body = JSON.stringify(opts.body);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
opts.headers.Accepts = 'application/json';
|
opts.headers.Accepts = 'application/json';
|
||||||
}
|
}
|
||||||
@ -130,16 +126,15 @@ common.signToken = function (state) {
|
|||||||
return jwt.sign(tokenData, state.config.secret);
|
return jwt.sign(tokenData, state.config.secret);
|
||||||
};
|
};
|
||||||
common.promiseTimeout = function (ms) {
|
common.promiseTimeout = function (ms) {
|
||||||
var tok;
|
var x = new PromiseA(function (resolve) {
|
||||||
var p = new PromiseA(function (resolve) {
|
x._tok = setTimeout(function () {
|
||||||
tok = setTimeout(function () {
|
|
||||||
resolve();
|
resolve();
|
||||||
}, ms);
|
}, ms);
|
||||||
});
|
});
|
||||||
p.cancel = function () {
|
x.cancel = function () {
|
||||||
clearTimeout(tok);
|
clearTimeout(x._tok);
|
||||||
};
|
};
|
||||||
return p;
|
return x;
|
||||||
};
|
};
|
||||||
common.api = {};
|
common.api = {};
|
||||||
common.api.directory = function (state) {
|
common.api.directory = function (state) {
|
||||||
@ -150,10 +145,15 @@ common.api.directory = function (state) {
|
|||||||
if (state._relays[state._relayUrl]) {
|
if (state._relays[state._relayUrl]) {
|
||||||
return PromiseA.resolve(state._relays[state._relayUrl]);
|
return PromiseA.resolve(state._relays[state._relayUrl]);
|
||||||
}
|
}
|
||||||
|
console.error('aaaaaaaaabsnthsnth');
|
||||||
return common.requestAsync({ url: state._relayUrl + common.apiDirectory, json: true }).then(function (resp) {
|
return common.requestAsync({ url: state._relayUrl + common.apiDirectory, json: true }).then(function (resp) {
|
||||||
|
console.error('123aaaaaaaaabsnthsnth');
|
||||||
var dir = resp.body;
|
var dir = resp.body;
|
||||||
state._relays[state._relayUrl] = dir;
|
state._relays[state._relayUrl] = dir;
|
||||||
return dir;
|
return dir;
|
||||||
|
}).catch(function (err) {
|
||||||
|
console.error('bsnthsnth');
|
||||||
|
return PromiseA.reject(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
common.api._parseWss = function (state, dir) {
|
common.api._parseWss = function (state, dir) {
|
||||||
@ -169,63 +169,15 @@ common.api.wss = function (state) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
common.api.token = function (state, handlers) {
|
common.api.token = function (state, handlers) {
|
||||||
|
|
||||||
var firstReady = true;
|
|
||||||
function pollStatus(req) {
|
|
||||||
if (common.debug) { console.log('[debug] pollStatus called'); }
|
|
||||||
if (common.debug) { console.log(req); }
|
|
||||||
return common.requestAsync(req).then(function checkLocation(resp) {
|
|
||||||
var body = resp.body;
|
|
||||||
if (common.debug) { console.log('[debug] checkLocation'); }
|
|
||||||
if (common.debug) { console.log(body); }
|
|
||||||
// pending, try again
|
|
||||||
if ('pending' === body.status && resp.headers.location) {
|
|
||||||
if (common.debug) { console.log('[debug] pending'); }
|
|
||||||
return common.promiseTimeout(2 * 1000).then(function () {
|
|
||||||
return pollStatus({ url: resp.headers.location, json: true });
|
|
||||||
});
|
|
||||||
} else if ('ready' === body.status) {
|
|
||||||
if (common.debug) { console.log('[debug] ready'); }
|
|
||||||
if (firstReady) {
|
|
||||||
if (common.debug) { console.log('[debug] first ready'); }
|
|
||||||
firstReady = false;
|
|
||||||
// falls through on purpose
|
|
||||||
PromiseA.resolve(handlers.offer(body.access_token)).then(function () {
|
|
||||||
/*ignore*/
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return common.promiseTimeout(2 * 1000).then(function () {
|
|
||||||
return pollStatus(req);
|
|
||||||
});
|
|
||||||
} else if ('complete' === body.status) {
|
|
||||||
if (common.debug) { console.log('[debug] complete'); }
|
|
||||||
return PromiseA.resolve(handlers.granted(null)).then(function () {
|
|
||||||
return PromiseA.resolve(handlers.end(null)).then(function () {});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (common.debug) { console.log('[debug] bad status'); }
|
|
||||||
var err = new Error("Bad State:" + body.status);
|
|
||||||
err._request = req;
|
|
||||||
return PromiseA.reject(err);
|
|
||||||
}
|
|
||||||
}).catch(function (err) {
|
|
||||||
if (common.debug) { console.log('[debug] pollStatus error'); }
|
|
||||||
err._request = req;
|
|
||||||
err._hint = '[telebitd.js] pair request';
|
|
||||||
return PromiseA.resolve(handlers.error(err)).then(function () {});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// directory, requested, connect, tunnelUrl, offer, granted, end
|
// directory, requested, connect, tunnelUrl, offer, granted, end
|
||||||
function requestAuth(dir) {
|
function afterDir(dir) {
|
||||||
if (common.debug) { console.log('[debug] after dir'); }
|
if (common.debug) { console.log('[debug] after dir'); }
|
||||||
state.wss = common.api._parseWss(state, dir);
|
state.wss = common.api._parseWss(state, dir);
|
||||||
|
|
||||||
return PromiseA.resolve(handlers.tunnelUrl(state.wss)).then(function () {
|
return PromiseA.resolve(handlers.tunnelUrl(state.wss)).then(function () {
|
||||||
if (common.debug) { console.log('[debug] after tunnelUrl'); }
|
if (common.debug) { console.log('[debug] after tunnelUrl'); }
|
||||||
if (state.config.secret /* && !state.config.token */) {
|
if (state.config.secret /* && !state.config.token */) {
|
||||||
// TODO make token here in the browser
|
state.config._token = common.signToken(state);
|
||||||
//state.config._token = common.signToken(state);
|
|
||||||
}
|
}
|
||||||
state.token = state.token || state.config.token || state.config._token;
|
state.token = state.token || state.config.token || state.config._token;
|
||||||
if (state.token) {
|
if (state.token) {
|
||||||
@ -238,13 +190,13 @@ common.api.token = function (state, handlers) {
|
|||||||
|
|
||||||
if (!dir.pair_request) {
|
if (!dir.pair_request) {
|
||||||
if (common.debug) { console.log('[debug] no dir, connect'); }
|
if (common.debug) { console.log('[debug] no dir, connect'); }
|
||||||
return PromiseA.resolve(handlers.error(new Error("No token found or generated, and no pair_request api found.")));
|
return PromiseA.resolve(handlers.error(err || new Error("No token found or generated, and no pair_request api found.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO sign token with own private key, including public key and thumbprint
|
// TODO sign token with own private key, including public key and thumbprint
|
||||||
// (much like ACME JOSE account)
|
// (much like ACME JOSE account)
|
||||||
// TODO handle agree
|
// TODO handle agree
|
||||||
var otp = state._otp; // common.otp();
|
var otp = state.config._otp; // common.otp();
|
||||||
var authReq = {
|
var authReq = {
|
||||||
subject: state.config.email
|
subject: state.config.email
|
||||||
, subject_scheme: 'mailto'
|
, subject_scheme: 'mailto'
|
||||||
@ -284,14 +236,59 @@ common.api.token = function (state, handlers) {
|
|||||||
, method: dir.pair_request.method
|
, method: dir.pair_request.method
|
||||||
, json: authReq
|
, json: authReq
|
||||||
};
|
};
|
||||||
|
var firstReq = true;
|
||||||
|
var firstReady = true;
|
||||||
|
|
||||||
return common.requestAsync(req).then(function doFirst(resp) {
|
function gotoNext(req) {
|
||||||
|
if (common.debug) { console.log('[debug] gotoNext called'); }
|
||||||
|
if (common.debug) { console.log(req); }
|
||||||
|
return common.requestAsync(req).then(function (resp) {
|
||||||
var body = resp.body;
|
var body = resp.body;
|
||||||
|
|
||||||
|
function checkLocation() {
|
||||||
|
if (common.debug) { console.log('[debug] checkLocation'); }
|
||||||
|
if (common.debug) { console.log(body); }
|
||||||
|
// pending, try again
|
||||||
|
if ('pending' === body.status && resp.headers.location) {
|
||||||
|
if (common.debug) { console.log('[debug] pending'); }
|
||||||
|
return common.promiseTimeout(2 * 1000).then(function () {
|
||||||
|
return gotoNext({ url: resp.headers.location, json: true });
|
||||||
|
});
|
||||||
|
} else if ('ready' === body.status) {
|
||||||
|
if (common.debug) { console.log('[debug] ready'); }
|
||||||
|
if (firstReady) {
|
||||||
|
if (common.debug) { console.log('[debug] first ready'); }
|
||||||
|
firstReady = false;
|
||||||
|
state.token = body.access_token;
|
||||||
|
state.config.token = state.token;
|
||||||
|
// falls through on purpose
|
||||||
|
PromiseA.resolve(handlers.offer(body.access_token)).then(function () {
|
||||||
|
/*ignore*/
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return common.promiseTimeout(2 * 1000).then(function () {
|
||||||
|
return gotoNext(req);
|
||||||
|
});
|
||||||
|
} else if ('complete' === body.status) {
|
||||||
|
if (common.debug) { console.log('[debug] complete'); }
|
||||||
|
return PromiseA.resolve(handlers.granted(null)).then(function () {
|
||||||
|
return PromiseA.resolve(handlers.end(null)).then(function () {});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (common.debug) { console.log('[debug] bad status'); }
|
||||||
|
var err = new Error("Bad State:" + body.status);
|
||||||
|
err._request = req;
|
||||||
|
return PromiseA.resolve(handlers.error(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstReq) {
|
||||||
if (common.debug) { console.log('[debug] first req'); }
|
if (common.debug) { console.log('[debug] first req'); }
|
||||||
if (!body.access_token && !body.jwt) {
|
if (!body.access_token && !body.jwt) {
|
||||||
return PromiseA.reject(new Error("something wrong with pre-authorization request"));
|
return PromiseA.reject(new Error("something wrong with pre-authorization request"));
|
||||||
}
|
}
|
||||||
return PromiseA.resolve(handlers.requested(authReq, resp.headers.location)).then(function () {
|
firstReq = false;
|
||||||
|
return PromiseA.resolve(handlers.requested(authReq)).then(function () {
|
||||||
return PromiseA.resolve(handlers.connect(body.access_token || body.jwt)).then(function () {
|
return PromiseA.resolve(handlers.connect(body.access_token || body.jwt)).then(function () {
|
||||||
var err;
|
var err;
|
||||||
if (!resp.headers.location) {
|
if (!resp.headers.location) {
|
||||||
@ -300,21 +297,25 @@ common.api.token = function (state, handlers) {
|
|||||||
return PromiseA.resolve(handlers.error(err)).then(function () {});
|
return PromiseA.resolve(handlers.error(err)).then(function () {});
|
||||||
}
|
}
|
||||||
return common.promiseTimeout(2 * 1000).then(function () {
|
return common.promiseTimeout(2 * 1000).then(function () {
|
||||||
return pollStatus({ url: resp.headers.location, json: true });
|
return gotoNext({ url: resp.headers.location, json: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (common.debug) { console.log('[debug] other req'); }
|
||||||
|
return checkLocation();
|
||||||
|
}
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
if (common.debug) { console.log('[debug] gotoFirst error'); }
|
if (common.debug) { console.log('[debug] gotoNext error'); }
|
||||||
err._request = req;
|
err._request = req;
|
||||||
err._hint = '[telebitd.js] pair request';
|
err._hint = '[telebitd.js] pair request';
|
||||||
return PromiseA.resolve(handlers.error(err)).then(function () {});
|
return PromiseA.resolve(handlers.error(err)).then(function () {});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.pollUrl) {
|
return gotoNext(req);
|
||||||
return pollStatus({ url: state.pollUrl, json: true });
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// backwards compat (TODO verify we can remove this)
|
// backwards compat (TODO verify we can remove this)
|
||||||
@ -330,9 +331,9 @@ common.api.token = function (state, handlers) {
|
|||||||
}).then(function (dir) {
|
}).then(function (dir) {
|
||||||
return PromiseA.resolve(handlers.directory(dir)).then(function () {
|
return PromiseA.resolve(handlers.directory(dir)).then(function () {
|
||||||
console.log('[debug] [directory]', dir);
|
console.log('[debug] [directory]', dir);
|
||||||
return requestAuth(dir);
|
return afterDir(dir);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
|
};
|
||||||
}('undefined' !== typeof module ? module.exports : window));
|
}('undefined' !== typeof module ? module.exports : window));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user