show many more things
This commit is contained in:
parent
783dd3c53b
commit
90f5eb11d5
|
@ -18,24 +18,18 @@
|
||||||
|
|
||||||
<div class="container" ng-controller="LoginController as vm" ng-init="vm.setSimple()">
|
<div class="container" ng-controller="LoginController as vm" ng-init="vm.setSimple()">
|
||||||
<h1 ng-if="!vm.authnUpdated">Initializing... {{vm.hello}}</h1>
|
<h1 ng-if="!vm.authnUpdated">Initializing... {{vm.hello}}</h1>
|
||||||
|
<div>
|
||||||
|
Configure Remote Server
|
||||||
|
<label>Configuration Address:</label>
|
||||||
|
<input type="text" placeholder="i.e. 192.168.1.100">
|
||||||
|
<label>Configuration Name:</label>
|
||||||
|
<input type="text" placeholder="i.e. localhost.daplie.invalid">
|
||||||
|
<label>Root Certificate Validation (optional):</label>
|
||||||
|
<textarea class="textarea" placeholder="paste the contents of a root.pem here"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div ng-if="!vm.authnUpdated">
|
<div ng-if="!vm.authnUpdated">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-link"
|
|
||||||
ng-if="!vm.advanced"
|
|
||||||
ng-click="vm.setAdvanced()"
|
|
||||||
>advanced</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-link"
|
|
||||||
ng-if="vm.advanced"
|
|
||||||
ng-click="vm.setSimple();"
|
|
||||||
>simple</button>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
ng-if="vm.advanced"
|
|
||||||
ng-change="vm.checkProviderUri(vm.myProviderUri)"
|
|
||||||
ng-model="vm.myProviderUri">
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
|
@ -43,48 +37,143 @@
|
||||||
ng-click="vm.authenticate()"
|
ng-click="vm.authenticate()"
|
||||||
>Login</button>
|
>Login</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-link"
|
||||||
|
ng-if="!vm.advanced"
|
||||||
|
ng-click="vm.setAdvanced()"
|
||||||
|
>advanced</button>
|
||||||
|
<div ng-if="vm.advanced">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-link"
|
||||||
|
ng-click="vm.setSimple();"
|
||||||
|
>simple</button>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
ng-change="vm.checkProviderUri(vm.myProviderUri)"
|
||||||
|
ng-model="vm.myProviderUri">
|
||||||
|
<br/>
|
||||||
|
<small>todo: allow per-device authorization</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div ng-if="vm.config">
|
<div ng-if="vm.config">
|
||||||
<div class="input-group" ng-init="siteconf = vm.config.global">
|
<div ng-init="siteconf = vm.config.global">
|
||||||
|
<h1>Server Device Name: <span ng-bind="vm.config.device.hostname"></span></h1>
|
||||||
|
<!-- input class="form-control" ng-model="vm.config.device.hostname" / -->
|
||||||
|
|
||||||
<h1>Server Working Directory:</h1>
|
<h1>Server Working Directory:</h1>
|
||||||
<input class="form-control" ng-model="vm.config.cwd" />
|
<input class="form-control" ng-model="vm.config.cwd" />
|
||||||
|
|
||||||
|
<h1>Addresses:</h1>
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th>Interface</th>
|
||||||
|
<th>Address</th>
|
||||||
|
<th>Family</th>
|
||||||
|
<th>Scope</th>
|
||||||
|
</tr>
|
||||||
|
<tr ng-repeat="addr in vm.config.addresses">
|
||||||
|
<td ng-bind="addr.iface"></td>
|
||||||
|
<td ng-bind="addr.address"></td>
|
||||||
|
<td ng-bind="addr.family"></td>
|
||||||
|
<td ng-bind="addr.range"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Managed Domains:</h1>
|
||||||
|
|
||||||
|
<div ng-if="!vm.domains.length">
|
||||||
|
You don't have any domains with this account.
|
||||||
|
<br/>
|
||||||
|
Try a different account?
|
||||||
|
<br/>
|
||||||
|
<input type="url" placeholder="https://daplie.domains">
|
||||||
|
<button type="button"
|
||||||
|
class="btn"
|
||||||
|
disabled
|
||||||
|
>Login</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="vm.domains.length">
|
||||||
|
<h2>Enable Tunnel</h2>
|
||||||
|
<input type="radio" ng-model="vm.config.tunnel.enabled" ng-value="true">
|
||||||
|
<input type="radio" ng-model="vm.config.tunnel.enabled" ng-value="false">
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th>Domain</th>
|
||||||
|
<th>Sub</th>
|
||||||
|
<th>Devices</th>
|
||||||
|
</tr>
|
||||||
|
<tr ng-repeat="d in vm.dns">
|
||||||
|
<td ng-bind="d.domain"></td>
|
||||||
|
<td ng-bind="d.name"></td>
|
||||||
|
<td>
|
||||||
|
<span ng-if="!d.domain">
|
||||||
|
<div ng-repeat="dev in d.devices">
|
||||||
|
<span ng-bind="dev"
|
||||||
|
></span> <button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-danger"
|
||||||
|
ng-click="vm.removeDevice(d, dev)"
|
||||||
|
>x</button>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h1>Global Settings:</h1>
|
<h1>Global Settings:</h1>
|
||||||
<br/>
|
<br/>
|
||||||
<div ng-repeat="path in siteconf.paths">Pathname:
|
<form class="form-inline">
|
||||||
<input class="form-control" ng-model="path.$id" />
|
<div ng-repeat="path in siteconf.paths">
|
||||||
<div ng-repeat="module in path.modules">Modulename: {{module.$id}}
|
<h2 ng-bind="path.$id"></h2>
|
||||||
<div ng-repeat="(key, value) in module">{{key}}:
|
<div ng-repeat="module in path.modules">
|
||||||
<input class="form-control" ng-model="value" />
|
<h3>{{module.$id}}</h3>
|
||||||
|
<div ng-repeat="(key, value) in module">
|
||||||
|
<label>{{key}}</label>: <input class="form-control" ng-model="module[key]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1>Per-Domain Settings:</h1>
|
<h1>Per-Domain Settings:</h1>
|
||||||
<div class="input-group" ng-repeat="siteconf in vm.config.sites">
|
<div ng-repeat="siteconf in vm.config.sites">
|
||||||
<label>Hostname:</label> <input class="form-control" ng-model="siteconf.$id" />
|
<h2 ng-bind="siteconf.$id"></h2>
|
||||||
<br/>
|
<div ng-repeat="path in siteconf.paths">
|
||||||
<div ng-repeat="path in siteconf.paths">Pathname:
|
<h2 ng-bind="path.$id"></h2>
|
||||||
<input class="form-control" ng-model="path.$id" />
|
<div ng-repeat="module in path.modules">
|
||||||
<div ng-repeat="module in path.modules">Modulename: {{module.$id}}
|
<h3>{{module.$id}}</h3>
|
||||||
<div ng-repeat="(key, value) in module">{{key}}:
|
<div ng-repeat="(key, value) in module">
|
||||||
<input class="form-control" ng-model="value" />
|
<label>{{key}}</label>: <input class="form-control" ng-model="module[key]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group" ng-init="defaultsconf = vm.config.defaults">
|
<div ng-init="defaultsconf = vm.config.defaults">
|
||||||
<h1>Fallback Settings:</h1>
|
<h1>Fallback Settings:</h1>
|
||||||
<br/>
|
<br/>
|
||||||
<div ng-repeat="path in defaultsconf.paths">Pathname:
|
<div ng-repeat="path in siteconf.paths">
|
||||||
<input class="form-control" ng-model="path.$id" />
|
<h2 ng-bind="path.$id"></h2>
|
||||||
<div ng-repeat="module in path.modules">Modulename: {{module.$id}}
|
<div ng-repeat="module in path.modules">
|
||||||
<div ng-repeat="(key, value) in module">{{key}}:
|
<h3>{{module.$id}}</h3>
|
||||||
<input class="form-control" ng-model="value" />
|
<div ng-repeat="(key, value) in module">
|
||||||
|
<label>{{key}}</label>: <input class="form-control" ng-model="module[key]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -104,6 +193,7 @@
|
||||||
<script src="/assets/org.oauth3/oauth3.core.js"></script>
|
<script src="/assets/org.oauth3/oauth3.core.js"></script>
|
||||||
<script src="/assets/org.oauth3/oauth3.ng.js"></script>
|
<script src="/assets/org.oauth3/oauth3.ng.js"></script>
|
||||||
<script src="/assets/org.oauth3/oauth3.domains.js"></script>
|
<script src="/assets/org.oauth3/oauth3.domains.js"></script>
|
||||||
|
<script src="/assets/org.oauth3/oauth3.dns.js"></script>
|
||||||
<script src="/js/app.js"></script>
|
<script src="/js/app.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,6 +38,91 @@ angular.module('com.daplie.cloud', [ 'org.oauth3' ])
|
||||||
}, 250);
|
}, 250);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.sortDnsRecords = function (a, b) {
|
||||||
|
if (a.sld !== b.sld) {
|
||||||
|
return a.sld > b.sld ? 1 : -1;
|
||||||
|
}
|
||||||
|
if (a.tld !== b.tld) {
|
||||||
|
return a.tld > b.tld ? 1 : -1;
|
||||||
|
}
|
||||||
|
// TODO normalize
|
||||||
|
a.sub = a.sub || '';
|
||||||
|
b.sub = b.sub || '';
|
||||||
|
if (a.sub !== b.sub) {
|
||||||
|
if (!a.sub) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!b.sub) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return a.sub > b.sub ? 1 : -1;
|
||||||
|
}
|
||||||
|
if (a.domain !== b.domain) {
|
||||||
|
if (!a.domain) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!b.domain) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.viewDomains = function (config, domains, dns) {
|
||||||
|
vm.dns = dns.slice(0);
|
||||||
|
vm.domains = domains.slice(0);
|
||||||
|
vm.dns = vm.dns.filter(function (record) {
|
||||||
|
if (-1 === [ 'A', 'AAAA', 'ANAME' ].indexOf(record.type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (record.device !== config.device.hostname) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
vm.dns.forEach(function (r) {
|
||||||
|
vm.domains.forEach(function (d) {
|
||||||
|
if (r.zone === d.domain) {
|
||||||
|
r.sub = r.name.substr(0, r.name.length - (d.domain.length + 1));
|
||||||
|
r.tld = d.tld;
|
||||||
|
r.sld = d.sld;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
vm.dns = vm.dns.concat(vm.domains);
|
||||||
|
vm.dns.sort(vm.sortDnsRecords);
|
||||||
|
vm.dns.forEach(function (r) {
|
||||||
|
if (r.domain) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r.devices = r.devices || [ r.device ];
|
||||||
|
|
||||||
|
dns.forEach(function (r2) {
|
||||||
|
if (r.name !== r2.name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (-1 !== r.devices.indexOf(r2.device)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r.devices.push(r2.device);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
console.log('vm.dns');
|
||||||
|
console.log(vm.dns);
|
||||||
|
/*
|
||||||
|
vm.domains.forEach(function (d) {
|
||||||
|
d.devices = [];
|
||||||
|
dns.forEach(function (r) {
|
||||||
|
// 0 === r.name.split('').reverse().join('').indexOf(d.domain.split('').reverse().join(''))
|
||||||
|
if (r.zone === d.domain) {
|
||||||
|
d.devices.push({
|
||||||
|
name: r.device
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
vm.authenticate = function () {
|
vm.authenticate = function () {
|
||||||
// TODO authorization redirect /api/org.oauth3.consumer/authorization_redirect/:provider_uri
|
// TODO authorization redirect /api/org.oauth3.consumer/authorization_redirect/:provider_uri
|
||||||
|
|
||||||
|
@ -46,44 +131,50 @@ angular.module('com.daplie.cloud', [ 'org.oauth3' ])
|
||||||
|
|
||||||
return oauth3.api('domains.list').then(function (domains) {
|
return oauth3.api('domains.list').then(function (domains) {
|
||||||
console.info("domains owned", domains);
|
console.info("domains owned", domains);
|
||||||
vm.domains = domains;
|
|
||||||
|
|
||||||
return OAUTH3.request({
|
return oauth3.api('dns.list').then(function (dns) {
|
||||||
method: 'POST'
|
console.info("dns records", dns);
|
||||||
, url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/init'
|
|
||||||
, session: session
|
|
||||||
, data: {
|
|
||||||
access_token: session.access_token
|
|
||||||
, refresh_token: session.refresh_token
|
|
||||||
, expires_in: session.expires_in
|
|
||||||
, scope: session.scope
|
|
||||||
, provider_uri: OAUTH3.uri.normalize(session.provider_uri)
|
|
||||||
, client_uri: vm.clientUri
|
|
||||||
, domains: domains.map(function (d) {
|
|
||||||
return {
|
|
||||||
id: d.id
|
|
||||||
, sub: d.sub
|
|
||||||
, sld: d.sld
|
|
||||||
, tld: d.tld
|
|
||||||
};
|
|
||||||
})
|
|
||||||
, jwk: null // TODO publish public key
|
|
||||||
}
|
|
||||||
}).then(function (resp) {
|
|
||||||
// TODO resp should contain a token
|
|
||||||
console.info('Initialized Goldilocks', resp);
|
|
||||||
return OAUTH3.request({
|
return OAUTH3.request({
|
||||||
method: 'GET'
|
method: 'POST'
|
||||||
, url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/config'
|
, url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/init'
|
||||||
, session: session
|
, session: session
|
||||||
}).then(function (configResp) {
|
, data: {
|
||||||
console.log('config', configResp.data);
|
access_token: session.access_token
|
||||||
vm.config = configResp.data;
|
, refresh_token: session.refresh_token
|
||||||
return resp;
|
, expires_in: session.expires_in
|
||||||
|
, scope: session.scope
|
||||||
|
, provider_uri: OAUTH3.uri.normalize(session.provider_uri)
|
||||||
|
, client_uri: vm.clientUri
|
||||||
|
, domains: domains.map(function (d) {
|
||||||
|
return {
|
||||||
|
id: d.id
|
||||||
|
, sub: d.sub
|
||||||
|
, sld: d.sld
|
||||||
|
, tld: d.tld
|
||||||
|
};
|
||||||
|
})
|
||||||
|
, jwk: null // TODO publish public key
|
||||||
|
}
|
||||||
|
}).then(function (resp) {
|
||||||
|
// TODO resp should contain a token
|
||||||
|
console.info('Initialized Goldilocks', resp);
|
||||||
|
return OAUTH3.request({
|
||||||
|
method: 'GET'
|
||||||
|
, url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/config'
|
||||||
|
, session: session
|
||||||
|
}).then(function (configResp) {
|
||||||
|
console.log('config', configResp.data);
|
||||||
|
vm.config = configResp.data;
|
||||||
|
//vm.config.ifaces
|
||||||
|
//vm.config.addresses = [];
|
||||||
|
vm.viewDomains(vm.config, domains, dns);
|
||||||
|
return resp;
|
||||||
|
});
|
||||||
|
}, function (err) {
|
||||||
|
console.error(err);
|
||||||
|
window.alert("Initialization failed:" + err.message);
|
||||||
});
|
});
|
||||||
}, function (err) {
|
|
||||||
console.error(err);
|
|
||||||
window.alert("Initialization failed:" + err.message);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
|
|
|
@ -92,152 +92,191 @@ function createServer(port, _delete_me_, content, opts) {
|
||||||
|
|
||||||
return new PromiseA(function (realResolve) {
|
return new PromiseA(function (realResolve) {
|
||||||
var app = require('../lib/app.js');
|
var app = require('../lib/app.js');
|
||||||
|
var ipaddr = require('ipaddr.js');
|
||||||
|
var addresses = [];
|
||||||
|
|
||||||
var directive = {
|
Object.keys(opts.ifaces).forEach(function (ifacename) {
|
||||||
global: opts.global
|
var iface = opts.ifaces[ifacename];
|
||||||
, sites: opts.sites
|
iface.ipv4.forEach(function (ip) {
|
||||||
, defaults: opts.defaults
|
addresses.push(ip);
|
||||||
, cwd: process.cwd()
|
});
|
||||||
};
|
iface.ipv6.forEach(function (ip) {
|
||||||
var server;
|
addresses.push(ip);
|
||||||
var insecureServer;
|
|
||||||
|
|
||||||
function resolve() {
|
|
||||||
realResolve({
|
|
||||||
plainServer: insecureServer
|
|
||||||
, server: server
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// returns an instance of node-letsencrypt with additional helper methods
|
|
||||||
var webrootPath = require('os').tmpdir();
|
|
||||||
var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath });
|
|
||||||
//var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath });
|
|
||||||
var leChallengeDdns = require('le-challenge-ddns').create({ ttl: 1 });
|
|
||||||
var lex = require('greenlock-express').create({
|
|
||||||
// set to https://acme-v01.api.letsencrypt.org/directory in production
|
|
||||||
server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory'
|
|
||||||
|
|
||||||
// If you wish to replace the default plugins, you may do so here
|
|
||||||
//
|
|
||||||
, challenges: {
|
|
||||||
'http-01': leChallengeFs
|
|
||||||
, 'tls-sni-01': leChallengeFs // leChallengeSni
|
|
||||||
, 'dns-01': leChallengeDdns
|
|
||||||
}
|
|
||||||
, challengeType: (opts.tunnel ? 'http-01' : 'dns-01')
|
|
||||||
, store: require('le-store-certbot').create({
|
|
||||||
webrootPath: webrootPath
|
|
||||||
, configDir: path.join((opts.homedir || '~'), 'letsencrypt', 'etc')
|
|
||||||
, homedir: opts.homedir
|
|
||||||
})
|
|
||||||
, webrootPath: webrootPath
|
|
||||||
|
|
||||||
// You probably wouldn't need to replace the default sni handler
|
|
||||||
// See https://git.daplie.com/Daplie/le-sni-auto if you think you do
|
|
||||||
//, sni: require('le-sni-auto').create({})
|
|
||||||
|
|
||||||
, approveDomains: approveDomains
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var secureContexts = {
|
addresses.sort(function (a, b) {
|
||||||
'localhost.daplie.me': null
|
if (a.family !== b.family) {
|
||||||
};
|
return 'IPv4' === a.family ? 1 : -1;
|
||||||
opts.httpsOptions.SNICallback = function (sni, cb ) {
|
|
||||||
var tlsOptions;
|
|
||||||
console.log('[https] sni', sni);
|
|
||||||
|
|
||||||
// Static Certs
|
|
||||||
if (/.*localhost.*\.daplie\.me/.test(sni.toLowerCase())) {
|
|
||||||
// TODO implement
|
|
||||||
if (!secureContexts[sni]) {
|
|
||||||
tlsOptions = require('localhost.daplie.me-certificates').mergeTlsOptions(sni, {});
|
|
||||||
}
|
|
||||||
if (tlsOptions) {
|
|
||||||
secureContexts[sni] = tls.createSecureContext(tlsOptions);
|
|
||||||
}
|
|
||||||
cb(null, secureContexts[sni]);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic Certs
|
return a.address > b.address ? 1 : -1;
|
||||||
lex.httpsOptions.SNICallback(sni, cb);
|
|
||||||
};
|
|
||||||
server = https.createServer(opts.httpsOptions);
|
|
||||||
|
|
||||||
server.on('error', function (err) {
|
|
||||||
if (opts.errorPort || opts.manualPort) {
|
|
||||||
showError(err, port);
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.errorPort = err.toString();
|
|
||||||
|
|
||||||
return createServer(portFallback, null, content, opts).then(resolve);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen(port, function () {
|
addresses.forEach(function (addr) {
|
||||||
opts.port = port;
|
addr.range = ipaddr.parse(addr.address).range();
|
||||||
opts.redirectOptions.port = port;
|
});
|
||||||
|
|
||||||
if (opts.livereload) {
|
var Oauth3 = require('oauth3-cli');
|
||||||
opts.lrPort = opts.lrPort || lrPort;
|
var oauth3 = Oauth3.create({ device: { hostname: opts.device } });
|
||||||
var livereload = require('livereload');
|
return Oauth3.Devices.one(oauth3).then(function (device) {
|
||||||
var server2 = livereload.createServer({
|
return Oauth3.Devices.all(oauth3).then(function (devices) {
|
||||||
https: opts.httpsOptions
|
return { devices: devices, device: device.device || device };
|
||||||
, port: opts.lrPort
|
});
|
||||||
, exclusions: [ 'node_modules' ]
|
}).then(function (devices) {
|
||||||
|
devices.device.secret = undefined;
|
||||||
|
console.log('devices');
|
||||||
|
console.log(devices);
|
||||||
|
var directive = {
|
||||||
|
global: opts.global
|
||||||
|
, sites: opts.sites
|
||||||
|
, defaults: opts.defaults
|
||||||
|
, cwd: process.cwd()
|
||||||
|
, ifaces: opts.ifaces
|
||||||
|
, addresses: addresses
|
||||||
|
, devices: devices.devices
|
||||||
|
, device: devices.device
|
||||||
|
};
|
||||||
|
var server;
|
||||||
|
var insecureServer;
|
||||||
|
|
||||||
|
function resolve() {
|
||||||
|
realResolve({
|
||||||
|
plainServer: insecureServer
|
||||||
|
, server: server
|
||||||
});
|
});
|
||||||
|
|
||||||
console.info("[livereload] watching " + opts.pubdir);
|
|
||||||
console.warn("WARNING: If CPU usage spikes to 100% it's because too many files are being watched");
|
|
||||||
// TODO create map of directories to watch from opts.sites and iterate over it
|
|
||||||
server2.watch(opts.pubdir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we haven't disabled insecure port
|
// returns an instance of node-letsencrypt with additional helper methods
|
||||||
if ('false' !== opts.insecurePort) {
|
var webrootPath = require('os').tmpdir();
|
||||||
// and both ports are the default
|
var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath });
|
||||||
if ((httpsPort === opts.port && httpPort === opts.insecurePort)
|
//var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath });
|
||||||
// or other case
|
var leChallengeDdns = require('le-challenge-ddns').create({ ttl: 1 });
|
||||||
|| (httpPort !== opts.insecurePort && opts.port !== opts.insecurePort)
|
var lex = require('greenlock-express').create({
|
||||||
) {
|
// set to https://acme-v01.api.letsencrypt.org/directory in production
|
||||||
return createInsecureServer(opts.insecurePort, null, opts).then(function (_server) {
|
server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory'
|
||||||
insecureServer = _server;
|
|
||||||
resolve();
|
// If you wish to replace the default plugins, you may do so here
|
||||||
});
|
//
|
||||||
|
, challenges: {
|
||||||
|
'http-01': leChallengeFs
|
||||||
|
, 'tls-sni-01': leChallengeFs // leChallengeSni
|
||||||
|
, 'dns-01': leChallengeDdns
|
||||||
}
|
}
|
||||||
}
|
, challengeType: (opts.tunnel ? 'http-01' : 'dns-01')
|
||||||
|
, store: require('le-store-certbot').create({
|
||||||
|
webrootPath: webrootPath
|
||||||
|
, configDir: path.join((opts.homedir || '~'), 'letsencrypt', 'etc')
|
||||||
|
, homedir: opts.homedir
|
||||||
|
})
|
||||||
|
, webrootPath: webrootPath
|
||||||
|
|
||||||
opts.insecurePort = opts.port;
|
// You probably wouldn't need to replace the default sni handler
|
||||||
resolve();
|
// See https://git.daplie.com/Daplie/le-sni-auto if you think you do
|
||||||
return;
|
//, sni: require('le-sni-auto').create({})
|
||||||
});
|
|
||||||
|
|
||||||
if ('function' === typeof app) {
|
, approveDomains: approveDomains
|
||||||
app = app(directive);
|
});
|
||||||
} else if ('function' === typeof app.create) {
|
|
||||||
app = app.create(directive);
|
|
||||||
}
|
|
||||||
|
|
||||||
server.on('request', function (req, res) {
|
var secureContexts = {
|
||||||
console.log('[' + req.method + '] ' + req.url);
|
'localhost.daplie.me': null
|
||||||
if (!req.socket.encrypted && !/\/\.well-known\/acme-challenge\//.test(req.url)) {
|
};
|
||||||
opts.redirectApp(req, res);
|
opts.httpsOptions.SNICallback = function (sni, cb ) {
|
||||||
|
var tlsOptions;
|
||||||
|
console.log('[https] sni', sni);
|
||||||
|
|
||||||
|
// Static Certs
|
||||||
|
if (/.*localhost.*\.daplie\.me/.test(sni.toLowerCase())) {
|
||||||
|
// TODO implement
|
||||||
|
if (!secureContexts[sni]) {
|
||||||
|
tlsOptions = require('localhost.daplie.me-certificates').mergeTlsOptions(sni, {});
|
||||||
|
}
|
||||||
|
if (tlsOptions) {
|
||||||
|
secureContexts[sni] = tls.createSecureContext(tlsOptions);
|
||||||
|
}
|
||||||
|
cb(null, secureContexts[sni]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic Certs
|
||||||
|
lex.httpsOptions.SNICallback(sni, cb);
|
||||||
|
};
|
||||||
|
server = https.createServer(opts.httpsOptions);
|
||||||
|
|
||||||
|
server.on('error', function (err) {
|
||||||
|
if (opts.errorPort || opts.manualPort) {
|
||||||
|
showError(err, port);
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.errorPort = err.toString();
|
||||||
|
|
||||||
|
return createServer(portFallback, null, content, opts).then(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(port, function () {
|
||||||
|
opts.port = port;
|
||||||
|
opts.redirectOptions.port = port;
|
||||||
|
|
||||||
|
if (opts.livereload) {
|
||||||
|
opts.lrPort = opts.lrPort || lrPort;
|
||||||
|
var livereload = require('livereload');
|
||||||
|
var server2 = livereload.createServer({
|
||||||
|
https: opts.httpsOptions
|
||||||
|
, port: opts.lrPort
|
||||||
|
, exclusions: [ 'node_modules' ]
|
||||||
|
});
|
||||||
|
|
||||||
|
console.info("[livereload] watching " + opts.pubdir);
|
||||||
|
console.warn("WARNING: If CPU usage spikes to 100% it's because too many files are being watched");
|
||||||
|
// TODO create map of directories to watch from opts.sites and iterate over it
|
||||||
|
server2.watch(opts.pubdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we haven't disabled insecure port
|
||||||
|
if ('false' !== opts.insecurePort) {
|
||||||
|
// and both ports are the default
|
||||||
|
if ((httpsPort === opts.port && httpPort === opts.insecurePort)
|
||||||
|
// or other case
|
||||||
|
|| (httpPort !== opts.insecurePort && opts.port !== opts.insecurePort)
|
||||||
|
) {
|
||||||
|
return createInsecureServer(opts.insecurePort, null, opts).then(function (_server) {
|
||||||
|
insecureServer = _server;
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.insecurePort = opts.port;
|
||||||
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
});
|
||||||
|
|
||||||
if ('function' === typeof app) {
|
if ('function' === typeof app) {
|
||||||
app(req, res);
|
app = app(directive);
|
||||||
return;
|
} else if ('function' === typeof app.create) {
|
||||||
|
app = app.create(directive);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.end('not ready');
|
server.on('request', function (req, res) {
|
||||||
});
|
console.log('[' + req.method + '] ' + req.url);
|
||||||
|
if (!req.socket.encrypted && !/\/\.well-known\/acme-challenge\//.test(req.url)) {
|
||||||
|
opts.redirectApp(req, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return PromiseA.resolve(app).then(function (_app) {
|
if ('function' === typeof app) {
|
||||||
app = _app;
|
app(req, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end('not ready');
|
||||||
|
});
|
||||||
|
|
||||||
|
return PromiseA.resolve(app).then(function (_app) {
|
||||||
|
app = _app;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
"greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
|
"greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
|
||||||
"greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master",
|
"greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master",
|
||||||
"httpolyglot": "^0.1.1",
|
"httpolyglot": "^0.1.1",
|
||||||
|
"ipaddr.js": "git+https://github.com/whitequark/ipaddr.js.git#v1.3.0",
|
||||||
"ipify": "^1.1.0",
|
"ipify": "^1.1.0",
|
||||||
"js-yaml": "^3.8.1",
|
"js-yaml": "^3.8.1",
|
||||||
"le-challenge-ddns": "git+https://git.daplie.com/Daplie/le-challenge-ddns.git#master",
|
"le-challenge-ddns": "git+https://git.daplie.com/Daplie/le-challenge-ddns.git#master",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 356a2d3131bcc6d0f6199a1d2039dcdcee0e3481
|
Subproject commit d64699977e883871246d3fc062a384e88a554e2a
|
Loading…
Reference in New Issue