@mblaney/holster 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/holster.js CHANGED
@@ -14,8 +14,6 @@ const Holster = opt => {
14
14
  const map = new Map()
15
15
  // Allow concurrent calls to the api by storing each context.
16
16
  const allctx = new Map()
17
- // Allow user queries by public key
18
- let publicKey
19
17
 
20
18
  const ok = data => {
21
19
  return (
@@ -37,21 +35,26 @@ const Holster = opt => {
37
35
  const keys = []
38
36
  for (const [key, value] of Object.entries(data)) {
39
37
  if (key === "_") {
40
- return "error underscore cannot be used as an item name"
38
+ return "error underscore cannot be used as a property name"
41
39
  }
42
40
  if (utils.obj.is(value) || ok(value)) {
43
41
  keys.push(key)
44
42
  continue
45
43
  }
46
- return `error {${key}:${value}} cannot be converted to graph`
44
+ if (typeof value === "undefined") {
45
+ return `error undefined ${key} cannot be converted to a graph`
46
+ }
47
+ const error = JSON.stringify({[key]: value})
48
+ return `error ${error} cannot be converted to a graph`
47
49
  }
48
50
  if (keys.length !== 0) return keys
49
51
  }
50
- return `error ${data} cannot be converted to a graph`
52
+ const error = JSON.stringify(data)
53
+ return `error ${error} cannot be converted to a graph`
51
54
  }
52
55
 
53
56
  const api = ctxid => {
54
- const get = (lex, soul, ack, opt) => {
57
+ const get = (lex, soul, ack, _opt) => {
55
58
  wire.get(
56
59
  utils.obj.put(lex, "#", soul),
57
60
  async msg => {
@@ -59,6 +62,7 @@ const Holster = opt => {
59
62
  if (msg.put && msg.put[soul]) {
60
63
  delete msg.put[soul]._
61
64
  delete msg.put[soul][utils.userPublicKey]
65
+ delete msg.put[soul][utils.userSignature]
62
66
  // Resolve any rels on the node before returning to the user.
63
67
  for (const key of Object.keys(msg.put[soul])) {
64
68
  const id = utils.rel.is(msg.put[soul][key])
@@ -77,19 +81,18 @@ const Holster = opt => {
77
81
  ack(null)
78
82
  }
79
83
  },
80
- opt,
84
+ _opt,
81
85
  )
82
86
  }
83
87
 
84
- const graph = async (soul, data, cb) => {
85
- if (!cb) cb = console.log
86
-
87
- if (user.is) {
88
- const signed = await SEA.sign(data, user.is)
89
- return utils.graph(soul, signed.m, signed.s, user.is.pub)
88
+ const graph = async (soul, data, userctx, cb) => {
89
+ if (userctx) {
90
+ const signed = await SEA.sign(data, userctx)
91
+ return utils.graph(soul, signed.m, signed.s, userctx.pub)
90
92
  }
91
93
 
92
94
  if (opt.secure) {
95
+ if (!cb) cb = console.log
93
96
  cb(`error putting data on ${soul}: user required in secure mode`)
94
97
  return null
95
98
  }
@@ -99,17 +102,27 @@ const Holster = opt => {
99
102
 
100
103
  const done = data => {
101
104
  const ctx = allctx.get(ctxid)
102
- if (ctx && typeof ctx.cb !== "undefined") ctx.cb(data)
103
- else if (data) console.log(data)
105
+ if (ctx && typeof ctx.cb !== "undefined") {
106
+ // Use a timeout so that the context can be removed before data is
107
+ // returned to the callback (allows nested get calls).
108
+ setTimeout(() => ctx.cb(data), 1)
109
+ } else if (data) {
110
+ console.log("error no callback for data", data, "ctx", ctx)
111
+ }
104
112
  // A context updated by "on" should only be removed by "off".
105
113
  if (ctx && !ctx.on) allctx.delete(ctxid)
106
114
  }
107
115
 
108
116
  const resolve = (request, cb) => {
109
- const get = request && typeof request.get !== "undefined"
110
- const put = request && typeof request.put !== "undefined"
111
- const on = request && typeof request.on !== "undefined"
112
- const off = request && typeof request.off !== "undefined"
117
+ if (!request) {
118
+ console.log("error resolve request parameter required")
119
+ return
120
+ }
121
+
122
+ const get = typeof request.get !== "undefined"
123
+ const put = typeof request.put !== "undefined"
124
+ const on = typeof request.on !== "undefined"
125
+ const off = typeof request.off !== "undefined"
113
126
 
114
127
  let found = false
115
128
  const ctx = allctx.get(ctxid)
@@ -124,34 +137,45 @@ const Holster = opt => {
124
137
  // Found a soul that needs resolving, need the previous context
125
138
  // (ie the parent node) to find a soul relation for it.
126
139
  const {item, soul} = ctx.chain[i - 1]
127
- wire.get({"#": soul, ".": item}, async msg => {
140
+ // If this is a user context or using secure mode then need to get the
141
+ // whole node for verification.
142
+ const lex =
143
+ ctx.user || opt.secure ? {"#": soul} : {"#": soul, ".": item}
144
+ wire.get(lex, async msg => {
128
145
  if (msg.err) {
129
- console.log(`error getting ${item} on ${soul}: ${msg.err}`)
146
+ if (ctx.user || opt.secure) {
147
+ console.log(`error getting ${soul}: ${msg.err}`)
148
+ } else {
149
+ console.log(`error getting ${item} on ${soul}: ${msg.err}`)
150
+ }
130
151
  if (cb) cb(null)
131
152
  return
132
153
  }
133
154
 
134
- const node = msg.put && msg.put[soul]
155
+ let node = msg.put && msg.put[soul]
135
156
  if (node && typeof node[item] !== "undefined") {
136
157
  let id = utils.rel.is(node[item])
137
158
  if (id) {
138
159
  ctx.chain[i].soul = id
139
- // Not sure why the map needs to be set rather than just ctx?
140
- allctx.set(ctxid, {chain: ctx.chain, cb: ctx.cb})
160
+ allctx.set(ctxid, {...ctx})
141
161
  // Call api again using the updated context.
142
- if (get) api(ctxid).next(null, request.get, cb)
143
- else if (put) api(ctxid).put(request.put, cb)
144
- else if (on) api(ctxid).on(request.on, cb)
145
- else if (off) api(ctxid).off(cb)
162
+ if (get) {
163
+ api(ctxid).next(null, request.get, cb, request._opt)
164
+ } else if (put) {
165
+ api(ctxid).put(request.put, cb)
166
+ } else if (on) {
167
+ api(ctxid).on(request.on, cb, request._get, request._opt)
168
+ } else if (off) {
169
+ api(ctxid).off(cb)
170
+ }
146
171
  } else if (get) {
147
- // Request was not for a node, return a property on the current
148
- // soul.
172
+ // Request was not for a node, return property on current soul.
149
173
  cb(node[item])
150
174
  } else if (put) {
151
175
  // Request was chained before put, so rel doesn't exist yet.
152
176
  id = utils.text.random()
153
- const rel = {[item]: utils.rel.ify(id)}
154
- const g = await graph(soul, rel, cb)
177
+ node[item] = utils.rel.ify(id)
178
+ const g = await graph(soul, node, ctx.user, cb)
155
179
  if (g === null) return
156
180
 
157
181
  wire.put(g, err => {
@@ -164,16 +188,31 @@ const Holster = opt => {
164
188
  api(ctxid).put(request.put, cb)
165
189
  })
166
190
  } else if (on) {
167
- console.log(`error resolving on for ${item} on ${soul}`)
191
+ // Allow listening to a node that doesn't exist.
168
192
  cb(null)
169
193
  } else if (off) {
170
- console.log(`error resolving off for ${item} on ${soul}`)
194
+ // Allow stop listening to a node that doesn't exist.
171
195
  if (cb) cb(null)
172
196
  }
173
197
  } else if (put) {
174
- cb(`error ${item} not found on ${soul}`)
198
+ // Request was chained before put, so rel doesn't exist yet.
199
+ const id = utils.text.random()
200
+ if (!node) node = {}
201
+ node[item] = utils.rel.ify(id)
202
+ const g = await graph(soul, node, ctx.user, cb)
203
+ if (g === null) return
204
+
205
+ wire.put(g, err => {
206
+ if (err) {
207
+ cb(`error putting ${item} on ${soul}: ${err}`)
208
+ return
209
+ }
210
+
211
+ ctx.chain[i].soul = id
212
+ api(ctxid).put(request.put, cb)
213
+ })
175
214
  } else {
176
- console.log(`error ${item} not found on ${soul}`)
215
+ // Allow querying a node that doesn't exist.
177
216
  if (cb) cb(null)
178
217
  }
179
218
  })
@@ -195,41 +234,40 @@ const Holster = opt => {
195
234
  }
196
235
 
197
236
  return {
198
- get: (key, lex, cb, opt) => {
237
+ get: (key, lex, cb, _opt) => {
199
238
  if (typeof lex === "function") {
239
+ _opt = cb
200
240
  cb = lex
201
241
  lex = null
202
242
  }
203
243
  if (key === null || key === "" || key === "_") {
244
+ console.log("error please provide a key")
204
245
  if (cb) cb(null)
205
246
  return
206
247
  }
207
248
 
208
249
  // lex requires a callback as it's not included in the chain below.
209
- if (lex && !cb) {
250
+ if (lex && typeof cb !== "function") {
210
251
  console.log("error lex requires a callback function")
211
252
  return
212
253
  }
213
254
 
214
255
  // Top level keys are added to a root node so their values don't need
215
- // to be objects, the user's public key is used as the root node when
216
- // publicKey or user.ctx is set.
217
- const root = publicKey ? publicKey : user.ctx ? user.ctx : "root"
218
-
256
+ // to be objects.
219
257
  ctxid = utils.text.random()
220
- allctx.set(ctxid, {chain: [{item: key, soul: root}], cb: cb})
258
+ allctx.set(ctxid, {chain: [{item: key, soul: "root"}], cb: cb})
221
259
  if (!cb) return api(ctxid)
222
260
 
223
261
  // When there's a callback need to resolve the context first.
224
- const {soul} = resolve({get: lex}, done)
225
- if (soul) get(lex, soul, done, opt)
262
+ const {soul} = resolve({get: lex, _opt: _opt}, done)
263
+ if (soul) get(lex, soul, done, _opt)
226
264
  },
227
- next: (key, lex, cb, opt) => {
265
+ next: (key, lex, cb, _opt) => {
228
266
  const ack = data => {
229
267
  cb ? cb(data) : done(data)
230
268
  }
231
-
232
269
  if (typeof lex === "function") {
270
+ _opt = cb
233
271
  cb = lex
234
272
  lex = null
235
273
  }
@@ -245,7 +283,7 @@ const Holster = opt => {
245
283
  }
246
284
 
247
285
  // lex requires a callback as it's not included in the chain below.
248
- if (lex && !cb) {
286
+ if (lex && typeof cb !== "function") {
249
287
  console.log("error lex requires a callback function")
250
288
  return
251
289
  }
@@ -266,8 +304,8 @@ const Holster = opt => {
266
304
  if (!ctx.cb) return api(ctxid)
267
305
 
268
306
  // When there's a callback need to resolve the context first.
269
- const {soul} = resolve({get: lex}, ack)
270
- if (soul) get(lex, soul, ack, opt)
307
+ const {soul} = resolve({get: lex, _opt: _opt}, ack)
308
+ if (soul) get(lex, soul, ack, _opt)
271
309
  },
272
310
  put: (data, set, cb) => {
273
311
  if (typeof set === "function") {
@@ -311,17 +349,23 @@ const Holster = opt => {
311
349
  // When result is true data is a property to put on the current soul.
312
350
  // Need to check if item is a rel and also set the node to null. (This
313
351
  // applies for any update from a rel to a property, not just null.)
314
- wire.get({"#": soul, ".": item}, async msg => {
352
+ // If using secure mode need to get the whole node for verification.
353
+ const lex =
354
+ ctx.user || opt.secure ? {"#": soul} : {"#": soul, ".": item}
355
+ wire.get(lex, async msg => {
315
356
  if (msg.err) {
316
- console.log(`error getting ${soul}: ${msg.err}`)
357
+ ack(`error getting ${soul}: ${msg.err}`)
317
358
  return
318
359
  }
319
360
 
320
- const current = msg.put && msg.put[soul] && msg.put[soul][item]
361
+ let node = msg.put && msg.put[soul]
362
+ const current = node && node[item]
321
363
  const id = utils.rel.is(current)
322
364
  if (!id) {
323
365
  // Not a rel, can just put the data.
324
- const g = await graph(soul, {[item]: data}, ack)
366
+ if (!node) node = {}
367
+ node[item] = data
368
+ const g = await graph(soul, node, ctx.user, ack)
325
369
  if (g === null) return
326
370
 
327
371
  wire.put(g, ack)
@@ -330,23 +374,29 @@ const Holster = opt => {
330
374
 
331
375
  wire.get({"#": id}, async msg => {
332
376
  if (msg.err) {
333
- console.log(`error getting ${id}: ${msg.err}`)
377
+ ack(`error getting ${id}: ${msg.err}`)
334
378
  return
335
379
  }
336
380
 
337
381
  if (!msg.put || !msg.put[id]) {
338
- console.log(`error ${id} not found`)
382
+ ack(`error ${id} not found`)
339
383
  return
340
384
  }
341
385
 
342
- delete msg.put[id]._
343
386
  // null each of the properties on the node before putting data.
344
387
  for (const key of Object.keys(msg.put[id])) {
345
- if (key === utils.userPublicKey) continue
388
+ if (
389
+ key === "_" ||
390
+ key === utils.userPublicKey ||
391
+ key === utils.userSignature
392
+ ) {
393
+ continue
394
+ }
346
395
 
347
396
  const err = await new Promise(res => {
348
397
  const _ctxid = utils.text.random()
349
- allctx.set(_ctxid, {chain: [{item: key, soul: id}]})
398
+ const chain = [{item: key, soul: id}]
399
+ allctx.set(_ctxid, {chain: chain, user: ctx.user})
350
400
  api(_ctxid).put(null, res)
351
401
  })
352
402
  if (err) {
@@ -354,7 +404,9 @@ const Holster = opt => {
354
404
  return
355
405
  }
356
406
  }
357
- const g = await graph(soul, {[item]: data}, ack)
407
+ if (!node) node = {}
408
+ node[item] = data
409
+ const g = await graph(soul, node, ctx.user, ack)
358
410
  if (g === null) return
359
411
 
360
412
  wire.put(g, ack)
@@ -365,18 +417,23 @@ const Holster = opt => {
365
417
 
366
418
  // Otherwise put the data using the keys returned in result.
367
419
  // Need to check if a rel has already been added on the current node.
368
- wire.get({"#": soul, ".": item}, async msg => {
420
+ // If using secure mode need to get the whole node for verification.
421
+ const lex =
422
+ ctx.user || opt.secure ? {"#": soul} : {"#": soul, ".": item}
423
+ wire.get(lex, async msg => {
369
424
  if (msg.err) {
370
425
  ack(`error getting ${soul}.${item}: ${msg.err}`)
371
426
  return
372
427
  }
373
428
 
374
- const current = msg.put && msg.put[soul] && msg.put[soul][item]
429
+ let node = msg.put && msg.put[soul]
430
+ const current = node && node[item]
375
431
  const id = utils.rel.is(current)
376
432
  if (!id) {
377
433
  // The current rel doesn't exist, so add it first.
378
- const rel = {[item]: utils.rel.ify(utils.text.random())}
379
- const g = await graph(soul, rel, ack)
434
+ if (!node) node = {}
435
+ node[item] = utils.rel.ify(utils.text.random())
436
+ const g = await graph(soul, node, ctx.user, ack)
380
437
  if (g === null) return
381
438
 
382
439
  wire.put(g, err => {
@@ -385,27 +442,26 @@ const Holster = opt => {
385
442
  } else {
386
443
  const _ctxid = utils.text.random()
387
444
  const chain = [{item: item, soul: soul}]
388
- // Pass the previous context's callback on here.
389
- allctx.set(_ctxid, {chain: chain, cb: ctx.cb})
445
+ // Pass on the previous context's callback and user flag here.
446
+ allctx.set(_ctxid, {chain: chain, user: ctx.user, cb: ctx.cb})
390
447
  api(_ctxid).put(data)
391
448
  }
392
449
  })
393
450
  return
394
451
  }
395
452
 
396
- let put = false
397
- const update = {}
453
+ const update = []
398
454
  for (const key of result) {
399
455
  const err = await new Promise(res => {
400
- if (utils.obj.is(data[key])) {
456
+ if (utils.obj.is(data[key]) && !utils.rel.is(data[key])) {
401
457
  // Use the current rel as the context for nested objects.
402
458
  const _ctxid = utils.text.random()
403
- allctx.set(_ctxid, {chain: [{item: key, soul: id}]})
459
+ const chain = [{item: key, soul: id}]
460
+ allctx.set(_ctxid, {chain: chain, user: ctx.user})
404
461
  api(_ctxid).put(data[key], res)
405
462
  } else {
406
- put = true
407
- // Group other properties into one update.
408
- update[key] = data[key]
463
+ // Group the rest of the updates for put below.
464
+ update.push(key)
409
465
  res(null)
410
466
  }
411
467
  })
@@ -414,23 +470,43 @@ const Holster = opt => {
414
470
  return
415
471
  }
416
472
  }
417
- if (put) {
418
- const g = await graph(id, update, ack)
419
- if (g === null) return
420
473
 
421
- wire.put(g, ack)
422
- } else {
423
- // Callback on behalf of nested objects.
474
+ if (update.length === 0) {
424
475
  ack(null)
476
+ return
425
477
  }
478
+
479
+ // The nested objects created above will also have rels on the parent
480
+ // object, so fetch the node so the rest of the updates can be added.
481
+ wire.get({"#": id}, async msg => {
482
+ if (msg.err) {
483
+ ack(`error getting ${id}: ${msg.err}`)
484
+ return
485
+ }
486
+
487
+ let node = msg.put && msg.put[id]
488
+ if (!node) node = {}
489
+ update.forEach(key => {
490
+ node[key] = data[key]
491
+ })
492
+ const g = await graph(id, node, ctx.user, ack)
493
+ if (g === null) return
494
+
495
+ wire.put(g, ack)
496
+ })
426
497
  })
427
498
  },
428
- on: (lex, cb) => {
499
+ on: (lex, cb, _get, _opt) => {
429
500
  if (typeof lex === "function") {
501
+ _opt = _get
502
+ _get = cb
430
503
  cb = lex
431
504
  lex = null
432
505
  }
433
- if (!cb) return
506
+ if (typeof cb !== "function") {
507
+ console.log("error on() requires a callback function")
508
+ return
509
+ }
434
510
 
435
511
  if (!ctxid) {
436
512
  console.log("error please provide a key using get(key)")
@@ -439,7 +515,7 @@ const Holster = opt => {
439
515
  }
440
516
 
441
517
  // Resolve the current context before adding event listener.
442
- const {item, soul} = resolve({on: lex}, cb)
518
+ const {item, soul} = resolve({on: lex, _get: _get, _opt: _opt}, cb)
443
519
  if (!soul) return
444
520
 
445
521
  // Flag that this context is set from on and shouldn't be removed.
@@ -463,7 +539,7 @@ const Holster = opt => {
463
539
  if (lex) lex = utils.obj.put(lex, "#", soul)
464
540
  else lex = {"#": soul, ".": item}
465
541
  }
466
- wire.on(lex, map.get(cb))
542
+ wire.on(lex, map.get(cb), _get, _opt)
467
543
  })
468
544
  },
469
545
  off: cb => {
@@ -492,14 +568,61 @@ const Holster = opt => {
492
568
  allctx.delete(ctxid)
493
569
  })
494
570
  },
495
- user: pub => {
496
- // Return the combined Holster and User APIs. Passing in a public key
497
- // will set the user context to that key, otherwise user.ctx is set when
498
- // a user logs in so that their public key will be used as the root node
499
- // in get(), also put() will sign all graph updates for verification.
500
- if (pub) publicKey = "~" + pub
501
- else publicKey = null
502
- return Object.assign(user, api())
571
+ user: () => {
572
+ if (!user.get) {
573
+ // Return the combined Holster and User APIs.
574
+ Object.assign(user, api())
575
+ // Need to provide a user specific get() function to know if user
576
+ // context should be checked.
577
+ user.get = (keys, lex, cb, _opt) => {
578
+ if (typeof lex === "function") {
579
+ _opt = cb
580
+ cb = lex
581
+ lex = null
582
+ }
583
+
584
+ let pub = null
585
+ let key = null
586
+ if (user.is) pub = user.is.pub
587
+ if (typeof keys === "string") {
588
+ key = keys
589
+ } else if (keys instanceof Array) {
590
+ if (keys.length === 2) {
591
+ pub = keys[0]
592
+ key = keys[1]
593
+ } else if (keys.length === 1) {
594
+ key = keys[0]
595
+ }
596
+ }
597
+ if (!pub) {
598
+ console.log("error please log in or provide a public key")
599
+ if (cb) cb(null)
600
+ return
601
+ }
602
+
603
+ if (key === null || key === "" || key === "_") {
604
+ console.log("error please provide a key")
605
+ if (cb) cb(null)
606
+ return
607
+ }
608
+
609
+ // lex requires a callback as it's not included in the chain below.
610
+ if (lex && !cb) {
611
+ console.log("error lex requires a callback function")
612
+ return
613
+ }
614
+
615
+ ctxid = utils.text.random()
616
+ const chain = [{item: key, soul: "~" + pub}]
617
+ allctx.set(ctxid, {chain: chain, user: user.is, cb: cb})
618
+ if (!cb) return api(ctxid)
619
+
620
+ // When there's a callback need to resolve the context first.
621
+ const {soul} = resolve({get: lex}, done)
622
+ if (soul) get(lex, soul, done, _opt)
623
+ }
624
+ }
625
+ return user
503
626
  },
504
627
  // Allow the wire spec to be used via holster.
505
628
  wire: wire,
package/src/sea.js CHANGED
@@ -1,4 +1,4 @@
1
- import {userPublicKey} from "./utils.js"
1
+ import {userPublicKey, userSignature} from "./utils.js"
2
2
  import * as utils from "./sea-utils.js"
3
3
  import SafeBuffer from "./buffer.js"
4
4
 
@@ -117,8 +117,10 @@ const SEA = {
117
117
  } else {
118
118
  // Allow data to be passed in with graph meta data,
119
119
  // (which should not be part of signature, so not verified).
120
- for (const k of Object.keys(signed.m)) {
121
- if (k !== "_" && k != userPublicKey) msg[k] = signed.m[k]
120
+ for (const k of Object.keys(signed.m).sort()) {
121
+ if (k !== "_" && k != userPublicKey && k != userSignature) {
122
+ msg[k] = signed.m[k]
123
+ }
122
124
  }
123
125
  }
124
126
  const hash = await utils.sha256(msg)
@@ -139,7 +141,17 @@ const SEA = {
139
141
  return null
140
142
  }
141
143
 
142
- const msg = utils.parse(data)
144
+ let msg = {}
145
+ if (typeof data === "string") {
146
+ msg = data
147
+ } else {
148
+ const check = utils.parse(data)
149
+ for (const k of Object.keys(check).sort()) {
150
+ if (k !== "_" && k != userPublicKey && k != userSignature) {
151
+ msg[k] = check[k]
152
+ }
153
+ }
154
+ }
143
155
  const hash = await utils.sha256(msg)
144
156
  const jwk = utils.jwk(pair.pub, pair.priv)
145
157
  const alg = {name: "ECDSA", namedCurve: "P-256"}
package/src/user.js CHANGED
@@ -48,20 +48,23 @@ const User = (opt, wire) => {
48
48
  priv: dec.priv,
49
49
  epriv: dec.epriv,
50
50
  }
51
- // Holster API uses ctx to set the root node for user data.
52
- user.ctx = "~" + data.pub
53
-
54
51
  if (newPassword !== "") {
55
52
  // Encrypt private key using new password and a new salt.
56
53
  const salt = utils.text.random(64)
57
54
  const work = await SEA.work(newPassword, salt)
58
55
  const enc = await SEA.encrypt(dec, work)
59
- const auth = {auth: JSON.stringify({enc: enc, salt: salt})}
60
- const signed = await SEA.sign(auth, user.is)
56
+ // Put all fields so that verification applies to the whole node.
57
+ const update = {
58
+ username: username,
59
+ pub: data.pub,
60
+ epub: data.epub,
61
+ auth: JSON.stringify({enc: enc, salt: salt}),
62
+ }
63
+ const signed = await SEA.sign(update, user.is)
61
64
  const graph = utils.graph(pub, signed.m, signed.s, data.pub)
62
65
  wire.put(graph, err => {
63
66
  if (err) {
64
- done(`error putting ${auth} on ${pub}: ${err}`)
67
+ done(`error putting ${update} on ${pub}: ${err}`)
65
68
  } else {
66
69
  done(null)
67
70
  }
@@ -236,40 +239,37 @@ const User = (opt, wire) => {
236
239
  if (typeof globalThis.localStorage !== "undefined") {
237
240
  globalThis.localStorage.setItem("user.is", JSON.stringify(user.is))
238
241
  }
242
+ if (typeof globalThis.sessionStorage !== "undefined") {
243
+ globalThis.sessionStorage.removeItem("user.is")
244
+ }
239
245
  return
240
246
  }
241
247
 
242
248
  if (typeof globalThis.sessionStorage !== "undefined") {
243
249
  globalThis.sessionStorage.setItem("user.is", JSON.stringify(user.is))
244
250
  }
251
+ if (typeof globalThis.localStorage !== "undefined") {
252
+ globalThis.localStorage.removeItem("user.is")
253
+ }
245
254
  },
246
- recall: localStorage => {
247
- if (localStorage) {
248
- if (typeof globalThis.localStorage !== "undefined") {
249
- const is = globalThis.localStorage.getItem("user.is")
250
- if (is) {
251
- user.is = JSON.parse(is)
252
- user.ctx = "~" + user.is.pub
253
- } else {
254
- console.log("User credentials not stored in local storage")
255
- }
255
+ recall: () => {
256
+ if (typeof globalThis.localStorage !== "undefined") {
257
+ const is = globalThis.localStorage.getItem("user.is")
258
+ if (is) {
259
+ user.is = JSON.parse(is)
260
+ return
256
261
  }
257
- return
258
262
  }
259
263
 
260
264
  if (typeof globalThis.sessionStorage !== "undefined") {
261
265
  const is = globalThis.sessionStorage.getItem("user.is")
262
266
  if (is) {
263
267
  user.is = JSON.parse(is)
264
- user.ctx = "~" + user.is.pub
265
- } else {
266
- console.log("User credentials not stored in session storage")
267
268
  }
268
269
  }
269
270
  },
270
271
  leave: () => {
271
272
  user.is = null
272
- user.ctx = null
273
273
  if (typeof globalThis.localStorage !== "undefined") {
274
274
  globalThis.localStorage.removeItem("user.is")
275
275
  }
@@ -316,7 +316,6 @@ const User = (opt, wire) => {
316
316
  }
317
317
 
318
318
  user.is = null
319
- user.ctx = null
320
319
  // Return null on success. Note currently not updating ~@username,
321
320
  // not sure if allowing username re-user is a good idea anyway?
322
321
  if (cb) cb(null)