Skip to content

Commit 21dd631

Browse files
committed
Fix: Recover account after error
1 parent e9933aa commit 21dd631

File tree

1 file changed

+114
-65
lines changed

1 file changed

+114
-65
lines changed

src/lib/Account.js

Lines changed: 114 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const Parallel = require('async-parallel')
77
const BATCH_SIZE = 10
88

99
export default class Account {
10-
static async get (id) {
10+
static async get(id) {
1111
if (!this.cache) {
1212
this.cache = {}
1313
}
@@ -27,7 +27,7 @@ export default class Account {
2727
return account
2828
}
2929

30-
static async create (data) {
30+
static async create(data) {
3131
let id = '' + Math.floor(Math.random() * 10000000000)
3232
let storage = new AccountStorage(id)
3333

@@ -36,50 +36,49 @@ export default class Account {
3636
return account
3737
}
3838

39-
constructor (id, storageAdapter, serverAdapter, treeAdapter) {
39+
constructor(id, storageAdapter, serverAdapter, treeAdapter) {
4040
this.server = serverAdapter
4141
this.id = id
4242
this.storage = storageAdapter
4343
this.tree = treeAdapter
4444
}
4545

46-
async delete () {
46+
async delete() {
4747
await this.storage.deleteAccountData()
4848
}
4949

50-
getLabel () {
50+
getLabel() {
5151
return this.server.getLabel()
5252
}
5353

54-
getData () {
54+
getData() {
5555
return this.server.getData()
5656
}
5757

58-
async setData (data) {
58+
async setData(data) {
5959
this.server.setData(data)
6060
let background = await browser.runtime.getBackgroundPage()
6161
await this.storage.setAccountData(data, background.controller.key)
6262
}
6363

64-
async updateFromStorage () {
64+
async updateFromStorage() {
6565
let background = await browser.runtime.getBackgroundPage()
6666
let data = await this.storage.getAccountData(background.controller.key)
6767
this.server.setData(data)
6868
}
6969

70-
async tracksBookmark (localId) {
71-
if (!(await this.isInitialized())) return false
70+
async tracksBookmark(localId) {
71+
if (!await this.isInitialized()) return false
7272
let mappings = await this.storage.getMappings()
73-
return Object.keys(mappings.LocalToServer)
74-
.some(id => localId === id)
73+
return Object.keys(mappings.LocalToServer).some(id => localId === id)
7574
}
7675

77-
renderOptions (ctl, rootPath) {
76+
renderOptions(ctl, rootPath) {
7877
let originalData = this.getData()
7978

8079
var modifiedCtl = {
81-
...ctl
82-
, update: (data) => {
80+
...ctl,
81+
update: data => {
8382
if (JSON.stringify(data) === JSON.stringify(originalData)) return
8483
if (originalData.serverRoot !== data.serverRoot) {
8584
this.storage.initCache()
@@ -92,7 +91,7 @@ export default class Account {
9291
return this.server.renderOptions(modifiedCtl, rootPath)
9392
}
9493

95-
async init () {
94+
async init() {
9695
console.log('initializing account ' + this.id)
9796
const accData = this.getData()
9897
try {
@@ -101,8 +100,8 @@ export default class Account {
101100
let parentNode = await browser.bookmarks.getTree()
102101
let bookmarksBar = parentNode[0].children[0]
103102
let node = await browser.bookmarks.create({
104-
title: 'Nextcloud (' + this.getLabel() + ')'
105-
, parentId: bookmarksBar.id
103+
title: 'Nextcloud (' + this.getLabel() + ')',
104+
parentId: bookmarksBar.id
106105
})
107106
accData.localRoot = node.id
108107
await this.setData(accData)
@@ -112,7 +111,7 @@ export default class Account {
112111
this.tree = new Tree(this.storage, accData.localRoot, accData.serverRoot)
113112
}
114113

115-
async isInitialized () {
114+
async isInitialized() {
116115
try {
117116
let localRoot = this.getData().localRoot
118117
await browser.bookmarks.getSubTree(localRoot)
@@ -123,13 +122,13 @@ export default class Account {
123122
}
124123
}
125124

126-
async sync () {
125+
async sync() {
127126
try {
128127
if (this.getData().syncing || this.syncing) return
129128
console.log('Starting sync process for account ' + this.getLabel())
130129
this.syncing = true
131-
await this.setData({...this.getData(), syncing: true})
132-
if (!(await this.isInitialized())) {
130+
await this.setData({ ...this.getData(), syncing: true })
131+
if (!await this.isInitialized()) {
133132
await this.init()
134133
}
135134

@@ -138,8 +137,11 @@ export default class Account {
138137
let mappings = await this.storage.getMappings()
139138
await this.tree.load(mappings)
140139

141-
if (Object.keys(mappings.LocalToServer).length === 0 && this.tree.getAllBookmarks().length !== 0) {
142-
await this.setData({...this.getData(), syncing: 'initial'})
140+
if (
141+
Object.keys(mappings.LocalToServer).length === 0 &&
142+
this.tree.getAllBookmarks().length !== 0
143+
) {
144+
await this.setData({ ...this.getData(), syncing: 'initial' })
143145
}
144146

145147
// Deletes things we've known but that are no longer there locally
@@ -148,8 +150,9 @@ export default class Account {
148150
await this.sync_createOnServer(mappings)
149151

150152
let serverRoot = this.getData().serverRoot
151-
let serverList = (await this.server.pullBookmarks())
152-
.filter(bm => serverRoot ? bm.path.indexOf(serverRoot) === 0 : true)
153+
let serverList = (await this.server.pullBookmarks()).filter(
154+
bm => (serverRoot ? bm.path.indexOf(serverRoot) === 0 : true)
155+
)
153156

154157
mappings = await this.storage.getMappings()
155158
await this.tree.load(mappings)
@@ -161,27 +164,46 @@ export default class Account {
161164

162165
await this.tree.removeOrphanedFolders()
163166

164-
await this.setData({...this.getData(), error: null, syncing: false, lastSync: Date.now()})
167+
await this.setData({
168+
...this.getData(),
169+
error: null,
170+
syncing: false,
171+
lastSync: Date.now()
172+
})
165173
this.syncing = false
166-
console.log('Successfully ended sync process for account ' + this.getLabel())
174+
console.log(
175+
'Successfully ended sync process for account ' + this.getLabel()
176+
)
167177
} catch (e) {
168178
if (e.list) {
169-
var combinedMessage = e.list.map(e => e.message, console.log(e)).join('\n')
179+
var combinedMessage = e.list
180+
.map(e => e.message, console.log(e))
181+
.join('\n')
170182
console.error('Syncing failed with', combinedMessage)
171-
await this.setData({...this.getData(), error: combinedMessage, syncing: false})
183+
await this.setData({
184+
...this.getData(),
185+
error: combinedMessage,
186+
syncing: false
187+
})
188+
this.syncing = false
172189
} else {
173190
console.log(e)
174191
console.error('Syncing failed with', e)
175-
await this.setData({...this.getData(), error: e.message, syncing: false})
192+
await this.setData({
193+
...this.getData(),
194+
error: e.message,
195+
syncing: false
196+
})
176197
this.syncing = false
177198
}
178199
}
179200
}
180201

181-
async sync_deleteFromServer (mappings) {
202+
async sync_deleteFromServer(mappings) {
182203
// In the mappings but not in the tree: SERVERDELETE
183204
var shouldExist = Object.keys(mappings.LocalToServer)
184-
await Parallel.each(shouldExist,
205+
await Parallel.each(
206+
shouldExist,
185207
async localId => {
186208
if (!this.tree.getBookmarkByLocalId(localId)) {
187209
console.log('SERVERDELETE', localId, mappings.LocalToServer[localId])
@@ -194,15 +216,26 @@ export default class Account {
194216
)
195217
}
196218

197-
async sync_createOnServer (mappings) {
219+
async sync_createOnServer(mappings) {
198220
// In the tree yet not in the mappings: SERVERCREATE
199221
await Parallel.each(
200-
this.tree.getAllBookmarks().filter(localId => typeof mappings.LocalToServer[localId] === 'undefined'),
222+
this.tree
223+
.getAllBookmarks()
224+
.filter(
225+
localId => typeof mappings.LocalToServer[localId] === 'undefined'
226+
),
201227
async localId => {
202228
const bookmark = this.tree.getBookmarkByLocalId(localId)
203229
if (mappings.UrlToLocal[bookmark.url]) {
204-
console.error('The same URL is bookmarked twice locally:', bookmark.url)
205-
throw new Error('The same URL is bookmarked twice locally: "' + bookmark.url + '". Delete one of the two.')
230+
console.error(
231+
'The same URL is bookmarked twice locally:',
232+
bookmark.url
233+
)
234+
throw new Error(
235+
'The same URL is bookmarked twice locally: "' +
236+
bookmark.url +
237+
'". Delete one of the two.'
238+
)
206239
}
207240
console.log('SERVERCREATE', bookmark)
208241
let serverMark = await this.server.createBookmark(bookmark)
@@ -218,18 +251,19 @@ export default class Account {
218251
)
219252
}
220253

221-
async sync_deleteFromTree (serverList) {
254+
async sync_deleteFromTree(serverList) {
222255
const received = {}
223-
serverList.forEach((bm) => (received[bm.id] = true))
256+
serverList.forEach(bm => (received[bm.id] = true))
224257

225258
const mappings = await this.storage.getMappings()
226259

227260
// removed on the server: DELETE
228-
await Parallel.each(Object.keys(mappings.ServerToLocal),
229-
// local bookmarks are only in the mappings if they have been added to the server successfully, so we never delete new ones!
261+
await Parallel.each(
262+
Object.keys(mappings.ServerToLocal),
263+
// local bookmarks are only in the mappings if they have been added to the server successfully, so we never delete new ones!
230264
async id => {
231265
if (!received[id]) {
232-
// If a bookmark was deleted on the server, we delete it as well
266+
// If a bookmark was deleted on the server, we delete it as well
233267
let localId = mappings.ServerToLocal[id]
234268
await this.tree.removeNode(this.tree.getBookmarkByLocalId(localId))
235269
await this.storage.removeFromCache(localId)
@@ -240,14 +274,15 @@ export default class Account {
240274
)
241275
}
242276

243-
async sync_update (serverMarks) {
277+
async sync_update(serverMarks) {
244278
const mappings = await this.storage.getMappings() // For detecting duplicates
245279
// Update known ones and create new ones
246-
await Parallel.each(serverMarks,
280+
await Parallel.each(
281+
serverMarks,
247282
async serverMark => {
248283
serverMark.localId = mappings.ServerToLocal[serverMark.id]
249284
if (serverMark.localId) {
250-
// known to mappings: (LOCAL|SERVER)UPDATE
285+
// known to mappings: (LOCAL|SERVER)UPDATE
251286
let localMark = this.tree.getBookmarkByLocalId(serverMark.localId)
252287

253288
let serverHash = await serverMark.hash()
@@ -258,13 +293,16 @@ export default class Account {
258293
}
259294

260295
if (!localMark.dirty) {
261-
// LOCALUPDATE
296+
// LOCALUPDATE
262297
await this.tree.updateNode(serverMark)
263298
await this.storage.addToCache(serverMark.localId, serverHash)
264299
} else {
265-
// SERVERUPDATE
300+
// SERVERUPDATE
266301
console.log('SERVERUPDATE', localMark, serverMark)
267-
let couldHandle = await this.server.updateBookmark(localMark.id, localMark)
302+
let couldHandle = await this.server.updateBookmark(
303+
localMark.id,
304+
localMark
305+
)
268306
if (!couldHandle) {
269307
// if the protocol is not supported updateBookmark returns false
270308
// and we ignore it
@@ -276,11 +314,17 @@ export default class Account {
276314
await this.storage.addToCache(localMark.localId, treeHash)
277315
}
278316
} else {
279-
// Not yet known:
280-
// CREATE
317+
// Not yet known:
318+
// CREATE
281319
if (mappings.UrlToLocal[serverMark.url]) {
282-
console.error('Trying to create a URL that is already bookmarked. This shouldn\'t happen! Please tell the developer about this! url=' + serverMark.url)
283-
throw new Error('Trying to create a URL that is already bookmarked. This shouldn\'t happen! Please tell the developer about this! url=' + serverMark.url)
320+
console.error(
321+
"Trying to create a URL that is already bookmarked. This shouldn't happen! Please tell the developer about this! url=" +
322+
serverMark.url
323+
)
324+
throw new Error(
325+
"Trying to create a URL that is already bookmarked. This shouldn't happen! Please tell the developer about this! url=" +
326+
serverMark.url
327+
)
284328
}
285329
const node = await this.tree.createNode(serverMark)
286330
await this.storage.addToCache(node.id, await serverMark.hash())
@@ -290,28 +334,33 @@ export default class Account {
290334
)
291335
}
292336

293-
static async getAllAccounts () {
294-
const d = await browser.storage.local.get({'accounts': {}})
337+
static async getAllAccounts() {
338+
const d = await browser.storage.local.get({ accounts: {} })
295339
var accounts = d['accounts']
296340

297341
accounts = await Promise.all(
298-
Object.keys(accounts)
299-
.map(accountId => Account.get(accountId))
342+
Object.keys(accounts).map(accountId => Account.get(accountId))
300343
)
301344

302345
return accounts
303346
}
304347

305-
static async getAccountContainingLocalId (localId, ancestors, allAccounts) {
306-
ancestors = ancestors || await Tree.getIdPathFromLocalId(localId)
307-
allAccounts = allAccounts || await this.getAllAccounts()
348+
static async getAccountContainingLocalId(localId, ancestors, allAccounts) {
349+
ancestors = ancestors || (await Tree.getIdPathFromLocalId(localId))
350+
allAccounts = allAccounts || (await this.getAllAccounts())
308351
var account = allAccounts
309-
.map((account) => ({account, index: ancestors.indexOf(account.getData().localRoot)}))
310-
.filter((acc) => acc.index !== -1)
311-
.reduce((acc1, acc2) => {
312-
if (acc1.index > acc2.index) return acc1
313-
else return acc2
314-
}, {account: null, index: -1}).account
352+
.map(account => ({
353+
account,
354+
index: ancestors.indexOf(account.getData().localRoot)
355+
}))
356+
.filter(acc => acc.index !== -1)
357+
.reduce(
358+
(acc1, acc2) => {
359+
if (acc1.index > acc2.index) return acc1
360+
else return acc2
361+
},
362+
{ account: null, index: -1 }
363+
).account
315364

316365
return account
317366
}

0 commit comments

Comments
 (0)