Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50671 views
1
###
2
TESTING of User (and project) client queries
3
4
COPYRIGHT : (c) 2017 SageMath, Inc.
5
LICENSE : AGPLv3
6
###
7
8
pgtest = require('./pgtest')
9
db = undefined
10
setup = (cb) -> (pgtest.setup (err) -> db=pgtest.db; cb(err))
11
teardown = pgtest.teardown
12
13
{create_accounts, create_projects} = pgtest
14
15
async = require('async')
16
expect = require('expect')
17
18
misc = require('smc-util/misc')
19
{SCHEMA} = require('smc-util/schema')
20
21
describe 'some basic testing of user_queries', ->
22
before(setup)
23
after(teardown)
24
account_id = undefined
25
# First create an account, so we can do some queries.
26
it 'creates an account', (done) ->
27
db.create_account(first_name:"Sage", last_name:"Math", created_by:"1.2.3.4",\
28
email_address:"[email protected]", password_hash:"blah", cb:(err, x) -> account_id=x; done(err))
29
30
it 'queries for the first_name and account_id property', (done) ->
31
db.user_query
32
account_id : account_id
33
query : {accounts:{account_id:account_id, first_name:null}}
34
cb : (err, result) ->
35
expect(result).toEqual({accounts:{ account_id:account_id, first_name: 'Sage' }})
36
done(err)
37
38
it 'query for the evaluate key fills in the correct default', (done) ->
39
db.user_query
40
account_id : account_id
41
query : {accounts:{account_id:account_id, evaluate_key:null}}
42
cb : (err, result) ->
43
x = SCHEMA.accounts.user_query.get.fields.evaluate_key
44
expect(result).toEqual({accounts:{ account_id:account_id, evaluate_key:x }})
45
done(err)
46
47
it 'queries the collaborators virtual table before there are any projects', (done) ->
48
db.user_query
49
account_id : account_id
50
query : {collaborators:[{account_id:null, first_name:null, last_name:null}]}
51
cb : (err, collabs) ->
52
if err
53
done(err); return
54
expect(collabs).toEqual({collaborators:[]})
55
done()
56
57
project_id = undefined
58
it 'creates a project that we will query about soon', (done) ->
59
db.create_project(account_id:account_id, title:"Test project", description:"The description",\
60
cb:(err, x) -> project_id=x; done(err))
61
62
it 'queries the collaborators virtual table after making one project', (done) ->
63
db.user_query
64
account_id : account_id
65
query : {collaborators:[{account_id:null, first_name:null, last_name:null}]}
66
cb : (err, collabs) ->
67
if err
68
done(err); return
69
user = {account_id:account_id, first_name:'Sage', last_name:'Math'}
70
expect(collabs).toEqual({collaborators:[user]})
71
done()
72
73
it 'queries the projects table and ensures there is one project with the correct title and description.', (done) ->
74
db.user_query
75
account_id : account_id
76
query : {projects:[{project_id:project_id, title:null, description:null}]}
77
cb : (err, projects) ->
78
expect(projects).toEqual(projects:[{description: 'The description', project_id: project_id, title: 'Test project' }])
79
done(err)
80
81
it 'changes the title of the project', (done) ->
82
db.user_query
83
account_id : account_id
84
query : {projects:{project_id:project_id, title:'The new title', description:'The new description'}}
85
cb : done
86
87
it 'and checks that the title/desc did indeed change', (done) ->
88
db.user_query
89
account_id : account_id
90
query : {projects:[{project_id:project_id, title:null, description:null}]}
91
cb : (err, projects) ->
92
expect(projects).toEqual(projects:[{description: 'The new description', project_id: project_id, title: 'The new title' }])
93
done(err)
94
95
account_id2 = undefined
96
it 'create a second account...', (done) ->
97
db.create_account(first_name:"Elliptic", last_name:"Curve", created_by:"3.1.3.4",\
98
email_address:"[email protected]", password_hash:"blahblah", cb:(err, x) -> account_id2=x; done(err))
99
it 'queries with second account for the first_name and account_id property of first account', (done) ->
100
db.user_query
101
account_id : account_id2
102
query : {accounts:{account_id:account_id, first_name:null}}
103
cb : (err, result) ->
104
# we get undefined, meaning no results in the data we know about that match the query
105
expect(result).toEqual({accounts:undefined})
106
done(err)
107
108
it 'queries for first user project but does not see it', (done) ->
109
db.user_query
110
account_id : account_id2
111
query : {projects:[{project_id:project_id, title:null, description:null}]}
112
cb : (err, projects) ->
113
expect(err).toEqual('you do not have read access to this project')
114
done()
115
116
it 'queries the collaborators virtual table before there are any projects for the second user', (done) ->
117
db.user_query
118
account_id : account_id2
119
query : {collaborators:[{account_id:null, first_name:null, last_name:null}]}
120
cb : (err, collabs) ->
121
if err
122
done(err); return
123
expect(collabs).toEqual({collaborators:[]})
124
done()
125
126
127
it 'add second user as a collaborator', (done) ->
128
db.add_user_to_project
129
project_id : project_id
130
account_id : account_id2
131
group : 'collaborator'
132
cb : done
133
134
it 'queries again and finds that the second user can see the first project', (done) ->
135
db.user_query
136
account_id : account_id2
137
query : {projects:[{project_id:project_id, title:null, description:null, users:null}]}
138
cb : (err, projects) ->
139
users =
140
"#{account_id}":{group:'owner'}
141
"#{account_id2}":{group:'collaborator'}
142
expect(projects).toEqual(projects:[{description: 'The new description', project_id: project_id, title: 'The new title', users:users}])
143
done(err)
144
145
it 'queries the collaborators virtual table for the first user', (done) ->
146
db.user_query
147
account_id : account_id
148
query : {collaborators:[{account_id:null, first_name:null, last_name:null}]}
149
cb : (err, collabs) ->
150
if err
151
done(err); return
152
collabs.collaborators.sort (a,b)->misc.cmp(a.last_name, b.last_name) # make canonical
153
user1 = {account_id:account_id2, first_name:'Elliptic', last_name:'Curve'}
154
user2 = {account_id:account_id, first_name:'Sage', last_name:'Math'}
155
expect(collabs).toEqual({collaborators:[user1,user2]})
156
done(err)
157
158
159
describe 'testing file_use -- ', ->
160
before(setup)
161
after(teardown)
162
# Create two users and two projects
163
accounts = []
164
projects = []
165
it 'setup accounts and projects', (done) ->
166
async.series([
167
(cb) ->
168
create_accounts 2, (err, x) -> accounts=x; cb()
169
(cb) ->
170
create_projects 1, accounts[0], (err, x) -> projects.push(x...); cb(err)
171
(cb) ->
172
create_projects 1, accounts[1], (err, x) -> projects.push(x...); cb(err)
173
], done)
174
175
time0 = new Date()
176
it 'writes a file_use entry via a user query (and gets it back)', (done) ->
177
obj =
178
project_id : projects[0]
179
path : 'foo'
180
users : {"#{accounts[0]}":{edit:time0}}
181
last_edited : time0
182
async.series([
183
(cb) ->
184
db.user_query
185
account_id : accounts[0]
186
query : {file_use : obj}
187
cb : cb
188
(cb) ->
189
db.user_query
190
account_id : accounts[0]
191
query :
192
file_use :
193
project_id : projects[0]
194
path : 'foo'
195
users : null
196
last_edited : null
197
cb : (err, result) ->
198
expect(result).toEqual(file_use:obj)
199
cb(err)
200
], done)
201
202
it 'writes another file_use entry and verifies that json is properly *merged*', (done) ->
203
obj =
204
project_id : projects[0]
205
path : 'foo'
206
users : {"#{accounts[0]}":{read:time0}}
207
async.series([
208
(cb) ->
209
db.user_query
210
account_id : accounts[0]
211
query : {file_use : obj}
212
cb : cb
213
(cb) ->
214
db.user_query
215
account_id : accounts[0]
216
query :
217
file_use :
218
project_id : projects[0]
219
path : 'foo'
220
users : null
221
last_edited : null
222
cb : (err, result) ->
223
# add rest of what we expect from previous insert in test above:
224
obj.last_edited = time0
225
obj.users["#{accounts[0]}"] = {read:time0, edit:time0}
226
expect(result).toEqual(file_use:obj)
227
cb(err)
228
], done)
229
230
it 'tries to read file use entry as user without project access and fails', (done) ->
231
db.user_query
232
account_id : accounts[1]
233
query :
234
file_use :
235
project_id : projects[0]
236
path : 'foo'
237
users : null
238
cb : (err, result) ->
239
expect(err).toEqual('you do not have read access to this project')
240
done()
241
242
it 'adds second user to first project, then reads and finds one file_use match', (done) ->
243
async.series([
244
(cb) ->
245
db.add_user_to_project
246
project_id : projects[0]
247
account_id : accounts[1]
248
cb : cb
249
(cb) ->
250
db.user_query
251
account_id : accounts[0]
252
query :
253
file_use : [{project_id:projects[0], path:'foo', users:null}]
254
cb : (err, x) ->
255
expect(x?.file_use?.length).toEqual(1)
256
cb(err)
257
], done)
258
259
260
it 'add a second file_use notification for first project (different path)', (done) ->
261
t = new Date()
262
obj =
263
project_id : projects[0]
264
path : 'foo2'
265
users : {"#{accounts[1]}":{read:t}}
266
last_edited : t
267
async.series([
268
(cb) ->
269
db.user_query
270
account_id : accounts[1]
271
query : {file_use : obj}
272
cb : cb
273
(cb) ->
274
db.user_query
275
account_id : accounts[0]
276
query :
277
file_use : [{project_id:projects[0], path:'foo', users:null}]
278
cb : (err, x) ->
279
expect(x?.file_use?.length).toEqual(1)
280
cb(err)
281
(cb) ->
282
db.user_query
283
account_id : accounts[0]
284
query :
285
file_use : [{project_id:projects[0], path:null, users:null}]
286
cb : (err, x) ->
287
if err
288
cb(err); return
289
expect(x.file_use.length).toEqual(2)
290
expect(x.file_use[0].path).toEqual('foo2') # order will be this way due to sort of last_edited
291
expect(x.file_use[1].path).toEqual('foo')
292
cb()
293
], done)
294
295
it 'add a file_use notification for second project as second user', (done) ->
296
obj =
297
project_id : projects[1]
298
path : 'bar'
299
last_edited : new Date()
300
db.user_query
301
account_id : accounts[1]
302
query : {file_use : obj}
303
cb : done
304
305
it 'confirm total of 3 file_use entries', (done) ->
306
db.user_query
307
account_id : accounts[1]
308
query :
309
file_use : [{project_id:null, path:null, last_edited: null}]
310
cb : (err, x) ->
311
if err
312
done(err)
313
else
314
expect(x.file_use.length).toEqual(3)
315
done()
316
317
it 'also check limit option works', (done) ->
318
db.user_query
319
account_id : accounts[1]
320
query : file_use : [{project_id:null, path:null}]
321
options : [{limit:2}]
322
cb : (err, x) ->
323
if err
324
done(err)
325
else
326
expect(x.file_use.length).toEqual(2)
327
done()
328
329
it 'verify that account 0 cannot write file_use notification to project 1; but as admin can.', (done) ->
330
obj =
331
project_id : projects[1]
332
path : 'bar'
333
last_edited : new Date()
334
async.series([
335
(cb) ->
336
db.user_query
337
account_id : accounts[0]
338
query : {file_use : obj}
339
cb : (err) ->
340
expect(err).toEqual('user must be an admin')
341
cb()
342
(cb) ->
343
# now make account 0 an admin
344
db.make_user_admin
345
account_id : accounts[0]
346
cb : cb
347
(cb) ->
348
# verify user 0 is admin
349
db.is_admin
350
account_id : accounts[0]
351
cb : (err, is_admin) ->
352
expect(is_admin).toEqual(true)
353
cb(err)
354
(cb) ->
355
# ... but 1 is not
356
db.is_admin
357
account_id : accounts[1]
358
cb : (err, is_admin) ->
359
expect(is_admin).toEqual(false)
360
cb(err)
361
(cb) ->
362
# ... , and see that it can write to project not on
363
db.user_query
364
account_id : accounts[0]
365
query : {file_use : obj}
366
cb : cb
367
], done)
368
369
370
describe 'test project_log table', ->
371
before(setup)
372
after(teardown)
373
374
# Create two users and one project
375
accounts = []
376
projects = []
377
it 'setup accounts and projects', (done) ->
378
async.series([
379
(cb) ->
380
create_accounts 3, (err, x) -> accounts=x; cb()
381
(cb) ->
382
create_projects 3, accounts[0], (err, x) -> projects.push(x...); cb(err)
383
], done)
384
385
it 'writes a project_log entry via a user query (and gets it back)', (done) ->
386
obj =
387
id : misc.uuid()
388
project_id : projects[0]
389
time : new Date()
390
event : {test:'thing'}
391
async.series([
392
(cb) ->
393
db.user_query(account_id : accounts[0], query:{project_log:obj}, cb:cb)
394
(cb) ->
395
db.user_query
396
account_id : accounts[0]
397
query :
398
project_log :
399
project_id : projects[0]
400
time : null
401
event : null
402
id : null
403
cb : (err, result) ->
404
expect(result).toEqual(project_log:obj)
405
cb(err)
406
], done)
407
408
it 'write two project_log entries with the same timestamp (but different ids)', (done) ->
409
t = new Date()
410
obj0 =
411
id : misc.uuid()
412
project_id : projects[0]
413
time : t
414
event : {test:'stuff', a:['x', 'y']}
415
obj1 =
416
id : misc.uuid()
417
project_id : projects[0]
418
time : t # SAME TIME
419
event : {test:'other stuff'}
420
async.series([
421
(cb) ->
422
db.user_query(account_id : accounts[0], query:[{project_log:obj0}, {project_log:obj1}], cb:cb)
423
(cb) ->
424
# get everything with the given time t
425
db.user_query
426
account_id : accounts[0]
427
query :
428
project_log : [{project_id:projects[0], time:t, id:null}]
429
cb : (err, result) ->
430
if err
431
cb(err)
432
else
433
expect(result.project_log.length).toEqual(2)
434
expect(result.project_log[0].time).toEqual(t)
435
expect(result.project_log[1].time).toEqual(t)
436
cb()
437
], done)
438
439
it "confirm other user can't read log of first project", (done) ->
440
db.user_query
441
account_id : accounts[1]
442
query :
443
project_log : [{project_id:projects[0], time:null, id:null}]
444
cb : (err, result) ->
445
expect(err).toEqual('you do not have read access to this project')
446
done()
447
448
it 'make third user an admin and verify can read log of first project', (done) ->
449
async.series([
450
(cb) ->
451
# now make account 2 an admin
452
db.make_user_admin
453
account_id : accounts[2]
454
cb : cb
455
(cb) ->
456
db.user_query
457
account_id : accounts[2]
458
query : project_log : [{project_id:projects[0], time:null, id:null}]
459
cb : (err, result) ->
460
if err
461
cb(err)
462
else
463
expect(result.project_log.length).toEqual(3)
464
cb()
465
], done)
466
467
it "add other user, and confirm other user now *CAN* read log", (done) ->
468
async.series([
469
(cb) ->
470
db.add_user_to_project
471
project_id : projects[0]
472
account_id : accounts[1]
473
cb : cb
474
(cb) ->
475
db.user_query
476
account_id : accounts[1]
477
query : project_log : [{project_id:projects[0], time:null, id:null}]
478
cb : (err, result) ->
479
expect(result.project_log.length).toEqual(3)
480
cb(err)
481
], done)
482
483
it "confirm other project doesn't have any log entries (testing that reads are by project)", (done) ->
484
db.user_query
485
account_id : accounts[0]
486
query :
487
project_log : [{project_id:projects[1], time:null, id:null}]
488
cb : (err, result) ->
489
expect(result.project_log.length).toEqual(0)
490
done(err)
491
492
it "add three entries to second project log and verify that they come back in the right order", (done) ->
493
f = (t, id, cb) ->
494
obj =
495
id : id
496
project_id : projects[2]
497
time : t
498
event : {test:'0'}
499
db.user_query(account_id:accounts[0], query:{project_log:obj}, cb:cb)
500
ids = (misc.uuid() for _ in [0,1,2])
501
async.series([
502
(cb) -> f(misc.minutes_ago(5), ids[0], cb)
503
(cb) -> f(misc.minutes_ago(1), ids[2], cb)
504
(cb) -> f(misc.minutes_ago(3), ids[1], cb)
505
(cb) ->
506
db.user_query
507
account_id : accounts[0]
508
query :
509
project_log : [{project_id:projects[2], time:null, id:null}]
510
cb : (err, result) ->
511
if err
512
cb(err)
513
else
514
expect(result.project_log.length).toEqual(3)
515
expect(result.project_log[0].id).toEqual(ids[2])
516
expect(result.project_log[1].id).toEqual(ids[1])
517
expect(result.project_log[2].id).toEqual(ids[0])
518
cb()
519
], done)
520
521
522
describe 'nonexistent tables', ->
523
before(setup)
524
after(teardown)
525
526
account_id = undefined
527
it 'creates account', (done) ->
528
create_accounts 1, (err, accounts) ->
529
account_id = accounts?[0]; done(err)
530
531
it 'write to non-existent table', (done) ->
532
db.user_query
533
account_id : account_id
534
query : {nonexistent_table: {foo:'bar'}}
535
cb : (err) ->
536
expect(err).toEqual("table 'nonexistent_table' does not exist")
537
done(not err)
538
539
it 'read from non-existent table (single thing)', (done) ->
540
db.user_query
541
account_id : account_id
542
query : {nonexistent_table: {foo:null}}
543
cb : (err) ->
544
expect(err).toEqual("get queries not allowed for table 'nonexistent_table'")
545
done(not err)
546
547
it 'read from non-existent table (multiple)', (done) ->
548
db.user_query
549
account_id : account_id
550
query : {nonexistent_table: [{foo:null}]}
551
cb : (err) ->
552
expect(err).toEqual("get queries not allowed for table 'nonexistent_table'")
553
done(not err)
554
555
556
describe 'test the get_account server query', ->
557
before(setup)
558
after(teardown)
559
560
accounts = undefined
561
it 'create two accounts', (done) ->
562
create_accounts 2, (err, x) ->
563
accounts = x; done(err)
564
565
it 'calls get_account with some columns for first account', (done) ->
566
db.get_account
567
account_id : accounts[0]
568
columns : ['account_id', 'email_address', 'password_is_set']
569
cb : (err, x) ->
570
expect(x).toEqual({account_id: accounts[0], email_address: "[email protected]", password_is_set:false})
571
done(err)
572
573
hash = 'sha512$4477684995985fb6bd2c9020d3f35c69$1000$41cc46a70ba52ade010b56ccbdca942af9271b256763479eb2d8d8283d1023e43745f4cc6fe7a970ce1cf28df6c9edb47d315d92b837a0c7db4fafbc38ed099a'
574
575
it 'sets the password hash', (done) ->
576
db.change_password
577
account_id : accounts[0]
578
password_hash : hash
579
cb : done
580
581
it 'checks that the password is now set', (done) ->
582
columns = ['password_is_set']
583
db.get_account
584
account_id : accounts[0]
585
columns : columns
586
cb : (err, x) ->
587
expect(x).toEqual({password_is_set:true})
588
expect(columns).toEqual(['password_is_set']) # ensure no mutation
589
done(err)
590
591
it 'calls get_account with some columns again', (done) ->
592
db.get_account
593
account_id : accounts[0]
594
columns : ['account_id', 'email_address', 'password_hash']
595
cb : (err, x) ->
596
expect(x).toEqual({account_id: accounts[0], email_address: "[email protected]", password_hash:hash})
597
done(err)
598
599
it 'calls get_account with some columns yet again', (done) ->
600
db.get_account
601
account_id : accounts[0]
602
columns : ['account_id', 'email_address', 'password_hash', 'password_is_set']
603
cb : (err, x) ->
604
expect(x).toEqual({account_id: accounts[0], email_address: "[email protected]", password_hash:hash, password_is_set:true})
605
done(err)
606
607
it 'calls get_account on the other account', (done) ->
608
db.get_account
609
account_id : accounts[1]
610
columns : ['account_id', 'email_address', 'password_hash', 'password_is_set']
611
cb : (err, x) ->
612
expect(x).toEqual({account_id: accounts[1], email_address: "[email protected]", password_is_set:false})
613
done(err)
614
615
it 'changes the email address of the first account', (done) ->
616
db.change_email_address
617
account_id : accounts[0]
618
email_address : '[email protected]'
619
cb : done
620
621
it 'confirms the change', (done) ->
622
db.get_account
623
account_id : accounts[0]
624
columns : ['email_address']
625
cb : (err, x) ->
626
expect(x).toEqual({email_address: "[email protected]"})
627
done(err)
628
629
630
describe 'test of automatic first and last name truncation', ->
631
before(setup)
632
after(teardown)
633
account_id = undefined
634
it 'creates an account', (done) ->
635
db.create_account(first_name:"Sage", last_name:"Math", created_by:"1.2.3.4",\
636
email_address:"[email protected]", password_hash:"blah", cb:(err, x) -> account_id=x; done(err))
637
638
long_first = (Math.random().toString(36) for _ in [0..15]).join('')
639
long_last = (Math.random().toString(36) for _ in [0..15]).join('')
640
it 'sets first_name and last_name to long character strings', (done) ->
641
db.user_query
642
account_id : account_id
643
query : {accounts:{account_id:account_id, first_name:long_first, last_name:long_last}}
644
cb : done
645
646
# NOTE: this is entirely to prevent malicious/idiotic clients.
647
it 'reads back and sees they were (silently!) truncated to 254 characters', (done) ->
648
db.user_query
649
account_id : account_id
650
query : {accounts:{account_id:account_id, first_name:null, last_name:null}}
651
cb : (err, x) ->
652
expect(x?.accounts).toEqual({account_id:account_id, first_name:long_first.slice(0,254), last_name:long_last.slice(0,254)})
653
done(err)
654
655