Better handling for errorDecrypting
This commit is contained in:
@@ -31,20 +31,27 @@ class ItemParams {
|
||||
console.assert(!this.item.dummy, "Item is dummy, should not have gotten here.", this.item.dummy)
|
||||
|
||||
var params = {uuid: this.item.uuid, content_type: this.item.content_type, deleted: this.item.deleted, created_at: this.item.created_at};
|
||||
if(this.keys && !this.item.doNotEncrypt()) {
|
||||
var encryptedParams = EncryptionHelper.encryptItem(this.item, this.keys, this.version);
|
||||
_.merge(params, encryptedParams);
|
||||
if(!this.item.errorDecrypting) {
|
||||
if(this.keys && !this.item.doNotEncrypt()) {
|
||||
var encryptedParams = EncryptionHelper.encryptItem(this.item, this.keys, this.version);
|
||||
_.merge(params, encryptedParams);
|
||||
|
||||
if(this.version !== "001") {
|
||||
params.auth_hash = null;
|
||||
if(this.version !== "001") {
|
||||
params.auth_hash = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
params.content = this.forExportFile ? this.item.createContentJSONFromProperties() : "000" + Neeto.crypto.base64(JSON.stringify(this.item.createContentJSONFromProperties()));
|
||||
if(!this.forExportFile) {
|
||||
params.enc_item_key = null;
|
||||
params.auth_hash = null;
|
||||
else {
|
||||
params.content = this.forExportFile ? this.item.createContentJSONFromProperties() : "000" + Neeto.crypto.base64(JSON.stringify(this.item.createContentJSONFromProperties()));
|
||||
if(!this.forExportFile) {
|
||||
params.enc_item_key = null;
|
||||
params.auth_hash = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Error decrypting, keep "content" and related fields as is (and do not try to encrypt, otherwise that would be undefined behavior)
|
||||
params.content = this.item.content;
|
||||
params.enc_item_key = this.item.enc_item_key;
|
||||
params.auth_hash = this.item.auth_hash;
|
||||
}
|
||||
|
||||
if(this.additionalFields) {
|
||||
|
||||
@@ -197,7 +197,8 @@ angular.module('app.frontend')
|
||||
|
||||
this.saveKeys = function(keys) {
|
||||
this._keys = keys;
|
||||
storageManager.setItem("pw", keys.pw);
|
||||
// Doesn't need to be saved.
|
||||
// storageManager.setItem("pw", keys.pw);
|
||||
storageManager.setItem("mk", keys.mk);
|
||||
storageManager.setItem("ak", keys.ak);
|
||||
}
|
||||
|
||||
@@ -149,6 +149,7 @@ class AccountMenu {
|
||||
var block = function() {
|
||||
$timeout(function(){
|
||||
$scope.onSuccessfulAuth()();
|
||||
syncManager.refreshErroredItems();
|
||||
syncManager.sync();
|
||||
})
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ class EncryptionHelper {
|
||||
|
||||
// return if uuid in auth hash does not match item uuid. Signs of tampering.
|
||||
if(keyParams.uuid && keyParams.uuid !== item.uuid) {
|
||||
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
|
||||
item.errorDecrypting = true;
|
||||
return;
|
||||
}
|
||||
@@ -99,6 +100,7 @@ class EncryptionHelper {
|
||||
var item_key = Neeto.crypto.decryptText(keyParams, requiresAuth);
|
||||
|
||||
if(!item_key) {
|
||||
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
|
||||
item.errorDecrypting = true;
|
||||
return;
|
||||
}
|
||||
@@ -110,6 +112,7 @@ class EncryptionHelper {
|
||||
|
||||
// return if uuid in auth hash does not match item uuid. Signs of tampering.
|
||||
if(itemParams.uuid && itemParams.uuid !== item.uuid) {
|
||||
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
|
||||
item.errorDecrypting = true;
|
||||
return;
|
||||
}
|
||||
@@ -121,11 +124,14 @@ class EncryptionHelper {
|
||||
|
||||
var content = Neeto.crypto.decryptText(itemParams, true);
|
||||
if(!content) {
|
||||
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
|
||||
item.errorDecrypting = true;
|
||||
} else {
|
||||
if(item.errorDecrypting == true) { item.errorDecryptingValueChanged = true;}
|
||||
// Content should only be set if it was successfully decrypted, and should otherwise remain unchanged.
|
||||
item.errorDecrypting = false;
|
||||
item.content = content;
|
||||
}
|
||||
item.content = content;
|
||||
}
|
||||
|
||||
static decryptMultipleItems(items, keys, throws) {
|
||||
@@ -139,6 +145,7 @@ class EncryptionHelper {
|
||||
try {
|
||||
this.decryptItem(item, keys);
|
||||
} catch (e) {
|
||||
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
|
||||
item.errorDecrypting = true;
|
||||
if(throws) {
|
||||
throw e;
|
||||
|
||||
@@ -118,7 +118,14 @@ class ModelManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
json_obj = _.omit(json_obj, omitFields || [])
|
||||
// Lodash's _.omit, which was previously used, seems to cause unexpected behavior
|
||||
// when json_obj is an ES6 item class. So we instead manually omit each key.
|
||||
if(Array.isArray(omitFields)) {
|
||||
for(var key of omitFields) {
|
||||
delete json_obj[key];
|
||||
}
|
||||
}
|
||||
|
||||
var item = this.findItem(json_obj.uuid);
|
||||
|
||||
if(item) {
|
||||
|
||||
@@ -77,7 +77,7 @@ class SyncManager {
|
||||
markAllItemsDirtyAndSaveOffline(callback, alternateUUIDs) {
|
||||
|
||||
// use a copy, as alternating uuid will affect array
|
||||
var originalItems = this.modelManager.allItems.slice();
|
||||
var originalItems = this.modelManager.allItems.filter((item) => {return !item.errorDecrypting}).slice();
|
||||
|
||||
var block = () => {
|
||||
var allItems = this.modelManager.allItems;
|
||||
@@ -359,9 +359,30 @@ class SyncManager {
|
||||
var keys = this.authManager.keys() || this.passcodeManager.keys();
|
||||
EncryptionHelper.decryptMultipleItems(responseItems, keys);
|
||||
var items = this.modelManager.mapResponseItemsToLocalModelsOmittingFields(responseItems, omitFields, source);
|
||||
|
||||
// During the decryption process, items may be marked as "errorDecrypting". If so, we want to be sure
|
||||
// to persist this new state by writing these items back to local storage. When an item's "errorDecrypting"
|
||||
// flag is changed, its "errorDecryptingValueChanged" flag will be set, so we can find these items by filtering (then unsetting) below:
|
||||
var itemsWithErrorStatusChange = items.filter((item) => {
|
||||
var valueChanged = item.errorDecryptingValueChanged;
|
||||
// unset after consuming value
|
||||
item.errorDecryptingValueChanged = false;
|
||||
return valueChanged;
|
||||
});
|
||||
if(itemsWithErrorStatusChange.length > 0) {
|
||||
this.writeItemsToLocalStorage(itemsWithErrorStatusChange, false, null);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
refreshErroredItems() {
|
||||
var erroredItems = this.modelManager.allItems.filter((item) => {return item.errorDecrypting == true});
|
||||
if(erroredItems.length > 0) {
|
||||
this.handleItemsResponse(erroredItems, null, ModelManager.MappingSourceLocalRetrieved);
|
||||
}
|
||||
}
|
||||
|
||||
handleUnsavedItemsResponse(unsaved) {
|
||||
if(unsaved.length == 0) {
|
||||
return;
|
||||
|
||||
@@ -89,9 +89,6 @@
|
||||
%label.block
|
||||
Encryption key:
|
||||
.wrap.normal.mt-1.selectable {{encryptionKey()}}
|
||||
%label.block.mt-5.mb-0
|
||||
Server password:
|
||||
.wrap.normal.mt-1.selectable {{serverPassword() ? serverPassword() : 'Not available. Sign out then sign back in to compute.'}}
|
||||
%label.block.mt-5.mb-0
|
||||
Authentication key:
|
||||
.wrap.normal.mt-1.selectable {{authKey() ? authKey() : 'Not available. Sign out then sign back in to compute.'}}
|
||||
|
||||
Reference in New Issue
Block a user