Merge pull request #5986 from gabrielbazan7/fix/lockedApp
Fix/locked app
This commit is contained in:
commit
38f8d1151e
14 changed files with 145 additions and 230 deletions
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('lockSetupController', function($state, $scope, $timeout, $log, configService, gettextCatalog, fingerprintService, profileService, lodash) {
|
||||
angular.module('copayApp.controllers').controller('lockSetupController', function($state, $rootScope, $scope, $timeout, $log, configService, gettextCatalog, fingerprintService, profileService, lodash, applicationService) {
|
||||
|
||||
function init() {
|
||||
$scope.options = [
|
||||
|
|
@ -53,7 +53,7 @@ angular.module('copayApp.controllers').controller('lockSetupController', functio
|
|||
o.disabled = false;
|
||||
});
|
||||
|
||||
// HACK: Disable untill we allow to change between methods directly
|
||||
// HACK: Disable until we allow to change between methods directly
|
||||
if (fingerprintService.isAvailable()) {
|
||||
switch (savedMethod) {
|
||||
case 'pin':
|
||||
|
|
@ -120,9 +120,7 @@ angular.module('copayApp.controllers').controller('lockSetupController', functio
|
|||
function disableMethod(method) {
|
||||
switch (method) {
|
||||
case 'pin':
|
||||
$state.transitionTo('tabs.pin', {
|
||||
action: 'disable'
|
||||
});
|
||||
applicationService.pinModal('disable');
|
||||
break;
|
||||
case 'fingerprint':
|
||||
fingerprintService.check('unlockingApp', function(err) {
|
||||
|
|
@ -136,9 +134,7 @@ angular.module('copayApp.controllers').controller('lockSetupController', functio
|
|||
function enableMethod(method) {
|
||||
switch (method) {
|
||||
case 'pin':
|
||||
$state.transitionTo('tabs.pin', {
|
||||
action: 'setup'
|
||||
});
|
||||
applicationService.pinModal('setup');
|
||||
break;
|
||||
case 'fingerprint':
|
||||
saveConfig('fingerprint');
|
||||
|
|
@ -159,4 +155,9 @@ angular.module('copayApp.controllers').controller('lockSetupController', functio
|
|||
initMethodSelector();
|
||||
});
|
||||
};
|
||||
|
||||
$rootScope.$on('pinModalClosed', function() {
|
||||
init()
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('lockedViewController', function($state, $scope, $ionicHistory, fingerprintService, appConfigService, gettextCatalog) {
|
||||
$scope.$on("$ionicView.beforeEnter", function(event) {
|
||||
$scope.title = appConfigService.nameCase + ' ' + gettextCatalog.getString('is locked');
|
||||
$scope.appName = appConfigService.name;
|
||||
});
|
||||
|
||||
$scope.requestFingerprint = function() {
|
||||
fingerprintService.check('unlockingApp', function(err) {
|
||||
if (err) return;
|
||||
$state.transitionTo('tabs.home').then(function() {
|
||||
$ionicHistory.clearHistory();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
@ -1,30 +1,25 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('pinController', function($state, $interval, $stateParams, $ionicHistory, $timeout, $scope, $log, configService, appConfigService) {
|
||||
angular.module('copayApp.controllers').controller('pinController', function($state, $interval, $stateParams, $ionicHistory, $timeout, $scope, $log, configService, appConfigService, applicationService) {
|
||||
var ATTEMPT_LIMIT = 3;
|
||||
var ATTEMPT_LOCK_OUT_TIME = 5 * 60;
|
||||
var currentPin;
|
||||
currentPin = $scope.confirmPin = '';
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event) {
|
||||
currentPin = $scope.confirmPin = '';
|
||||
$scope.action = $stateParams.action;
|
||||
$scope.match = $scope.error = $scope.disableButtons = false;
|
||||
$scope.currentAttempts = 0;
|
||||
$scope.appName = appConfigService.name;
|
||||
});
|
||||
$scope.match = $scope.error = $scope.disableButtons = false;
|
||||
$scope.currentAttempts = 0;
|
||||
$scope.appName = appConfigService.name;
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event) {
|
||||
configService.whenAvailable(function(config) {
|
||||
if (!config.lock) return;
|
||||
$scope.bannedUntil = config.lock.bannedUntil || null;
|
||||
if ($scope.bannedUntil) {
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
if (now < $scope.bannedUntil) {
|
||||
$scope.error = $scope.disableButtons = true;
|
||||
lockTimeControl($scope.bannedUntil);
|
||||
}
|
||||
configService.whenAvailable(function(config) {
|
||||
if (!config.lock) return;
|
||||
$scope.bannedUntil = config.lock.bannedUntil || null;
|
||||
if ($scope.bannedUntil) {
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
if (now < $scope.bannedUntil) {
|
||||
$scope.error = $scope.disableButtons = true;
|
||||
lockTimeControl($scope.bannedUntil);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function getSavedMethod() {
|
||||
|
|
@ -126,7 +121,10 @@ angular.module('copayApp.controllers').controller('pinController', function($sta
|
|||
}
|
||||
break;
|
||||
case 'check':
|
||||
if (isMatch(currentPin)) return $scope.close();
|
||||
if (isMatch(currentPin)) {
|
||||
$scope.hideModal();
|
||||
return;
|
||||
}
|
||||
showError();
|
||||
checkAttempts();
|
||||
break;
|
||||
|
|
@ -174,7 +172,7 @@ angular.module('copayApp.controllers').controller('pinController', function($sta
|
|||
|
||||
configService.set(opts, function(err) {
|
||||
if (err) $log.debug(err);
|
||||
$scope.close();
|
||||
$scope.hideModal();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -189,7 +187,7 @@ angular.module('copayApp.controllers').controller('pinController', function($sta
|
|||
|
||||
configService.set(opts, function(err) {
|
||||
if (err) $log.debug(err);
|
||||
$scope.close();
|
||||
$scope.hideModal();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -206,14 +204,4 @@ angular.module('copayApp.controllers').controller('pinController', function($sta
|
|||
});
|
||||
};
|
||||
|
||||
$scope.close = function(delay) {
|
||||
$timeout(function() {
|
||||
var shouldReturn = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName != 'starting';
|
||||
|
||||
if (shouldReturn)
|
||||
$ionicHistory.goBack()
|
||||
else
|
||||
$state.go('tabs.home');
|
||||
}, delay || 1);
|
||||
};
|
||||
});
|
||||
|
|
@ -119,30 +119,6 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
}
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
* Pin
|
||||
*
|
||||
*/
|
||||
|
||||
.state('pin', {
|
||||
url: '/pin/:action',
|
||||
controller: 'pinController',
|
||||
templateUrl: 'views/pin.html',
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
* Locked
|
||||
*
|
||||
*/
|
||||
|
||||
.state('lockedView', {
|
||||
url: '/lockedView/',
|
||||
controller: 'lockedViewController',
|
||||
templateUrl: 'views/lockedView.html',
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
* URI
|
||||
|
|
@ -1135,7 +1111,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
}
|
||||
});
|
||||
})
|
||||
.run(function($rootScope, $state, $location, $log, $timeout, startupService, fingerprintService, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, configService, /* plugins START HERE => */ coinbaseService, glideraService, amazonService, bitpayCardService) {
|
||||
.run(function($rootScope, $state, $location, $log, $timeout, startupService, fingerprintService, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, configService, /* plugins START HERE => */ coinbaseService, glideraService, amazonService, bitpayCardService, applicationService) {
|
||||
|
||||
uxLanguage.init();
|
||||
|
||||
|
|
@ -1197,56 +1173,8 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
// Nothing to do
|
||||
});
|
||||
|
||||
|
||||
function checkAndApplyLock(onResume) {
|
||||
var defaultView = 'tabs.home';
|
||||
|
||||
if (!platformInfo.isCordova && !platformInfo.isDevel) {
|
||||
goTo(defaultView);
|
||||
}
|
||||
|
||||
if (onResume) {
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
if (now < openURLService.unlockUntil) {
|
||||
openURLService.unlockUntil = null;
|
||||
$log.debug('Skip startup locking');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function goTo(nextView) {
|
||||
nextView = nextView || defaultView;
|
||||
$state.transitionTo(nextView, {
|
||||
action: 'check'
|
||||
}).then(function() {
|
||||
if (nextView == 'lockedView')
|
||||
$ionicHistory.clearHistory();
|
||||
});
|
||||
};
|
||||
|
||||
startupService.ready();
|
||||
|
||||
configService.whenAvailable(function(config) {
|
||||
var lockMethod = config.lock && config.lock.method;
|
||||
$log.debug('App Lock:' + (lockMethod || 'no'));
|
||||
|
||||
if (lockMethod == 'fingerprint' && fingerprintService.isAvailable()) {
|
||||
fingerprintService.check('unlockingApp', function(err) {
|
||||
if (err)
|
||||
goTo('lockedView');
|
||||
else if ($ionicHistory.currentStateName() == 'lockedView' || !onResume)
|
||||
goTo('tabs.home');
|
||||
});
|
||||
} else if (lockMethod == 'pin') {
|
||||
goTo('pin');
|
||||
} else {
|
||||
goTo(defaultView);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$ionicPlatform.on('resume', function() {
|
||||
checkAndApplyLock(true);
|
||||
applicationService.appLockModal('check');
|
||||
});
|
||||
|
||||
$ionicPlatform.on('menubutton', function() {
|
||||
|
|
@ -1289,14 +1217,17 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
disableAnimate: true,
|
||||
historyRoot: true
|
||||
});
|
||||
|
||||
checkAndApplyLock();
|
||||
$state.transitionTo('tabs.home').then(function() {
|
||||
// Clear history
|
||||
$ionicHistory.clearHistory();
|
||||
});
|
||||
applicationService.appLockModal('check');
|
||||
});
|
||||
};
|
||||
// After everything have been loaded, initialize handler URL
|
||||
$timeout(function() {
|
||||
openURLService.init();
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('applicationService', function($rootScope, $timeout, $ionicHistory, platformInfo, $state) {
|
||||
.factory('applicationService', function($rootScope, $timeout, $ionicHistory, $ionicModal, platformInfo, fingerprintService, openURLService, configService, $state) {
|
||||
var root = {};
|
||||
|
||||
root.isPinModalOpen = false;
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var isNW = platformInfo.isNW;
|
||||
|
||||
|
|
@ -33,5 +35,75 @@ angular.module('copayApp.services')
|
|||
}
|
||||
};
|
||||
|
||||
root.fingerprintModal = function() {
|
||||
|
||||
var scope = $rootScope.$new(true);
|
||||
$ionicModal.fromTemplateUrl('views/modals/fingerprintCheck.html', {
|
||||
scope: scope,
|
||||
animation: 'none',
|
||||
backdropClickToClose: false,
|
||||
hardwareBackButtonClose: false
|
||||
}).then(function(modal) {
|
||||
scope.fingerprintCheckModal = modal;
|
||||
root.isModalOpen = true;
|
||||
scope.openModal();
|
||||
});
|
||||
scope.openModal = function() {
|
||||
scope.fingerprintCheckModal.show();
|
||||
checkFingerprint();
|
||||
};
|
||||
scope.hideModal = function() {
|
||||
root.isModalOpen = false;
|
||||
scope.fingerprintCheckModal.hide();
|
||||
};
|
||||
|
||||
function checkFingerprint() {
|
||||
fingerprintService.check('unlockingApp', function(err) {
|
||||
if (err) {
|
||||
checkFingerprint();
|
||||
return;
|
||||
}
|
||||
scope.hideModal();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
root.pinModal = function(action) {
|
||||
|
||||
var scope = $rootScope.$new(true);
|
||||
scope.action = action;
|
||||
$ionicModal.fromTemplateUrl('views/modals/pin.html', {
|
||||
scope: scope,
|
||||
animation: 'none',
|
||||
backdropClickToClose: false,
|
||||
hardwareBackButtonClose: false
|
||||
}).then(function(modal) {
|
||||
scope.pinModal = modal;
|
||||
root.isModalOpen = true;
|
||||
scope.openModal();
|
||||
});
|
||||
scope.openModal = function() {
|
||||
scope.pinModal.show();
|
||||
};
|
||||
scope.hideModal = function() {
|
||||
scope.$emit('pinModalClosed');
|
||||
root.isModalOpen = false;
|
||||
scope.pinModal.hide();
|
||||
};
|
||||
};
|
||||
|
||||
root.appLockModal = function(action) {
|
||||
|
||||
if (root.isModalOpen) return;
|
||||
|
||||
configService.whenAvailable(function(config) {
|
||||
var lockMethod = config.lock && config.lock.method;
|
||||
if (!lockMethod || lockMethod == 'none') return;
|
||||
|
||||
if (lockMethod == 'fingerprint' && fingerprintService.isAvailable()) root.fingerprintModal();
|
||||
if (lockMethod == 'pin') root.pinModal(action);
|
||||
|
||||
});
|
||||
}
|
||||
return root;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var _get = function(endpoint, token) {
|
||||
|
|
@ -365,7 +365,7 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
|
||||
getPermissions(accessToken, credentials.NETWORK, true, function(err, permissions) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
||||
storageService.getGlideraStatus(credentials.NETWORK, function(err, status) {
|
||||
if (lodash.isString(status)) status = JSON.parse(status);
|
||||
storageService.getGlideraTxs(credentials.NETWORK, function(err, txs) {
|
||||
|
|
@ -386,17 +386,21 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
root.updateStatus = function(data) {
|
||||
storageService.getGlideraToken(credentials.NETWORK, function(err, accessToken) {
|
||||
if (err) return;
|
||||
|
||||
|
||||
getPermissions(accessToken, credentials.NETWORK, false, function(err, permissions) {
|
||||
if (err) return;
|
||||
data.permissions = permissions;
|
||||
|
||||
data.price = {};
|
||||
root.buyPrice(accessToken, {qty: 1}, function(err, buy) {
|
||||
root.buyPrice(accessToken, {
|
||||
qty: 1
|
||||
}, function(err, buy) {
|
||||
if (err) return;
|
||||
data.price['buy'] = buy.price;
|
||||
});
|
||||
root.sellPrice(accessToken, {qty: 1}, function(err, sell) {
|
||||
root.sellPrice(accessToken, {
|
||||
qty: 1
|
||||
}, function(err, sell) {
|
||||
if (err) return;
|
||||
data.price['sell'] = sell.price;
|
||||
});
|
||||
|
|
@ -405,12 +409,12 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
if (err) return;
|
||||
data.status = status;
|
||||
storageService.setGlideraStatus(credentials.NETWORK, JSON.stringify(status), function() {});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
root.getLimits(accessToken, function(err, limits) {
|
||||
data.limits = limits;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
if (permissions.transaction_history) {
|
||||
root.getTransactions(accessToken, function(err, txs) {
|
||||
if (err) return;
|
||||
|
|
@ -431,8 +435,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
data.personalInfo = info;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var register = function() {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('openURLService', function($rootScope, $ionicHistory, $document, $log, $state, platformInfo, lodash, profileService, incomingData, appConfigService) {
|
||||
var DELAY_UNLOCK_TIME = 2 * 60;
|
||||
var root = {};
|
||||
|
||||
root.unlockUntil = null;
|
||||
|
||||
var handleOpenURL = function(args) {
|
||||
root.unlockUntil = Math.floor(Date.now() / 1000) + DELAY_UNLOCK_TIME;
|
||||
$log.debug('Set unlock time until: ' + root.unlockUntil);
|
||||
|
||||
$log.info('Handling Open URL: ' + JSON.stringify(args));
|
||||
// Stop it from caching the first view as one to return when the app opens
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
#pin {
|
||||
background-color: #FAFAFA;
|
||||
.bar.bar-clear {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
.back-button .icon:before {
|
||||
color: #2d3f50;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.app-icon {
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
#locked-view {
|
||||
@mixin img-frame {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
box-shadow: none;
|
||||
margin: auto;
|
||||
}
|
||||
.img-container-copay {
|
||||
padding: 20%;
|
||||
@media(min-width: 480px) {
|
||||
max-height: 150px;
|
||||
}
|
||||
.big-icon-svg {
|
||||
> .bg {
|
||||
@include img-frame;
|
||||
background-image: url("../img/icon-fingerprint-copay.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
.img-container-bitpay {
|
||||
padding: 20%;
|
||||
@media(min-width: 480px) {
|
||||
max-height: 150px;
|
||||
}
|
||||
.big-icon-svg {
|
||||
> .bg {
|
||||
@include img-frame;
|
||||
background-image: url("../img/icon-fingerprint-bitpay.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
.comments {
|
||||
text-align: center;
|
||||
.header {
|
||||
font-size: 20px;
|
||||
}
|
||||
.text-content {
|
||||
width: 90%;
|
||||
margin: 5% auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,5 +46,4 @@
|
|||
@import "includes/accountSelector";
|
||||
@import "integrations/integrations";
|
||||
@import "custom-amount";
|
||||
@import "pin";
|
||||
@import "lockedView";
|
||||
@import "includes/pin";
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
<ion-view id="locked-view">
|
||||
<ion-nav-bar class="bar-royal">
|
||||
<ion-nav-title>{{title}}</ion-nav-title>
|
||||
</ion-nav-bar>
|
||||
|
||||
<ion-content>
|
||||
<div ng-if="appName == 'copay'" class="img-container-copay">
|
||||
<i class="icon big-icon-svg"><div class="bg"></div></i>
|
||||
</div>
|
||||
<div ng-if="appName == 'bitpay'" class="img-container-bitpay">
|
||||
<i class="icon big-icon-svg"><div class="bg"></div></i>
|
||||
</div>
|
||||
<div class="comments">
|
||||
<div class="header" translate>One-touch Sign In</div>
|
||||
<div class="text-content" translate>Please place your fingertip on the scanner to verify your identity</div>
|
||||
</div>
|
||||
<button type="submit" style="margin-top: 15%"
|
||||
class="button button-standard button-primary" ng-click="requestFingerprint()" translate>Scan again
|
||||
</button>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
10
www/views/modals/fingerprintCheck.html
Normal file
10
www/views/modals/fingerprintCheck.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<ion-modal-view id="pin">
|
||||
<div class="content">
|
||||
<div class="block-text row"></div>
|
||||
<div class="app-icon">
|
||||
<i class="icon big-icon-svg">
|
||||
<div class="bg"></div>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
</ion-modal-view>
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
<ion-view id="pin" hide-tabs hide-back-button="action == 'check'">
|
||||
<ion-nav-bar class="bar-clear">
|
||||
<ion-nav-back-button>
|
||||
</ion-nav-back-button>
|
||||
</ion-nav-bar>
|
||||
<ion-modal-view id="pin" ng-controller="pinController">
|
||||
<ion-header-bar align-title="center" class="bar-royal">
|
||||
<button ng-if="action != 'check'" class="button button-back button-clear" ng-click="hideModal()">
|
||||
Close
|
||||
</button>
|
||||
</ion-header-bar>
|
||||
<div class="content">
|
||||
<div class="block-text row">
|
||||
<div class="message" ng-if="!confirmPin && !error" translate>Please enter your PIN</div>
|
||||
|
|
@ -70,4 +71,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-view>
|
||||
</ion-modal-view>
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
<i class="icon bp-arrow-right"></i>
|
||||
</a>
|
||||
|
||||
<a class="item has-setting-value item-icon-left item-icon-right" ui-sref="tabs.lockSetup" ng-if="isCordova || isDevel">
|
||||
<a class="item has-setting-value item-icon-left item-icon-right" ui-sref="tabs.lockSetup" ng-if="isCordova">
|
||||
<i class="icon ion-ios-locked-outline" ng-if="locked"></i>
|
||||
<i class="icon ion-ios-unlocked-outline" ng-if="!locked"></i>
|
||||
<span class="setting-title">{{'Lock App' | translate}}</span>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue