git ssb

10+

Matt McKegg / patchwork



Tree: ffb7bedc3c585728df51f065d1d5d2f2d826319e

Files: ffb7bedc3c585728df51f065d1d5d2f2d826319e / lib / private-with-index.js

3964 bytesRaw
1var ssbKeys = require('ssb-keys')
2var explain = require('explain-error')
3var valid = require('scuttlebot/lib/validators')
4var Links = require('streamview-links')
5var pull = require('pull-stream')
6var Notify = require('pull-notify')
7var path = require('path')
8var Value = require('mutant/value')
9var watchThrottle = require('mutant/watch-throttle')
10
11var indexes = [
12 { key: 'TSP', value: ['timestamp'] },
13 { key: 'ATY', value: [['value', 'author'], ['value', 'content', 'type'], 'timestamp'] }
14]
15
16module.exports = {
17 name: 'private',
18 version: '0.0.0',
19 manifest: {
20 publish: 'async', unbox: 'sync', read: 'source', progress: 'source'
21 },
22 permissions: {
23 anonymous: {}
24 },
25 init: function (sbot, config) {
26 var dir = path.join(config.path, 'private')
27 var version = 0
28
29 var index = Links(dir, indexes, (x, emit) => {
30 var value = unbox(x)
31 if (value) {
32 emit(value)
33 }
34 }, version)
35
36 var notify = Notify()
37 var pending = Value(0)
38
39 watchThrottle(pending, 200, (value) => {
40 notify({pending: Math.max(0, value)})
41 })
42
43 index.init(function (_, since) {
44 countChanges(since, function (err, changes) {
45 if (err) throw err
46 pending.set(changes)
47 onChange(() => {
48 pending.set(pending() + 1)
49 })
50 pull(
51 sbot.createLogStream({gt: since || 0, live: true, sync: false}),
52 pull.through(function () {
53 pending.set(pending() - 1)
54 }),
55 index.write(function (err) {
56 if (err) throw err
57 })
58 )
59 })
60 })
61
62 return {
63 publish: valid.async(function (data, recps, cb) {
64 var ciphertext
65 try { ciphertext = ssbKeys.box(data, recps) }
66 catch (e) { return cb(explain(e, 'failed to encrypt')) }
67 sbot.publish(ciphertext, cb)
68 }, 'string|object', 'array'),
69 unbox: valid.sync(function (ciphertext) {
70 var data
71 try { data = ssbKeys.unbox(ciphertext, sbot.keys.private) }
72 catch (e) { throw explain(e, 'failed to decrypt') }
73 return data
74 }, 'string'),
75 read: function (opts) {
76 if (opts && typeof opts === 'string') {
77 try {
78 opts = {query: JSON.parse(opts)}
79 } catch (err) {
80 return pull.error(err)
81 }
82 }
83 return index.read(opts, function (ts, cb) {
84 sbot.sublevel('log').get(ts, function (err, key) {
85 if (err) return cb(explain(err, 'missing timestamp:'+ts))
86 sbot.get(key, function (err, value) {
87 if(err) return cb(explain(err, 'missing key:'+key))
88 cb(null, {key: key, value: unboxValue(value), timestamp: ts})
89 })
90 })
91 })
92 },
93 progress: notify.listen
94 }
95
96 function countChanges (since, cb) {
97 var result = 0
98 pull(
99 sbot.createLogStream({gt: since || 0, keys: false, values: false}),
100 pull.drain(function () {
101 result += 1
102 }, function (err) {
103 cb(err, result)
104 })
105 )
106 }
107
108 function onChange (cb) {
109 pull(
110 sbot.createLogStream({keys: false, values: false, old: false}),
111 pull.drain(function () {
112 cb()
113 })
114 )
115 }
116
117 function unbox (msg) {
118 if (typeof msg.value.content === 'string') {
119 var value = unboxValue(msg.value)
120 if (value) {
121 return {
122 key: msg.key, value: value, timestamp: msg.timestamp
123 }
124 }
125 }
126 }
127
128 function unboxValue (value) {
129 var plaintext = null
130 try {
131 plaintext = ssbKeys.unbox(value.content, sbot.keys.private)
132 } catch (ex) {}
133 if (!plaintext) return null
134 return {
135 previous: value.previous,
136 author: value.author,
137 sequence: value.sequence,
138 timestamp: value.timestamp,
139 hash: value.hash,
140 content: plaintext,
141 private: true
142 }
143 }
144 }
145}
146

Built with git-ssb-web