before destruction

This commit is contained in:
Mo Bitar
2017-01-27 18:32:27 -06:00
parent 7c88531cff
commit ce053226a5
8 changed files with 29 additions and 51 deletions

View File

@@ -1,9 +1,8 @@
class ItemParams { class ItemParams {
constructor(item, ek, encryptionHelper) { constructor(item, ek) {
this.item = item; this.item = item;
this.ek = ek; this.ek = ek;
this.encryptionHelper = encryptionHelper;
} }
paramsForExportFile() { paramsForExportFile() {
@@ -34,7 +33,7 @@ class ItemParams {
var params = {uuid: this.item.uuid, content_type: this.item.content_type, deleted: this.item.deleted, created_at: this.item.created_at}; var params = {uuid: this.item.uuid, content_type: this.item.content_type, deleted: this.item.deleted, created_at: this.item.created_at};
if(this.ek) { if(this.ek) {
this.encryptionHelper.encryptItem(itemCopy, this.ek); EncryptionHelper.encryptItem(itemCopy, this.ek);
params.content = itemCopy.content; params.content = itemCopy.content;
params.enc_item_key = itemCopy.enc_item_key; params.enc_item_key = itemCopy.enc_item_key;
params.auth_hash = itemCopy.auth_hash; params.auth_hash = itemCopy.auth_hash;

View File

@@ -10,7 +10,7 @@ class AccountNewAccountSection {
controller($scope, apiController, modelManager, $timeout, dbManager, syncManager) { controller($scope, apiController, modelManager, $timeout, dbManager, syncManager) {
'ngInject'; 'ngInject';
$scope.formData = {mergeLocal: true, url: syncManager.defaultServerURL()}; $scope.formData = {url: syncManager.defaultServerURL()};
$scope.user = apiController.user; $scope.user = apiController.user;
$scope.showForm = syncManager.syncProviders.length == 0; $scope.showForm = syncManager.syncProviders.length == 0;
@@ -42,18 +42,6 @@ class AccountNewAccountSection {
}) })
} }
$scope.localNotesCount = function() {
return modelManager.filteredNotes.length;
}
$scope.mergeLocalChanged = function() {
if(!$scope.formData.mergeLocal) {
if(!confirm("Unchecking this option means any of the notes you have written while you were signed out will be deleted. Are you sure you want to discard these notes?")) {
$scope.formData.mergeLocal = true;
}
}
}
$scope.loginSubmitPressed = function() { $scope.loginSubmitPressed = function() {
$scope.formData.status = "Generating Login Keys..."; $scope.formData.status = "Generating Login Keys...";
console.log("logging in with url", $scope.formData.url); console.log("logging in with url", $scope.formData.url);
@@ -87,12 +75,6 @@ class AccountNewAccountSection {
}); });
}) })
} }
$scope.encryptionStatusForNotes = function() {
var allNotes = modelManager.filteredNotes;
return allNotes.length + "/" + allNotes.length + " notes encrypted";
}
} }
} }

View File

@@ -17,9 +17,11 @@ class KeyManager {
} }
keyForName(name) { keyForName(name) {
return _.find(this.keys, function(key){ var keyObj = _.find(this.keys, function(key){
return key.name.toLowerCase() == name.toLowerCase(); return key.name.toLowerCase() == name.toLowerCase();
}); });
return keyObj ? keyObj.key : null;
} }
deleteKey(name) { deleteKey(name) {

View File

@@ -1,8 +1,9 @@
class EncryptionHelper { class EncryptionHelper {
encryptItem(item, key) { static encryptItem(item, key) {
var item_key = null; var item_key = null;
if(item.enc_item_key) { if(item.enc_item_key) {
// we reuse the key, but this is optional
item_key = Neeto.crypto.decryptText(item.enc_item_key, key); item_key = Neeto.crypto.decryptText(item.enc_item_key, key);
} else { } else {
item_key = Neeto.crypto.generateRandomEncryptionKey(); item_key = Neeto.crypto.generateRandomEncryptionKey();
@@ -19,7 +20,7 @@ class EncryptionHelper {
item.local_encryption_scheme = "1.0"; item.local_encryption_scheme = "1.0";
} }
decryptItem(item, key) { static decryptItem(item, key) {
var item_key = Neeto.crypto.decryptText(item.enc_item_key, key); var item_key = Neeto.crypto.decryptText(item.enc_item_key, key);
var ek = Neeto.crypto.firstHalfOfKey(item_key); var ek = Neeto.crypto.firstHalfOfKey(item_key);
@@ -34,7 +35,7 @@ class EncryptionHelper {
item.content = content; item.content = content;
} }
decryptMultipleItems(items, key) { static decryptMultipleItems(items, key) {
for (var item of items) { for (var item of items) {
if(item.deleted == true) { if(item.deleted == true) {
continue; continue;
@@ -59,5 +60,3 @@ class EncryptionHelper {
} }
} }
angular.module('app.frontend').service('encryptionHelper', EncryptionHelper);

View File

@@ -60,7 +60,7 @@ class SyncManager {
this.didMakeChangesToSyncProviders(); this.didMakeChangesToSyncProviders();
} }
primarySyncProvider() { get primarySyncProvider() {
return _.find(this.syncProviders, {primary: true}); return _.find(this.syncProviders, {primary: true});
} }
@@ -107,7 +107,7 @@ class SyncManager {
addAccountBasedSyncProvider({url, email, uuid, ek, jwt, auth_params} = {}) { addAccountBasedSyncProvider({url, email, uuid, ek, jwt, auth_params} = {}) {
var provider = new SyncProvider({ var provider = new SyncProvider({
url: url + "/items/sync", url: url + "/items/sync",
primary: !this.primarySyncProvider(), primary: !this.primarySyncProvider,
email: email, email: email,
uuid: uuid, uuid: uuid,
jwt: jwt, jwt: jwt,
@@ -119,8 +119,6 @@ class SyncManager {
this.syncProviders.push(provider); this.syncProviders.push(provider);
this.didMakeChangesToSyncProviders();
this.keyManager.addKey(provider.keyName, ek); this.keyManager.addKey(provider.keyName, ek);
this.enableSyncProvider(provider, this.enabledProviders == 0); this.enableSyncProvider(provider, this.enabledProviders == 0);
@@ -136,6 +134,9 @@ class SyncManager {
} }
enableSyncProvider(syncProvider, primary) { enableSyncProvider(syncProvider, primary) {
// we want to sync the new provider where our current primary one is
syncProvider.syncToken = this.primarySyncProvider ? this.primarySyncProvider.syncToken : null;
if(primary) { if(primary) {
for(var provider of this.syncProviders) { for(var provider of this.syncProviders) {
provider.primary = false; provider.primary = false;
@@ -161,7 +162,7 @@ class SyncManager {
} }
clearSyncToken() { clearSyncToken() {
var primary = this.primarySyncProvider(); var primary = this.primarySyncProvider;
if(primary) { if(primary) {
primary.syncToken = null; primary.syncToken = null;
} }

View File

@@ -16,7 +16,7 @@ class SyncProvider {
this.pendingItems = []; this.pendingItems = [];
} }
this.pendingItems = this.pendingItems.concat(items); this.pendingItems = _.uniqBy(this.pendingItems.concat(items), "uuid");
} }
removePendingItems(items) { removePendingItems(items) {

View File

@@ -1,10 +1,9 @@
class SyncRunner { class SyncRunner {
constructor($rootScope, modelManager, dbManager, encryptionHelper, keyManager, Restangular) { constructor($rootScope, modelManager, dbManager, keyManager, Restangular) {
this.rootScope = $rootScope; this.rootScope = $rootScope;
this.modelManager = modelManager; this.modelManager = modelManager;
this.dbManager = dbManager; this.dbManager = dbManager;
this.encryptionHelper = encryptionHelper;
this.keyManager = keyManager; this.keyManager = keyManager;
this.Restangular = Restangular; this.Restangular = Restangular;
} }
@@ -90,9 +89,9 @@ class SyncRunner {
return; return;
} }
// whether this is a repeat sync (a continuation from another sync; we use this to update status accurately) var isContinuationSync = provider.needsMoreSync;
var isRepeatRun = provider.repeatOnCompletion;
provider.repeatOnCompletion = false;
provider.syncOpInProgress = true; provider.syncOpInProgress = true;
let submitLimit = 100; let submitLimit = 100;
@@ -100,17 +99,16 @@ class SyncRunner {
var subItems = allItems.slice(0, submitLimit); var subItems = allItems.slice(0, submitLimit);
if(subItems.length < allItems.length) { if(subItems.length < allItems.length) {
// more items left to be synced, repeat // more items left to be synced, repeat
provider.repeatOnCompletion = true; provider.needsMoreSync = true;
} else { } else {
provider.repeatOnCompletion = false; provider.needsMoreSync = false;
} }
if(!isRepeatRun) { if(!isContinuationSync) {
provider.syncStatus.total = allItems.length; provider.syncStatus.total = allItems.length;
provider.syncStatus.current = 0; provider.syncStatus.current = 0;
} }
// Remove dirty items now. If this operation fails, we'll re-add them. // Remove dirty items now. If this operation fails, we'll re-add them.
// This allows us to queue changes on the same item // This allows us to queue changes on the same item
provider.removePendingItems(subItems); provider.removePendingItems(subItems);
@@ -118,12 +116,13 @@ class SyncRunner {
var request = this.Restangular.oneUrl(provider.url, provider.url); var request = this.Restangular.oneUrl(provider.url, provider.url);
request.limit = 150; request.limit = 150;
request.items = _.map(subItems, function(item){ request.items = _.map(subItems, function(item){
var itemParams = new ItemParams(item, provider.ek); var key = this.keyManager.keyForName(provider.keyName);
var itemParams = new ItemParams(item, key);
itemParams.additionalFields = options.additionalFields; itemParams.additionalFields = options.additionalFields;
return itemParams.paramsForSync(); return itemParams.paramsForSync();
}.bind(this)); }.bind(this));
// request.sync_token = provider.syncToken; request.sync_token = provider.syncToken;
request.cursor_token = provider.cursorToken; request.cursor_token = provider.cursorToken;
console.log("Syncing with provider:", provider, "items:", subItems.length, "token", request.sync_token); console.log("Syncing with provider:", provider, "items:", subItems.length, "token", request.sync_token);
@@ -155,7 +154,7 @@ class SyncRunner {
provider.syncOpInProgress = false; provider.syncOpInProgress = false;
provider.syncStatus.current += subItems.length; provider.syncStatus.current += subItems.length;
if(provider.cursorToken || provider.repeatOnCompletion == true) { if(provider.cursorToken || provider.repeatOnCompletion || provider.needsMoreSync) {
this.__performSyncWithProvider(provider, options, callback); this.__performSyncWithProvider(provider, options, callback);
} else { } else {
if(callback) { if(callback) {
@@ -206,8 +205,8 @@ class SyncRunner {
} }
handleItemsResponse(responseItems, omitFields, syncProvider) { handleItemsResponse(responseItems, omitFields, syncProvider) {
var ek = syncProvider ? this.keyManager.keyForName(syncProvider.keyName).key : null; var ek = syncProvider ? this.keyManager.keyForName(syncProvider.keyName) : null;
this.encryptionHelper.decryptMultipleItems(responseItems, ek); EncryptionHelper.decryptMultipleItems(responseItems, ek);
return this.modelManager.mapResponseItemsToLocalModelsOmittingFields(responseItems, omitFields); return this.modelManager.mapResponseItemsToLocalModelsOmittingFields(responseItems, omitFields);
} }
} }

View File

@@ -10,10 +10,6 @@
%input.form-control{:placeholder => 'Password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'formData.user_password'} %input.form-control{:placeholder => 'Password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'formData.user_password'}
%div{"ng-if" => "!formData.status"} %div{"ng-if" => "!formData.status"}
.checkbox{"ng-if" => "localNotesCount() > 0"}
%label
%input{"type" => "checkbox", "ng-model" => "formData.mergeLocal", "ng-bind" => "true", "ng-change" => "mergeLocalChanged()"}
Merge local notes ({{localNotesCount()}} notes)
%button.btn.dark-button.half-button{"ng-click" => "loginSubmitPressed()", "data-style" => "expand-right", "data-size" => "s", "state" => "buttonState"} %button.btn.dark-button.half-button{"ng-click" => "loginSubmitPressed()", "data-style" => "expand-right", "data-size" => "s", "state" => "buttonState"}
%span Sign In %span Sign In
%button.btn.dark-button.half-button{"ng-click" => "submitRegistrationForm()", "data-style" => "expand-right", "data-size" => "s", "state" => "buttonState"} %button.btn.dark-button.half-button{"ng-click" => "submitRegistrationForm()", "data-style" => "expand-right", "data-size" => "s", "state" => "buttonState"}