git ssb

0+

Dominic / ssb-feed



Tree: 17ac021e99559bfa480c415d010a6f35f1eb9c6a

Files: 17ac021e99559bfa480c415d010a6f35f1eb9c6a / util.js

3638 bytesRaw
1var ssbKeys = require('ssb-keys')
2var timestamp = require('monotonic-timestamp')
3var isRef = require('ssb-ref')
4var isHash = isRef.isHash
5var isFeedId = isRef.isFeedId
6
7var encode = exports.encode = function (obj) {
8 return JSON.stringify(obj, null, 2)
9}
10
11function isString (s) {
12 return 'string' === typeof s
13}
14
15function isInteger (n) {
16 return ~~n === n
17}
18
19function isObject (o) {
20 return o && 'object' === typeof o
21}
22
23function clone (obj) {
24 var o = {}
25 for(var k in obj) o[k] = obj[k];
26 return o
27}
28
29function isEncrypted (str) {
30 return isString(str) && /^[0-9A-Za-z\/+]+={0,2}\.box/.test(str)
31}
32
33exports.toBuffer = function (b) {
34 if('string' == typeof b) return new Buffer(b, 'base64')
35 return b
36}
37
38
39exports.BatchQueue = function BatchQueue (db) {
40
41 var batch = [], writing = false
42
43 function drain () {
44 writing = true
45 var _batch = batch
46 batch = []
47
48 db.batch(_batch, function () {
49 writing = false
50 write.size = batch.length
51 if(batch.length) drain()
52 _batch.forEach(function (op) {
53 op.cb(null, {key:op.key, value: op.value})
54 })
55 })
56 }
57
58 function write (op) {
59 batch.push(op)
60 write.size = batch.length
61 if(!writing) drain()
62 }
63
64 write.size = 0
65
66 return write
67}
68
69exports.create = function (keys, type, content, prev, prev_key, sign_cap) {
70
71 //this noise is to handle things calling this with legacy api.
72 if(isString(type) && (Buffer.isBuffer(content) || isString(content)))
73 content = {type: type, value: content}
74 if(isObject(content))
75 content.type = content.type || type
76 //noise end
77
78 prev_key = !prev_key && prev ? ('%'+ssbKeys.hash(encode(prev))) : prev_key || null
79
80 return ssbKeys.signObj(keys, sign_cap, {
81 previous: prev_key,
82 author: keys.id,
83 sequence: prev ? prev.sequence + 1 : 1,
84 timestamp: timestamp(),
85 hash: 'sha256',
86 content: content,
87 })
88}
89
90var isInvalidContent = exports.isInvalidContent = function (content) {
91 if(!isEncrypted(content)) {
92
93 type = content.type
94
95 if (!(isString(type) && type.length <= 52 && type.length >= 3)) {
96 return new Error('type must be a string' +
97 '3 <= type.length < 52, was:' + type
98 )
99 }
100 }
101 return false
102}
103
104exports.isInvalidShape = function (msg) {
105 if(
106 !isObject(msg) ||
107 !isInteger(msg.sequence) ||
108 !isFeedId(msg.author) ||
109 !(isObject(msg.content) || isEncrypted(msg.content))
110 )
111 return new Error('message has invalid properties')
112
113 //allow encrypted messages, where content is a base64 string.
114
115 var asJson = encode(msg)
116 if (asJson.length > 8192) // 8kb
117 return new Error( 'encoded message must not be larger than 8192 bytes')
118
119 return isInvalidContent(msg.content)
120}
121
122exports.isInvalid = function (pub, msg, previous, sign_cap) {
123 // :TODO: is there a faster way to measure the size of this message?
124
125 var key = previous.key
126 var prev = previous.value
127
128 if(prev) {
129 if(msg.previous !== key)
130 return new Error(
131 'expected previous: '
132 + key
133 + 'but found:' + msg.previous
134 )
135
136 if(msg.sequence !== prev.sequence + 1
137 || msg.timestamp <= prev.timestamp)
138 return new Error('out of order')
139 }
140 else {
141 if(!(msg.previous == null
142 && msg.sequence === 1 && msg.timestamp > 0))
143 return new Error('expected initial message')
144 }
145
146 if(msg.author !== pub) {
147
148 return new Error(
149 'expected different author:'
150 + hash(pub.public || pub).toString('base64')
151 + 'but found:' + msg.author.toString('base64')
152 )
153 }
154
155 if(!ssbKeys.verifyObj(pub, sign_cap, msg))
156 return new Error('signature was invalid')
157
158 return false
159}
160
161
162

Built with git-ssb-web