getting closer to accounts via api
This commit is contained in:
parent
58ed4baff1
commit
e4640a8a00
104
bin/telebitd.js
104
bin/telebitd.js
|
@ -7,6 +7,8 @@ var pkg = require('../package.json');
|
||||||
var url = require('url');
|
var url = require('url');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var os = require('os');
|
var os = require('os');
|
||||||
|
var fs = require('fs');
|
||||||
|
var urequest = require('@coolaj86/urequest');
|
||||||
var common = require('../lib/cli-common.js');
|
var common = require('../lib/cli-common.js');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var YAML = require('js-yaml');
|
var YAML = require('js-yaml');
|
||||||
|
@ -397,7 +399,6 @@ function serveControlsHelper() {
|
||||||
|
|
||||||
res.end('{"error":{"message":"unrecognized rpc"}}');
|
res.end('{"error":{"message":"unrecognized rpc"}}');
|
||||||
});
|
});
|
||||||
var fs = require('fs');
|
|
||||||
if (fs.existsSync(state._ipc.path)) {
|
if (fs.existsSync(state._ipc.path)) {
|
||||||
fs.unlinkSync(state._ipc.path);
|
fs.unlinkSync(state._ipc.path);
|
||||||
}
|
}
|
||||||
|
@ -494,15 +495,7 @@ function connectTunnel() {
|
||||||
controlServer.close();
|
controlServer.close();
|
||||||
}
|
}
|
||||||
// reverse 2FA otp
|
// reverse 2FA otp
|
||||||
function leftpad(i, n, c) {
|
|
||||||
while (i.toString().length < (n || 4)) {
|
|
||||||
i = (c || '0') + i;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
function getOtp() {
|
|
||||||
return leftpad(Math.round(Math.random() * 9999), 4, '0');
|
|
||||||
}
|
|
||||||
process.on('SIGINT', sigHandler);
|
process.on('SIGINT', sigHandler);
|
||||||
state.net = state.net || {
|
state.net = state.net || {
|
||||||
createConnection: function (info, cb) {
|
createConnection: function (info, cb) {
|
||||||
|
@ -515,7 +508,6 @@ function connectTunnel() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
state.otp = getOtp();
|
|
||||||
state.greenlockConf = state.config.greenlock || {};
|
state.greenlockConf = state.config.greenlock || {};
|
||||||
state.sortingHat = state.config.sortingHat || path.resolve(__dirname, '..', 'lib/sorting-hat.js');
|
state.sortingHat = state.config.sortingHat || path.resolve(__dirname, '..', 'lib/sorting-hat.js');
|
||||||
|
|
||||||
|
@ -653,39 +645,79 @@ function rawTunnel(cb) {
|
||||||
state.relayUrl = common.parseUrl(state.relay);
|
state.relayUrl = common.parseUrl(state.relay);
|
||||||
state.relayHostname = common.parseHostname(state.relay);
|
state.relayHostname = common.parseHostname(state.relay);
|
||||||
|
|
||||||
if (!state.config.token && state.config.secret) {
|
urequest({ url: state.relayUrl + common.apiDirectory, json: true }, function (err, resp, body) {
|
||||||
var jwt = require('jsonwebtoken');
|
state._apiDirectory = body;
|
||||||
var tokenData = {
|
state.wss = body.tunnel.method + '://' + body.api_host.replace(/:hostname/g, state.relayHostname) + body.tunnel.pathname;
|
||||||
domains: Object.keys(state.config.servernames || {}).filter(function (name) {
|
|
||||||
return /\./.test(name);
|
console.log('api dir:');
|
||||||
})
|
console.log(body);
|
||||||
, ports: Object.keys(state.config.ports || {}).filter(function (port) {
|
|
||||||
port = parseInt(port, 10);
|
console.log('state.wss:');
|
||||||
return port > 0 && port <= 65535;
|
console.log(state.wss);
|
||||||
})
|
|
||||||
, aud: aud
|
if (!state.config.token && state.config.secret) {
|
||||||
, iss: Math.round(Date.now() / 1000)
|
var jwt = require('jsonwebtoken');
|
||||||
|
var tokenData = {
|
||||||
|
domains: Object.keys(state.config.servernames || {}).filter(function (name) {
|
||||||
|
return /\./.test(name);
|
||||||
|
})
|
||||||
|
, ports: Object.keys(state.config.ports || {}).filter(function (port) {
|
||||||
|
port = parseInt(port, 10);
|
||||||
|
return port > 0 && port <= 65535;
|
||||||
|
})
|
||||||
|
, aud: state.relayUrl
|
||||||
|
, iss: Math.round(Date.now() / 1000)
|
||||||
|
};
|
||||||
|
|
||||||
|
state.token = jwt.sign(tokenData, state.config.secret);
|
||||||
|
}
|
||||||
|
state.token = state.token || state.config.token;
|
||||||
|
if (state.token) { cb(null, connectTunnel()); return; }
|
||||||
|
|
||||||
|
if (!state.config.email) {
|
||||||
|
cb(new Error("No email... how did that happen?"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO sign token with own private key, including public key and thumbprint
|
||||||
|
// (much like ACME JOSE account)
|
||||||
|
|
||||||
|
state.otp = common.otp();
|
||||||
|
state._auth = {
|
||||||
|
subject: state.config.email
|
||||||
|
, subject_scheme: 'mailto'
|
||||||
|
// TODO create domains list earlier
|
||||||
|
, scope: Object.keys(state.config.servernames || {}).join(',')
|
||||||
|
, otp: state.otp
|
||||||
|
, hostname: os.hostname()
|
||||||
|
// Used for User-Agent
|
||||||
|
, os_type: os.type()
|
||||||
|
, os_platform: os.platform()
|
||||||
|
, os_release: os.release()
|
||||||
|
, os_arch: os.arch()
|
||||||
};
|
};
|
||||||
|
|
||||||
state.token = jwt.sign(tokenData, state.config.secret);
|
if (err || !body || !body.pair_request) {
|
||||||
}
|
|
||||||
state.token = state.token || state.config.token;
|
|
||||||
|
|
||||||
common.urequest({ url: state.relayUrl + common.apiDirectory, json: true }, function (err, resp, body) {
|
|
||||||
state._apiDirectory = body;
|
|
||||||
state.wss = body.tunnel.method + '://' + body.api_host.replace(/:hostname/g, state.relayHostname) + body.tunnel.pathname
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
cb(null, connectTunnel());
|
cb(null, connectTunnel());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO sign token with own private key, including public key and thumbprint
|
|
||||||
// (much like ACME JOSE account)
|
|
||||||
|
|
||||||
// TODO do auth stuff
|
// TODO do auth stuff
|
||||||
|
var pairRequest = url.resolve('https://' + body.api_host.replace(/:hostname/g, state.relayHostname), body.pair_request.pathname);
|
||||||
|
var req = {
|
||||||
|
url: pairRequest
|
||||||
|
, method: body.pair_request.method
|
||||||
|
, json: state._auth
|
||||||
|
};
|
||||||
|
console.log('[telebitd.js] req');
|
||||||
|
console.log(req);
|
||||||
|
urequest(req, function (err, resp, body) {
|
||||||
|
if (err) { console.error('[telebitd.js] pair request', err); }
|
||||||
|
|
||||||
cb(null, connectTunnel());
|
console.log(body);
|
||||||
|
// TODO poll for token
|
||||||
|
//cb(null, connectTunnel());
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,30 @@ common.parseUrl = function (hostname) {
|
||||||
hostname = location.protocol.replace(/https?/, 'https') + '//' + hostname + location.pathname;
|
hostname = location.protocol.replace(/https?/, 'https') + '//' + hostname + location.pathname;
|
||||||
return hostname;
|
return hostname;
|
||||||
};
|
};
|
||||||
|
common.parseHostname = function (hostname) {
|
||||||
|
var url = require('url');
|
||||||
|
var location = url.parse(hostname);
|
||||||
|
if (!location.protocol || /\./.test(location.protocol)) {
|
||||||
|
hostname = 'https://' + hostname;
|
||||||
|
location = url.parse(hostname);
|
||||||
|
}
|
||||||
|
//hostname = location.hostname + (location.port ? ':' + location.port : '');
|
||||||
|
//hostname = location.protocol.replace(/https?/, 'https') + '//' + hostname + location.pathname;
|
||||||
|
return location.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
common.apiDirectory = '_apis/telebit.cloud/index.json';
|
common.apiDirectory = '_apis/telebit.cloud/index.json';
|
||||||
|
|
||||||
|
function leftpad(i, n, c) {
|
||||||
|
while (i.toString().length < (n || 4)) {
|
||||||
|
i = (c || '0') + i;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
common.otp = function getOtp() {
|
||||||
|
return leftpad(Math.round(Math.random() * 9999), 4, '0');
|
||||||
|
};
|
||||||
|
|
||||||
common.urequest = function (opts, cb) {
|
common.urequest = function (opts, cb) {
|
||||||
var https = require('https');
|
var https = require('https');
|
||||||
// request.js behavior:
|
// request.js behavior:
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var email = 'jon@example.com';
|
||||||
|
|
||||||
|
var urequest = require('@coolaj86/urequest');
|
||||||
|
var req = {
|
||||||
|
url: 'https://api.telebit.ppl.family/api/telebit.cloud/pair_request'
|
||||||
|
, method: 'POST'
|
||||||
|
, headers: { 'cOntEnt-tYpE': 'application/json;charset=utf-8' }
|
||||||
|
, json: {
|
||||||
|
subject: email
|
||||||
|
, subject_scheme: 'mailto'
|
||||||
|
, scope: ''
|
||||||
|
, otp: '321654'
|
||||||
|
, hostname: "Jon's Macbook Pro"
|
||||||
|
, os_type: 'Linux'
|
||||||
|
, os_platform: 'linux'
|
||||||
|
, os_release: '4.4.0-116-generic'
|
||||||
|
, os_arch: 'x64'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
urequest(req, function (err, resp, body) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Location:', resp.headers.location);
|
||||||
|
console.log('Body:');
|
||||||
|
console.log(body);
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var stateUrl = 'https://api.telebit.ppl.family/api/telebit.cloud/pair_state/bca27428719e9c67805359f1';
|
||||||
|
|
||||||
|
var urequest = require('@coolaj86/urequest');
|
||||||
|
var req = {
|
||||||
|
url: stateUrl
|
||||||
|
, method: 'GET'
|
||||||
|
, json: true
|
||||||
|
};
|
||||||
|
urequest(req, function (err, resp, body) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Done:');
|
||||||
|
console.log(body);
|
||||||
|
});
|
Loading…
Reference in New Issue