angular.module('com.daplie.cloud', [ 'org.oauth3' ]) .service('oauth3', [ 'Oauth3', function (Oauth3) { // for security this app should not store the refresh token // (the localhost.* domains should never store them) Oauth3.hooks.session._store = {}; Oauth3.hooks.session._get = function (providerUri) { return Oauth3.PromiseA.resolve(Oauth3.hooks.session._store[providerUri]); }; Oauth3.hooks.session._set = function (providerUri, session) { Oauth3.hooks.session._store[providerUri] = session; return Oauth3.PromiseA.resolve(session); }; var auth = Oauth3.create(); auth.setProvider('oauth3.org').then(function () { auth.checkSession().then(function (session) { console.log('hasSession?', session); }); }); window.oauth3 = auth; // debug return auth; } ]) .controller('LoginController', [ '$scope', '$timeout', 'oauth3', function ($scope, $timeout, oauth3) { var vm = this; var OAUTH3 = window.OAUTH3; vm.admin = { network: { iface: null, ipv4: null, ipv6: null } }; vm.admin.ipify = 'https://api.ipify.org?format=json'; vm.clientUri = OAUTH3.clientUri(window.location); vm.setSimple = function () { vm.advanced = false; vm.providerUri = vm.providerUri || 'oauth3.org'; }; vm.setAdvanced = function () { vm.advanced = true; vm.myProviderUri = vm.providerUri; }; vm.checkProviderUri = function (myProviderUri) { $timeout.cancel(vm.checkProviderTimeout); vm.providerUri = null; vm.checkProviderTimeout = $timeout(function () { //var providerUri = vm.providerUri; return oauth3.setProvider(myProviderUri).then(function (directives) { console.log('directives', directives); vm.providerUri = myProviderUri; }, function (err) { console.error('failed provider lookup', err); vm.checkProviderTimeout = null; }); }, 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.domains.sort(vm.sortDnsRecords); 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 () { // TODO authorization redirect /api/org.oauth3.consumer/authorization_redirect/:provider_uri var opts = { type: 'popup' , scope: 'domains,dns' // , debug: true }; return oauth3.authenticate(opts).then(function (session) { console.info("Authorized Session", session); return oauth3.api('domains.list').then(function (domains) { console.info("domains owned", domains); return oauth3.api('dns.list').then(function (dns) { console.info("dns records", dns); return OAUTH3.request({ method: 'POST' , url: 'https://' + vm.clientUri + '/api/com.daplie.goldilocks/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({ method: 'GET' , url: 'https://' + vm.clientUri + '/api/com.daplie.goldilocks/config' , session: session }).then(function (configResp) { console.log('config', configResp.data); vm.config = configResp.data; vm.config.addresses.forEach(function (addr) { if (/unicast/.test(addr.range) || /internet/i.test(addr.range)) { // TODO // there could be more than one iface (ipv4 on one and ipv6 on the other) // there could also be more than one valid public ip if ("IPv4" === addr.family) { vm.admin.network.iface = addr.iface; vm.admin.network.ipv4 = addr.address; } else if ("IPv6" === addr.family) { // IPv6 gives valid internet address even when behind a firewall // IPv6 requires a loopback test // TODO always do the loopback / firewall test anyway vm.admin.network.ipv6 = addr.address; } } }); vm.admin.servername = vm.config.device.hostname; //vm.config.ifaces //vm.config.addresses = []; vm.viewDomains(vm.config, domains, dns); if (vm.admin.network.iface) { return resp; } // TODO try UPnP IGD / NAT-PMP / DNS-SD / PCP (ipv6) here // TODO two requests - one to {{ipv4.ipify.org}}, the other to {{ipv6.ipify.org}} vm.admin.network.iface = 'gateway'; return OAUTH3.request({ method: 'POST' , url: 'https://' + vm.clientUri + '/api/com.daplie.goldilocks/request' , session: session , data: { method: 'GET' , url: 'https://api.ipify.org?format=json' } }).then(function (ipResp) { console.log('ip-response', ipResp); vm.admin.network.ipv4 = ipResp.data.body.ipv4 || ipResp.data.body.ip; vm.admin.network.ipv6 = ipResp.data.body.ipv6; return resp; }); }); }, function (err) { console.error(err); window.alert("Initialization failed:" + err.message); }); }); }); }, function (err) { console.error(err); window.alert("Authentication failed:" + err.message); }); }; vm.enableTunnel = function (/*opts*/) { return oauth3.request({ method: 'POST' , url: 'https://' + vm.clientUri + '/api/com.daplie.goldilocks/tunnel' }).then(function (result) { // vm.admin.network.iface = 'oauth3-tunnel'; return result; }); }; /* console.log('OAUTH3.PromiseA', OAUTH3.PromiseA); return oauth3.setProvider('oauth3.org').then(function () { return oauth3.authenticate({ windowType: 'background' }).then(function () { console.log('HELLO!!'); //vm.authnUpdated = Date.now(); vm.hasSession = true; }, function () { console.log('GOODBYE!!'); //vm.authnUpdated = Date.now(); vm.hasSession = false; $timeout(function () { console.log('GOODBYE!!'); vm.hello = 'Nope!'; }, 1); }); }); //*/ }]); /* $(function () { 'use strict'; var ui = { function login() { } }; var auth = window.OAUTH3.create(); // TODO put explicit in dns record // TODO CCA record auth.setProvider('oauth3.org'); $('body').on('click', '.js-login', login); }); */