git ssb

0+

Dominic / ssb-feed



Tree: eac1a89db33ba24513a85795a552c0f28da8c4bf

Files: eac1a89db33ba24513a85795a552c0f28da8c4bf / util.js

3501 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.BatchQueue = function BatchQueue (db) {
34
35 var batch = [], writing = false
36
37 function drain () {
38 writing = true
39 var _batch = batch
40 batch = []
41
42 db.batch(_batch, function () {
43 writing = false
44 write.size = batch.length
45 if(batch.length) drain()
46 _batch.forEach(function (op) {
47 op.cb(null, {key:op.key, value: op.value})
48 })
49 })
50 }
51
52 function write (op) {
53 batch.push(op)
54 write.size = batch.length
55 if(!writing) drain()
56 }
57
58 write.size = 0
59
60 return write
61}
62
63exports.create = function (keys, type, content, prev, prev_key) {
64
65 //this noise is to handle things calling this with legacy api.
66 if(isString(type) && (Buffer.isBuffer(content) || isString(content)))
67 content = {type: type, value: content}
68 if(isObject(content))
69 content.type = content.type || type
70 //noise end
71
72 prev_key = !prev_key && prev ? ('%'+ssbKeys.hash(encode(prev))) : prev_key || null
73
74 return ssbKeys.signObj(keys, {
75 previous: prev_key,
76 author: keys.id,
77 sequence: prev ? prev.sequence + 1 : 1,
78 timestamp: timestamp(),
79 hash: 'sha256',
80 content: content,
81 })
82}
83
84var isInvalidContent = exports.isInvalidContent = function (content) {
85 if(!isEncrypted(content)) {
86
87 type = content.type
88
89 if (!(isString(type) && type.length <= 52 && type.length >= 3)) {
90 return new Error('type must be a string' +
91 '3 <= type.length < 52, was:' + type
92 )
93 }
94 }
95 return false
96}
97
98exports.isInvalidShape = function (msg) {
99 if(
100 !isObject(msg) ||
101 !isInteger(msg.sequence) ||
102 !isFeedId(msg.author) ||
103 !(isObject(msg.content) || isEncrypted(msg.content))
104 )
105 return new Error('message has invalid properties')
106
107 //allow encrypted messages, where content is a base64 string.
108
109 var asJson = encode(msg)
110 if (asJson.length > 8192) // 8kb
111 return new Error( 'encoded message must not be larger than 8192 bytes')
112
113 return isInvalidContent(msg.content)
114}
115
116exports.isInvalid = function validateSync (pub, msg, previous) {
117 // :TODO: is there a faster way to measure the size of this message?
118
119 var key = previous.key
120 var prev = previous.value
121
122 if(prev) {
123 if(msg.previous !== key)
124 return new Error(
125 'expected previous: '
126 + key
127 + 'but found:' + msg.previous
128 )
129
130 if(msg.sequence !== prev.sequence + 1
131 || msg.timestamp <= prev.timestamp)
132 return new Error('out of order')
133 }
134 else {
135 if(!(msg.previous == null
136 && msg.sequence === 1 && msg.timestamp > 0))
137 return new Error('expected initial message')
138 }
139
140 if(msg.author !== pub) {
141
142 return new Error(
143 'expected different author:'
144 + hash(pub.public || pub).toString('base64')
145 + 'but found:' + msg.author.toString('base64')
146 )
147 }
148
149 if(!ssbKeys.verifyObj(pub, msg))
150 return new Error('signature was invalid')
151
152 return false
153}
154
155

Built with git-ssb-web