forked from coolaj86/goldilocks.js
		
	updated the DDNS and loopback to use async/await
This commit is contained in:
		
							parent
							
								
									a625ee9db9
								
							
						
					
					
						commit
						cfcc1acb8c
					
				
							
								
								
									
										111
									
								
								lib/ddns.js
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								lib/ddns.js
									
									
									
									
									
								
							| @ -16,14 +16,14 @@ module.exports.create = function (deps, conf) { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   function setDeviceAddress(addr) { | ||||
|     return deps.storage.owners.all().then(function (sessions) { | ||||
|       return sessions.filter(function (sess) { | ||||
|   async function getSession() { | ||||
|     var sessions = await deps.storage.owners.all(); | ||||
|     var session = sessions.filter(function (sess) { | ||||
|       return sess.token.scp.indexOf('dns') >= 0; | ||||
|     })[0]; | ||||
|     }).then(function (session) { | ||||
| 
 | ||||
|     if (!session) { | ||||
|         return PromiseA.reject(new Error('no sessions with DNS grants')); | ||||
|       throw new Error('no sessions with DNS grants'); | ||||
|     } | ||||
| 
 | ||||
|     // The OAUTH3 library stores some things on the root session object that we usually
 | ||||
| @ -31,9 +31,15 @@ module.exports.create = function (deps, conf) { | ||||
|     session.provider_uri = session.provider_uri || session.token.provider_uri || session.token.iss; | ||||
|     session.client_uri = session.client_uri || session.token.azp; | ||||
|     session.scope = session.scope || session.token.scp; | ||||
|     return session; | ||||
|   } | ||||
| 
 | ||||
|       return OAUTH3.discover(session.token.aud).then(function (directives) { | ||||
|         return request({ | ||||
|   async function setDeviceAddress(addr) { | ||||
|     var session = await getSession(); | ||||
|     var directives = await OAUTH3.discover(session.token.aud); | ||||
| 
 | ||||
|     // Set the address of the device to our public address.
 | ||||
|     await request({ | ||||
|       url: directives.api+'/api/com.daplie.domains/acl/devices/' + conf.device.hostname | ||||
|     , method: 'POST' | ||||
|     , headers: { | ||||
| @ -45,60 +51,49 @@ module.exports.create = function (deps, conf) { | ||||
|           { value: addr, type:  dnsType(addr) } | ||||
|         ] | ||||
|       } | ||||
|         }).then(function () { | ||||
|           return OAUTH3.api(directives.api, {session: session, api: 'dns.list'}).then(function (list) { | ||||
|             return list.filter(function (record) { | ||||
|     }); | ||||
| 
 | ||||
|     // Then update all of the records attached to our hostname, first removing the old records
 | ||||
|     // to remove the reference to the old address, then creating new records for the same domains
 | ||||
|     // using our new address.
 | ||||
|     var allDns = OAUTH3.api(directives.api, {session: session, api: 'dns.list'}); | ||||
|     var ourDomains = allDns.filter(function (record) { | ||||
|       return record.device === conf.device.hostname; | ||||
|     }).map(function (record) { | ||||
|               var split = record.zone.split('.'); | ||||
|       var zoneSplit = record.zone.split('.'); | ||||
|       return { | ||||
|                 tld: split.slice(1).join('.') | ||||
|               , sld: split[0] | ||||
|         tld: zoneSplit.slice(1).join('.') | ||||
|       , sld: zoneSplit[0] | ||||
|       , sub: record.host.slice(0, -(record.zone.length + 1)) | ||||
|       }; | ||||
|     }); | ||||
|           }); | ||||
|         }).then(function (domains) { | ||||
| 
 | ||||
|     var common = { | ||||
|       api: 'devices.detach' | ||||
|     , session: session | ||||
|     , device: conf.device.hostname | ||||
|     }; | ||||
| 
 | ||||
|           return PromiseA.all(domains.map(function (record) { | ||||
|     await PromiseA.all(ourDomains.map(function (record) { | ||||
|       return OAUTH3.api(directives.api, Object.assign({}, common, record)); | ||||
|           })).then(function () { | ||||
|             return domains; | ||||
|           }); | ||||
|         }).then(function (domains) { | ||||
|           var common = { | ||||
|     })); | ||||
| 
 | ||||
|     common = { | ||||
|       api: 'devices.attach' | ||||
|     , session: session | ||||
|     , device: conf.device.hostname | ||||
|     , ip: addr | ||||
|     , ttl: 300 | ||||
|     }; | ||||
| 
 | ||||
|           return PromiseA.all(domains.map(function (record) { | ||||
|     await PromiseA.all(ourDomains.map(function (record) { | ||||
|       return OAUTH3.api(directives.api, Object.assign({}, common, record)); | ||||
|     })); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function getDeviceAddresses() { | ||||
|     return deps.storage.owners.all().then(function (sessions) { | ||||
|       return sessions.filter(function (sess) { | ||||
|         return sess.token.scp.indexOf('dns') >= 0; | ||||
|       })[0]; | ||||
|     }).then(function (session) { | ||||
|       if (!session) { | ||||
|         return PromiseA.reject(new Error('no sessions with DNS grants')); | ||||
|       } | ||||
|   async function getDeviceAddresses() { | ||||
|     var session = await getSession(); | ||||
|     var directives = await OAUTH3.discover(session.token.aud); | ||||
| 
 | ||||
|       return OAUTH3.discover(session.token.aud).then(function (directives) { | ||||
|         return request({ | ||||
|     var result = await request({ | ||||
|       url: directives.api+'/api/org.oauth3.dns/acl/devices' | ||||
|     , method: 'GET' | ||||
|     , headers: { | ||||
| @ -107,54 +102,40 @@ module.exports.create = function (deps, conf) { | ||||
|       } | ||||
|     , json: true | ||||
|     }); | ||||
|       }).then(function (result) { | ||||
| 
 | ||||
|     if (!result.body) { | ||||
|           return PromiseA.reject(new Error('No response body in request for device addresses')); | ||||
|       throw new Error('No response body in request for device addresses'); | ||||
|     } | ||||
|     if (result.body.error) { | ||||
|           var err = new Error(result.body.error.message); | ||||
|           return PromiseA.reject(Object.assign(err, result.body.error)); | ||||
|       throw Object.assign(new Error('error getting device list'), result.body.error); | ||||
|     } | ||||
|         return result.body.devices.filter(function (dev) { | ||||
| 
 | ||||
|     var dev = result.body.devices.filter(function (dev) { | ||||
|       return dev.name === conf.device.hostname; | ||||
|     })[0]; | ||||
|       }).then(function (dev) { | ||||
|     return (dev || {}).addresses || []; | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   var publicAddress; | ||||
|   function recheckPubAddr() { | ||||
|   async function recheckPubAddr() { | ||||
|     if (!conf.ddns.enabled) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     deps.storage.owners.all().then(function (sessions) { | ||||
|       return sessions.filter(function (sess) { | ||||
|         return sess.token.scp.indexOf('dns') >= 0; | ||||
|       })[0]; | ||||
|     }).then(function (session) { | ||||
|       if (!session) { | ||||
|     var session = await getSession(); | ||||
|     var directives = await OAUTH3.discover(session.token.aud); | ||||
|     var addr = await deps.loopback.checkPublicAddr(directives.api); | ||||
| 
 | ||||
|     if (publicAddress === addr) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|       OAUTH3.discover(session.token.aud).then(function (directives) { | ||||
|         return deps.loopback.checkPublicAddr(directives.api); | ||||
|       }).then(function (addr) { | ||||
|         if (publicAddress !== addr) { | ||||
|     if (conf.debug) { | ||||
|       console.log('previous public address',publicAddress, 'does not match current public address', addr); | ||||
|     } | ||||
| 
 | ||||
|     await setDeviceAddress(addr); | ||||
|     publicAddress = addr; | ||||
|           setDeviceAddress(addr); | ||||
|         } | ||||
|       }, function (err) { | ||||
|         if (conf.debug) { | ||||
|           console.error('error getting public address', err); | ||||
|         } | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   recheckPubAddr(); | ||||
|  | ||||
| @ -5,46 +5,52 @@ module.exports.create = function (deps, conf) { | ||||
|   var request = PromiseA.promisify(require('request')); | ||||
|   var pending = {}; | ||||
| 
 | ||||
|   function checkPublicAddr(host) { | ||||
|     return request({ | ||||
|   async function checkPublicAddr(host) { | ||||
|     var result = await request({ | ||||
|       method: 'GET' | ||||
|     , url: host+'/api/org.oauth3.tunnel/checkip' | ||||
|     , json: true | ||||
|     }).then(function (result) { | ||||
|     }); | ||||
| 
 | ||||
|     if (!result.body) { | ||||
|         return PromiseA.reject(new Error('No response body in request for public address')); | ||||
|       throw new Error('No response body in request for public address'); | ||||
|     } | ||||
|     if (result.body.error) { | ||||
|         var err = new Error(result.body.error.message); | ||||
|         return PromiseA.reject(Object.assign(err, result.body.error)); | ||||
|       // Note that the error on the body will probably have a message that overwrites the default
 | ||||
|       throw Object.assign(new Error('error in check IP response'), result.body.error); | ||||
|     } | ||||
|     return result.body.address; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function checkSinglePort(host, address, port) { | ||||
|   async function checkSinglePort(host, address, port) { | ||||
|     var crypto = require('crypto'); | ||||
|     var token   = crypto.randomBytes(8).toString('hex'); | ||||
|     var keyAuth = crypto.randomBytes(32).toString('hex'); | ||||
|     pending[token] = keyAuth; | ||||
| 
 | ||||
|     var opts = { | ||||
|     var reqObj = { | ||||
|       method: 'POST' | ||||
|     , url: host+'/api/org.oauth3.tunnel/loopback' | ||||
|     , json: { | ||||
|         address: address | ||||
|       , port: port | ||||
|       , token: token | ||||
|       , keyAuthorization: keyAuth | ||||
|       , iat: Date.now() | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     return request({ | ||||
|       method: 'POST' | ||||
|     , url: host+'/api/org.oauth3.tunnel/loopback' | ||||
|     , json: opts | ||||
|     }) | ||||
|     .then(function (result) { | ||||
|     var result; | ||||
|     try { | ||||
|       result = await request(reqObj); | ||||
|     } catch (err) { | ||||
|       delete pending[token]; | ||||
|       throw err; | ||||
|     } | ||||
| 
 | ||||
|     delete pending[token]; | ||||
|     if (!result.body) { | ||||
|         return PromiseA.reject(new Error('No response body in loopback request for port '+port)); | ||||
|       throw new Error('No response body in loopback request for port '+port); | ||||
|     } | ||||
|     // If the loopback requests don't go to us then there are all kinds of ways it could
 | ||||
|     // error, but none of them really provide much extra information so we don't do
 | ||||
| @ -53,21 +59,18 @@ module.exports.create = function (deps, conf) { | ||||
|       console.log('error on remote side of port '+port+' loopback', result.body.error); | ||||
|     } | ||||
|     return !!result.body.success; | ||||
|     }, function (err) { | ||||
|       delete pending[token]; | ||||
|       throw err; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function loopback(provider) { | ||||
|     return deps.OAUTH3.discover(provider).then(function (directives) { | ||||
|       return checkPublicAddr(directives.api).then(function (address) { | ||||
|   async function loopback(provider) { | ||||
|     var directives = await deps.OAUTH3.discover(provider); | ||||
|     var address = await checkPublicAddr(directives.api); | ||||
|     console.log('checking to see if', address, 'gets back to us'); | ||||
| 
 | ||||
|     var ports = require('./servers').listeners.tcp.list(); | ||||
|         return PromiseA.all(ports.map(function (port) { | ||||
|     var values = await PromiseA.all(ports.map(function (port) { | ||||
|       return checkSinglePort(directives.api, address, port); | ||||
|         })) | ||||
|         .then(function (values) { | ||||
|     })); | ||||
| 
 | ||||
|     if (conf.debug) { | ||||
|       console.log('remaining loopback tokens', pending); | ||||
|     } | ||||
| @ -77,9 +80,6 @@ module.exports.create = function (deps, conf) { | ||||
|       result[port] = values[ind]; | ||||
|     }); | ||||
|     return result; | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   loopback.checkPublicAddr = checkPublicAddr; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user