Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50671 views
1
###
2
TESTING of syncstring user and project queries
3
4
COPYRIGHT : (c) 2017 SageMath, Inc.
5
LICENSE : AGPLv3
6
###
7
8
async = require('async')
9
expect = require('expect')
10
11
pgtest = require('./pgtest')
12
db = undefined
13
setup = (cb) -> (pgtest.setup (err) -> db=pgtest.db; cb(err))
14
teardown = pgtest.teardown
15
16
{create_accounts, create_projects, changefeed_series} = pgtest
17
misc = require('smc-util/misc')
18
19
describe 'basic use of syncstring table from user -- ', ->
20
before(setup)
21
after(teardown)
22
23
accounts = projects = undefined
24
path = 'a.txt'
25
it 'creates 2 accounts', (done) ->
26
create_accounts 2, (err, x) -> accounts=x; done(err)
27
it 'creates 2 projects', (done) ->
28
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
29
30
it 'verifies anonymous set queries are not allowed', (done) ->
31
db.user_query
32
query : {syncstrings:{project_id:projects[0], path:path, users:accounts}}
33
cb : (err) ->
34
expect(err).toEqual("no anonymous set queries")
35
done()
36
37
it 'verifies anonymous get queries are not allowed', (done) ->
38
db.user_query
39
query : {syncstrings:{project_id:projects[0], path:path, users:null}}
40
cb : (err) ->
41
expect(err).toEqual("anonymous get queries not allowed for table 'syncstrings'")
42
done()
43
44
it 'creates a syncstring entry', (done) ->
45
db.user_query
46
account_id : accounts[0]
47
query : {syncstrings:{project_id:projects[0], path:path, users:accounts}}
48
cb : done
49
50
it 'verifies that entry has the documented string_id', (done) ->
51
db.user_query
52
account_id : accounts[0]
53
query : {syncstrings:{project_id:projects[0], path:path, users:null, string_id:null}}
54
cb : (err, result) ->
55
string_id = db.sha1(projects[0], path)
56
expect(result?.syncstrings).toEqual({project_id:projects[0], path:path, users:accounts, string_id:string_id})
57
done(err)
58
59
it "verifies that account1 can't write to project it isn't on", (done) ->
60
db.user_query
61
account_id : accounts[1]
62
query : {syncstrings:{project_id:projects[0], path:'b.txt'}}
63
cb : (err) ->
64
expect(err).toEqual('user must be an admin')
65
done()
66
67
it 'makes account1 an admin', (done) ->
68
db.make_user_admin
69
account_id : accounts[1]
70
cb : done
71
72
it "verifies that account1 as admin *can* write to project it isn't on", (done) ->
73
db.user_query
74
account_id : accounts[1]
75
query : {syncstrings:{project_id:projects[0], path:'b.txt'}}
76
cb : done
77
78
ss_every = undefined
79
it 'writes a syncstring with every field set', (done) ->
80
ss_every =
81
project_id : projects[1]
82
path : path
83
users : accounts
84
last_snapshot : misc.hours_ago(5)
85
snapshot_interval : 100
86
deleted : true
87
save : {state:'requested'}
88
last_active : misc.hours_ago(2)
89
init : {time:new Date()}
90
read_only : true
91
last_file_change : misc.hours_ago(3)
92
db.user_query
93
account_id : accounts[0]
94
query : {syncstrings:ss_every}
95
cb : done
96
97
it 'reads back syncstring with every field set', (done) ->
98
t = misc.copy(ss_every)
99
for k of t
100
if k == 'project_id' or k == 'path'
101
continue
102
t[k] = null
103
db.user_query
104
account_id : accounts[0]
105
query : {syncstrings:t}
106
cb : (err, result) ->
107
ss_every.string_id = db.sha1(projects[1], path)
108
expect(result?.syncstrings).toEqual(ss_every)
109
done(err)
110
111
it 'modifies a field of the syncstring we just created', (done) ->
112
db.user_query
113
account_id : accounts[0]
114
query : {syncstrings:{project_id:projects[1], path:path, read_only:false}}
115
cb : done
116
117
it 'verifies the modification', (done) ->
118
db.user_query
119
account_id : accounts[0]
120
query : {syncstrings:{project_id:projects[1], path:path, read_only:null}}
121
cb : (err, result) ->
122
expect(result?.syncstrings).toEqual({project_id:projects[1], path:path, read_only:false, string_id:db.sha1(projects[1], path)})
123
done(err)
124
125
it 'confirms that project_id must be given in set query', (done) ->
126
db.user_query
127
account_id : accounts[0]
128
query : {syncstrings:{path:path, read_only:true}}
129
cb : (err) ->
130
expect(err).toEqual('project_id must be a valid uuid')
131
done()
132
133
it 'confirms that path does NOT have to be given (this would be the project-wide syncstring)', (done) ->
134
db.user_query
135
account_id : accounts[0]
136
query : {syncstrings:{project_id:projects[1], read_only:true}}
137
cb : done
138
139
it 'confirms that project_id must be given in get query', (done) ->
140
db.user_query
141
account_id : accounts[0]
142
query : {syncstrings:{path:path, read_only:null}}
143
cb : (err) ->
144
expect(err).toEqual('project_id must be a valid uuid')
145
done()
146
147
it 'confirms that path does NOT have to be given in get query either', (done) ->
148
db.user_query
149
account_id : accounts[0]
150
query : {syncstrings:{project_id:projects[1], read_only:null}}
151
cb : done
152
153
it 'check that there are two syncstrings in second project', (done) ->
154
db._count
155
table : 'syncstrings'
156
where : {project_id:projects[1]}
157
cb : (err, n) ->
158
expect(n).toEqual(2)
159
done(err)
160
161
it 'check two syncstring in first project', (done) ->
162
db._count
163
table : 'syncstrings'
164
where : {project_id:projects[0]}
165
cb : (err, n) ->
166
expect(n).toEqual(2)
167
done(err)
168
169
describe 'syncstring changefeed from account -- ', ->
170
before(setup)
171
after(teardown)
172
173
accounts = projects = undefined
174
path = 'a.txt'
175
it 'creates 2 accounts', (done) ->
176
create_accounts 2, (err, x) -> accounts=x; done(err)
177
it 'creates 2 projects', (done) ->
178
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
179
180
changefeed_id = misc.uuid()
181
it 'creates a changefeed', (done) ->
182
obj = {project_id:projects[0], path:path, read_only:true, users:accounts}
183
db.user_query
184
account_id : accounts[0]
185
query : {syncstrings:[{project_id:projects[0], path:path, read_only:null, users:null}]}
186
changes : changefeed_id
187
cb : changefeed_series([
188
(x, cb) ->
189
expect(x.syncstrings.length).toEqual(0)
190
191
# create an entry matching the condition
192
db.user_query(account_id: accounts[0], query: {syncstrings: obj}, cb: cb)
193
(x, cb) ->
194
obj.string_id = db.sha1(projects[0], path)
195
expect(x).toEqual({action:'insert', new_val:obj})
196
197
# modify the read_only field
198
obj.read_only = false
199
db.user_query(account_id: accounts[0], query: {syncstrings: obj}, cb: cb)
200
(x, cb) ->
201
expect(x).toEqual({action:'update', new_val:obj})
202
203
# modify the users field
204
obj.users = [accounts[0]]
205
db.user_query(account_id: accounts[0], query: {syncstrings: obj}, cb: cb)
206
(x, cb) ->
207
expect(x).toEqual({action:'update', new_val:obj})
208
209
# change an irrelevant field and get no update, then change the read_only field back so we see something
210
db.user_query
211
account_id : accounts[0]
212
query : {syncstrings: {string_id:obj.string_id, project_id:obj.project_id, path:obj.path, last_active:new Date()}}
213
cb : (err) ->
214
if err
215
cb(err)
216
else
217
delete obj.last_active
218
obj.read_only = true
219
db.user_query(account_id: accounts[0], query: {syncstrings: obj}, cb: cb)
220
(x, cb) ->
221
expect(x).toEqual({action:'update', new_val:obj})
222
223
db.user_query_cancel_changefeed(id:changefeed_id, cb:cb)
224
(x, cb) ->
225
expect(x).toEqual({action:'close'})
226
cb()
227
], done)
228
229
describe 'basic use of syncstring table from project -- ', ->
230
before(setup)
231
after(teardown)
232
233
accounts = projects = undefined
234
path = 'a.txt'
235
it 'creates 2 accounts', (done) ->
236
create_accounts 2, (err, x) -> accounts=x; done(err)
237
it 'creates 2 projects', (done) ->
238
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
239
240
it 'creates a syncstring entry', (done) ->
241
db.user_query
242
project_id : projects[0]
243
query : {syncstrings:{project_id:projects[0], path:path, users:accounts}}
244
cb : done
245
246
it 'verifies that entry has the documented string_id', (done) ->
247
db.user_query
248
project_id : projects[0]
249
query : {syncstrings:{project_id:projects[0], path:path, users:null, string_id:null}}
250
cb : (err, result) ->
251
string_id = db.sha1(projects[0], path)
252
expect(result?.syncstrings).toEqual({project_id:projects[0], path:path, users:accounts, string_id:string_id})
253
done(err)
254
255
it "verifies that project1 can't write to syncstring for other project", (done) ->
256
db.user_query
257
project_id : projects[1]
258
query : {syncstrings:{project_id:projects[0], path:'b.txt'}}
259
cb : (err) ->
260
expect(err).toEqual('projects can only access their own syncstrings')
261
done()
262
263
ss_every = undefined
264
it 'project1 writes a syncstring with every field set', (done) ->
265
ss_every =
266
project_id : projects[1]
267
path : path
268
users : accounts
269
last_snapshot : misc.hours_ago(5)
270
snapshot_interval : 100
271
deleted : true
272
save : {state:'requested'}
273
last_active : misc.hours_ago(2)
274
init : {time:new Date()}
275
read_only : true
276
last_file_change : misc.hours_ago(3)
277
db.user_query
278
project_id : projects[1]
279
query : {syncstrings:ss_every}
280
cb : done
281
282
it 'reads back syncstring with every field set', (done) ->
283
t = misc.copy(ss_every)
284
for k of t
285
if k == 'project_id' or k == 'path'
286
continue
287
t[k] = null
288
db.user_query
289
project_id : projects[1]
290
query : {syncstrings:t}
291
cb : (err, result) ->
292
ss_every.string_id = db.sha1(projects[1], path)
293
expect(result?.syncstrings).toEqual(ss_every)
294
done(err)
295
296
it 'modifies a field of the syncstring we just created', (done) ->
297
db.user_query
298
project_id : projects[1]
299
query : {syncstrings:{project_id:projects[1], path:path, read_only:false}}
300
cb : done
301
302
it 'verifies the modification', (done) ->
303
db.user_query
304
project_id : projects[1]
305
query : {syncstrings:{project_id:projects[1], path:path, read_only:null}}
306
cb : (err, result) ->
307
expect(result?.syncstrings).toEqual({project_id:projects[1], path:path, read_only:false, string_id:db.sha1(projects[1], path)})
308
done(err)
309
310
it 'confirms that project_id must be given in set query', (done) ->
311
db.user_query
312
project_id : projects[1]
313
query : {syncstrings:{path:path, read_only:true}}
314
cb : (err) ->
315
expect(err).toEqual('project_id must be a valid uuid')
316
done()
317
318
it 'confirms that path does NOT have to be given (this would be the project-wide syncstring)', (done) ->
319
db.user_query
320
project_id : projects[1]
321
query : {syncstrings:{project_id:projects[1], read_only:true}}
322
cb : done
323
324
it 'confirms that project_id must be given in get query', (done) ->
325
db.user_query
326
project_id : projects[1]
327
query : {syncstrings:{path:path, read_only:null}}
328
cb : (err) ->
329
expect(err).toEqual('project_id must be a valid uuid')
330
done()
331
332
it 'confirms that path does NOT have to be given in get query either', (done) ->
333
db.user_query
334
project_id : projects[1]
335
query : {syncstrings:{project_id:projects[1], read_only:null}}
336
cb : done
337
338
describe 'syncstring changefeed from project -- ', ->
339
before(setup)
340
after(teardown)
341
342
accounts = projects = undefined
343
path = 'a.txt'
344
it 'creates 2 accounts', (done) ->
345
create_accounts 2, (err, x) -> accounts=x; done(err)
346
it 'creates 2 projects', (done) ->
347
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
348
349
changefeed_id = misc.uuid()
350
it 'creates a changefeed', (done) ->
351
obj = {project_id:projects[0], path:path, read_only:true, users:accounts}
352
db.user_query
353
project_id : projects[0]
354
query : {syncstrings:[{project_id:projects[0], path:path, read_only:null, users:null}]}
355
changes : changefeed_id
356
cb : changefeed_series([
357
(x, cb) ->
358
expect(x.syncstrings.length).toEqual(0)
359
360
# create an entry matching the condition
361
db.user_query(project_id: projects[0], query: {syncstrings: obj}, cb: cb)
362
(x, cb) ->
363
obj.string_id = db.sha1(projects[0], path)
364
expect(x).toEqual({action:'insert', new_val:obj})
365
366
# modify the read_only field (as user not project...)
367
obj.read_only = false
368
db.user_query(account_id: accounts[0], query: {syncstrings: obj}, cb: cb)
369
(x, cb) ->
370
expect(x).toEqual({action:'update', new_val:obj})
371
372
# modify the users field
373
obj.users = [accounts[0]]
374
db.user_query(project_id: projects[0], query: {syncstrings: obj}, cb: cb)
375
(x, cb) ->
376
expect(x).toEqual({action:'update', new_val:obj})
377
378
# change an irrelevant field and get no update, then change the read_only field back so we see something
379
db.user_query
380
project_id : projects[0]
381
query : {syncstrings: {string_id:obj.string_id, project_id:obj.project_id, path:obj.path, last_active:new Date()}}
382
cb : (err) ->
383
if err
384
cb(err)
385
else
386
delete obj.last_active
387
obj.read_only = true
388
db.user_query(project_id: projects[0], query: {syncstrings: obj}, cb: cb)
389
(x, cb) ->
390
expect(x).toEqual({action:'update', new_val:obj})
391
392
db.user_query_cancel_changefeed(id:changefeed_id, cb:cb)
393
(x, cb) ->
394
expect(x).toEqual({action:'close'})
395
cb()
396
], done)
397
398
describe 'test syncstrings_delete -- ', ->
399
before(setup)
400
after(teardown)
401
402
accounts = projects = undefined
403
path = 'a.txt'
404
it 'creates 1 accounts', (done) ->
405
create_accounts 1, (err, x) -> accounts=x; done(err)
406
it 'creates 1 projects', (done) ->
407
create_projects 1, accounts[0], (err, x) -> projects=x; done(err)
408
409
it 'creates a syncstring entry', (done) ->
410
db.user_query
411
account_id : accounts[0]
412
query : {syncstrings:{project_id:projects[0], path:path, users:accounts}}
413
cb : done
414
415
it 'confirms syncstring was properly written', (done) ->
416
db.user_query
417
account_id : accounts[0]
418
query : {syncstrings:{project_id:projects[0], path:path, users:null}}
419
cb : (err, result) ->
420
expect(result).toEqual({syncstrings:{project_id:projects[0], path:path, users:accounts, string_id:db.sha1(projects[0], path)}})
421
done(err)
422
423
it "verifies that account can't delete (since not admin)", (done) ->
424
db.user_query
425
account_id : accounts[0]
426
query : {syncstrings_delete:{project_id:projects[0], path:path}}
427
cb : (err) ->
428
expect(err).toEqual('user must be an admin')
429
done()
430
431
it 'makes account an admin', (done) ->
432
db.make_user_admin(account_id: accounts[0], cb: done)
433
434
it 'verifies that admin can delete', (done) ->
435
db.user_query
436
account_id : accounts[0]
437
query : {syncstrings_delete:{project_id:projects[0], path:path}}
438
cb : done
439
440
it 'confirms syncstring was deleted', (done) ->
441
db.user_query
442
account_id : accounts[0]
443
query : {syncstrings:{project_id:projects[0], path:path, users:null}}
444
cb : (err, result) ->
445
expect(result).toEqual({syncstrings:undefined})
446
done(err)
447
448
describe 'test access roles for recent_syncstrings_in_project', ->
449
before(setup)
450
after(teardown)
451
452
accounts = projects = undefined
453
path = 'a.txt'
454
it 'creates 2 accounts', (done) ->
455
create_accounts 2, (err, x) -> accounts=x; done(err)
456
it 'creates 2 projects', (done) ->
457
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
458
459
it 'verifies anonymous set queries are not allowed', (done) ->
460
db.user_query
461
query : {recent_syncstrings_in_project:{project_id:projects[0], path:'foo.txt'}}
462
cb : (err) ->
463
expect(err).toEqual("no anonymous set queries")
464
done()
465
466
it 'verifies anonymous get queries are not allowed', (done) ->
467
db.user_query
468
query : {recent_syncstrings_in_project:{project_id:projects[0], max_age_m:15, string_id:null}}
469
cb : (err) ->
470
expect(err).toEqual("anonymous get queries not allowed for table 'recent_syncstrings_in_project'")
471
done()
472
473
it 'account do a valid get query and confirms no recent syncstrings', (done) ->
474
db.user_query
475
account_id : accounts[0]
476
query : {recent_syncstrings_in_project:{project_id:projects[0], max_age_m:15, string_id:null}}
477
cb : (err, result) ->
478
expect(result).toEqual(recent_syncstrings_in_project:undefined)
479
done(err)
480
481
it 'project does a valid get query and confirms no recent syncstrings', (done) ->
482
db.user_query
483
project_id : projects[0]
484
query : {recent_syncstrings_in_project:{project_id:projects[0], max_age_m:15, string_id:null}}
485
cb : (err, result) ->
486
expect(result).toEqual(recent_syncstrings_in_project:undefined)
487
done(err)
488
489
it 'project does an invalid get query and confirms get error', (done) ->
490
db.user_query
491
project_id : projects[1]
492
query : {recent_syncstrings_in_project:{project_id:projects[0], max_age_m:15, string_id:null}}
493
cb : (err, result) ->
494
expect(err).toEqual('projects can only access their own syncstrings')
495
done()
496
497
it 'account do invalid get query and error', (done) ->
498
db.user_query
499
account_id : accounts[1]
500
query : {recent_syncstrings_in_project:{project_id:projects[0], max_age_m:15, string_id:null}}
501
cb : (err, result) ->
502
expect(err).toEqual('user must be an admin')
503
done()
504
505
it 'makes account1 an admin', (done) ->
506
db.make_user_admin
507
account_id : accounts[1]
508
cb : done
509
510
it 'admin does previously disallowed get query and it works', (done) ->
511
db.user_query
512
account_id : accounts[1]
513
query : {recent_syncstrings_in_project:{project_id:projects[0], max_age_m:15, string_id:null}}
514
cb : (err, result) ->
515
expect(result).toEqual(recent_syncstrings_in_project:undefined)
516
done(err)
517
518
describe 'test writing and reading for recent_syncstrings_in_project -- ', ->
519
before(setup)
520
after(teardown)
521
522
accounts = projects = undefined
523
it 'creates 2 accounts', (done) ->
524
create_accounts 2, (err, x) -> accounts=x; done(err)
525
526
path0 = '1.txt'
527
path1 = '2.txt'
528
time0 = misc.minutes_ago(10)
529
time1 = misc.minutes_ago(20)
530
string_id0 = string_id1 = undefined
531
it 'creates 2 projects', (done) ->
532
create_projects 2, accounts[0], (err, x) ->
533
projects=x
534
string_id0 = db.sha1(projects[0], path0)
535
string_id1 = db.sha1(projects[0], path1)
536
done(err)
537
538
it 'creates a syncstring entry', (done) ->
539
db.user_query
540
account_id : accounts[0]
541
query : {syncstrings:{project_id:projects[0], path:path0, users:accounts, last_active:time0}}
542
cb : done
543
544
it 'creates an older syncstring entry', (done) ->
545
db.user_query
546
account_id : accounts[0]
547
query : {syncstrings:{project_id:projects[0], path:path1, users:accounts, last_active:time1}}
548
cb : done
549
550
it 'as user, queries for recent syncstrings and gets it', (done) ->
551
db.user_query
552
account_id : accounts[0]
553
query : {recent_syncstrings_in_project:[{project_id:projects[0], max_age_m:15, last_active:null, string_id:null}]}
554
cb : (err, result) ->
555
expect(result).toEqual(recent_syncstrings_in_project:[{project_id:projects[0], last_active:time0, string_id:string_id0}])
556
done(err)
557
558
it 'as project, queries for recent syncstrings and gets it', (done) ->
559
db.user_query
560
project_id : projects[0]
561
query : {recent_syncstrings_in_project:[{project_id:projects[0], max_age_m:15, last_active:null, string_id:null}]}
562
cb : (err, result) ->
563
expect(result).toEqual(recent_syncstrings_in_project:[{project_id:projects[0], last_active:time0, string_id:string_id0}])
564
done(err)
565
566
it 'query for older syncstrings', (done) ->
567
db.user_query
568
project_id : projects[0]
569
query : {recent_syncstrings_in_project:[{project_id:projects[0], max_age_m:30, last_active:null, string_id:null}]}
570
cb : (err, result) ->
571
expect(result).toEqual(recent_syncstrings_in_project:[{project_id:projects[0], last_active:time0, string_id:string_id0}, {project_id:projects[0], last_active:time1, string_id:string_id1}])
572
done(err)
573
574
it 'ensure other project syncstrings are separate', (done) ->
575
db.user_query
576
account_id : accounts[0]
577
query : {recent_syncstrings_in_project:[{project_id:projects[1], max_age_m:30, last_active:null, string_id:null}]}
578
cb : (err, result) ->
579
expect(result).toEqual(recent_syncstrings_in_project:[])
580
done(err)
581
582
changefeed_id = misc.uuid()
583
time2 = new Date()
584
time3 = new Date()
585
it 'creates and works with a changefeed', (done) ->
586
obj0 = undefined
587
db.user_query
588
project_id : projects[0]
589
query :
590
recent_syncstrings_in_project:
591
[{project_id:projects[0], max_age_m:15, last_active:null, string_id:null, deleted:null}]
592
changes : changefeed_id
593
cb : changefeed_series([
594
(x, cb) ->
595
expect(x.recent_syncstrings_in_project.length).toEqual(1)
596
obj0 = x.recent_syncstrings_in_project[0]
597
598
# change time of syncstring
599
db.user_query
600
account_id : accounts[0]
601
query : {syncstrings:{project_id:projects[0], path:path0, last_active:time2}}
602
cb : cb
603
(x, cb) ->
604
obj0.last_active = time2
605
expect(x).toEqual({action:'update', new_val:obj0, old_val:{last_active:time0}})
606
607
# change time introducing a syncstring that was old
608
db.user_query
609
project_id : projects[0]
610
query : {syncstrings:{project_id:projects[0], path:path1, last_active:time3}}
611
cb : cb
612
(x, cb) ->
613
expect(x).toEqual({action:'update', new_val:{last_active:time3, project_id:projects[0], string_id:string_id1}, old_val:{last_active:time1}})
614
615
# create new syncstring
616
db.user_query
617
project_id : projects[0]
618
query : {syncstrings:{project_id:projects[0], path:'xyz', last_active:time3}}
619
cb : cb
620
(x, cb) ->
621
expect(x).toEqual({action:'insert', new_val:{last_active:time3, project_id:projects[0], string_id:db.sha1(projects[0], 'xyz')}})
622
623
# make obj0 have old time and see get deleted
624
db.user_query
625
account_id : accounts[0]
626
query : {syncstrings:{project_id:projects[0], path:path0, last_active:time1}}
627
cb : cb
628
(x, cb) ->
629
expect(x).toEqual({action:'delete', old_val:{last_active:time3, project_id:projects[0], string_id:string_id0}})
630
631
db.user_query_cancel_changefeed(id:changefeed_id, cb:cb)
632
(x, cb) ->
633
expect(x).toEqual({action:'close'})
634
635
cb()
636
], done)
637
638
639
640