@@ -29,18 +29,19 @@ const request = require('@arangodb/request');
29
29
const users = require ( '@arangodb/users' ) ;
30
30
const db = require ( '@arangodb' ) . db ;
31
31
32
- describe ( 'Grants' , function ( ) {
33
- before ( function ( ) {
32
+ describe ( 'Grants' , function ( ) {
33
+ before ( function ( ) {
34
34
db . _drop ( 'grants' ) ;
35
35
db . _create ( 'grants' ) ;
36
36
} ) ;
37
- beforeEach ( function ( ) {
37
+ beforeEach ( function ( ) {
38
38
try {
39
39
// remove any such user if it exists
40
40
users . remove ( 'hans' ) ;
41
- } catch ( err ) { }
41
+ } catch ( err ) {
42
+ }
42
43
} ) ;
43
- afterEach ( function ( ) {
44
+ afterEach ( function ( ) {
44
45
let resp = request . put ( {
45
46
url : '/_admin/server/mode' ,
46
47
body : { 'mode' : 'default' } ,
@@ -51,10 +52,10 @@ describe('Grants', function() {
51
52
require ( 'internal' ) . wait ( 5.0 ) ;
52
53
users . remove ( 'hans' ) ;
53
54
} ) ;
54
- after ( function ( ) {
55
+ after ( function ( ) {
55
56
db . _drop ( 'grants' ) ;
56
57
} ) ;
57
- it ( 'should show the effective rights for a user' , function ( ) {
58
+ it ( 'should show the effective rights for a user' , function ( ) {
58
59
users . save ( 'hans' ) ;
59
60
users . grantDatabase ( 'hans' , '_system' , 'rw' ) ;
60
61
let resp = request . get ( {
@@ -63,11 +64,11 @@ describe('Grants', function() {
63
64
} ) ;
64
65
expect ( JSON . parse ( resp . body ) ) . to . have . property ( 'result' , 'rw' ) ;
65
66
} ) ;
66
-
67
- it ( 'should show the effective rights when readonly mode is on' , function ( ) {
67
+
68
+ it ( 'should show the effective rights when readonly mode is on' , function ( ) {
68
69
users . save ( 'hans' ) ;
69
70
users . grantDatabase ( 'hans' , '_system' , 'rw' ) ;
70
-
71
+
71
72
let resp ;
72
73
resp = request . put ( {
73
74
url : '/_admin/server/mode' ,
@@ -81,10 +82,10 @@ describe('Grants', function() {
81
82
expect ( JSON . parse ( resp . body ) ) . to . have . property ( 'result' , 'ro' ) ;
82
83
} ) ;
83
84
84
- it ( 'should show the configured rights when readonly mode is on and configured is requested' , function ( ) {
85
+ it ( 'should show the configured rights when readonly mode is on and configured is requested' , function ( ) {
85
86
users . save ( 'hans' ) ;
86
87
users . grantDatabase ( 'hans' , '_system' , 'rw' ) ;
87
-
88
+
88
89
let resp ;
89
90
resp = request . put ( {
90
91
url : '/_admin/server/mode' ,
@@ -98,11 +99,11 @@ describe('Grants', function() {
98
99
expect ( JSON . parse ( resp . body ) ) . to . have . property ( 'result' , 'rw' ) ;
99
100
} ) ;
100
101
101
- it ( 'should show the effective rights when readonly mode is on' , function ( ) {
102
+ it ( 'should show the effective rights when readonly mode is on' , function ( ) {
102
103
users . save ( 'hans' ) ;
103
104
users . grantDatabase ( 'hans' , '_system' , 'rw' ) ;
104
105
users . grantCollection ( 'hans' , '_system' , 'grants' ) ;
105
-
106
+
106
107
let resp ;
107
108
resp = request . put ( {
108
109
url : '/_admin/server/mode' ,
@@ -116,11 +117,11 @@ describe('Grants', function() {
116
117
expect ( JSON . parse ( resp . body ) ) . to . have . property ( 'result' , 'ro' ) ;
117
118
} ) ;
118
119
119
- it ( 'should show the configured rights when readonly mode is on and configured is requested' , function ( ) {
120
+ it ( 'should show the configured rights when readonly mode is on and configured is requested' , function ( ) {
120
121
users . save ( 'hans' ) ;
121
122
users . grantDatabase ( 'hans' , '_system' , 'rw' ) ;
122
123
users . grantCollection ( 'hans' , '_system' , 'grants' ) ;
123
-
124
+
124
125
let resp ;
125
126
resp = request . put ( {
126
127
url : '/_admin/server/mode' ,
@@ -134,3 +135,219 @@ describe('Grants', function() {
134
135
expect ( JSON . parse ( resp . body ) ) . to . have . property ( 'result' , 'rw' ) ;
135
136
} ) ;
136
137
} ) ;
138
+
139
+ describe ( 'UserProperties' , function ( ) {
140
+ const rootUser = 'root' ;
141
+ const rootDB = '_system' ;
142
+
143
+ const nonRootDB = 'nonRootDB' ;
144
+ const nonRootUser = 'notRoot' ;
145
+
146
+ const configPropertyAttribute = 'graphs' ;
147
+ const additionalPropertyAttribute = 'someAdditionalAttribute' ;
148
+
149
+ const initConfigObject = {
150
+ a : true ,
151
+ b : false ,
152
+ c : 1 ,
153
+ d : 1.1 ,
154
+ e : "aString" ,
155
+ f : [ 1 , 2 , 3 ] ,
156
+ g : { "anObjectKey" : "anObjectValue" }
157
+ } ;
158
+
159
+ const overwriteConfigObject = {
160
+ c : 1337 ,
161
+ someNewParam : "MJ7"
162
+ } ;
163
+
164
+ const mergeConfigObject = {
165
+ "thisMustStay" : true
166
+ } ;
167
+
168
+ const verifyEmptyConfig = ( result ) => {
169
+ expect ( result . error ) . to . be . false ;
170
+ expect ( result ) . to . have . property ( 'code' , 200 ) ;
171
+ expect ( result ) . to . have . property ( 'result' , null ) ;
172
+ } ;
173
+
174
+ const verifyInitObject = ( result ) => {
175
+ expect ( result . error ) . to . be . false ;
176
+ expect ( result ) . to . have . property ( 'code' , 200 ) ;
177
+
178
+ result = result . result [ configPropertyAttribute ] ;
179
+ expect ( result . a ) . to . be . true ;
180
+ expect ( result . b ) . to . be . false ;
181
+ expect ( result ) . to . have . property ( 'c' , 1 ) ;
182
+ expect ( result ) . to . have . property ( 'd' , 1.1 ) ;
183
+ expect ( result ) . to . have . property ( 'e' , "aString" ) ;
184
+ expect ( result . f ) . to . be . an ( 'array' ) ;
185
+ expect ( result . g ) . to . be . an ( 'object' ) ;
186
+ } ;
187
+
188
+ const verifyOverwriteConfigObject = ( result ) => {
189
+ // We do have one "global" property we can modify. If we write to that same top-level attribute again, it will be
190
+ // fully replaced by the supplied object given. In case we write to another top-level attribute, it will be merged with
191
+ // the other already available ones (This is tested in verifyMergedConfigObject).
192
+ expect ( result . error ) . to . be . false ;
193
+ expect ( result ) . to . have . property ( 'code' , 200 ) ;
194
+
195
+ result = result . result [ configPropertyAttribute ] ;
196
+ expect ( result ) . to . have . property ( 'c' , 1337 ) ;
197
+ expect ( result ) . to . have . property ( 'someNewParam' , "MJ7" ) ;
198
+ } ;
199
+
200
+ const verifyMergedConfigObject = ( result ) => {
201
+ // needs to be called after we've written `overwriteConfigObject`
202
+ verifyOverwriteConfigObject ( result ) ;
203
+ const expectedMergeObject = result . result [ additionalPropertyAttribute ] ;
204
+ expect ( expectedMergeObject . thisMustStay ) . to . be . true ;
205
+ } ;
206
+
207
+ const generateReadConfigUrl = ( user , database ) => {
208
+ return `/_db/${ database } /_api/user/${ user } /config` ;
209
+ } ;
210
+
211
+ const generateWriteConfigUrl = ( user , database , attribute ) => {
212
+ if ( ! attribute ) {
213
+ attribute = configPropertyAttribute ;
214
+ }
215
+ return `/_db/${ database } /_api/user/${ user } /config/${ attribute } ` ;
216
+ } ;
217
+
218
+ const generateConfigBody = ( object ) => {
219
+ return {
220
+ value : object
221
+ } ;
222
+ } ;
223
+
224
+ before ( function ( ) {
225
+ db . _createDatabase ( nonRootDB ) ;
226
+ } ) ;
227
+
228
+ beforeEach ( function ( ) {
229
+ try {
230
+ // remove any such user if it exists
231
+ users . remove ( nonRootUser ) ;
232
+ } catch ( ignore ) {
233
+ }
234
+ } ) ;
235
+
236
+ afterEach ( function ( ) {
237
+ try {
238
+ users . remove ( nonRootUser ) ;
239
+ } catch ( ignore ) {
240
+ }
241
+
242
+ // cleanup root users config we might have been modified in any of our tests
243
+ const cleanupRootUrl = generateWriteConfigUrl ( rootUser , rootDB ) ;
244
+ request . delete ( {
245
+ url : cleanupRootUrl ,
246
+ json : true
247
+ } ) ;
248
+ } ) ;
249
+
250
+ after ( function ( ) {
251
+ db . _dropDatabase ( nonRootDB ) ;
252
+ } ) ;
253
+
254
+ const testSuiteHelper = ( user , database ) => {
255
+ const readUrl = generateReadConfigUrl ( user , database ) ;
256
+ const writeUrl = generateWriteConfigUrl ( user , database ) ;
257
+ let response ;
258
+
259
+ // should be empty by default
260
+ response = request . get ( {
261
+ url : readUrl ,
262
+ json : true
263
+ } ) ;
264
+ verifyEmptyConfig ( JSON . parse ( response . body ) ) ;
265
+
266
+ // stores the init object
267
+ response = request . put ( {
268
+ url : writeUrl ,
269
+ body : generateConfigBody ( initConfigObject ) ,
270
+ json : true
271
+ } ) ;
272
+ expect ( response . statusCode ) . to . equal ( 200 ) ;
273
+
274
+ // should now be the same as init object
275
+ response = request . get ( {
276
+ url : readUrl ,
277
+ json : true
278
+ } ) ;
279
+ verifyInitObject ( JSON . parse ( response . body ) ) ;
280
+
281
+ // now try to overwrite as well
282
+ response = request . put ( {
283
+ url : writeUrl ,
284
+ body : generateConfigBody ( overwriteConfigObject ) ,
285
+ json : true
286
+ } ) ;
287
+ expect ( response . statusCode ) . to . equal ( 200 ) ;
288
+
289
+ response = request . get ( {
290
+ url : readUrl ,
291
+ json : true
292
+ } ) ;
293
+ verifyOverwriteConfigObject ( JSON . parse ( response . body ) ) ;
294
+
295
+ // now try a merge with another storage attribute
296
+ const additionalWriteUrl = generateWriteConfigUrl ( user , database , additionalPropertyAttribute ) ;
297
+ response = request . put ( {
298
+ url : additionalWriteUrl ,
299
+ body : generateConfigBody ( mergeConfigObject ) ,
300
+ json : true
301
+ } ) ;
302
+ expect ( response . statusCode ) . to . equal ( 200 ) ;
303
+ response = request . get ( {
304
+ url : readUrl ,
305
+ json : true
306
+ } ) ;
307
+ verifyMergedConfigObject ( JSON . parse ( response . body ) ) ;
308
+
309
+ // test delete (remove additional key)
310
+ response = request . delete ( {
311
+ url : additionalWriteUrl ,
312
+ json : true
313
+ } ) ;
314
+ response = request . get ( {
315
+ url : readUrl ,
316
+ json : true
317
+ } ) ;
318
+ verifyOverwriteConfigObject ( JSON . parse ( response . body ) ) ;
319
+
320
+ // finally, test delete of graph attribute
321
+ response = request . delete ( {
322
+ url : writeUrl ,
323
+ json : true
324
+ } ) ;
325
+ // should be fully empty now again
326
+ response = request . get ( {
327
+ url : readUrl ,
328
+ json : true
329
+ } ) ;
330
+ verifyEmptyConfig ( JSON . parse ( response . body ) ) ;
331
+ } ;
332
+
333
+ it ( 'should store/patch/delete root config data in _system database' , function ( ) {
334
+ testSuiteHelper ( rootUser , rootDB ) ;
335
+ } ) ;
336
+
337
+ it ( 'should store/patch/delete root config data in non-system database' , function ( ) {
338
+ testSuiteHelper ( rootUser , nonRootDB ) ;
339
+ } ) ;
340
+
341
+ it ( 'should store/patch/delete non-root user config data in _system database' , function ( ) {
342
+ users . save ( nonRootUser ) ;
343
+ users . grantDatabase ( nonRootUser , rootDB , 'rw' ) ;
344
+ testSuiteHelper ( nonRootUser , rootDB ) ;
345
+ } ) ;
346
+
347
+ it ( 'should store/patch/delete non-root user config data in non-system database' , function ( ) {
348
+ users . save ( nonRootUser ) ;
349
+ users . grantDatabase ( nonRootUser , nonRootDB , 'rw' ) ;
350
+ testSuiteHelper ( nonRootUser , nonRootDB ) ;
351
+ } ) ;
352
+
353
+ } ) ;
0 commit comments