mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 17:02:17 -05:00
commit
47270b659c
@ -63,7 +63,6 @@ var app = angular.module('mail', [
|
|||||||
'read',
|
'read',
|
||||||
'contacts',
|
'contacts',
|
||||||
'login-new-device',
|
'login-new-device',
|
||||||
'privatekey-upload',
|
|
||||||
'infinite-scroll'
|
'infinite-scroll'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -33,26 +33,6 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.handlePaste = function(event) {
|
|
||||||
var evt = event;
|
|
||||||
if (evt.originalEvent) {
|
|
||||||
evt = evt.originalEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = evt.clipboardData.getData('text/plain');
|
|
||||||
if (!value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = value.replace(/-/g, '');
|
|
||||||
$scope.code0 = value.slice(0, 4);
|
|
||||||
$scope.code1 = value.slice(4, 8);
|
|
||||||
$scope.code2 = value.slice(8, 12);
|
|
||||||
$scope.code3 = value.slice(12, 16);
|
|
||||||
$scope.code4 = value.slice(16, 20);
|
|
||||||
$scope.code5 = value.slice(20, 24);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.checkServerForKey = function(callback) {
|
$scope.checkServerForKey = function(callback) {
|
||||||
var keyParams = pgp.getKeyParams();
|
var keyParams = pgp.getKeyParams();
|
||||||
keychain.hasPrivateKey({
|
keychain.hasPrivateKey({
|
||||||
@ -80,14 +60,12 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) {
|
|||||||
$scope.code = util.randomString(24);
|
$scope.code = util.randomString(24);
|
||||||
$scope.displayedCode = $scope.code.slice(0, 4) + '-' + $scope.code.slice(4, 8) + '-' + $scope.code.slice(8, 12) + '-' + $scope.code.slice(12, 16) + '-' + $scope.code.slice(16, 20) + '-' + $scope.code.slice(20, 24);
|
$scope.displayedCode = $scope.code.slice(0, 4) + '-' + $scope.code.slice(4, 8) + '-' + $scope.code.slice(8, 12) + '-' + $scope.code.slice(12, 16) + '-' + $scope.code.slice(16, 20) + '-' + $scope.code.slice(20, 24);
|
||||||
|
|
||||||
// clear input fields of any previous artifacts
|
// clear input field of any previous artifacts
|
||||||
$scope.code0 = $scope.code1 = $scope.code2 = $scope.code3 = $scope.code4 = $scope.code5 = '';
|
$scope.inputCode = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.verifyCode = function() {
|
$scope.verifyCode = function() {
|
||||||
var inputCode = '' + $scope.code0 + $scope.code1 + $scope.code2 + $scope.code3 + $scope.code4 + $scope.code5;
|
if ($scope.inputCode.toUpperCase() !== $scope.code) {
|
||||||
|
|
||||||
if (inputCode.toUpperCase() !== $scope.code) {
|
|
||||||
var err = new Error('The code does not match. Please go back and check the generated code.');
|
var err = new Error('The code does not match. Please go back and check the generated code.');
|
||||||
dialog.error(err);
|
dialog.error(err);
|
||||||
return false;
|
return false;
|
||||||
@ -171,26 +149,4 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// Directives
|
|
||||||
//
|
|
||||||
|
|
||||||
var ngModule = angular.module('privatekey-upload', []);
|
|
||||||
ngModule.directive('focusNext', function() {
|
|
||||||
return {
|
|
||||||
link: function(scope, element, attr) {
|
|
||||||
var maxLen = element[0].maxLength;
|
|
||||||
|
|
||||||
scope.$watch(attr.ngModel, function(val) {
|
|
||||||
if (val && val.length === maxLen) {
|
|
||||||
var nextinput = element.next('input');
|
|
||||||
if (nextinput.length) {
|
|
||||||
nextinput[0].focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = PrivateKeyUploadCtrl;
|
module.exports = PrivateKeyUploadCtrl;
|
@ -70,10 +70,8 @@ var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams, auth
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.decryptAndStorePrivateKeyLocally = function() {
|
$scope.decryptAndStorePrivateKeyLocally = function() {
|
||||||
var inputCode = '' + $scope.code0 + $scope.code1 + $scope.code2 + $scope.code3 + $scope.code4 + $scope.code5;
|
|
||||||
|
|
||||||
var options = $scope.encryptedPrivateKey;
|
var options = $scope.encryptedPrivateKey;
|
||||||
options.code = inputCode.toUpperCase();
|
options.code = $scope.code.toUpperCase();
|
||||||
|
|
||||||
keychain.decryptAndStorePrivateKeyLocally(options, function(err, privateKey) {
|
keychain.decryptAndStorePrivateKeyLocally(options, function(err, privateKey) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -108,26 +106,6 @@ var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams, auth
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.handlePaste = function(event) {
|
|
||||||
var evt = event;
|
|
||||||
if (evt.originalEvent) {
|
|
||||||
evt = evt.originalEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = evt.clipboardData.getData('text/plain');
|
|
||||||
if (!value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = value.replace(/-/g, '');
|
|
||||||
$scope.code0 = value.slice(0, 4);
|
|
||||||
$scope.code1 = value.slice(4, 8);
|
|
||||||
$scope.code2 = value.slice(8, 12);
|
|
||||||
$scope.code3 = value.slice(12, 16);
|
|
||||||
$scope.code4 = value.slice(16, 20);
|
|
||||||
$scope.code5 = value.slice(20, 24);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// helper functions
|
// helper functions
|
||||||
//
|
//
|
||||||
|
@ -173,4 +173,135 @@ ngModule.directive('woClickFileInput', function() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ngModule.directive('woInputCode', function() {
|
||||||
|
var BLOCK_SIZE = 4;
|
||||||
|
var NUM_BLOCKS = 6;
|
||||||
|
var BLOCK_DIVIDER = '-';
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
|
||||||
|
function getBlockIndex(code, pos) {
|
||||||
|
return code.substr(0, pos).replace(new RegExp('[^' + BLOCK_DIVIDER + ']', 'g'), '').length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlockDimensions(code, i) {
|
||||||
|
var start = 0;
|
||||||
|
var end = code.length;
|
||||||
|
var found = 0;
|
||||||
|
for(var j = 0; j < code.length; j++) {
|
||||||
|
if(code[j] === BLOCK_DIVIDER) {
|
||||||
|
found++;
|
||||||
|
if(found === i) {
|
||||||
|
start = j + 1;
|
||||||
|
}
|
||||||
|
if(found === i + 1) {
|
||||||
|
end = j - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlock(code, i) {
|
||||||
|
var dims = getBlockDimensions(code, i);
|
||||||
|
return code.substring(dims.start, dims.end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBlock(code, i, val) {
|
||||||
|
var dims = getBlockDimensions(code, i);
|
||||||
|
return code.substring(0, dims.start) + val + code.substring(dims.end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
require: 'ngModel',
|
||||||
|
link: function(scope, elm, attrs, ngModelCtrl) {
|
||||||
|
function format(val) {
|
||||||
|
var str = '';
|
||||||
|
|
||||||
|
// check if value exists
|
||||||
|
if (!val) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i = 0; i < val.length; i++) {
|
||||||
|
if(i > 0 && i % BLOCK_SIZE === 0) {
|
||||||
|
str += BLOCK_DIVIDER;
|
||||||
|
}
|
||||||
|
str += val[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(val) {
|
||||||
|
var parsed = val.replace(new RegExp(BLOCK_DIVIDER, 'g'), '').trim();
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModelCtrl.$parsers.push(parse);
|
||||||
|
ngModelCtrl.$formatters.push(format);
|
||||||
|
|
||||||
|
var maxlength = NUM_BLOCKS * (BLOCK_SIZE + 1) - 1;
|
||||||
|
|
||||||
|
elm.on('input', function() {
|
||||||
|
var start = this.selectionStart;
|
||||||
|
var end = this.selectionEnd;
|
||||||
|
var val = this.value;
|
||||||
|
|
||||||
|
var blockIndex = getBlockIndex(val, start);
|
||||||
|
var blockDims = getBlockDimensions(val, blockIndex);
|
||||||
|
var block = getBlock(val, blockIndex);
|
||||||
|
|
||||||
|
// add new block to the end
|
||||||
|
if(val.length < maxlength && start === val.length && block.length > BLOCK_SIZE) {
|
||||||
|
val = setBlock(val, blockIndex, block.substr(0, BLOCK_SIZE) + BLOCK_DIVIDER + block.substr(BLOCK_SIZE));
|
||||||
|
start = val.length;
|
||||||
|
end = val.length;
|
||||||
|
}
|
||||||
|
// maxsize in last block
|
||||||
|
else if(start === val.length && block.length > BLOCK_SIZE) {
|
||||||
|
val = setBlock(val, blockIndex, block.substr(0, BLOCK_SIZE));
|
||||||
|
start = val.length;
|
||||||
|
end = val.length;
|
||||||
|
}
|
||||||
|
// overwrite next char if block is full
|
||||||
|
else if(block.length > BLOCK_SIZE && start <= blockDims.end) {
|
||||||
|
val = val.substring(0, start) + val.substring(start + 1);
|
||||||
|
}
|
||||||
|
// jump to next block if cursor is at the end of the block and block is full
|
||||||
|
else if(block.length > BLOCK_SIZE && start === blockDims.end + 1) {
|
||||||
|
var overflow = block.substr(BLOCK_SIZE);
|
||||||
|
if(overflow.length > BLOCK_SIZE) {
|
||||||
|
overflow = overflow.substr(0, BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
val = setBlock(val, blockIndex, block.substr(0, BLOCK_SIZE));
|
||||||
|
|
||||||
|
var nextBlock = getBlock(val, blockIndex + 1);
|
||||||
|
val = setBlock(val, blockIndex + 1, (overflow + nextBlock).substr(0, BLOCK_SIZE));
|
||||||
|
|
||||||
|
start++;
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModelCtrl.$setViewValue(val);
|
||||||
|
ngModelCtrl.$render();
|
||||||
|
|
||||||
|
this.setSelectionRange(start, end);
|
||||||
|
});
|
||||||
|
|
||||||
|
elm.on('click', function() {
|
||||||
|
var blockIndex = getBlockIndex(this.value, this.selectionStart);
|
||||||
|
var dims = getBlockDimensions(this.value, blockIndex);
|
||||||
|
|
||||||
|
this.setSelectionRange(dims.start, dims.end + 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = ngModule;
|
module.exports = ngModule;
|
@ -43,14 +43,8 @@
|
|||||||
<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
|
<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
|
||||||
|
|
||||||
<div class="form__row">
|
<div class="form__row">
|
||||||
<div class="input-code">
|
<input type="text" class="input-text" ng-model="code" wo-input-code wo-focus-me="step === 2"
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code0" wo-focus-me="step === 2" focus-next required ng-paste="handlePaste($event)"> -
|
required pattern="([a-zA-Z0-9\-]*)" placeholder="0000-0000-0000-0000-0000-0000">
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code1" focus-next required> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code2" focus-next required> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code3" focus-next required> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code4" focus-next required> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code5" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="spinner-block" ng-show="busy">
|
<div class="spinner-block" ng-show="busy">
|
||||||
<span class="spinner spinner--big"></span>
|
<span class="spinner spinner--big"></span>
|
||||||
|
@ -25,14 +25,8 @@
|
|||||||
<div ng-show="step === 2">
|
<div ng-show="step === 2">
|
||||||
<p class="typo-paragraph">Please confirm the keychain code you have written down.</p>
|
<p class="typo-paragraph">Please confirm the keychain code you have written down.</p>
|
||||||
<form class="form">
|
<form class="form">
|
||||||
<div class="input-code">
|
<input type="text" class="input-text" ng-model="inputCode" wo-input-code wo-focus-me="step === 2"
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code0" wo-focus-me="step === 2" focus-next ng-paste="handlePaste($event)"> -
|
required pattern="([a-zA-Z0-9\-]*)" placeholder="0000-0000-0000-0000-0000-0000">
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code1" focus-next> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code2" focus-next> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code3" focus-next> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code4" focus-next> -
|
|
||||||
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code5">
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -78,70 +78,33 @@ describe('Private Key Upload Controller unit test', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handlePaste', function() {
|
|
||||||
it('should work', function() {
|
|
||||||
scope.handlePaste({
|
|
||||||
clipboardData: {
|
|
||||||
getData: function(val) {
|
|
||||||
expect(val).to.equal('text/plain');
|
|
||||||
return '1qaz-2wsx-3edc-4rfv-5tgb-6yhn';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(scope.code0).to.equal('1qaz');
|
|
||||||
expect(scope.code1).to.equal('2wsx');
|
|
||||||
expect(scope.code2).to.equal('3edc');
|
|
||||||
expect(scope.code3).to.equal('4rfv');
|
|
||||||
expect(scope.code4).to.equal('5tgb');
|
|
||||||
expect(scope.code5).to.equal('6yhn');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('displayUploadUi', function() {
|
describe('displayUploadUi', function() {
|
||||||
it('should work', function() {
|
it('should work', function() {
|
||||||
// add some artifacts from a previous key input
|
// add some artifacts from a previous key input
|
||||||
scope.code0 = scope.code1 = scope.code2 = scope.code3 = scope.code4 = scope.code5 = 'asdasd';
|
scope.inputCode = 'asdasd';
|
||||||
|
|
||||||
scope.displayUploadUi();
|
scope.displayUploadUi();
|
||||||
expect(scope.step).to.equal(1);
|
expect(scope.step).to.equal(1);
|
||||||
expect(scope.code.length).to.equal(24);
|
expect(scope.code.length).to.equal(24);
|
||||||
|
|
||||||
// artifacts should be cleared
|
// artifacts should be cleared
|
||||||
expect(scope.code0).to.be.empty;
|
expect(scope.inputCode).to.be.empty;
|
||||||
expect(scope.code1).to.be.empty;
|
|
||||||
expect(scope.code2).to.be.empty;
|
|
||||||
expect(scope.code3).to.be.empty;
|
|
||||||
expect(scope.code4).to.be.empty;
|
|
||||||
expect(scope.code5).to.be.empty;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('verifyCode', function() {
|
describe('verifyCode', function() {
|
||||||
it('should fail for wrong code', function() {
|
it('should fail for wrong code', function() {
|
||||||
scope.code0 = 'b';
|
scope.inputCode = 'bbbbbb';
|
||||||
scope.code1 = 'b';
|
scope.code = 'AAAAAA';
|
||||||
scope.code2 = 'b';
|
|
||||||
scope.code3 = 'b';
|
|
||||||
scope.code4 = 'b';
|
|
||||||
scope.code5 = 'b';
|
|
||||||
scope.code = 'aaaaaa';
|
|
||||||
|
|
||||||
scope.onError = function() {};
|
|
||||||
expect(scope.verifyCode()).to.be.false;
|
expect(scope.verifyCode()).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work', function() {
|
it('should work', function() {
|
||||||
scope.code0 = 'a';
|
scope.inputCode = 'aaAaaa';
|
||||||
scope.code1 = 'a';
|
scope.code = 'AAAAAA';
|
||||||
scope.code2 = 'a';
|
|
||||||
scope.code3 = 'a';
|
|
||||||
scope.code4 = 'a';
|
|
||||||
scope.code5 = 'a';
|
|
||||||
scope.code = 'aaaaaa';
|
|
||||||
|
|
||||||
scope.onError = function() {};
|
expect(scope.verifyCode()).to.be.true;
|
||||||
expect(scope.verifyCode()).to.be.false;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -113,34 +113,9 @@ describe('Login Private Key Download Controller unit test', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handlePaste', function() {
|
|
||||||
it('should work', function() {
|
|
||||||
scope.handlePaste({
|
|
||||||
clipboardData: {
|
|
||||||
getData: function(val) {
|
|
||||||
expect(val).to.equal('text/plain');
|
|
||||||
return '1qaz-2wsx-3edc-4rfv-5tgb-6yhn';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(scope.code0).to.equal('1qaz');
|
|
||||||
expect(scope.code1).to.equal('2wsx');
|
|
||||||
expect(scope.code2).to.equal('3edc');
|
|
||||||
expect(scope.code3).to.equal('4rfv');
|
|
||||||
expect(scope.code4).to.equal('5tgb');
|
|
||||||
expect(scope.code5).to.equal('6yhn');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('decryptAndStorePrivateKeyLocally', function() {
|
describe('decryptAndStorePrivateKeyLocally', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
scope.code0 = '0';
|
scope.code = '012345';
|
||||||
scope.code1 = '1';
|
|
||||||
scope.code2 = '2';
|
|
||||||
scope.code3 = '3';
|
|
||||||
scope.code4 = '4';
|
|
||||||
scope.code5 = '5';
|
|
||||||
|
|
||||||
scope.encryptedPrivateKey = {
|
scope.encryptedPrivateKey = {
|
||||||
encryptedPrivateKey: 'encryptedPrivateKey'
|
encryptedPrivateKey: 'encryptedPrivateKey'
|
||||||
|
Loading…
Reference in New Issue
Block a user