statebus 7.0.4 → 7.0.7
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/{clients.js → client-library.js} +256 -127
- package/extras/coffee.js +12 -0
- package/extras/sockjs.js +27 -0
- package/extras/tests.js +58 -58
- package/package.json +6 -4
- package/{servers.js → server-library.js} +134 -97
- package/statebus.js +86 -59
|
@@ -105,17 +105,17 @@ function import_server (bus, make_statebus, options)
|
|
|
105
105
|
// Now handle backup handlers
|
|
106
106
|
if (count === 0) {
|
|
107
107
|
|
|
108
|
-
// A set to master without a
|
|
108
|
+
// A set to master without a setter defined should be
|
|
109
109
|
// automatically reflected to all clients.
|
|
110
|
-
if (method === '
|
|
110
|
+
if (method === 'setter') {
|
|
111
111
|
bus.set.fire(arg, t)
|
|
112
112
|
bus.route(arg.key, 'on_set_sync', arg, t)
|
|
113
113
|
count++
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
// A get to master without a
|
|
116
|
+
// A get to master without a getter defined should go to
|
|
117
117
|
// the database, if we have one.
|
|
118
|
-
if (method === '
|
|
118
|
+
if (method === 'getter') {
|
|
119
119
|
bus.db_get(key)
|
|
120
120
|
// This basically renders the count useless-- you probably
|
|
121
121
|
// don't want to wrap this route() with another route().
|
|
@@ -163,15 +163,10 @@ function import_server (bus, make_statebus, options)
|
|
|
163
163
|
|
|
164
164
|
// Handle the GET or PUT request!
|
|
165
165
|
if (req.method === 'GET') {
|
|
166
|
+
var key = req.path.substr(1)
|
|
166
167
|
|
|
167
168
|
// Make a temporary client bus
|
|
168
169
|
var cbus = bus.bus_for_http_client(req, res)
|
|
169
|
-
var cb
|
|
170
|
-
function end_subscription () {
|
|
171
|
-
cbus.forget(key, cb)
|
|
172
|
-
res.end()
|
|
173
|
-
cbus.http_unsubscribe(req)
|
|
174
|
-
}
|
|
175
170
|
|
|
176
171
|
braidify(req, res)
|
|
177
172
|
if (req.subscribe)
|
|
@@ -182,16 +177,12 @@ function import_server (bus, make_statebus, options)
|
|
|
182
177
|
// We only return JSON
|
|
183
178
|
res.setHeader('Content-Type', 'application/json')
|
|
184
179
|
|
|
185
|
-
// Do the get
|
|
186
|
-
// cbus.honk = 'statelog'
|
|
187
|
-
var key = req.path.substr(1)
|
|
188
180
|
// console.log('http_in: doing cbus.get(', key, ')')
|
|
189
|
-
|
|
181
|
+
|
|
182
|
+
var send_to_client = (o, t) => {
|
|
190
183
|
// console.trace('http_in: Sending update of', key)
|
|
191
184
|
var body = to_http_body(o)
|
|
192
185
|
|
|
193
|
-
// If we're braiding, send via subscription
|
|
194
|
-
|
|
195
186
|
// Note: if body === undefined, we need to send the
|
|
196
187
|
// equivalent of a 404. This is missing in braid spec:
|
|
197
188
|
// https://github.com/braid-org/braid-spec/issues/110
|
|
@@ -200,7 +191,31 @@ function import_server (bus, make_statebus, options)
|
|
|
200
191
|
// And shut down the connection if there's no subscription
|
|
201
192
|
if (!req.subscribe)
|
|
202
193
|
end_subscription()
|
|
203
|
-
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function end_subscription () {
|
|
197
|
+
cbus.forget(key, send_to_client)
|
|
198
|
+
res.end()
|
|
199
|
+
cbus.http_unsubscribe(req)
|
|
200
|
+
|
|
201
|
+
let peer = req.headers.peer
|
|
202
|
+
if (cbus.http_callbacks)
|
|
203
|
+
delete cbus.http_callbacks[JSON.stringify({peer, key})]
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// If we have a peer id, then register this callback at that peer,
|
|
207
|
+
// so it can avoid getting its own PUT versions echoed back to
|
|
208
|
+
// itself.
|
|
209
|
+
if (req.headers.peer) {
|
|
210
|
+
if (!cbus.http_callbacks)
|
|
211
|
+
cbus.http_callbacks = {}
|
|
212
|
+
let peer = req.headers.peer
|
|
213
|
+
cbus.http_callbacks[JSON.stringify({peer, key})]
|
|
214
|
+
= send_to_client
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// And issue the get!
|
|
218
|
+
cbus.get(key, send_to_client)
|
|
204
219
|
}
|
|
205
220
|
|
|
206
221
|
else if (req.method === 'PUT') {
|
|
@@ -233,7 +248,24 @@ function import_server (bus, make_statebus, options)
|
|
|
233
248
|
|
|
234
249
|
// Make a temporary client bus
|
|
235
250
|
var cbus = bus.bus_for_http_client(req, res)
|
|
236
|
-
|
|
251
|
+
var t = {
|
|
252
|
+
version: req.version || cbus.new_version(),
|
|
253
|
+
parents: req.parents
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// If the peer declares itself, let's remember it so that
|
|
257
|
+
// we don't send it echoes
|
|
258
|
+
if (req.headers.peer) {
|
|
259
|
+
let peer = req.headers.peer,
|
|
260
|
+
key = obj.key
|
|
261
|
+
var cb = cbus.http_callbacks[
|
|
262
|
+
JSON.stringify({peer, key})
|
|
263
|
+
]
|
|
264
|
+
if (cb) cb.has_seen(cbus, key, t.version)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Now send the version to the bus!
|
|
268
|
+
cbus.set(obj, t)
|
|
237
269
|
|
|
238
270
|
res.statusCode = 200
|
|
239
271
|
res.end()
|
|
@@ -523,7 +555,7 @@ function import_server (bus, make_statebus, options)
|
|
|
523
555
|
if (client_bus_func && !master.options.__secure) {
|
|
524
556
|
|
|
525
557
|
// A connection
|
|
526
|
-
client('connection/*').
|
|
558
|
+
client('connection/*').getter = function (key, star) {
|
|
527
559
|
var result = bus.clone(master.get(key))
|
|
528
560
|
if (master.options.connections.include_users && result.user)
|
|
529
561
|
result.user = client.get(result.user.key)
|
|
@@ -531,7 +563,7 @@ function import_server (bus, make_statebus, options)
|
|
|
531
563
|
result.client = star // Deprecated. Delete this line in v7.
|
|
532
564
|
return result
|
|
533
565
|
}
|
|
534
|
-
client('connection/*').
|
|
566
|
+
client('connection/*').setter = function (o, star, t) {
|
|
535
567
|
// Check permissions before editing
|
|
536
568
|
if (star !== conn.id && !master.options.connections.edit_others) {
|
|
537
569
|
t.abort()
|
|
@@ -543,7 +575,7 @@ function import_server (bus, make_statebus, options)
|
|
|
543
575
|
}
|
|
544
576
|
|
|
545
577
|
// Your connection
|
|
546
|
-
client('connection').
|
|
578
|
+
client('connection').getter = function () {
|
|
547
579
|
// subscribe to changes in authentication
|
|
548
580
|
client.get('current_user')
|
|
549
581
|
|
|
@@ -551,15 +583,15 @@ function import_server (bus, make_statebus, options)
|
|
|
551
583
|
delete result.key
|
|
552
584
|
return result
|
|
553
585
|
}
|
|
554
|
-
client('connection').
|
|
586
|
+
client('connection').setter = function (o) {
|
|
555
587
|
o = client.clone(o)
|
|
556
588
|
o.key = 'connection/' + conn.id
|
|
557
589
|
client.set(o)
|
|
558
590
|
}
|
|
559
591
|
|
|
560
592
|
// All connections
|
|
561
|
-
client('connections').
|
|
562
|
-
client('connections').
|
|
593
|
+
client('connections').setter = function noop (t) {t.abort()}
|
|
594
|
+
client('connections').getter = function () {
|
|
563
595
|
var result = []
|
|
564
596
|
var conns = master.get('connections').val
|
|
565
597
|
for (var connid in conns)
|
|
@@ -663,7 +695,7 @@ function import_server (bus, make_statebus, options)
|
|
|
663
695
|
}
|
|
664
696
|
on_set.priority = true
|
|
665
697
|
bus(prefix).on_set = on_set
|
|
666
|
-
bus(prefix).
|
|
698
|
+
bus(prefix).deleter = function (key) {
|
|
667
699
|
delete db[key]
|
|
668
700
|
if (active) save_later()
|
|
669
701
|
}
|
|
@@ -729,7 +761,7 @@ function import_server (bus, make_statebus, options)
|
|
|
729
761
|
return decodeURIComponent(k.replace('%2E', '.'))
|
|
730
762
|
}
|
|
731
763
|
|
|
732
|
-
bus(prefix).
|
|
764
|
+
bus(prefix).getter = function (key, t) {
|
|
733
765
|
firebase_ref.child(encode_firebase_key(key)).on('value', function (x) {
|
|
734
766
|
t.done(x.val() || {})
|
|
735
767
|
}, function (err) { t.abort() })
|
|
@@ -739,19 +771,19 @@ function import_server (bus, make_statebus, options)
|
|
|
739
771
|
firebase_ref.child(encode_firebase_key(o.key)).set(o)
|
|
740
772
|
}
|
|
741
773
|
|
|
742
|
-
// bus(prefix).
|
|
774
|
+
// bus(prefix).setter = function (o, t) {
|
|
743
775
|
// firebase_ref.child(encode_firebase_key(o.key)).set(o, (err) => {
|
|
744
776
|
// err ? t.abort() : t.done()
|
|
745
777
|
// })
|
|
746
778
|
// }
|
|
747
779
|
|
|
748
|
-
bus(prefix).
|
|
780
|
+
bus(prefix).deleter = function (key, t) {
|
|
749
781
|
firebase_ref.child(encode_firebase_key(key)).set(null, (err) => {
|
|
750
782
|
err ? t.abort() : t.done()
|
|
751
783
|
})
|
|
752
784
|
}
|
|
753
785
|
|
|
754
|
-
bus(prefix).
|
|
786
|
+
bus(prefix).forgetter = function (key, t) {
|
|
755
787
|
firebase_ref.child(encode_firebase_key(key)).off()
|
|
756
788
|
}
|
|
757
789
|
},
|
|
@@ -843,7 +875,7 @@ function import_server (bus, make_statebus, options)
|
|
|
843
875
|
: o))
|
|
844
876
|
|
|
845
877
|
// Publish this to the bus
|
|
846
|
-
bus.set.fire(obj, {
|
|
878
|
+
bus.set.fire(obj, {getter: true})
|
|
847
879
|
})
|
|
848
880
|
}
|
|
849
881
|
|
|
@@ -872,13 +904,13 @@ function import_server (bus, make_statebus, options)
|
|
|
872
904
|
if (opts.set_sync) {
|
|
873
905
|
var old_route = bus.route
|
|
874
906
|
bus.route = function (key, method, arg, t) {
|
|
875
|
-
if (method === '
|
|
907
|
+
if (method === 'setter') on_set(arg)
|
|
876
908
|
return old_route(key, method, arg, t)
|
|
877
909
|
}
|
|
878
910
|
} else
|
|
879
911
|
bus(prefix).on_set_sync = on_set
|
|
880
912
|
|
|
881
|
-
bus(prefix).
|
|
913
|
+
bus(prefix).deleter = function (key) {
|
|
882
914
|
if (opts.use_transactions && !open_transaction){
|
|
883
915
|
console.time('save db')
|
|
884
916
|
db.prepare('BEGIN TRANSACTION').run()
|
|
@@ -976,7 +1008,7 @@ function import_server (bus, make_statebus, options)
|
|
|
976
1008
|
}
|
|
977
1009
|
pg_set.priority = true
|
|
978
1010
|
bus(opts.prefix).on_set = pg_set
|
|
979
|
-
bus(opts.prefix).
|
|
1011
|
+
bus(opts.prefix).deleter = function (key) {
|
|
980
1012
|
db.query('delete from store where key = $1', [key])
|
|
981
1013
|
}
|
|
982
1014
|
|
|
@@ -1036,7 +1068,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1036
1068
|
bus.usage_log_nots = nots
|
|
1037
1069
|
|
|
1038
1070
|
// Aggregate all accesses by day, to get daily active users
|
|
1039
|
-
bus('usage').
|
|
1071
|
+
bus('usage').getter = () => {
|
|
1040
1072
|
bus.get('time/' + refresh_interval)
|
|
1041
1073
|
var days = []
|
|
1042
1074
|
var last_day
|
|
@@ -1075,7 +1107,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1075
1107
|
return {_: days}
|
|
1076
1108
|
}
|
|
1077
1109
|
|
|
1078
|
-
bus('recent_hits/*').
|
|
1110
|
+
bus('recent_hits/*').getter = (rest) => {
|
|
1079
1111
|
bus.get('time/' + refresh_interval)
|
|
1080
1112
|
var result = []
|
|
1081
1113
|
for (var row of db.prepare('select * from usage where '
|
|
@@ -1091,7 +1123,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1091
1123
|
return {_: result}
|
|
1092
1124
|
}
|
|
1093
1125
|
|
|
1094
|
-
bus('recent_referers/*').
|
|
1126
|
+
bus('recent_referers/*').getter = (rest) => {
|
|
1095
1127
|
bus.get('time/' + refresh_interval)
|
|
1096
1128
|
var result = []
|
|
1097
1129
|
for (var row of db.prepare('select * from usage where '
|
|
@@ -1140,7 +1172,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1140
1172
|
return times
|
|
1141
1173
|
}
|
|
1142
1174
|
|
|
1143
|
-
bus('socket_load_times').
|
|
1175
|
+
bus('socket_load_times').getter = () => {
|
|
1144
1176
|
return {_: sock_open_times()}
|
|
1145
1177
|
}
|
|
1146
1178
|
},
|
|
@@ -1152,21 +1184,21 @@ function import_server (bus, make_statebus, options)
|
|
|
1152
1184
|
},
|
|
1153
1185
|
|
|
1154
1186
|
time () {
|
|
1155
|
-
if (bus('time*').
|
|
1187
|
+
if (bus('time*').getter.length > 0)
|
|
1156
1188
|
// Then it's already installed
|
|
1157
1189
|
return
|
|
1158
1190
|
|
|
1159
1191
|
// Time ticker
|
|
1160
1192
|
var timeouts = {}
|
|
1161
1193
|
bus('time*', {
|
|
1162
|
-
|
|
1194
|
+
getter: (key, rest, t) => {
|
|
1163
1195
|
if (key === 'time') rest = '/1000'
|
|
1164
1196
|
timeout = parseInt(rest.substr(1))
|
|
1165
1197
|
function f () { bus.set.fire({key: key, val: Date.now()}) }
|
|
1166
1198
|
timeouts[key] = setInterval(f, timeout)
|
|
1167
1199
|
f()
|
|
1168
1200
|
},
|
|
1169
|
-
|
|
1201
|
+
forgetter: (key, rest) => {
|
|
1170
1202
|
if (key === 'time') key = 'time/1000'
|
|
1171
1203
|
clearTimeout(timeouts[key])
|
|
1172
1204
|
}
|
|
@@ -1237,8 +1269,8 @@ function import_server (bus, make_statebus, options)
|
|
|
1237
1269
|
// - Is there security hole if users have a ? or a / in their name?
|
|
1238
1270
|
// - Make the master.posts/ state not require /
|
|
1239
1271
|
// - Make standard url tools for optional slashes, and ? query params
|
|
1240
|
-
// - Should a e.g. client
|
|
1241
|
-
// - e.g. if master('posts*').
|
|
1272
|
+
// - Should a e.g. client setter abort if it calls set that aborts?
|
|
1273
|
+
// - e.g. if master('posts*').setter aborts
|
|
1242
1274
|
|
|
1243
1275
|
// Helpers
|
|
1244
1276
|
function get_posts (args) {
|
|
@@ -1293,15 +1325,15 @@ function import_server (bus, make_statebus, options)
|
|
|
1293
1325
|
// }
|
|
1294
1326
|
|
|
1295
1327
|
// Define state on master
|
|
1296
|
-
if (master('posts_for/*').
|
|
1328
|
+
if (master('posts_for/*').getter.length === 0) {
|
|
1297
1329
|
// Get posts for each user
|
|
1298
|
-
master('posts_for/*').
|
|
1330
|
+
master('posts_for/*').getter = (json) => {
|
|
1299
1331
|
watch_for_dirt('posts-for/' + json.for)
|
|
1300
1332
|
return {_: get_posts(json)}
|
|
1301
1333
|
}
|
|
1302
1334
|
// Saving any post will dirty the list for all users mentioned in
|
|
1303
1335
|
// the post
|
|
1304
|
-
master('post/*').
|
|
1336
|
+
master('post/*').setter = (old, New, t) => {
|
|
1305
1337
|
// To do: diff the cc, to, and from lists, and only dirty
|
|
1306
1338
|
// posts_for people who have been changed
|
|
1307
1339
|
|
|
@@ -1348,19 +1380,19 @@ function import_server (bus, make_statebus, options)
|
|
|
1348
1380
|
function dirty (key) { drtbus.set({key: 'dirty-'+key, n: Math.random()}) }
|
|
1349
1381
|
function watch_for_dirt (key) { drtbus.get('dirty-'+key) }
|
|
1350
1382
|
|
|
1351
|
-
client('current_email').
|
|
1383
|
+
client('current_email').getter = () => {
|
|
1352
1384
|
return {_: current_addy()}
|
|
1353
1385
|
}
|
|
1354
1386
|
|
|
1355
1387
|
// Define state on client
|
|
1356
|
-
client('posts*').
|
|
1388
|
+
client('posts*').getter = (k, rest) => {
|
|
1357
1389
|
var args = bus.parse(rest.substr(1))
|
|
1358
1390
|
args.for = current_addy()
|
|
1359
1391
|
var e = master.get('posts_for/' + JSON.stringify(args))
|
|
1360
1392
|
return {_: master.clone(e._).map(x=>client.get(x.key))}
|
|
1361
1393
|
}
|
|
1362
1394
|
|
|
1363
|
-
client('post/*').
|
|
1395
|
+
client('post/*').getter = (k) => {
|
|
1364
1396
|
var e = master.clone(master.get(k))
|
|
1365
1397
|
if (!e._) return {}
|
|
1366
1398
|
if (!can_see(e))
|
|
@@ -1372,7 +1404,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1372
1404
|
return e
|
|
1373
1405
|
}
|
|
1374
1406
|
|
|
1375
|
-
client('post/*').
|
|
1407
|
+
client('post/*').setter = (o, t) => {
|
|
1376
1408
|
if (!(client.validate(o, {key: 'string',
|
|
1377
1409
|
_: {to: 'array',
|
|
1378
1410
|
cc: 'array',
|
|
@@ -1407,7 +1439,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1407
1439
|
t.done()
|
|
1408
1440
|
}
|
|
1409
1441
|
|
|
1410
|
-
client('post/*').
|
|
1442
|
+
client('post/*').deleter = (key, o, t) => {
|
|
1411
1443
|
// Validate
|
|
1412
1444
|
if (!is_author(o)) {
|
|
1413
1445
|
console.error('User', current_addy(),
|
|
@@ -1431,14 +1463,14 @@ function import_server (bus, make_statebus, options)
|
|
|
1431
1463
|
t.done()
|
|
1432
1464
|
}
|
|
1433
1465
|
|
|
1434
|
-
client('friends').
|
|
1466
|
+
client('friends').getter = t => {
|
|
1435
1467
|
return {_: (master.get('users').val||[])
|
|
1436
1468
|
.map(u=>client.get('email/' + user_addy(u)))
|
|
1437
1469
|
.concat([client.get('email/public')])
|
|
1438
1470
|
}
|
|
1439
1471
|
}
|
|
1440
1472
|
|
|
1441
|
-
client('email/*').
|
|
1473
|
+
client('email/*').getter = (rest) => {
|
|
1442
1474
|
var m = rest.match(email_regex)
|
|
1443
1475
|
var result = {address: rest}
|
|
1444
1476
|
if (rest === 'public') {
|
|
@@ -1461,7 +1493,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1461
1493
|
|
|
1462
1494
|
sqlite_query_server: function sqlite_query_server (db) {
|
|
1463
1495
|
var get = bus.get
|
|
1464
|
-
bus('table_columns/*').
|
|
1496
|
+
bus('table_columns/*').getter =
|
|
1465
1497
|
function get_table_columns (key, rest) {
|
|
1466
1498
|
if (typeof key !== 'string')
|
|
1467
1499
|
console.log(handlers.hash)
|
|
@@ -1484,7 +1516,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1484
1516
|
}
|
|
1485
1517
|
|
|
1486
1518
|
|
|
1487
|
-
bus('table_foreign_keys/*').
|
|
1519
|
+
bus('table_foreign_keys/*').getter =
|
|
1488
1520
|
function table_foreign_keys (key, rest) {
|
|
1489
1521
|
var table_name = rest
|
|
1490
1522
|
var foreign_keys = get('sql/PRAGMA foreign_key_list(' + table_name + ')').rows
|
|
@@ -1496,7 +1528,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1496
1528
|
return result
|
|
1497
1529
|
}
|
|
1498
1530
|
|
|
1499
|
-
bus('sql/*').
|
|
1531
|
+
bus('sql/*').getter =
|
|
1500
1532
|
function sql (key, rest) {
|
|
1501
1533
|
get('time/60000')
|
|
1502
1534
|
var query = rest
|
|
@@ -1573,7 +1605,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1573
1605
|
// ************************
|
|
1574
1606
|
|
|
1575
1607
|
// Getting the whole table, or a single row
|
|
1576
|
-
bus(table_name + '*').
|
|
1608
|
+
bus(table_name + '*').getter = function (key, rest) {
|
|
1577
1609
|
if (rest === '')
|
|
1578
1610
|
// Return the whole table
|
|
1579
1611
|
return render_table()
|
|
@@ -1593,7 +1625,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1593
1625
|
}
|
|
1594
1626
|
|
|
1595
1627
|
// Saving a row
|
|
1596
|
-
bus(table_name + '/*').
|
|
1628
|
+
bus(table_name + '/*').setter = function (obj, rest) {
|
|
1597
1629
|
var columns = table_columns.columns
|
|
1598
1630
|
var key = remapped_keys.keys[obj.key] || obj.key
|
|
1599
1631
|
|
|
@@ -1619,7 +1651,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1619
1651
|
}
|
|
1620
1652
|
|
|
1621
1653
|
// Inserting a new row
|
|
1622
|
-
bus('new/' + table_name + '/*').
|
|
1654
|
+
bus('new/' + table_name + '/*').setter = function (obj) {
|
|
1623
1655
|
var columns = table_columns.columns
|
|
1624
1656
|
var stmt = ('insert into ' + table_name + ' (' + columns.join(',')
|
|
1625
1657
|
+ ') values (' + new Array(columns.length).join('?,') + '?)')
|
|
@@ -1638,7 +1670,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1638
1670
|
}
|
|
1639
1671
|
|
|
1640
1672
|
// Deleting a row
|
|
1641
|
-
bus(table_name + '/*').
|
|
1673
|
+
bus(table_name + '/*').deleter = function (key, rest) {
|
|
1642
1674
|
if (remapped_keys.keys[key]) {
|
|
1643
1675
|
var old_key = key
|
|
1644
1676
|
var new_key = remapped_keys.keys[key]
|
|
@@ -1659,6 +1691,11 @@ function import_server (bus, make_statebus, options)
|
|
|
1659
1691
|
},
|
|
1660
1692
|
|
|
1661
1693
|
serves_auth: function serves_auth (conn, master) {
|
|
1694
|
+
// Right now, we only support accounts at '@username', but in general
|
|
1695
|
+
// we could allow the prefix to be configurable. We just have to go
|
|
1696
|
+
// through this function and make all the regular expressions (like
|
|
1697
|
+
// /@*.../) parameterizable.
|
|
1698
|
+
var prefix = '@'
|
|
1662
1699
|
var client = this // to keep me straight while programming
|
|
1663
1700
|
function logout (user_key) {
|
|
1664
1701
|
var clients = master.get('logged_in_clients')
|
|
@@ -1690,9 +1727,9 @@ function import_server (bus, make_statebus, options)
|
|
|
1690
1727
|
if (!master.auth_initialized) {
|
|
1691
1728
|
|
|
1692
1729
|
// A hash for fast lookup of a user's password
|
|
1693
|
-
master('users/passwords').
|
|
1730
|
+
master('users/passwords').getter = function (k) {
|
|
1694
1731
|
// We compute it from the 'users' state
|
|
1695
|
-
master.log('users/passwords.
|
|
1732
|
+
master.log('users/passwords.getter: Computing!')
|
|
1696
1733
|
var result = {key: 'users/passwords', val: {}}
|
|
1697
1734
|
var users = master.get('users')
|
|
1698
1735
|
users.val = users.val || []
|
|
@@ -1715,7 +1752,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1715
1752
|
master.auth_initialized = true
|
|
1716
1753
|
master.get('users/passwords')
|
|
1717
1754
|
|
|
1718
|
-
master('
|
|
1755
|
+
master(prefix + '*').deleter = (key, t) => {
|
|
1719
1756
|
master.log('Deleteinggg!!!', key)
|
|
1720
1757
|
// Remove from users.all
|
|
1721
1758
|
var users = master.get('users')
|
|
@@ -1788,11 +1825,11 @@ function import_server (bus, make_statebus, options)
|
|
|
1788
1825
|
// might create it, even though the account hasn't been created
|
|
1789
1826
|
// yet, and then this will rename it to some random ID.
|
|
1790
1827
|
//
|
|
1791
|
-
var key =
|
|
1828
|
+
var key = prefix + params.name
|
|
1792
1829
|
if (!params.name)
|
|
1793
|
-
key =
|
|
1830
|
+
key = prefix + Math.random().toString(36).substring(7,13)
|
|
1794
1831
|
while (master.cache.hasOwnProperty(key))
|
|
1795
|
-
key =
|
|
1832
|
+
key = prefix + Math.random().toString(36).substring(7,13)
|
|
1796
1833
|
|
|
1797
1834
|
// Make account object
|
|
1798
1835
|
var new_account = {
|
|
@@ -1817,7 +1854,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1817
1854
|
}
|
|
1818
1855
|
|
|
1819
1856
|
// Current User
|
|
1820
|
-
client('current_user').
|
|
1857
|
+
client('current_user').getter = function (k) {
|
|
1821
1858
|
if (!conn.client)
|
|
1822
1859
|
return {val: {error: 'no client'}}
|
|
1823
1860
|
|
|
@@ -1826,7 +1863,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1826
1863
|
return result
|
|
1827
1864
|
}
|
|
1828
1865
|
|
|
1829
|
-
client('current_user').
|
|
1866
|
+
client('current_user').setter = function (o, t) {
|
|
1830
1867
|
var val = o.val
|
|
1831
1868
|
if (typeof val !== 'object') {
|
|
1832
1869
|
console.error('current_user: set to something not an object:', val)
|
|
@@ -1930,17 +1967,17 @@ function import_server (bus, make_statebus, options)
|
|
|
1930
1967
|
|
|
1931
1968
|
t.reget()
|
|
1932
1969
|
}
|
|
1933
|
-
client('current_user').
|
|
1970
|
+
client('current_user').deleter = function () {}
|
|
1934
1971
|
|
|
1935
|
-
// Users have closet space at
|
|
1936
|
-
var closet_space_key = /^(
|
|
1937
|
-
var private_closet_space_key =
|
|
1972
|
+
// Users have closet space at @<name>/*
|
|
1973
|
+
var closet_space_key = /^(@[^\/]+)\/.*/
|
|
1974
|
+
var private_closet_space_key = /^@[^\/]+\/private.*/
|
|
1938
1975
|
|
|
1939
1976
|
// User
|
|
1940
|
-
client('
|
|
1977
|
+
client(prefix + '*').setter = function (o, t) {
|
|
1941
1978
|
var c = client.get('current_user')
|
|
1942
|
-
var user_key = o.key.match(
|
|
1943
|
-
user_key = user_key && (
|
|
1979
|
+
var user_key = o.key.match(/^@([^\/]+)/)
|
|
1980
|
+
user_key = user_key && (prefix + user_key[1])
|
|
1944
1981
|
|
|
1945
1982
|
// Only the current user can touch himself.
|
|
1946
1983
|
if (!c.val.logged_in || c.val.user.link !== user_key) {
|
|
@@ -1953,7 +1990,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1953
1990
|
return
|
|
1954
1991
|
}
|
|
1955
1992
|
|
|
1956
|
-
// Users have closet space at
|
|
1993
|
+
// Users have closet space at @<name>/*
|
|
1957
1994
|
if (o.key.match(closet_space_key)) {
|
|
1958
1995
|
client.log('saving closet data')
|
|
1959
1996
|
master.set(o, t)
|
|
@@ -1961,7 +1998,7 @@ function import_server (bus, make_statebus, options)
|
|
|
1961
1998
|
}
|
|
1962
1999
|
|
|
1963
2000
|
// Ok, then it must be a plain user
|
|
1964
|
-
console.assert(o.key.match(
|
|
2001
|
+
console.assert(o.key.match(/^@[^\/]+$/))
|
|
1965
2002
|
|
|
1966
2003
|
// Validate types
|
|
1967
2004
|
if (!client.validate(o, {key: 'string',
|
|
@@ -2040,11 +2077,11 @@ function import_server (bus, make_statebus, options)
|
|
|
2040
2077
|
|
|
2041
2078
|
master.set(u)
|
|
2042
2079
|
}
|
|
2043
|
-
client('
|
|
2080
|
+
client(prefix + '*').getter = function user_getter (k) {
|
|
2044
2081
|
var c = client.get('current_user')
|
|
2045
2082
|
client.log('* getting:', k, 'as', c.val.user)
|
|
2046
2083
|
|
|
2047
|
-
// Users have closet space at
|
|
2084
|
+
// Users have closet space at @<name>/*
|
|
2048
2085
|
if (k.match(closet_space_key)) {
|
|
2049
2086
|
var obj_user = k.match(closet_space_key)[1]
|
|
2050
2087
|
if (k.match(private_closet_space_key)
|
|
@@ -2059,10 +2096,10 @@ function import_server (bus, make_statebus, options)
|
|
|
2059
2096
|
// Otherwise return the actual user
|
|
2060
2097
|
return user_obj(k, c.val.logged_in && c.val.user.link === k)
|
|
2061
2098
|
}
|
|
2062
|
-
client('
|
|
2099
|
+
client(prefix + '*').deleter = function () {}
|
|
2063
2100
|
function user_obj (k, logged_in) {
|
|
2064
2101
|
var o = master.clone(master.get(k))
|
|
2065
|
-
if (k.match(
|
|
2102
|
+
if (k.match(/^@([^\/]+)\/private\/(.*)$/))
|
|
2066
2103
|
return logged_in ? o : {key: k}
|
|
2067
2104
|
|
|
2068
2105
|
o.val = o.val || {}
|
|
@@ -2074,10 +2111,10 @@ function import_server (bus, make_statebus, options)
|
|
|
2074
2111
|
// Blacklist sensitive stuff on master, in case we have a shadow set up
|
|
2075
2112
|
var blacklist = 'users users/passwords logged_in_clients'.split(' ')
|
|
2076
2113
|
for (var i=0; i<blacklist.length; i++) {
|
|
2077
|
-
client(blacklist[i]).
|
|
2078
|
-
client(blacklist[i]).
|
|
2079
|
-
client(blacklist[i]).
|
|
2080
|
-
client(blacklist[i]).
|
|
2114
|
+
client(blacklist[i]).getter = function () {}
|
|
2115
|
+
client(blacklist[i]).setter = function () {}
|
|
2116
|
+
client(blacklist[i]).deleter = function () {}
|
|
2117
|
+
client(blacklist[i]).forgetter = function () {}
|
|
2081
2118
|
}
|
|
2082
2119
|
},
|
|
2083
2120
|
|
|
@@ -2145,7 +2182,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2145
2182
|
was_logged_in = c.val.logged_in
|
|
2146
2183
|
})
|
|
2147
2184
|
|
|
2148
|
-
client(prefix_to_sync).
|
|
2185
|
+
client(prefix_to_sync).getter = function (key) {
|
|
2149
2186
|
var c = client.get('current_user')
|
|
2150
2187
|
if (client.loading()) return
|
|
2151
2188
|
var prefix = client_prefix(c)
|
|
@@ -2162,7 +2199,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2162
2199
|
return obj
|
|
2163
2200
|
}
|
|
2164
2201
|
|
|
2165
|
-
client(prefix_to_sync).
|
|
2202
|
+
client(prefix_to_sync).setter = function (obj) {
|
|
2166
2203
|
if (validate && !validate(obj)) {
|
|
2167
2204
|
console.warn('Validation failed on', obj)
|
|
2168
2205
|
client.set.abort(obj)
|
|
@@ -2190,7 +2227,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2190
2227
|
p_keys && client.master.set(p_keys)
|
|
2191
2228
|
}
|
|
2192
2229
|
|
|
2193
|
-
client(prefix_to_sync).
|
|
2230
|
+
client(prefix_to_sync).deleter = function (k) {
|
|
2194
2231
|
k = client_prefix(client.get('current_user')) + k
|
|
2195
2232
|
client.master.delete(k)
|
|
2196
2233
|
|
|
@@ -2216,19 +2253,19 @@ function import_server (bus, make_statebus, options)
|
|
|
2216
2253
|
// to the global cache
|
|
2217
2254
|
if (count === 0) {
|
|
2218
2255
|
count++
|
|
2219
|
-
if (method === '
|
|
2256
|
+
if (method === 'getter')
|
|
2220
2257
|
bus.run_handler(function get_from_master (k) {
|
|
2221
2258
|
// console.log('DEFAULT GETting', k)
|
|
2222
2259
|
var r = master_bus.get(k)
|
|
2223
2260
|
// console.log('DEFAULT GETted', r)
|
|
2224
2261
|
bus.set.fire(r, {version: master_bus.versions[r.key]})
|
|
2225
2262
|
}, method, arg)
|
|
2226
|
-
else if (method === '
|
|
2263
|
+
else if (method === 'setter')
|
|
2227
2264
|
bus.run_handler(function set_to_master (o, t) {
|
|
2228
2265
|
// console.log('DEFAULT ROUTE', t)
|
|
2229
2266
|
master_bus.set(bus.clone(o), t)
|
|
2230
2267
|
}, method, arg, {t: t})
|
|
2231
|
-
else if (method == '
|
|
2268
|
+
else if (method == 'deleter')
|
|
2232
2269
|
bus.run_handler(function delete_from_master (k, t) {
|
|
2233
2270
|
master_bus.delete(k)
|
|
2234
2271
|
return 'done'
|
|
@@ -2282,7 +2319,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2282
2319
|
// file or recursive directory structure at fs_path
|
|
2283
2320
|
sync_files: function sync_files (state_path, file_path) {
|
|
2284
2321
|
// To do:
|
|
2285
|
-
// - Hook up a
|
|
2322
|
+
// - Hook up a deleter handler
|
|
2286
2323
|
// - recursively remove directories if all files gone
|
|
2287
2324
|
|
|
2288
2325
|
console.assert(state_path.substr(-1) !== '*'
|
|
@@ -2293,7 +2330,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2293
2330
|
var buffer = {}
|
|
2294
2331
|
var full_file_path = require('path').join(__dirname, file_path)
|
|
2295
2332
|
|
|
2296
|
-
bus(state_path + '*').
|
|
2333
|
+
bus(state_path + '*').getter = (rest) => {
|
|
2297
2334
|
// We DO want to handle:
|
|
2298
2335
|
// - "foo"
|
|
2299
2336
|
// - "foo/*"
|
|
@@ -2319,7 +2356,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2319
2356
|
return {_:f}
|
|
2320
2357
|
}
|
|
2321
2358
|
|
|
2322
|
-
bus(state_path + '/*').
|
|
2359
|
+
bus(state_path + '/*').setter = (o, rest, t) => {
|
|
2323
2360
|
if (rest.length>0 && rest[0] !== '/') return
|
|
2324
2361
|
var f = Buffer.from(o._, 'base64')
|
|
2325
2362
|
require('fs').writeFile(file_path + rest, f,
|
|
@@ -2336,7 +2373,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2336
2373
|
var textbus = make_statebus()
|
|
2337
2374
|
textbus.label = 'textbus'
|
|
2338
2375
|
var watched = new Set()
|
|
2339
|
-
textbus('*').
|
|
2376
|
+
textbus('*').getter = (filename, old) => {
|
|
2340
2377
|
return {etag: Math.random() + '',
|
|
2341
2378
|
_: getter(filename)}
|
|
2342
2379
|
}
|
|
@@ -2402,7 +2439,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2402
2439
|
path = path || 'client.js'
|
|
2403
2440
|
bus.http.get('/' + path, (req, res) => {
|
|
2404
2441
|
var files =
|
|
2405
|
-
['extras/coffee.js', 'extras/sockjs.js',
|
|
2442
|
+
['extras/coffee.js', 'extras/sockjs.js',
|
|
2406
2443
|
'statebus.js', 'client.js'].map((f) => fs.readFileSync('node_modules/statebus/' + f))
|
|
2407
2444
|
files.unshift(fs.readFileSync(
|
|
2408
2445
|
'node_modules/braidify/braidify-client.js'
|
|
@@ -2412,7 +2449,7 @@ function import_server (bus, make_statebus, options)
|
|
|
2412
2449
|
},
|
|
2413
2450
|
|
|
2414
2451
|
serve_wiki: () => {
|
|
2415
|
-
bus('edit/*').
|
|
2452
|
+
bus('edit/*').getter = () => ({_: require('./extras/wiki.coffee').code})
|
|
2416
2453
|
},
|
|
2417
2454
|
|
|
2418
2455
|
unix_socket_repl: function (filename) {
|
|
@@ -2559,7 +2596,7 @@ module.exports.import_module = function (statebus) {
|
|
|
2559
2596
|
|
|
2560
2597
|
statebus.serve = function serve (options) {
|
|
2561
2598
|
var bus = statebus()
|
|
2562
|
-
require('./
|
|
2599
|
+
require('./server-library').run_server(bus, options)
|
|
2563
2600
|
return bus
|
|
2564
2601
|
}
|
|
2565
2602
|
|