From 2274e6835df9bc297e76386bf97f25f8615ff1de Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Sun, 29 Jan 2017 11:36:20 -0600 Subject: [PATCH] handle uuid conflicts --- .../app/frontend/models/api/item.js | 4 --- .../javascripts/app/services/dbManager.js | 3 +- .../services/directives/views/accountMenu.js | 6 ++-- .../javascripts/app/services/modelManager.js | 16 ++++++++-- .../javascripts/app/services/syncManager.js | 31 ++++++++++++------- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/app/frontend/models/api/item.js b/app/assets/javascripts/app/frontend/models/api/item.js index 0409580eb..f6129f5a0 100644 --- a/app/assets/javascripts/app/frontend/models/api/item.js +++ b/app/assets/javascripts/app/frontend/models/api/item.js @@ -50,10 +50,6 @@ class Item { } } - alternateUUID() { - this.uuid = Neeto.crypto.generateUUID(); - } - setDirty(dirty) { this.dirty = dirty; diff --git a/app/assets/javascripts/app/services/dbManager.js b/app/assets/javascripts/app/services/dbManager.js index 0d702b032..5c33bc5de 100644 --- a/app/assets/javascripts/app/services/dbManager.js +++ b/app/assets/javascripts/app/services/dbManager.js @@ -98,11 +98,12 @@ class DBManager { }, null) } - deleteItem(item) { + deleteItem(item, callback) { this.openDatabase((db) => { var request = db.transaction("items", "readwrite").objectStore("items").delete(item.uuid); request.onsuccess = function(event) { console.log("Successfully deleted item", item.uuid); + callback(true); }; }, null) } diff --git a/app/assets/javascripts/app/services/directives/views/accountMenu.js b/app/assets/javascripts/app/services/directives/views/accountMenu.js index 42766057f..5e9d74e62 100644 --- a/app/assets/javascripts/app/services/directives/views/accountMenu.js +++ b/app/assets/javascripts/app/services/directives/views/accountMenu.js @@ -221,8 +221,10 @@ class AccountMenu { items: items } - // auth params are only needed when encrypted with a standard file key - data["auth_params"] = authManager.getAuthParams(); + if(ek) { + // auth params are only needed when encrypted with a standard file key + data["auth_params"] = authManager.getAuthParams(); + } return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */)); } diff --git a/app/assets/javascripts/app/services/modelManager.js b/app/assets/javascripts/app/services/modelManager.js index e07cd0893..aa436b6e2 100644 --- a/app/assets/javascripts/app/services/modelManager.js +++ b/app/assets/javascripts/app/services/modelManager.js @@ -22,6 +22,18 @@ class ModelManager { }) } + alternateUUIDForItem(item, callback) { + // we need to clone this item and give it a new uuid, then delete item with old uuid from db (you can't mofidy uuid's in our indexeddb setup) + var newItem = this.createItem(item); + newItem.uuid = Neeto.crypto.generateUUID(); + this.removeItemLocally(item, function(){ + this.addItem(newItem); + newItem.setDirty(true); + newItem.markAllReferencesDirty(); + callback(); + }.bind(this)); + } + allItemsMatchingTypes(contentTypes) { return this.items.filter(function(item){ return (_.includes(contentTypes, item.content_type) || _.includes(contentTypes, "*")) && !item.dummy; @@ -213,7 +225,7 @@ class ModelManager { item.removeAllRelationships(); } - removeItemLocally(item) { + removeItemLocally(item, callback) { _.pull(this.items, item); item.isBeingRemovedLocally(); @@ -227,7 +239,7 @@ class ModelManager { _.pull(this._extensions, item); } - this.dbManager.deleteItem(item); + this.dbManager.deleteItem(item, callback); } /* diff --git a/app/assets/javascripts/app/services/syncManager.js b/app/assets/javascripts/app/services/syncManager.js index ca5cd19f1..fadb6977e 100644 --- a/app/assets/javascripts/app/services/syncManager.js +++ b/app/assets/javascripts/app/services/syncManager.js @@ -50,7 +50,7 @@ class SyncManager { this.modelManager.removeItemLocally(item); } } - + if(callback) { callback({success: true}); } @@ -202,18 +202,25 @@ class SyncManager { } console.log("Handle unsaved", unsaved); - for(var mapping of unsaved) { - var itemResponse = mapping.item; - var item = this.modelManager.findItem(itemResponse.uuid); - var error = mapping.error; - if(error.tag == "uuid_conflict") { - item.alternateUUID(); - item.setDirty(true); - item.markAllReferencesDirty(); - } - } - this.sync(null, {additionalFields: ["created_at", "updated_at"]}); + var i = 0; + var handleNext = function() { + if (i < unsaved.length) { + var mapping = unsaved[i]; + var itemResponse = mapping.item; + var item = this.modelManager.findItem(itemResponse.uuid); + var error = mapping.error; + if(error.tag == "uuid_conflict") { + // uuid conflicts can occur if a user attempts to import an old data archive with uuids form the old account into a new account + this.modelManager.alternateUUIDForItem(item, handleNext); + } + ++i; + } else { + this.sync(null, {additionalFields: ["created_at", "updated_at"]}); + } + }.bind(this); + + handleNext(); } handleItemsResponse(responseItems, omitFields) {