Commit 4f6a9b08479bfd25c838d25a7a44d99b99fe57e7
comment edge cases. rememer guest ids, incase they need to reconfirm. also do not leave undefined properties in messages, because it breaks deepEqual
Dominic Tarr committed on 12/16/2018, 2:10:06 AMParent: 5b1f218a3f28e90d43dcf6b0798da47536ee7fb7
Files changed
index.js | changed |
types.js | changed |
valid.js | changed |
index.js | ||
---|---|---|
@@ -49,18 +49,27 @@ | ||
49 | 49 … | var init = false |
50 | 50 … | var layer = sbot.friends.createLayer('user-invites') |
51 | 51 … | |
52 | 52 … | var caps = config.caps || {} |
53 … | + var initial = {invites: {}, accepts: {}, hosts: {}, guests: {}} | |
53 | 54 … | caps.userInvite = caps.userInvite || require('./cap') |
54 | 55 … | |
55 | 56 … | function reduce (acc, data, _seq) { |
56 | - if(!acc) acc = {invited: {}, invites:{}, accepts: {}, hosts: {}} | |
57 … | + if(!acc) acc = initial | |
57 | 58 … | var msg = data.value |
58 | 59 … | var invite, accept |
59 | 60 … | if(types.isInvite(msg, caps)) { |
60 | 61 … | //TODO: validate that this is a msg we understand! |
61 | 62 … | invite = msg |
62 | 63 … | accept = acc.accepts[data.key] |
64 … | + | |
65 … | + //remember guest ids, so that you can process pub messages. | |
66 … | + //this is necessary to confirm invites here the guest failed before they received | |
67 … | + //the confirmation, and do not realize they are confirmed yet. they'll try again later. | |
68 … | + | |
69 … | + //id rather not have this here. it's gonna bloat. better a different kind of index. | |
70 … | + //can fix this later though. | |
71 … | + acc.guests[data.value.content.invite] = true | |
63 | 72 … | } |
64 | 73 … | else if(types.isAccept(msg, caps)) { |
65 | 74 … | accept = msg |
66 | 75 … | invite = acc.invites[accept.content.receipt] |
@@ -98,9 +107,8 @@ | ||
98 | 107 … | |
99 | 108 … | return acc |
100 | 109 … | } |
101 | 110 … | |
102 | - var initial = {invites: {}, accepts: {}, hosts: {}} | |
103 | 111 … | var state |
104 | 112 … | //a hack here, so that we can grab a handle on invites.value.set |
105 | 113 … | var invites = sbot._flumeUse('user-invites', function (log, name) { |
106 | 114 … | var _invites = Reduce(2, reduce, null, null, initial)(log, name) |
@@ -122,18 +130,18 @@ | ||
122 | 130 … | }) |
123 | 131 … | |
124 | 132 … | sbot.auth.hook(function (fn, args) { |
125 | 133 … | var id = args[0], cb = args[1] |
134 … | + //currently a problem here where message may be confirmed, | |
135 … | + //but guest didn't get the welcome yet. they need to be able to connect | |
136 … | + //and request it again. | |
126 | 137 … | invites.get(function (err, v) { |
127 | 138 … | if(err) return cb(err) |
128 | - for(var k in v.invites) { | |
129 | - if(v.invites[k].content.invite === id) { | |
130 | - return cb(null, { | |
131 | - allow: ['userInvites.getInvite', 'userInvites.confirm'], | |
132 | - deny: null | |
133 | - }) | |
134 | - } | |
135 | - } | |
139 … | + if(v.guests[id]) | |
140 … | + return cb(null, { | |
141 … | + allow: ['userInvites.getInvite', 'userInvites.confirm'], | |
142 … | + deny: null | |
143 … | + }) | |
136 | 144 … | fn.apply(null, args) |
137 | 145 … | }) |
138 | 146 … | }) |
139 | 147 … | |
@@ -222,17 +230,9 @@ | ||
222 | 230 … | //before this write completes, it will write twice, so just return an error. |
223 | 231 … | if(accepted[invite_id]) return cb(new Error('race condition: try again soon')) |
224 | 232 … | |
225 | 233 … | accepted[invite_id] = true |
226 | - sbot.publish({ | |
227 | - type: 'user-invite/confirm', | |
228 | - embed: accept, | |
229 | - //second pointer back to receipt, so that links can find it | |
230 | - //(since it unfortunately does not handle links nested deeper | |
231 | - //inside objects. when we look up the message, | |
232 | - //confirm that content.embed.content.receipt is the same) | |
233 | - receipt: accept.content.receipt | |
234 | - }, function (err, data) { | |
234 … | + sbot.publish(I.createConfirm(accept), function (err, data) { | |
235 | 235 … | delete accepted[invite_id] |
236 | 236 … | cb(err, data.value) |
237 | 237 … | }) |
238 | 238 … | }) |
types.js | ||
---|---|---|
@@ -49,9 +49,14 @@ | ||
49 | 49 … | |
50 | 50 … | exports.isConfirm = function (msg) { |
51 | 51 … | return isObject(msg) && isObject(msg.content) && ( |
52 | 52 … | 'user-invite/confirm' === msg.content.type && |
53 | - exports.isAccept(msg.content.embed) | |
53 … | + exports.isAccept(msg.content.embed) && | |
54 … | + //second pointer back to receipt, so that links can find it | |
55 … | + //(since it unfortunately does not handle links nested deeper | |
56 … | + //inside objects. when we look up the message, | |
57 … | + //confirm that content.embed.content.receipt is the same) | |
58 … | + msg.content.embed.content.receipt === msg.content.receipt | |
54 | 59 … | ) |
55 | 60 … | } |
56 | 61 … | |
57 | 62 … |
valid.js | ||
---|---|---|
@@ -66,14 +66,16 @@ | ||
66 | 66 … | var keys = ssbKeys.generate(null, seed) //K |
67 | 67 … | if(keys.id != msg.content.invite) |
68 | 68 … | throw code(new Error('seed does not match invite'), 'seed-must-match-invite') |
69 | 69 … | var inviteId = '%'+ssbKeys.hash(JSON.stringify(msg, null, 2)) |
70 | - return ssbKeys.signObj(keys, caps.userInvite, { | |
70 … | + var content = { | |
71 | 71 … | type: 'user-invite/accept', |
72 | 72 … | receipt: inviteId, |
73 | - id: id, | |
74 | - key: msg.content.reveal ? u.hash(u.hash(seed)).toString('base64') : undefined | |
75 | - }) | |
73 … | + id: id | |
74 … | + } | |
75 … | + if(msg.content.reveal) | |
76 … | + content.key = u.hash(u.hash(seed)).toString('base64') | |
77 … | + return ssbKeys.signObj(keys, caps.userInvite, content) | |
76 | 78 … | } |
77 | 79 … | |
78 | 80 … | exports.verifyAcceptOnly = function (accept, caps) { |
79 | 81 … | if(!isObject(caps)) throw new Error('caps *must* be provided') |
@@ -115,5 +117,18 @@ | ||
115 | 117 … | //an ordinary message, so does not use hmac_key |
116 | 118 … | return reveal || true |
117 | 119 … | } |
118 | 120 … | |
121 … | +exports.createConfirm = function (accept) { | |
122 … | + return { | |
123 … | + type: 'user-invite/confirm', | |
124 … | + embed: accept, | |
125 … | + //second pointer back to receipt, so that links can find it | |
126 … | + //(since it unfortunately does not handle links nested deeper | |
127 … | + //inside objects. when we look up the message, | |
128 … | + //confirm that content.embed.content.receipt is the same) | |
129 … | + receipt: accept.content.receipt | |
130 … | + } | |
131 … | +} | |
119 | 132 … | |
133 … | + | |
134 … | + |
Built with git-ssb-web