From 741d9721a05872997551953f43636f8369ea34ec Mon Sep 17 00:00:00 2001 From: lane-c-wagner Date: Tue, 27 Nov 2018 07:46:51 -0700 Subject: [PATCH 1/2] opencap service --- src/js/services/opencapService.js | 114 ++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/js/services/opencapService.js diff --git a/src/js/services/opencapService.js b/src/js/services/opencapService.js new file mode 100644 index 00000000..6538ba0a --- /dev/null +++ b/src/js/services/opencapService.js @@ -0,0 +1,114 @@ +'use strict'; + +(function() { + angular.module('canoeApp.services').factory('opencapService', function($q, $http) { + function getAddress(alias) { + let aliasData = validateAlias(alias); + if (aliasData.username === '' || aliasData.domain === '') { + return $q((resolve, reject) => { + return reject('Invalid OpenCAP alias'); + }); + } + + let deferred = $q.defer(); + $http + .get(`https://dns.google.com/resolve?name=_opencap._tcp.${aliasData.domain}&type=SRV`) + .then(function(response) { + deferred.resolve( + parseSRV(response.data) + .then(data => getAddressFromServer(alias, data.host, data.dnssec)) + .catch(function(error) { + return $q((resolve, reject) => { + reject(error); + }); + }) + ); + }) + .catch(function(response) { + deferred.reject("Couldn't find srv record for the provided domain"); + }); + return deferred.promise; + } + + var parseSRV = function(respData) { + return $q((resolve, reject) => { + let dnssec = respData.AD; + + if (typeof respData.Answer === 'undefined') { + return reject('Error contacting google dns server, no srv data'); + } + if (respData.Answer.length < 1) { + return reject('Error contacting google dns server, not enough srv data'); + } + + let record = respData.Answer[0].data.split(' '); + if (record.length != 4) { + return reject('Error contacting google dns server, improper srv data'); + } + + if (record[3].slice(-1) == '.') { + record[3] = record[3].substring(0, record[3].length - 1); + } + + return resolve({ host: record[3], dnssec }); + }); + }; + + var getAddressFromServer = function(alias, host, dnssec) { + let deferred = $q.defer(); + $http + .get(`https://${host}/v1/addresses?alias=${alias}&address_type=300`) + .then(function(response) { + deferred.resolve(parseAddress(response.data, dnssec).then()); + }) + .catch(function(response) { + deferred.reject('Address not found for the specified alias'); + }); + return deferred.promise; + }; + + var parseAddress = function(respData, dnssec) { + return $q((resolve, reject) => { + if (respData.address_type === 'undefined') { + return reject('Error contacting opencap server, no response'); + } + if (respData.address === 'undefined') { + return reject('Error contacting opencap server, no response'); + } + return resolve({ address: respData.address, dnssec }); + }); + }; + + function validateUsername(username) { + return /^[a-z0-9._-]{1,25}$/.test(username); + } + + function validateDomain(username) { + return /^[a-z0-9.\-]+\.[a-z]{2,4}$/.test(username); + } + + function validateAlias(alias) { + let splitAlias = alias.split('$'); + if (splitAlias.length != 2) { + return { username: '', domain: '' }; + } + let username = splitAlias[0]; + let domain = splitAlias[1]; + + if (!validateUsername(username)) { + return { username: '', domain: '' }; + } + if (!validateDomain(domain)) { + return { username: '', domain: '' }; + } + + return { username, domain }; + } + + var service = { + getAddress, + }; + + return service; + }); +})(); From 4c91f2ceb8d20b196dc835774e6914a5fe12333c Mon Sep 17 00:00:00 2001 From: Lane Wagner Date: Sat, 1 Dec 2018 11:13:44 -0700 Subject: [PATCH 2/2] complete send feature --- src/js/controllers/tab-send.js | 33 +++++++++++- src/js/services/opencapService.js | 84 ++++++++++++++++++++++++++++- www/templates/popoverAliasSend.html | 16 ++++++ www/views/tab-send.html | 2 +- 4 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 www/templates/popoverAliasSend.html diff --git a/src/js/controllers/tab-send.js b/src/js/controllers/tab-send.js index f1a03235..3af5faa3 100644 --- a/src/js/controllers/tab-send.js +++ b/src/js/controllers/tab-send.js @@ -1,6 +1,6 @@ 'use strict' /* global angular */ -angular.module('canoeApp.controllers').controller('tabSendController', function ($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, incomingData, popupService, platformInfo, gettextCatalog, scannerService, externalLinkService) { +angular.module('canoeApp.controllers').controller('tabSendController', function ($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, $ionicPopover, addressbookService, profileService, lodash, $state, incomingData, popupService, platformInfo, gettextCatalog, scannerService, externalLinkService, opencapService) { var originalList var completeContacts var CONTACTS_SHOW_LIMIT @@ -101,7 +101,38 @@ angular.module('canoeApp.controllers').controller('tabSendController', function } } + $scope.closePopover = function() { + $scope.popover.hide(); + }; + + $scope.$on('$destroy', function() { + $scope.popover.remove(); + }); + + $scope.confirmOpenapAddress = function(address){ + $scope.popover.remove(); + $scope.findContact(address); + } + + $scope.resolveOpencapAlias = function(alias){ + opencapService.getAddress(alias) + .then(result => { + $scope.opencapAddress = result.address; + $scope.opencapDnssec = result.dnssec; + $ionicPopover.fromTemplateUrl('templates/popoverAliasSend.html', {scope: $scope}) + .then(function(popover) { + $scope.popover = popover; + popover.show(angular.element(document.querySelector('#search-input'))) + }); + }) + .catch(status => { + // do nothing because they may have been typing + }); + } + $scope.findContact = function (search) { + $scope.resolveOpencapAlias(search); + // If redir returns true it matched something and // will already have moved us to amount. incomingData.redir(search, $scope.acc.id, function (err, code) { diff --git a/src/js/services/opencapService.js b/src/js/services/opencapService.js index 6538ba0a..8449b044 100644 --- a/src/js/services/opencapService.js +++ b/src/js/services/opencapService.js @@ -16,7 +16,7 @@ .then(function(response) { deferred.resolve( parseSRV(response.data) - .then(data => getAddressFromServer(alias, data.host, data.dnssec)) + .then(data => getAddressReqeust(alias, data.host, data.dnssec)) .catch(function(error) { return $q((resolve, reject) => { reject(error); @@ -54,7 +54,7 @@ }); }; - var getAddressFromServer = function(alias, host, dnssec) { + var getAddressReqeust = function(alias, host, dnssec) { let deferred = $q.defer(); $http .get(`https://${host}/v1/addresses?alias=${alias}&address_type=300`) @@ -79,6 +79,85 @@ }); }; + function updateAddress(alias, password, address) { + let aliasData = validateAlias(alias); + if (aliasData.username === '' || aliasData.domain === '') { + return $q((resolve, reject) => { + return reject('Invalid OpenCAP alias'); + }); + } + + let deferred = $q.defer(); + $http + .get(`https://dns.google.com/resolve?name=_opencap._tcp.${aliasData.domain}&type=SRV`) + .then(function(response) { + deferred.resolve( + parseSRV(response.data) + .then(data => + loginRequest(alias, password, data.host) + .then(jwt => updateAddressRequest(alias, address, data.host, jwt)) + .catch(function(error) { + return $q((resolve, reject) => { + reject(error); + }); + }) + ) + .catch(function(error) { + return $q((resolve, reject) => { + reject(error); + }); + }) + ); + }) + .catch(function(response) { + deferred.reject("Couldn't find srv record for the provided domain"); + }); + return deferred.promise; + } + + function updateAddressRequest(alias, address, host, jwt) { + let deferred = $q.defer(); + let headers = new Headers({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${jwt}`, + }); + let options = new RequestOptions({ headers: headers }); + const nano_address_type = 300; + $http + .put(`https://${host}/v1/addresses`, { address_type: nano_address_type, address }, options) + .then(function(response) { + deferred.resolve('Alias was updated succesfully'); + }) + .catch(function(response) { + deferred.reject('Failed to update alias'); + }); + return deferred.promise; + } + + function loginRequest(alias, password, host) { + let deferred = $q.defer(); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + $http + .post(`https://${host}/v1/auth`, { alias, password }, options) + .then(function(response) { + deferred.resolve(parseJWT(response.data).then()); + }) + .catch(function(response) { + deferred.reject('Invalid login credentials'); + }); + return deferred.promise; + } + + var parseJWT = function(respData) { + return $q((resolve, reject) => { + if (respData.jwt === 'undefined') { + return reject('Error contacting opencap server, no response'); + } + return resolve(respData.jwt); + }); + }; + function validateUsername(username) { return /^[a-z0-9._-]{1,25}$/.test(username); } @@ -106,6 +185,7 @@ } var service = { + updateAddress, getAddress, }; diff --git a/www/templates/popoverAliasSend.html b/www/templates/popoverAliasSend.html new file mode 100644 index 00000000..2fff414b --- /dev/null +++ b/www/templates/popoverAliasSend.html @@ -0,0 +1,16 @@ + +
+
+ Address found! +
+
+
+ {{opencapAddress}} + + + DNSSEC not used + +
+
+
+
\ No newline at end of file diff --git a/www/views/tab-send.html b/www/views/tab-send.html index 8e8f065c..78f68a96 100644 --- a/www/views/tab-send.html +++ b/www/views/tab-send.html @@ -15,7 +15,7 @@
- +