cloudcms-server 4.0.0-beta.2 → 4.0.0-beta.21

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.
Files changed (78) hide show
  1. package/README.md +0 -5
  2. package/cloudcms-server.iml +1 -0
  3. package/index.js +58 -32
  4. package/middleware/authentication/authentication.js +40 -12
  5. package/middleware/authentication/providers/saml.js +8 -4
  6. package/middleware/awareness/awareness.js +8 -7
  7. package/middleware/awareness/plugins/api_event.js +105 -0
  8. package/middleware/awareness/plugins/editorial.js +54 -3
  9. package/middleware/awareness/plugins/resources.js +13 -5
  10. package/middleware/config/adapter.js +0 -44
  11. package/middleware/deployment/deployment.js +22 -24
  12. package/middleware/driver/driver.js +24 -1
  13. package/middleware/driver-config/driver-config.js +0 -6
  14. package/middleware/modules/modules.js +11 -5
  15. package/middleware/perf/perf.js +3 -2
  16. package/middleware/registration/registration.js +0 -5
  17. package/middleware/stores/engines/empty.js +0 -4
  18. package/middleware/stores/engines/fs-caching-adapter.js +0 -5
  19. package/middleware/stores/engines/fs.js +0 -9
  20. package/middleware/stores/engines/s3.js +0 -5
  21. package/middleware/stores/engines/s3fs.js +0 -5
  22. package/middleware/stores/multistore.js +0 -29
  23. package/middleware/stores/store.js +0 -10
  24. package/middleware/stores/stores.js +2 -2
  25. package/middleware/virtual-config/virtual-config.js +253 -206
  26. package/middleware/virtual-files/virtual-files.js +0 -3
  27. package/middleware/welcome/welcome.js +0 -3
  28. package/notifications/notifications.js +72 -10
  29. package/notifications/providers/kafka.js +182 -0
  30. package/notifications/providers/stomp.js +4 -0
  31. package/package.json +40 -56
  32. package/server/index.js +216 -123
  33. package/server/standalone.js +1 -6
  34. package/util/auth.js +10 -4
  35. package/util/cloudcms.js +77 -35
  36. package/util/loaders.js +113 -0
  37. package/util/proxy-factory.js +143 -168
  38. package/util/request.js +6 -2
  39. package/util/workqueue.js +111 -0
  40. package/.last_command +0 -7
  41. package/duster/helpers/core/cloudcms/associations.js +0 -34
  42. package/duster/helpers/core/cloudcms/beta/markdown.js +0 -46
  43. package/duster/helpers/core/cloudcms/beta/nodeAttachmentText.js +0 -46
  44. package/duster/helpers/core/cloudcms/beta/params.js +0 -33
  45. package/duster/helpers/core/cloudcms/beta/processTemplate.js +0 -82
  46. package/duster/helpers/core/cloudcms/content.js +0 -34
  47. package/duster/helpers/core/cloudcms/expand.js +0 -38
  48. package/duster/helpers/core/cloudcms/form.js +0 -34
  49. package/duster/helpers/core/cloudcms/query.js +0 -34
  50. package/duster/helpers/core/cloudcms/queryOne.js +0 -34
  51. package/duster/helpers/core/cloudcms/relatives.js +0 -34
  52. package/duster/helpers/core/cloudcms/search.js +0 -34
  53. package/duster/helpers/core/cloudcms/searchOne.js +0 -34
  54. package/duster/helpers/core/cloudcms/wcm/dependency.js +0 -83
  55. package/duster/helpers/core/cloudcms/wcm/fragment.js +0 -34
  56. package/duster/helpers/core/dev/debug.js +0 -42
  57. package/duster/helpers/core/dom/block.js +0 -49
  58. package/duster/helpers/core/dom/include.js +0 -38
  59. package/duster/helpers/core/dom/layout.js +0 -49
  60. package/duster/helpers/core/dom/link.js +0 -81
  61. package/duster/helpers/core/dom/resource.js +0 -77
  62. package/duster/helpers/core/engine.js +0 -1580
  63. package/duster/helpers/core/ice/value.js +0 -65
  64. package/duster/helpers/core/index.js +0 -49
  65. package/duster/helpers/core/operators/if.js +0 -64
  66. package/duster/helpers/core/operators/iter.js +0 -45
  67. package/duster/helpers/core/operators/iterate.js +0 -129
  68. package/duster/helpers/sample/nyt.js +0 -114
  69. package/duster/index.js +0 -319
  70. package/duster/support.js +0 -436
  71. package/duster/tracker.js +0 -262
  72. package/middleware/authentication/providers/cas.js +0 -73
  73. package/middleware/authentication/providers/facebook.js +0 -120
  74. package/middleware/authentication/providers/github.js +0 -88
  75. package/middleware/authentication/providers/linkedin.js +0 -112
  76. package/middleware/authentication/providers/twitter.js +0 -120
  77. package/middleware/server-tags/server-tags.js +0 -113
  78. package/middleware/wcm/wcm.js +0 -1437
@@ -1,1580 +0,0 @@
1
- var path = require('path');
2
- var fs = require('fs');
3
- var http = require('http');
4
- var async = require("async");
5
-
6
- var tracker = require("../../tracker");
7
- var util = require("../../../util/util");
8
-
9
- var DEFAULT_PAGINATION_LIMIT = 25;
10
-
11
- module.exports = function(app, dust)
12
- {
13
- var support = require("../../support")(dust);
14
-
15
- var enhanceNode = util.enhanceNode;
16
-
17
- // helper functions
18
- var isDefined = support.isDefined;
19
- //var resolveVariables = support.resolveVariables;
20
- var map = support.map;
21
- var end = support.end;
22
- var _MARK_INSIGHT = support._MARK_INSIGHT;
23
-
24
- // return value
25
- var r = {};
26
-
27
- /**
28
- * Handles behavior for @expand
29
- *
30
- * @param chunk
31
- * @param context
32
- * @param bodies
33
- * @param params
34
- * @returns {*}
35
- * @private
36
- */
37
- r.handleExpand = function(chunk, context, bodies, params)
38
- {
39
- params = params || {};
40
-
41
- var key = context.resolve(params.key);
42
- var list = context.resolve(params.list);
43
-
44
- list = context.get(list) || [];
45
-
46
- if (!util.isArray(list)) {
47
- list = [list];
48
- }
49
-
50
- var idList = util.pluck(list, key);
51
- var finalIdList = [];
52
- for(var i = 0; i < idList.length; i++) {
53
- if (idList[i] && util.isString(idList[i])) {
54
- finalIdList.push(idList[i]);
55
- }
56
- }
57
-
58
- params._userQuery = {
59
- "_doc": {
60
- "$in": finalIdList
61
- }
62
- };
63
- params._orderResults = finalIdList;
64
-
65
- return handleQuery(chunk, context, bodies, params);
66
- };
67
-
68
- /**
69
- * Handles behavior for @query and @queryOne.
70
- *
71
- * @param chunk
72
- * @param context
73
- * @param bodies
74
- * @param params
75
- * @param keepOne
76
- * @returns {*}
77
- * @private
78
- */
79
- var handleQuery = r.handleQuery = function(chunk, context, bodies, params, keepOne)
80
- {
81
- params = params || {};
82
-
83
- // type
84
- var type = context.resolve(params.type);
85
-
86
- // pagination
87
- var sort = context.resolve(params.sort);
88
- var sortDirection = context.resolve(params.sortDirection);
89
- var limit = context.resolve(params.limit);
90
- var skip = context.resolve(params.skip);
91
-
92
- // scope
93
- var scope = context.resolve(params.scope);
94
-
95
- // as
96
- var as = context.resolve(params.as);
97
-
98
- // single field constraints
99
- var field = context.resolve(params.field);
100
- var fieldRegex = context.resolve(params.fieldRegex);
101
- var fieldValue = context.resolve(params.fieldValue);
102
-
103
- // limit response document fields (MongoDB _fields)
104
- var fields = context.resolve(params.fields) || null;
105
- var _fields;
106
- if (fields) {
107
- _fields = {};
108
- fields.split(",").map(f => {
109
- _fields[f.trim()] = 1;
110
- });
111
- }
112
-
113
- // role
114
- var role = context.resolve(params.role);
115
-
116
- // geolocation (near)
117
- var near = context.resolve(params.near);
118
-
119
- // locale
120
- var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
121
-
122
- var emptyResultCode = context.resolve(params.emptyResultCode);
123
-
124
- // whether to cache this fragment
125
- var cache = context.resolve(params.cache);
126
- if (typeof(cache) === "undefined" || !cache)
127
- {
128
- cache = false;
129
- }
130
- var fragmentId = null;
131
- if (cache) {
132
- fragmentId = context.get("fragmentIdGenerator")();
133
- }
134
-
135
- // user defined query
136
- var userQuery = params._userQuery;
137
- delete params._userQuery;
138
- if (!userQuery) {
139
- userQuery = {};
140
- }
141
-
142
- // order the resulting records by _doc using this array of IDs
143
- var orderResultsByList = params._orderResults;
144
- delete params._orderResults;
145
-
146
- // ensure limit and skip are numerical
147
- if (isDefined(limit))
148
- {
149
- limit = parseInt(limit);
150
- }
151
- if (isDefined(skip))
152
- {
153
- skip = parseInt(skip);
154
- }
155
-
156
- // DEBUG
157
- var forceError = context.resolve(params["forceError"]);
158
-
159
- var requirements = support.buildRequirements(context, {
160
- "type": type,
161
- "sort": sort,
162
- "sortDirection": sortDirection,
163
- "limit": limit,
164
- "skip": skip,
165
- "scope": scope,
166
- "as": as,
167
- "field": field,
168
- "fieldRegex": fieldRegex,
169
- "fieldValue": fieldValue,
170
- "near": near,
171
- "locale": locale,
172
- "role": role,
173
- "userQuery": JSON.stringify(userQuery),
174
- "_fields": JSON.stringify(_fields)
175
- });
176
-
177
- var finishQueryHandler = function(context)
178
- {
179
- tracker.finish(context);
180
- };
181
-
182
- return map(chunk, function(chunk2) {
183
-
184
- // if we can serve this from the fragment cache, we do so
185
- support.loadFragment(context, fragmentId, requirements, function(err, fragmentText) {
186
-
187
- // if we found a fragment, stream it back
188
- if (!err && fragmentText)
189
- {
190
- chunk2.write(fragmentText);
191
- return chunk2.end();
192
- }
193
-
194
- // not cached, so run this puppy...
195
-
196
- // TRACKER: START
197
- tracker.start(context, fragmentId, requirements);
198
-
199
- var query = userQuery || {};
200
- if (_fields) {
201
- query._fields = _fields;
202
- }
203
-
204
- if (isDefined(type))
205
- {
206
- query._type = type;
207
- }
208
- if (isDefined(field))
209
- {
210
- if (isDefined(fieldRegex))
211
- {
212
- query[field] = {
213
- $regex: fieldRegex,
214
- $options: "i"
215
- };
216
- }
217
- else if (isDefined(fieldValue))
218
- {
219
- query[field] = fieldValue;
220
- }
221
- }
222
-
223
- if (near)
224
- {
225
- var nearArray = near.split(",");
226
- nearArray[0] = parseFloat(nearArray[0]);
227
- nearArray[1] = parseFloat(nearArray[1]);
228
-
229
- query["loc"] = {
230
- "$near": {
231
- "lat": nearArray[0],
232
- "long": nearArray[1]
233
- }
234
- };
235
- }
236
-
237
- // strip out translations
238
- query["_features.f:translation"] = {
239
- "$exists": false
240
- };
241
-
242
- var pagination = {};
243
- if (!isDefined(limit))
244
- {
245
- limit = DEFAULT_PAGINATION_LIMIT;
246
- }
247
- pagination.limit = limit;
248
- if (isDefined(sort))
249
- {
250
- if (typeof(sortDirection) !== "undefined")
251
- {
252
- sortDirection = parseInt(sortDirection, 10);
253
- }
254
- else
255
- {
256
- sortDirection = 1;
257
- }
258
-
259
- pagination.sort = {};
260
- pagination.sort[sort] = sortDirection;
261
- }
262
- if (isDefined(skip))
263
- {
264
- pagination.skip = skip;
265
- }
266
-
267
- if (locale)
268
- {
269
- var gitana = context.get("gitana");
270
- gitana.getDriver().setLocale(locale);
271
- }
272
-
273
- var req = context.get("req");
274
- req.branch(function (err, branch) {
275
-
276
- // DEBUG: force error
277
- if (forceError)
278
- {
279
- console.log("FORCE ERROR");
280
- err = {
281
- "message": "Force error"
282
- };
283
- }
284
-
285
- if (err)
286
- {
287
- return end(chunk2, context, err);
288
- }
289
-
290
- var handleQueryResults = function (array) {
291
- if (array.length > 0)
292
- {
293
- for (var i = 0; i < array.length; i++)
294
- {
295
- array[i]._statistics = array[i].__stats();
296
- }
297
- }
298
-
299
- if (orderResultsByList && util.isArray(orderResultsByList))
300
- {
301
- var newArray = [];
302
- for (var i = 0; i < orderResultsByList.length; i++)
303
- {
304
- for (var j = 0; j < array.length; j++)
305
- {
306
- if (array[j]._doc == orderResultsByList[i])
307
- {
308
- newArray.push(array[j]);
309
- continue;
310
- }
311
- }
312
- }
313
- array = newArray;
314
- }
315
-
316
- if (array.length === 0 && emptyResultCode)
317
- {
318
- console.log("Query results were empty and dust tag configured to override HTTP response code to: " + emptyResultCode);
319
- return end(chunk2, context, {
320
- "message": "empty query results",
321
- "status": emptyResultCode
322
- });
323
- }
324
-
325
- if (keepOne)
326
- {
327
- var newContext = null;
328
- if (array.length > 0)
329
- {
330
- var result = array[0];
331
-
332
- var resultObject = null;
333
- if (as)
334
- {
335
- resultObject = {};
336
- resultObject[as] = util.clone(result, true);
337
-
338
- _MARK_INSIGHT(result, resultObject[as]);
339
- }
340
- else
341
- {
342
- resultObject = util.clone(result, true);
343
-
344
- _MARK_INSIGHT(result, resultObject);
345
- }
346
-
347
- newContext = context.push(resultObject);
348
- }
349
- else
350
- {
351
- newContext = context.push({});
352
- }
353
-
354
- support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function (err) {
355
-
356
- if (err)
357
- {
358
- console.log("Caught error in handleQuery/renderFragment: " + err);
359
- return end(chunk2, newContext, err);
360
- }
361
-
362
- finishQueryHandler(newContext);
363
- });
364
- }
365
- else
366
- {
367
- for (var a = 0; a < array.length; a++)
368
- {
369
- _MARK_INSIGHT(array[a], array[a]);
370
- }
371
-
372
- var resultObject = null;
373
- if (as)
374
- {
375
- resultObject = {
376
- "offset": array._offset,
377
- "total": array._totalRows
378
- };
379
- resultObject[as] = array;
380
- }
381
- else
382
- {
383
- resultObject = {
384
- "rows": array,
385
- "offset": array._offset,
386
- "total": array._totalRows
387
- };
388
- }
389
-
390
- var newContext = context.push(resultObject);
391
-
392
- support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function (err) {
393
-
394
- if (err)
395
- {
396
- console.log("Caught error in handleQuery/renderFragment: " + err);
397
- return end(chunk2, newContext, err);
398
- }
399
-
400
- finishQueryHandler(newContext);
401
- });
402
- }
403
- };
404
-
405
- var doQuery = function (branch, query, pagination) {
406
- Chain(branch).trap(function (err) {
407
- console.log("Caught error in handleQuery: " + err);
408
- end(chunk2, context, err);
409
- return false;
410
- }).queryNodes(query, pagination).then(function () {
411
-
412
- _convertToArray(this, function (array) {
413
- _filterWithAuthorityChecks(array, context, branch, role, function (array) {
414
- _enhanceQueryResults(array, function (array) {
415
- _trackQueryResults(array, context, function (array) {
416
- handleQueryResults(array);
417
- });
418
- });
419
- });
420
- });
421
-
422
- });
423
- };
424
-
425
- var doQueryPageHasContents = function (branch, query, pagination) {
426
- var page = context.get("helpers")["page"];
427
-
428
- Chain(page).trap(function (err) {
429
- console.log("Caught error in handleQuery: " + err);
430
- end(chunk2, context, err);
431
- return false;
432
- }).queryRelatives(query, {
433
- "type": "wcm:page_has_content"
434
- }, pagination).then(function () {
435
-
436
- _convertToArray(this, function (array) {
437
- _filterWithAuthorityChecks(array, context, branch, role, function (array) {
438
- _enhanceQueryResults(array, function (array) {
439
- _trackQueryResults(array, context, function (array) {
440
- handleQueryResults(array);
441
- });
442
- });
443
- });
444
- });
445
-
446
- });
447
- };
448
-
449
- if (isDefined(scope))
450
- {
451
- doQueryPageHasContents(branch, query, pagination);
452
- }
453
- else
454
- {
455
- doQuery(branch, query, pagination);
456
- }
457
-
458
- });
459
- });
460
- });
461
- };
462
-
463
- /**
464
- * Handles behavior for @search and @searchOne.
465
- *
466
- * @param chunk
467
- * @param context
468
- * @param bodies
469
- * @param params
470
- * @param keepOne
471
- * @returns {*}
472
- * @private
473
- */
474
- r.handleSearch = function(chunk, context, bodies, params, keepOne)
475
- {
476
- params = params || {};
477
-
478
- // pagination
479
- var sort = context.resolve(params.sort);
480
- var sortDirection = context.resolve(params.sortDirection);
481
- var limit = context.resolve(params.limit);
482
- var skip = context.resolve(params.skip);
483
-
484
- // scope
485
- //var scope = context.resolve(params.scope);
486
-
487
- // text
488
- var text = context.resolve(params.text);
489
-
490
- // as
491
- var as = context.resolve(params.as);
492
-
493
- // locale
494
- var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
495
-
496
- // ensure limit and skip are numerical
497
- if (isDefined(limit))
498
- {
499
- limit = parseInt(limit);
500
- }
501
- if (isDefined(skip))
502
- {
503
- limit = parseInt(skip);
504
- }
505
-
506
- // TRACKER: START
507
- tracker.start(context);
508
-
509
- if (locale) {
510
- tracker.requires(context, "locale", locale);
511
- }
512
-
513
- return map(chunk, function(chunk) {
514
-
515
- if (locale)
516
- {
517
- var gitana = context.get("gitana");
518
- gitana.getDriver().setLocale(locale);
519
- }
520
-
521
- var req = context.get("req");
522
- req.branch(function(err, branch) {
523
-
524
- if (err) {
525
- return end(chunk, context, err);
526
- }
527
-
528
- // TODO: use a "find" to limit to a range of nodes (for page scope)?
529
-
530
- var pagination = {};
531
- if (!isDefined(limit)) {
532
- limit = DEFAULT_PAGINATION_LIMIT;
533
- }
534
- pagination.limit = limit;
535
- if (sort)
536
- {
537
- if (typeof(sortDirection) !== "undefined")
538
- {
539
- sortDirection = parseInt(sortDirection, 10);
540
- }
541
- else
542
- {
543
- sortDirection = 1;
544
- }
545
-
546
- pagination.sort = {};
547
- pagination.sort[sort] = sortDirection;
548
- }
549
- if (skip)
550
- {
551
- pagination.skip = skip;
552
- }
553
-
554
- Chain(branch).trap(function(err){
555
- console.log("Caught error in handleSearch: " + err);
556
- end(chunk, context, err);
557
- return false;
558
- }).searchNodes(text, pagination).each(function() {
559
-
560
- // enhance node information
561
- enhanceNode(this);
562
-
563
- // TRACKER - PRODUCES "node"
564
- tracker.produces(context, "node", this._doc);
565
-
566
- }).then(function() {
567
-
568
- var array = this.asArray();
569
- for (var a = 0; a < array.length; a++)
570
- {
571
- _MARK_INSIGHT(array[a], array[a]);
572
- }
573
-
574
- var resultObject = null;
575
- if (as)
576
- {
577
- resultObject = {
578
- "offset": this.offset(),
579
- "total": this.totalRows()
580
- };
581
- resultObject[as] = array;
582
- }
583
- else
584
- {
585
- resultObject = {
586
- "rows": array,
587
- "offset": this.offset(),
588
- "total": this.totalRows()
589
- };
590
- }
591
-
592
- var newContext = context.push(resultObject);
593
-
594
- chunk.render(bodies.block, newContext);
595
- end(chunk, context);
596
- });
597
- });
598
- });
599
- };
600
-
601
- r.handleAssociations = function(chunk, context, bodies, params)
602
- {
603
- params = params || {};
604
-
605
- // pagination
606
- var sort = context.resolve(params.sort);
607
- var sortDirection = context.resolve(params.sortDirection);
608
- var limit = context.resolve(params.limit);
609
- var skip = context.resolve(params.skip);
610
- var nodeSort = context.resolve(params.nodeSort);
611
- var nodeSortDirection = context.resolve(params.nodeSortDirection);
612
- var nodeSkip = context.resolve(params.nodeSkip);
613
- var nodeLimit = context.resolve(params.nodeLimit);
614
-
615
- // as
616
- var as = context.resolve(params.as);
617
-
618
- // node
619
- var nodeId = context.resolve(params.node);
620
- var associationType = context.resolve(params.type);
621
- var associationDirection = context.resolve(params.direction);
622
-
623
- // locale
624
- var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
625
-
626
- // ensure limit and skip are numerical
627
- if (isDefined(limit))
628
- {
629
- limit = parseInt(limit);
630
- }
631
- if (isDefined(skip))
632
- {
633
- skip = parseInt(skip);
634
- }
635
- if (isDefined(nodeLimit))
636
- {
637
- nodeLimit = parseInt(nodeLimit);
638
- }
639
- if (isDefined(nodeSkip))
640
- {
641
- nodeSkip = parseInt(nodeSkip);
642
- }
643
-
644
- // TRACKER: START
645
- tracker.start(context);
646
- if (locale) {
647
- tracker.requires(context, "locale", locale);
648
- }
649
-
650
- return map(chunk, function(chunk) {
651
-
652
- if (locale)
653
- {
654
- var gitana = context.get("gitana");
655
- gitana.getDriver().setLocale(locale);
656
- }
657
-
658
- var req = context.get("req");
659
- req.branch(function(err, branch) {
660
-
661
- if (err) {
662
- return end(chunk, context, err);
663
- }
664
-
665
- Chain(branch).trap(function(err) {
666
- console.log("Caught error in handleAssociations: " + err);
667
- end(chunk, context, err);
668
- return false;
669
- }).readNode(nodeId).then(function() {
670
-
671
- var pagination = {};
672
- if (!isDefined(limit)) {
673
- limit = DEFAULT_PAGINATION_LIMIT;
674
- }
675
- pagination.limit = limit;
676
- if (sort)
677
- {
678
- if (typeof(sortDirection) !== "undefined")
679
- {
680
- sortDirection = parseInt(sortDirection, 10);
681
- }
682
- else
683
- {
684
- sortDirection = 1;
685
- }
686
-
687
- pagination.sort = {};
688
- pagination.sort[sort] = sortDirection;
689
- }
690
- if (skip)
691
- {
692
- pagination.skip = skip;
693
- }
694
-
695
- var config = {};
696
- if (associationType)
697
- {
698
- config.type = associationType;
699
- }
700
- if (associationDirection)
701
- {
702
- config.direction = associationDirection;
703
- }
704
-
705
- var node = this;
706
-
707
- this.associations(config, pagination).each(function() {
708
-
709
- // TRACKER - PRODUCES "node"
710
- tracker.produces(context, "node", this._doc);
711
-
712
- }).then(function() {
713
-
714
- var array = this.asArray();
715
- for (var a = 0; a < array.length; a++)
716
- {
717
- _MARK_INSIGHT(array[a], array[a]);
718
- }
719
-
720
- var resultObject = null;
721
- if (as)
722
- {
723
- resultObject = {
724
- "offset": this.offset(),
725
- "total": this.totalRows()
726
- };
727
- resultObject[as] = array;
728
- }
729
- else
730
- {
731
- resultObject = {
732
- "rows": array,
733
- "offset": this.offset(),
734
- "total": this.totalRows()
735
- };
736
- }
737
-
738
- var cf = function(sortedArray)
739
- {
740
- if (sortedArray) {
741
- resultObject[as || "rows"] = sortedArray;
742
- resultObject.total = sortedArray.length;
743
- }
744
- var newContext = context.push(resultObject);
745
-
746
- chunk.render(bodies.block, newContext);
747
- end(chunk, context);
748
- };
749
-
750
- if (array.length == 0)
751
- {
752
- cf();
753
- return;
754
- }
755
-
756
- // load target node data for each association
757
- var otherNodeIdsMap = {};
758
- var otherNodeIds = [];
759
- var otherNodeIdToAssociations = {};
760
- for (var z = 0; z < array.length; z++)
761
- {
762
- var otherNodeId = null;
763
- if (array[z].source == node._doc) {
764
- otherNodeId = array[z].target;
765
- } else {
766
- otherNodeId = array[z].source;
767
- }
768
-
769
- if (!otherNodeIdsMap[otherNodeId])
770
- {
771
- otherNodeIdsMap[otherNodeId] = true;
772
- otherNodeIds.push(otherNodeId);
773
- }
774
-
775
- if (!otherNodeIdToAssociations[otherNodeId])
776
- {
777
- otherNodeIdToAssociations[otherNodeId] = [];
778
- }
779
-
780
- otherNodeIdToAssociations[otherNodeId].push(array[z]);
781
- }
782
-
783
- pagination = {
784
- limit: nodeLimit || otherNodeIds.length,
785
- skip: nodeSkip || 0
786
- };
787
- if (nodeSort)
788
- {
789
- if (typeof(nodeSortDirection) !== "undefined")
790
- {
791
- sortDirection = parseInt(nodeSortDirection, 10);
792
- }
793
- else
794
- {
795
- sortDirection = 1;
796
- }
797
-
798
- pagination.sort = {};
799
- pagination.sort[nodeSort] = sortDirection;
800
- }
801
- var otherNodeIdToAssociationsSorted = [];
802
- Chain(node.getBranch()).queryNodes({
803
- "_doc": {
804
- "$in": otherNodeIds
805
- }
806
- }, pagination).each(function() {
807
-
808
- var associations_array = otherNodeIdToAssociations[this._doc];
809
- for (var z = 0; z < associations_array.length; z++)
810
- {
811
- associations_array[z].other = util.clone(this, true);
812
-
813
- // sorting by node properties (not association properties)
814
- otherNodeIdToAssociationsSorted.push(associations_array[z]);
815
- }
816
-
817
- // enhance node information
818
- enhanceNode(this);
819
-
820
- // TRACKER - PRODUCES "node"
821
- tracker.produces(context, "node", this._doc);
822
-
823
- }).then(function() {
824
- if (pagination.sort) {
825
- cf(otherNodeIdToAssociationsSorted);
826
- }
827
- else{
828
- cf();
829
- }
830
- });
831
- });
832
- });
833
- });
834
- });
835
- };
836
-
837
- r.handleRelatives = function(chunk, context, bodies, params)
838
- {
839
- params = params || {};
840
-
841
- // pagination
842
- var sort = context.resolve(params.sort);
843
- var sortDirection = context.resolve(params.sortDirection);
844
- var limit = context.resolve(params.limit);
845
- var skip = context.resolve(params.skip);
846
-
847
- // as
848
- var as = context.resolve(params.as);
849
-
850
- // from and type
851
- var fromNodeId = context.resolve(params.node);
852
- var associationType = context.resolve(params.associationType);
853
- var associationDirection = context.resolve(params.direction);
854
-
855
- var type = context.resolve(params.type);
856
-
857
- // single field constraints
858
- var field = context.resolve(params.field);
859
- var fieldRegex = context.resolve(params.fieldRegex);
860
- var fieldValue = context.resolve(params.fieldValue);
861
-
862
- // locale
863
- var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
864
-
865
- // role
866
- var role = context.resolve(params.role);
867
-
868
- // ensure limit and skip are numerical
869
- if (isDefined(limit))
870
- {
871
- limit = parseInt(limit);
872
- }
873
- if (isDefined(skip))
874
- {
875
- limit = parseInt(skip);
876
- }
877
-
878
- // TRACKER: START
879
- tracker.start(context);
880
- if (locale) {
881
- tracker.requires(context, "locale", locale);
882
- }
883
-
884
- return map(chunk, function(chunk) {
885
-
886
- var gitana = context.get("gitana");
887
-
888
- var req = context.get("req");
889
- req.branch(function(err, branch) {
890
-
891
- if (err) {
892
- return end(chunk, context, err);
893
- }
894
-
895
- Chain(branch).trap(function(err){
896
- console.log("Caught error in handleRelatives: " + err);
897
- end(chunk, context, err);
898
- return false;
899
- }).readNode(fromNodeId).then(function() {
900
-
901
- // first query for relatives
902
- var query = {};
903
- if (isDefined(type))
904
- {
905
- query._type = type;
906
- }
907
- if (isDefined(field))
908
- {
909
- if (isDefined(fieldRegex))
910
- {
911
- query[field] = {
912
- $regex: fieldRegex,
913
- $options: "i"
914
- };
915
- }
916
- else if (isDefined(fieldValue))
917
- {
918
- query[field] = fieldValue;
919
- }
920
- }
921
-
922
- // pagination
923
- var pagination = {};
924
- if (!isDefined(limit)) {
925
- limit = DEFAULT_PAGINATION_LIMIT;
926
- }
927
- pagination.limit = limit;
928
- if (sort)
929
- {
930
- if (typeof(sortDirection) !== "undefined")
931
- {
932
- sortDirection = parseInt(sortDirection, 10);
933
- }
934
- else
935
- {
936
- sortDirection = 1;
937
- }
938
-
939
- pagination.sort = {};
940
- pagination.sort[sort] = sortDirection;
941
- }
942
- if (skip)
943
- {
944
- pagination.skip = skip;
945
- }
946
-
947
- var config = {};
948
- if (associationType)
949
- {
950
- config.type = associationType;
951
- }
952
- if (associationDirection)
953
- {
954
- config.direction = associationDirection;
955
- }
956
-
957
- var handleResults = function(array) {
958
-
959
- for (var a = 0; a < array.length; a++)
960
- {
961
- _MARK_INSIGHT(array[a], array[a]);
962
- }
963
-
964
- var resultObject = null;
965
- if (as)
966
- {
967
- resultObject = {
968
- "offset": array._offset,
969
- "total": array._totalRows
970
- };
971
- resultObject[as] = array;
972
- }
973
- else
974
- {
975
- resultObject = {
976
- "rows": array,
977
- "offset": array._offset,
978
- "total": array._totalRows
979
- };
980
- }
981
-
982
- var newContext = context.push(resultObject);
983
-
984
- chunk.render(bodies.block, newContext);
985
- end(chunk, context);
986
-
987
- };
988
-
989
- Chain(this).trap(function(err) {
990
- console.log("Caught error in handleRelatives/queryRelatives: " + err);
991
- end(chunk, context, err);
992
- return false;
993
- }).queryRelatives(query, config, pagination).then(function () {
994
-
995
- _convertToArray(this, function (array) {
996
- _filterWithAuthorityChecks(array, context, branch, role, function (array) {
997
- _enhanceQueryResults(array, function (array) {
998
- _trackQueryResults(array, context, function (array) {
999
- handleResults(array);
1000
- });
1001
- });
1002
- });
1003
- });
1004
-
1005
- });
1006
- });
1007
- });
1008
- });
1009
- };
1010
-
1011
- r.handleContent = function(chunk, context, bodies, params)
1012
- {
1013
- params = params || {};
1014
-
1015
- var id = context.resolve(params.id);
1016
- var contentPath = context.resolve(params.path);
1017
-
1018
- // as
1019
- var as = context.resolve(params.as);
1020
-
1021
- // locale
1022
- var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
1023
-
1024
- var requirements = support.buildRequirements(context, {
1025
- "as": as,
1026
- "id": id,
1027
- "contentPath": contentPath,
1028
- "locale": locale
1029
- });
1030
-
1031
- var finishHandler = function(context, err)
1032
- {
1033
- tracker.finish(context);
1034
- };
1035
-
1036
- // identifier for this fragment
1037
- var fragmentId = context.resolve(params.fragment);
1038
-
1039
- return map(chunk, function(chunk2) {
1040
-
1041
- // if we can serve this from the fragment cache, we do so
1042
- support.loadFragment(context, fragmentId, requirements, function(err, fragmentText) {
1043
-
1044
- // if we found a fragment, stream it back
1045
- if (!err && fragmentText) {
1046
- chunk2.write(fragmentText);
1047
- return chunk2.end();
1048
- }
1049
-
1050
- // TRACKER: START
1051
- tracker.start(context);
1052
- if (locale) {
1053
- tracker.requires(context, "locale", locale);
1054
- }
1055
-
1056
- if (locale)
1057
- {
1058
- var gitana = context.get("gitana");
1059
- gitana.getDriver().setLocale(locale);
1060
- }
1061
-
1062
- var f = function(node)
1063
- {
1064
- // enhance node information
1065
- enhanceNode(node);
1066
-
1067
- // TRACKER - PRODUCES "node"
1068
- tracker.produces(context, "node", node._doc);
1069
-
1070
- var newContextObject = {};
1071
- if (as)
1072
- {
1073
- newContextObject[as] = util.clone(node, true);
1074
-
1075
- _MARK_INSIGHT(node, newContextObject[as]);
1076
- }
1077
- else
1078
- {
1079
- newContextObject["content"] = util.clone(node, true);
1080
-
1081
- _MARK_INSIGHT(node, newContextObject.content);
1082
- }
1083
-
1084
- var newContext = context.push(newContextObject);
1085
- //newContext.get("content").attachments = attachments;
1086
-
1087
- support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function(err) {
1088
- finishHandler(newContext, err);
1089
- });
1090
-
1091
- // chunk.render(bodies.block, newContext);
1092
- // end(chunk, context);
1093
- };
1094
-
1095
- var req = context.get("req");
1096
- req.branch(function(err, branch) {
1097
-
1098
- if (err) {
1099
- return end(chunk2, context, err);
1100
- }
1101
-
1102
- // select by ID or select by Path
1103
- if (id)
1104
- {
1105
- Chain(branch).trap(function(err) {
1106
- console.log("Caught error in handleContent: " + err);
1107
- end(chunk2, context, err);
1108
- return false;
1109
- }).readNode(id).then(function() {
1110
- f(this);
1111
- });
1112
- }
1113
- else if (contentPath)
1114
- {
1115
- Chain(branch).trap(function(err) {
1116
- console.log("Caught error in handleContent: " + err);
1117
- end(chunk2, context, err);
1118
- return false;
1119
- }).readNode("root", contentPath).then(function() {
1120
- f(this);
1121
- });
1122
- }
1123
- else
1124
- {
1125
- // missing both ID and Path?
1126
- console.log("Missing ID and PATH! {@content} helper must have either a path or an id");
1127
- }
1128
- });
1129
- });
1130
- });
1131
- };
1132
-
1133
- r.handleForm = function(chunk, context, bodies, params)
1134
- {
1135
- params = params || {};
1136
-
1137
- var definition = context.resolve(params.definition);
1138
- var form = context.resolve(params.form);
1139
- var list = context.resolve(params.list);
1140
- var successUrl = context.resolve(params.success);
1141
- var errorUrl = context.resolve(params.error);
1142
- var formId = context.resolve(params.formId);
1143
- var submitTitle = context.resolve(params.submitTitle);
1144
-
1145
- return map(chunk, function(chunk) {
1146
-
1147
- var gitana = context.get("gitana");
1148
-
1149
- var req = context.get("req");
1150
- req.branch(function(err, branch) {
1151
-
1152
- if (err) {
1153
- return end(chunk, context, err);
1154
- }
1155
-
1156
- // read the definition
1157
- Chain(branch).trap(function(err) {
1158
- console.log("Caught error in handleForm: " + err);
1159
- end(chunk, context, err);
1160
- return false;
1161
- }).readDefinition(definition).then(function() {
1162
- var schema = this;
1163
-
1164
- // if a form is specified, read the form
1165
- var options = null;
1166
- this.readForm(form).then(function() {
1167
- options = this;
1168
- });
1169
-
1170
- this.then(function() {
1171
-
1172
- if (!options)
1173
- {
1174
- options = {};
1175
- }
1176
-
1177
- var config = {
1178
- "schema": schema,
1179
- "options": options
1180
- };
1181
- var action = "/_form/submit";
1182
- /*
1183
- if (list)
1184
- {
1185
- action += "&list=" + list;
1186
- }
1187
- if (successUrl)
1188
- {
1189
- action += "&successUrl=" + successUrl;
1190
- }
1191
- if (errorUrl)
1192
- {
1193
- action += "&errorUrl=" + errorUrl;
1194
- }
1195
- */
1196
- /*
1197
- options.renderForm = true;
1198
- options.form = {
1199
- "attributes": {
1200
- "method": "POST",
1201
- "action": action,
1202
- "enctype": "application/json",
1203
- "data-ajax": "true"
1204
- },
1205
- "buttons": {
1206
- "submit": {
1207
- "title": "Submit"
1208
- }
1209
- }
1210
- };
1211
- */
1212
- config.helper = {};
1213
- config.helper.method = "POST";
1214
- config.helper.action = action;
1215
- config.helper.submitTitle = submitTitle;
1216
- if (list)
1217
- {
1218
- config.helper.list = list;
1219
- }
1220
- if (successUrl)
1221
- {
1222
- config.helper.successUrl = successUrl;
1223
- }
1224
- if (errorUrl)
1225
- {
1226
- config.helper.errorUrl = errorUrl;
1227
- }
1228
-
1229
- config.connector = {
1230
- "id": "appserver",
1231
- "config": {}
1232
- };
1233
-
1234
- var divId = formId || "form" + new Date().getTime();
1235
-
1236
- chunk.write("<div id='" + divId + "'></div>");
1237
- chunk.write("<script src='/_lib/formhelper/formhelper.js'></script>");
1238
-
1239
- chunk.write("<script>");
1240
- chunk.write("var formConfig = GenerateForm(" + JSON.stringify(config) + ");");
1241
- chunk.write("$('#" + divId + "').alpaca(formConfig);");
1242
- chunk.write("</script>");
1243
-
1244
- end(chunk, context);
1245
-
1246
- });
1247
- });
1248
- });
1249
- });
1250
- };
1251
-
1252
- // NOTE: this can also be done like this:
1253
- // NOTE: as per source dust.js line 521
1254
- /*
1255
- Context.prototype.resolve = function(body) {
1256
- var chunk;
1257
-
1258
- if(typeof body !== 'function') {
1259
- return body;
1260
- }
1261
- chunk = new Chunk().render(body, this);
1262
- if(chunk instanceof Chunk) {
1263
- return chunk.data.join(''); // ie7 perf
1264
- }
1265
- return chunk;
1266
- };
1267
- */
1268
-
1269
- /**
1270
- * Handles include behavior for @include and @module
1271
- *
1272
- * @param chunk
1273
- * @param context
1274
- * @param bodies
1275
- * @param params
1276
- * @param targetPath
1277
- * @returns {*}
1278
- * @private
1279
- */
1280
- r.handleInclude = function(chunk, context, bodies, params, targetPath)
1281
- {
1282
- params = params || {};
1283
-
1284
- var log = context.options.log;
1285
-
1286
- targetPath = targetPath.replace(/\\/g, '/');
1287
-
1288
- return map(chunk, function(chunk2) {
1289
-
1290
- var store = context.options.store;
1291
-
1292
- // the stack of executing template file paths
1293
- var currentTemplateFilePaths = context.get("templateFilePaths").reverse();
1294
-
1295
- var resolveMatchingFilePath = function(callback)
1296
- {
1297
- // absolute path
1298
- if (targetPath.indexOf("/") === 0)
1299
- {
1300
- currentTemplateFilePaths = currentTemplateFilePaths.reverse();
1301
-
1302
- // absolute path, always relative to the first element in the template file paths list
1303
- var filePath = path.normalize(path.join(currentTemplateFilePaths[0], "..", "." + targetPath));
1304
-
1305
- // if the file path does not end with ".html", we append
1306
- if (filePath.indexOf(".html") == -1)
1307
- {
1308
- filePath += ".html";
1309
- }
1310
-
1311
- store.existsFile(filePath, function(exists) {
1312
-
1313
- if (exists) {
1314
- callback(null, filePath);
1315
- } else {
1316
- callback();
1317
- // callback({"message": "file not found in store: " + filePath});
1318
- }
1319
- });
1320
- }
1321
- else
1322
- {
1323
- var fns = [];
1324
-
1325
- // relative path, walk the template file paths list backwards
1326
- var filePaths = [];
1327
- for (var a = 0; a < currentTemplateFilePaths.length; a++)
1328
- {
1329
- var fn = function(currentTemplateFilePath) {
1330
- return function(done) {
1331
-
1332
- // target template path
1333
- var filePath = path.normalize(path.join(currentTemplateFilePath, "..", targetPath));
1334
-
1335
- // if the file path does not end with ".html", we append
1336
- if (filePath.indexOf(".html") == -1)
1337
- {
1338
- filePath += ".html";
1339
- }
1340
-
1341
- store.existsFile(filePath, function(exists) {
1342
-
1343
- if (exists) {
1344
- filePaths.push(filePath);
1345
- }
1346
-
1347
- done();
1348
- });
1349
- }
1350
- };
1351
- fns.push(fn);
1352
- }
1353
-
1354
- async.series(fns, function() {
1355
-
1356
- for (var i = 0; i < filePaths.length; i++) {
1357
- if (filePaths[i]) {
1358
- callback(null, filePaths[i]);
1359
- break;
1360
- }
1361
- }
1362
- })
1363
-
1364
- }
1365
- };
1366
-
1367
- resolveMatchingFilePath(function(err, matchingFilePath) {
1368
-
1369
- // if no match...
1370
- if (!matchingFilePath) {
1371
- console.log("Unable to find included file for path: " + targetPath);
1372
- end(chunk2, context);
1373
- return;
1374
- }
1375
-
1376
- var filePath = matchingFilePath;
1377
-
1378
- var templatePath = filePath.split(path.sep).join("/");
1379
-
1380
- var includeContextObject = {};
1381
-
1382
- // override with any params
1383
- for (var k in params) {
1384
- var value = context.resolve(params[k]);
1385
- if (value) {
1386
- includeContextObject[k] = value;
1387
- }
1388
- }
1389
-
1390
- // some additional overrides that we enforce
1391
- var templateFilePaths = context.get("templateFilePaths");
1392
- var newTemplateFilePaths = [];
1393
- for (var r = 0; r < templateFilePaths.length; r++) {
1394
- newTemplateFilePaths.push(templateFilePaths[r]);
1395
- }
1396
- newTemplateFilePaths.push(filePath);
1397
- includeContextObject["templateFilePaths"] = newTemplateFilePaths;
1398
-
1399
- // include the subcontext
1400
- var subContext = context.push(includeContextObject);
1401
-
1402
- dust.render(templatePath, subContext, function (err, out) {
1403
-
1404
- if (err) {
1405
- log("Error while rendering include for: " + templatePath + ", err: " + (err && err.message ? err.message : err));
1406
- return end(chunk2, subContext, err);
1407
- }
1408
-
1409
- chunk2.write(out);
1410
- end(chunk2, subContext);
1411
- });
1412
- });
1413
- });
1414
- };
1415
-
1416
- /**
1417
- * Handles behavior for @fragment.
1418
- *
1419
- * @param chunk
1420
- * @param context
1421
- * @param bodies
1422
- * @param params
1423
- *
1424
- * @returns {*}
1425
- * @private
1426
- */
1427
- var handleFragment = r.handleFragment = function(chunk, context, bodies, params)
1428
- {
1429
- params = params || {};
1430
-
1431
- var fragmentId = context.get("fragmentIdGenerator")();
1432
-
1433
- var requirements = support.buildRequirements(context, {});
1434
-
1435
- var finishHandler = function(context, err)
1436
- {
1437
- tracker.finish(context);
1438
- };
1439
-
1440
- return map(chunk, function(chunk2) {
1441
-
1442
- // if we can serve this from the fragment cache, we do so
1443
- support.loadFragment(context, fragmentId, requirements, function(err, fragmentText) {
1444
-
1445
- // if we found a fragment, stream it back
1446
- if (!err && fragmentText) {
1447
- chunk2.write(fragmentText);
1448
- return chunk2.end();
1449
- }
1450
-
1451
- // not cached, so run this puppy...
1452
-
1453
- // TRACKER: START
1454
- tracker.start(context, fragmentId, requirements);
1455
-
1456
- var requirements = support.buildRequirements(context, {});
1457
-
1458
- var newContext = context.push({});
1459
-
1460
- support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function(err) {
1461
- finishHandler(newContext, err);
1462
- });
1463
-
1464
- });
1465
- });
1466
- };
1467
-
1468
- r.util = util;
1469
- r.map = support.map;
1470
- r.end = support.end;
1471
- r.resolveVariables = support.resolveVariables;
1472
-
1473
-
1474
- // pipeline
1475
-
1476
- var _convertToArray = function(map, _done)
1477
- {
1478
- var array = [];
1479
-
1480
- for (var i = 0; i < map.__keys().length; i++)
1481
- {
1482
- array.push(map[map.__keys()[i]]);
1483
- }
1484
-
1485
- // additional values
1486
- array._totalRows = map.totalRows();
1487
- array._offset = map.offset();
1488
-
1489
- _done(array);
1490
- };
1491
-
1492
- var _filterWithAuthorityChecks = function(array, context, branch, role, _done)
1493
- {
1494
- if (!role) {
1495
- return _done(array);
1496
- }
1497
-
1498
- var req = context.get("req");
1499
- if (!req) {
1500
- return _done(array);
1501
- }
1502
-
1503
- var user = req.user;
1504
- if (!user) {
1505
- return _done(array);
1506
- }
1507
- if (!user.domainId || !user.id) {
1508
- return _done(array);
1509
- }
1510
-
1511
- var principalId = user.domainId + "/" + user.id;
1512
-
1513
- // filter via authority checks
1514
- var checks = [];
1515
- for (var i = 0; i < array.length; i++)
1516
- {
1517
- checks.push({
1518
- "permissionedId": array[i]._doc,
1519
- "authorityId": role,
1520
- "principalId": principalId
1521
- });
1522
- }
1523
-
1524
- Chain(branch).checkNodeAuthorities(checks, function(results) {
1525
-
1526
- // create a quick lookup map
1527
- var resultsMap = {};
1528
- for (var i = 0; i < results.length; i++)
1529
- {
1530
- resultsMap[results[i].permissionedId] = results[i].result;
1531
- }
1532
-
1533
- // now filter the array
1534
- var i = 0;
1535
- do
1536
- {
1537
- if (i < array.length)
1538
- {
1539
- var permissionedId = array[i]._doc;
1540
-
1541
- if (resultsMap[permissionedId])
1542
- {
1543
- i++;
1544
- }
1545
- else
1546
- {
1547
- array.splice(i, 1);
1548
- }
1549
- }
1550
- }
1551
- while (i < array.length);
1552
-
1553
- _done(array);
1554
- });
1555
- };
1556
-
1557
- var _enhanceQueryResults = function(array, _done)
1558
- {
1559
- for (var i = 0; i < array.length; i++)
1560
- {
1561
- // enhance node information
1562
- enhanceNode(array[i]);
1563
- }
1564
-
1565
- _done(array);
1566
- };
1567
-
1568
- var _trackQueryResults = function(array, context, _done)
1569
- {
1570
- for (var i = 0; i < array.length; i++)
1571
- {
1572
- // TRACKER - PRODUCES "node"
1573
- tracker.produces(context, "node", array[i]._doc);
1574
- }
1575
-
1576
- _done(array);
1577
- };
1578
-
1579
- return r;
1580
- };