@webresto/graphql 1.3.6 → 1.3.8

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 (142) hide show
  1. package/.gitattributes +2 -0
  2. package/.gitlab-ci.yml +18 -0
  3. package/.vscode/extensions.json +5 -0
  4. package/docs/actions.md +25 -0
  5. package/docs/authorization.md +215 -0
  6. package/docs/captcha.md +71 -0
  7. package/docs/device-id.md +30 -0
  8. package/docs/messages.md +10 -0
  9. package/docs/user.md +54 -0
  10. package/index.d.ts +0 -1
  11. package/index.js +6 -2
  12. package/index.ts +2 -2
  13. package/lib/afterHook.js +8 -0
  14. package/lib/afterHook.ts +9 -0
  15. package/lib/bindTranslations.d.ts +1 -0
  16. package/lib/bindTranslations.js +40 -0
  17. package/lib/bindTranslations.ts +39 -0
  18. package/lib/defaults.d.ts +1 -0
  19. package/lib/defaults.js +49 -10
  20. package/lib/defaults.ts +55 -0
  21. package/lib/eventHelper.d.ts +14 -5
  22. package/lib/eventHelper.js +28 -9
  23. package/lib/eventHelper.ts +41 -8
  24. package/lib/getRecomended.d.ts +1 -0
  25. package/lib/getRecomended.js +29 -0
  26. package/lib/getRecomended.ts +31 -0
  27. package/lib/graphqlHelper.d.ts +3 -4
  28. package/lib/graphqlHelper.js +184 -73
  29. package/lib/graphqlHelper.ts +329 -186
  30. package/lib/jwt.d.ts +10 -0
  31. package/lib/jwt.js +43 -0
  32. package/lib/jwt.ts +61 -0
  33. package/package.json +13 -6
  34. package/src/additionalResolvers.d.ts +72 -9
  35. package/src/additionalResolvers.js +93 -24
  36. package/src/additionalResolvers.ts +105 -34
  37. package/src/graphql.d.ts +5 -3
  38. package/src/graphql.js +170 -37
  39. package/src/graphql.ts +210 -60
  40. package/src/resolvers/bonusProgram.d.ts +32 -0
  41. package/src/resolvers/bonusProgram.js +65 -0
  42. package/src/resolvers/bonusProgram.ts +79 -0
  43. package/src/resolvers/captcha.d.ts +11 -0
  44. package/src/resolvers/captcha.js +19 -0
  45. package/src/resolvers/captcha.ts +16 -0
  46. package/src/resolvers/checkout.d.ts +43 -14
  47. package/src/resolvers/checkout.js +172 -122
  48. package/src/resolvers/checkout.ts +218 -142
  49. package/src/resolvers/dishAndModifier.js +8 -4
  50. package/src/resolvers/dishAndModifier.ts +4 -0
  51. package/src/resolvers/error.d.ts +9 -0
  52. package/src/resolvers/error.js +21 -0
  53. package/src/resolvers/error.ts +21 -0
  54. package/src/resolvers/menu.d.ts +9 -0
  55. package/src/resolvers/menu.js +12 -0
  56. package/src/resolvers/menu.ts +10 -0
  57. package/src/resolvers/order.d.ts +527 -0
  58. package/src/resolvers/order.js +349 -0
  59. package/src/resolvers/order.ts +435 -0
  60. package/src/resolvers/paymentMethod.js +7 -3
  61. package/src/resolvers/paymentMethod.ts +9 -5
  62. package/src/resolvers/pickupPoint.d.ts +1 -0
  63. package/src/resolvers/pickupPoint.js +24 -0
  64. package/src/resolvers/pickupPoint.ts +23 -0
  65. package/src/resolvers/recomended.d.ts +13 -0
  66. package/src/resolvers/recomended.js +80 -0
  67. package/src/resolvers/recomended.ts +86 -0
  68. package/src/resolvers/restrictions.d.ts +37 -1
  69. package/src/resolvers/restrictions.js +100 -15
  70. package/src/resolvers/restrictions.ts +106 -14
  71. package/src/resolvers/streets.d.ts +1 -1
  72. package/src/resolvers/streets.js +1 -4
  73. package/src/resolvers/streets.ts +1 -3
  74. package/src/resolvers/subscriptions.d.ts +4 -4
  75. package/src/resolvers/subscriptions.js +49 -12
  76. package/src/resolvers/subscriptions.ts +59 -14
  77. package/src/resolvers/telemetry.d.ts +14 -0
  78. package/src/resolvers/telemetry.js +25 -0
  79. package/src/resolvers/telemetry.ts +24 -0
  80. package/src/resolvers/user.d.ts +82 -0
  81. package/src/resolvers/user.js +416 -0
  82. package/src/resolvers/user.ts +621 -0
  83. package/src/resolvers/userLocation.d.ts +53 -0
  84. package/src/resolvers/userLocation.js +74 -0
  85. package/src/resolvers/userLocation.ts +125 -0
  86. package/src/resolvers/userOTPrequest.d.ts +21 -0
  87. package/src/resolvers/userOTPrequest.js +57 -0
  88. package/src/resolvers/userOTPrequest.ts +75 -0
  89. package/test/e2e_helper.js +157 -0
  90. package/test/e2e_helper.ts +212 -0
  91. package/test/fixture/config/i18n.js +7 -20
  92. package/test/fixture/config/locales/de.json +1 -0
  93. package/test/fixture/config/locales/en.json +10 -0
  94. package/test/fixture/config/locales/es.json +3 -0
  95. package/test/fixture/config/locales/fr.json +1 -0
  96. package/test/fixture/config/log.js +1 -1
  97. package/test/fixture/package.json +5 -6
  98. package/test/fixture/patches/rttc+10.0.1.patch +17 -0
  99. package/test/integration/captcha.test.js +20 -0
  100. package/test/integration/captcha.test.ts +25 -0
  101. package/test/integration/dish.test.js +35 -0
  102. package/test/integration/dish.test.ts +43 -0
  103. package/test/integration/graphql.test.js +5 -2
  104. package/test/integration/graphql.test.ts +2 -4
  105. package/test/integration/images.test.js +35 -0
  106. package/test/integration/images.test.ts +40 -0
  107. package/test/integration/locale.test.js +26 -0
  108. package/test/integration/locale.test.ts +32 -0
  109. package/test/integration/order.test.js +56 -43
  110. package/test/integration/order.test.ts +59 -59
  111. package/test/integration/subscriptions.test.js +136 -0
  112. package/test/integration/subscriptions.test.ts +162 -0
  113. package/test/integration/user.test.js +249 -0
  114. package/test/integration/user.test.ts +299 -0
  115. package/test/unit/first.test.js +4 -2
  116. package/test/unit/first.test.ts +1 -1
  117. package/test/unit/get-recomended.test.js +56 -0
  118. package/test/unit/get-recomended.test.ts +63 -0
  119. package/translations/de.json +2 -0
  120. package/translations/en.json +3 -0
  121. package/translations/es.json +3 -0
  122. package/translations/fr.json +2 -0
  123. package/translations/ru.json +36 -0
  124. package/tsconfig.json +20 -5
  125. package/types/global.d.ts +30 -0
  126. package/types/global.js +2 -0
  127. package/types/global.ts +31 -0
  128. package/types/primitives.d.ts +19 -0
  129. package/types/references.d.ts +1 -0
  130. package/types/restoGraphQLConfig.d.ts +13 -0
  131. package/lib/afterHook.ts___graphql-transport-ws +0 -138
  132. package/lib/afterHook.ts___graphql-ws +0 -133
  133. package/lib/errorWrapper.d.ts +0 -4
  134. package/lib/errorWrapper.js +0 -13
  135. package/lib/errorWrapper.ts +0 -12
  136. package/notes.md +0 -1976
  137. package/src/resolvers/cart.d.ts +0 -343
  138. package/src/resolvers/cart.js +0 -196
  139. package/src/resolvers/cart.ts +0 -277
  140. package/test/fixture/config/connections.js +0 -9
  141. package/test/integration/sails_not_crash.test.js +0 -3
  142. package/test/integration/sails_not_crash.test.ts +0 -3
@@ -1,23 +1,18 @@
1
- /// <reference path="../../core/libs/globalTypes.ts"/>
2
-
3
1
  import _ = require("lodash");
4
- import { WorkTimeValidator} from '@webresto/worktime'
5
- import getEmitter from "@webresto/core/libs/getEmitter";
2
+ import { WorkTimeValidator } from '@webresto/worktime'
3
+
6
4
  import * as WLCriteria from 'waterline-criteria';
7
- const fs = require('fs');
8
- const path = require('path');
9
-
10
-
11
- const scalarTypes = {
12
- string: "String",
13
- text: "String",
14
- date: "String",
15
- datetime: "String",
16
- integer: "Int",
17
- float: "Float",
18
- boolean: "Boolean",
19
- // "json": "Json",
20
- // "array": "Array",
5
+ import { JWTAuth } from "./jwt";
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+
10
+ const scalarTypes = {
11
+ string: "String",
12
+ number: "Float",
13
+ boolean: "Boolean",
14
+ // json: "Json",
15
+ // "array": "Array",
21
16
  }
22
17
 
23
18
  /*
@@ -75,30 +70,31 @@ const models: Set<string> = new Set();
75
70
  * @returns void
76
71
  */
77
72
 
78
- function addModel (modelName: string) {
79
- modelName = firstLetterToUpperCase(modelName);
80
- if (blackList.includes(modelName)) {
81
- // schemaScalars.add(modelName);
82
- return;
83
- }
84
- models.add(modelName.toLowerCase());
73
+ function addModel(modelName: string) {
74
+ modelName = firstLetterToUpperCase(modelName);
75
+ if (blackList.includes(modelName)) {
76
+ // schemaScalars.add(modelName);
77
+ return;
78
+ }
79
+ models.add(modelName.toLowerCase());
85
80
  }
86
- function addType (typeString: String) {
87
- schemaTypes.push(typeString);
81
+
82
+ function addType(type: string) {
83
+ schemaTypes.push(type);
88
84
  }
89
85
  /**
90
86
  * Мержит новый резолвер с объектом резолверов. Новый резолвер заменит старый при совпадении имен
91
87
  *
92
88
  * @param resolvers
93
89
  * resolverExample = {
94
- * def: "user(id: String)",
90
+ * def: "user(id: string)",
95
91
  * fn: function (parent, args, context) {
96
92
  * return User.find({id: args.id})
97
93
  * }
98
94
  * }
99
95
  */
100
- function addResolvers (resolvers: Object) {
101
- _.merge(schemaResolvers, resolvers);
96
+ function addResolvers(resolvers: Object) {
97
+ _.merge(schemaResolvers, resolvers);
102
98
  }
103
99
 
104
100
  /**
@@ -107,7 +103,7 @@ function addResolvers (resolvers: Object) {
107
103
  function addAllSailsModels() {
108
104
  Object.keys(sails.models).forEach((key) => {
109
105
  if (key.includes("__")) return;
110
- if (sails.models[key].graphql && sails.models[key].graphql.public === false){
106
+ if (sails.models[key].graphql && sails.models[key].graphql.public === false) {
111
107
  addToBlackList([key]);
112
108
  return;
113
109
  }
@@ -125,12 +121,12 @@ function addAllSailsModels() {
125
121
  * @param list array<string>
126
122
  */
127
123
  function addToBlackList(list: Array<string>) {
128
- blackList.push(...list);
124
+ blackList.push(...list);
129
125
  }
130
126
 
131
127
  /**
132
128
  * Добавляет в указаную модель новое поле
133
- * Пример: addCustomField("Order", "customField: String")
129
+ * Пример: addCustomField("Order", "customField: string")
134
130
  *
135
131
  * @param model string
136
132
  * @param field string
@@ -148,7 +144,7 @@ function addCustomField(model, field) {
148
144
  * @param field string
149
145
  */
150
146
  function addToReplaceList(model, field) {
151
- replaceList[model] = field;
147
+ replaceList[model] = field;
152
148
  }
153
149
 
154
150
  /**
@@ -174,7 +170,7 @@ function addDirResolvers(dir) {
174
170
  *
175
171
  * @returns {schemaTypes, schemaResolvers}
176
172
  */
177
- function getSchema () {
173
+ function getSchema() {
178
174
  Object.keys(whiteList).forEach(modelname => {
179
175
  if (sails.models[modelname]?.graphql?.public !== false) {
180
176
  addModelResolver(modelname);
@@ -182,7 +178,7 @@ function getSchema () {
182
178
  });
183
179
 
184
180
  addResolvers(modelsResolvers);
185
- return createSchema({types: schemaTypes, resolvers: schemaResolvers});
181
+ return createSchema({ types: schemaTypes, resolvers: schemaResolvers });
186
182
  }
187
183
 
188
184
  function firstLetterToUpperCase(string) {
@@ -213,26 +209,37 @@ function createType(model) {
213
209
 
214
210
  let scalarType;
215
211
  if (attributes[prop].type) {
216
- if (scalarTypes[attributes[prop].type.toLowerCase()]) {
217
- scalarType = scalarTypes[attributes[prop].type.toLowerCase()];
212
+
213
+ // TODO: make method add AddModelFieldType(path, type) for pass custom type for specific model
214
+ if (modelName.toLowerCase() === "user" && prop === "phone") {
215
+ scalarType = "Phone"
218
216
  } else {
219
- scalarType = firstLetterToUpperCase(attributes[prop].type);
220
- schemaScalars.add(scalarType);
217
+ if (scalarTypes[attributes[prop].type.toLowerCase()]) {
218
+ scalarType = scalarTypes[attributes[prop].type.toLowerCase()];
219
+ } else {
220
+ scalarType = firstLetterToUpperCase(attributes[prop].type);
221
+ schemaScalars.add(scalarType);
222
+ }
221
223
  }
222
224
  type += ' ' + prop + ': ' + scalarType + '\n';
223
225
  }
224
-
226
+
225
227
  // MODEL SCHEMA GENERATION
226
228
  if (attributes[prop].model) {
227
229
  let relationModel = sails.models[attributes[prop].model.toLowerCase()]
228
- scalarType = scalarTypes[relationModel.attributes[relationModel.primaryKey].type]
230
+ scalarType = scalarTypes[relationModel.attributes[relationModel.primaryKey].type.toLowerCase()]
229
231
  const name = sails.models[attributes[prop].model.toLowerCase()].globalId;
230
232
  type += ` ${prop}: ${name}\n`;
233
+
234
+ // Virtual Id field
235
+ type += ` ${prop}Id: ${scalarType}\n`;
236
+
231
237
  }
232
238
 
233
239
  // COLLECTION SCHEMA GENERATION
234
240
  if (attributes[prop].collection) {
235
- scalarType = scalarTypes[attributes[sails.models[attributes[prop].collection.toLowerCase()].primaryKey].type.toLowerCase()]
241
+ let collectionModel = sails.models[attributes[prop].collection.toLowerCase()];
242
+ scalarType = scalarTypes[collectionModel.attributes[collectionModel.primaryKey].type.toLowerCase()];
236
243
  const name = sails.models[attributes[prop].collection.toLowerCase()].globalId;
237
244
  type += ` ${prop}: [${name}]\n`;
238
245
  }
@@ -241,7 +248,7 @@ function createType(model) {
241
248
  type += ` ${customFields[modelName]}\n`;
242
249
  }
243
250
  if (!attributes.customData) {
244
- type += '""" autogenerated """ customData: Json';
251
+ type += `""" [autogenerated] ${isAuthRequired(modelName) ? '\n[auth required]' : ''}""" customData: Json`;
245
252
  }
246
253
  type += '}\n';
247
254
  return type;
@@ -308,10 +315,9 @@ function createSchema(typeDefsObj) {
308
315
  const whiteList = {
309
316
  // group: ['subscription', 'query'] // order - modelname , 'subscription' - resolver type
310
317
  }
311
- const userAuth = typeof sails.config.restographql?.authService === 'function' ? sails.config.restographql.authService : null;
312
318
 
313
- let modelsResolvers: {Query?: Object, Subscription?: Object} = { Query: {}};
314
- const { withFilter } = require("apollo-server");
319
+ let modelsResolvers: { Query?: Object, Subscription?: Object } = { Query: {} };
320
+ import { withFilter } from "apollo-server";
315
321
 
316
322
  /**
317
323
  * Патчит waterline criteria во время автогенерации
@@ -322,17 +328,17 @@ const { withFilter } = require("apollo-server");
322
328
  */
323
329
  function sanitizeCriteria(modelname, criteria) {
324
330
 
325
- if (sails.models[modelname].attributes.enable){
331
+ if (sails.models[modelname].attributes.enable) {
326
332
  criteria.enable = true;
327
333
  }
328
334
 
329
- if (sails.models[modelname].attributes.isDeleted){
335
+ if (sails.models[modelname].attributes.isDeleted) {
330
336
  criteria.isDeleted = false;
331
337
  }
332
338
 
333
339
  switch (modelname) {
334
340
  case 'dish':
335
- criteria.balance = {'!=': 0};
341
+ criteria.balance = { '!=': 0 };
336
342
  criteria.isDeleted = false;
337
343
  break;
338
344
  case 'group':
@@ -376,52 +382,81 @@ function addModelResolver(modelname) {
376
382
  models.add(modelname); // make schema Type for Model
377
383
  const methodName = firstLetterToLowerCase(modelName)
378
384
  let resolverQuery = {
379
- def: `""" autogenerated """ ${methodName}(criteria: Json): [${modelName}]`,
385
+ def: `""" [autogenerated] ${isAuthRequired(modelname) ? '\n[auth required]' : ''}""" ${methodName}(criteria: Json, skip: Int, limit: Int, sort: String): [${modelName}]`,
380
386
  fn: async function (parent, args, context) {
381
387
 
382
388
  let criteria = args.criteria || {};
383
389
  criteria = sanitizeCriteria(modelname, criteria);
384
390
 
385
391
  // If model has User field need auth
386
- if (sails.models[modelname].attributes.user) {
387
- if (userAuth) {
388
- let user = await userAuth(
389
- context.connectionParams.authorization
390
- );
391
- if (user.id) {
392
- criteria.user = user.id;
393
- } else return null;
392
+ if (isAuthRequired(modelName)) {
393
+ let auth = await JWTAuth.verify(
394
+ context.connectionParams.authorization
395
+ );
396
+
397
+ if (auth.userId && UserDevice.checkSession(auth.sessionId, auth.userId, { lastIP: "IP", userAgent: context.connectionParams["user-agent"] })) {
398
+ if (modelName.toLowerCase() === "user") {
399
+ criteria.id = auth.userId
400
+ } else {
401
+ criteria.user = auth.userId
402
+ }
394
403
  } else {
395
- return null;
404
+ throw 'Authorization failed'
396
405
  }
397
406
  }
398
407
 
399
- let query: any = { where: criteria};
408
+
409
+ let query: any;
410
+ if (criteria.where === undefined) {
411
+ query = { where: criteria }
412
+ } else {
413
+ query = criteria
414
+ }
415
+
400
416
  //sorting
401
- if (sails.models[modelname].attributes.order) {
402
- query.sort = 'order ASC'
417
+ if (sails.models[modelname].attributes.sortOrder) {
418
+ query.sort = 'sortOrder ASC'
403
419
  }
404
420
 
405
- let result = await sails.models[modelname].find(query);
406
421
 
407
- getEmitter().emit(`graphql-query-${modelname}`, result);
422
+ let ORMrequest = sails.models[modelname].find(query);
423
+
424
+ if (args.skip) {
425
+ ORMrequest.skip(args.skip)
426
+ }
427
+
428
+ if (args.limit) {
429
+ ORMrequest.limit(args.limit)
430
+ }
431
+
432
+ if (args.sort) {
433
+ ORMrequest.sort(args.sort)
434
+ } else {
435
+ if (sails.models[modelname].attributes.sortOrder) {
436
+ ORMrequest.sort('sortOrder ASC')
437
+ }
438
+ }
408
439
 
409
- //workTime filter
440
+ let result = await ORMrequest
410
441
 
411
- if (sails.models[modelname].attributes.workTime) {
442
+ emitter.emit(`graphql-query-${modelname}`, result);
443
+
444
+ //worktime filter
445
+
446
+ if (sails.models[modelname].attributes.worktime) {
412
447
  result = result.filter(record => {
413
- if (!record.workTime) return true;
448
+ if (!record.worktime) return true;
414
449
  try {
415
- return (WorkTimeValidator.isWorkNow({workTime: record.workTime})).workNow
450
+ return (WorkTimeValidator.isWorkNow({ worktime: record.worktime })).workNow
416
451
  } catch (error) {
417
- sails.log.error("Graphql > helper > error: ",error)
452
+ sails.log.error("Graphql > helper > error: ", error)
418
453
  }
419
454
  })
420
455
  }
421
456
 
422
457
  result.forEach(item => {
423
458
 
424
- getEmitter().emit(
459
+ emitter.emit(
425
460
  `http-api:before-send-${modelname.toLowerCase()}`,
426
461
  item
427
462
  );
@@ -431,106 +466,206 @@ function addModelResolver(modelname) {
431
466
  },
432
467
  };
433
468
  modelsResolvers.Query[methodName] = resolverQuery;
469
+
470
+
471
+ let resolverQueryCount = {
472
+ def: `""" [autogenerated] ${isAuthRequired(modelname) ? '\n[auth required]' : ''}""" ${methodName}Count(criteria: Json): Int`,
473
+ fn: async function (parent, args, context) {
474
+
475
+ let criteria = args.criteria || {};
476
+ criteria = sanitizeCriteria(modelname, criteria);
477
+
478
+ // If model has User field need auth
479
+ if (isAuthRequired(modelName)) {
480
+ let auth = await JWTAuth.verify(
481
+ context.connectionParams.authorization
482
+ );
483
+
484
+ if (auth.userId && UserDevice.checkSession(auth.sessionId, auth.userId, { lastIP: "IP", userAgent: context.connectionParams["user-agent"] })) {
485
+ if (modelName.toLowerCase() === "user") {
486
+ criteria.id = auth.userId
487
+ } else {
488
+ criteria.user = auth.userId
489
+ }
490
+ } else {
491
+ throw 'Authorization failed'
492
+ }
493
+ }
494
+
495
+
496
+ let query: any;
497
+ if (criteria.where === undefined) {
498
+ query = { where: criteria }
499
+ } else {
500
+ query = criteria
501
+ }
502
+
503
+
504
+
505
+ let ORMrequest = sails.models[modelname].find(query);
506
+
507
+ let result = await ORMrequest
508
+
509
+ //worktime filter
510
+ if (sails.models[modelname].attributes.worktime) {
511
+ result = result.filter(record => {
512
+ if (!record.worktime) return true;
513
+ try {
514
+ return (WorkTimeValidator.isWorkNow({ worktime: record.worktime })).workNow
515
+ } catch (error) {
516
+ sails.log.error("Graphql > helper > error: ", error)
517
+ }
518
+ })
519
+ }
520
+
521
+ return result.length;
522
+ },
523
+ };
524
+
525
+ modelsResolvers.Query[`${methodName}Count`] = resolverQueryCount;
526
+
434
527
  }
435
- // Model fields resolvers
436
- let resolvers = {};
437
- // iterate separate resolvers in model (type])
438
- Object.keys(sails.models[modelname].attributes).forEach((key) => {
439
- if (key.includes("__")) return;
440
- if (blackList.includes(`${modelName}.${key}`) || blackList.includes(`${key}`)) return;
441
- if (typeof sails.models[modelname].attributes[key] === 'function') return;
442
-
443
- if (sails.models[modelname].attributes[key].graphql) {
444
- if (sails.models[modelname].attributes[key].graphql.public === false)
445
- return;
446
- }
528
+ // Model fields resolvers
529
+ let resolvers = {};
530
+ // iterate separate resolvers in model (type])
531
+ Object.keys(sails.models[modelname].attributes).forEach((key) => {
532
+ if (key.includes("__")) return;
533
+ if (blackList.includes(`${modelName}.${key}`) || blackList.includes(`${key}`)) return;
534
+ if (typeof sails.models[modelname].attributes[key] === 'function') return;
535
+
536
+ if (sails.models[modelname].attributes[key].graphql) {
537
+ if (sails.models[modelname].attributes[key].graphql.public === false)
538
+ return;
539
+ }
447
540
 
448
- let modelAttribute = sails.models[modelname].attributes[key];
541
+ let modelAttribute = sails.models[modelname].attributes[key];
449
542
 
450
- if (modelAttribute.collection || modelAttribute.model) {
451
- let modelRelationType = modelAttribute.collection
452
- ? "collection"
453
- : "model";
543
+ if (modelAttribute.collection || modelAttribute.model) {
544
+ let modelRelationType = modelAttribute.collection
545
+ ? "collection"
546
+ : "model";
454
547
 
455
- let relationKey =
456
- modelAttribute.via !== undefined
457
- ? modelAttribute.via
458
- : "id";
548
+ let relationKey =
549
+ modelAttribute.via !== undefined
550
+ ? modelAttribute.via
551
+ : "id";
459
552
 
460
- let criteria = {};
461
- criteria = sanitizeCriteria(modelAttribute[modelRelationType], criteria);
553
+ let criteria = {};
554
+ criteria = sanitizeCriteria(modelAttribute[modelRelationType], criteria);
462
555
 
463
- switch (modelRelationType) {
464
- case "model":
465
- resolvers[key] = async (parent, args, context) => {
466
- criteria[relationKey] = parent[key];
467
- let result = await sails.models[modelAttribute[modelRelationType]].findOne(criteria);
556
+ switch (modelRelationType) {
557
+ case "model":
558
+ resolvers[key] = async (parent, args, context) => {
559
+ criteria[relationKey] = parent[key];
468
560
 
469
- // TODO: this need only for support legacy patching (discount)
470
- getEmitter().emit(
471
- `http-api:before-send-${modelAttribute.model.toLowerCase()}`,
472
- result
561
+ // Check access rights
562
+ if (isAuthRequired(modelAttribute[modelRelationType])) {
563
+ let auth = await JWTAuth.verify(
564
+ context.connectionParams.authorization
473
565
  );
474
566
 
475
- // celan if not work time
476
- if (result && result.workTime && !WorkTimeValidator.isWorkNow({workTime: result.workTime}).workNow) {
477
- result = null;
567
+ if (auth.userId && UserDevice.checkSession(auth.sessionId, auth.userId, { lastIP: "IP", userAgent: context.connectionParams["user-agent"] })) {
568
+ if (modelName.toLowerCase() === "user") {
569
+ criteria["id"] = auth.userId
570
+ } else {
571
+ criteria["user"] = auth.userId
572
+ }
573
+ } else {
574
+ throw 'Authorization failed'
478
575
  }
479
- };
480
-
481
- return;
482
- case "collection":
483
- resolvers[key] = async (parent, args, context) => {
576
+ }
484
577
 
578
+ let result = await sails.models[modelAttribute[modelRelationType]].findOne(criteria);
485
579
 
486
- let subcriteria: any = {};
580
+ // TODO: this need only for support legacy patching (discount)
581
+ emitter.emit(
582
+ `http-api:before-send-${modelAttribute.model.toLowerCase()}`,
583
+ result
584
+ );
487
585
 
488
- let subquery: any = { where: criteria};
489
- //sorting
490
- if (sails.models[modelname].attributes.order) {
491
- subquery.sort = 'order ASC'
492
- }
586
+ // celan if not work time
587
+ if (result && result.worktime && !WorkTimeValidator.isWorkNow({ worktime: result.worktime }).workNow) {
588
+ result = null;
589
+ }
590
+ return result;
591
+ };
493
592
 
494
- let result = (await sails.models[modelname].findOne({id: parent.id}).populate(key, subquery));
495
- result = result ? result[key] : null;
496
-
497
- // TODO: this need only for support legacy patching (discount)
498
- if (result && result.length){
499
- result.forEach(item => {
500
- getEmitter().emit(
501
- `http-api:before-send-${modelAttribute.collection.toLowerCase()}`,
502
- item
503
- );
504
- });
505
- }
593
+ // add virtual ids
594
+ resolvers[`${key}Id`] = async (parent, args, context) => {
595
+ return parent && parent[key];
596
+ };
597
+
598
+ return;
599
+ case "collection":
600
+ resolvers[key] = async (parent, args, context) => {
601
+ let parentPrimaryKey = sails.models[modelname].primaryKey
602
+ let criteria = {}
603
+ criteria[relationKey] = parent[parentPrimaryKey];
604
+
605
+ // Check access rights
606
+ if (isAuthRequired(modelAttribute[modelRelationType])) {
607
+ let auth = await JWTAuth.verify(
608
+ context.connectionParams.authorization
609
+ );
506
610
 
507
- if (sails.models[modelname].attributes.workTime && Array.isArray(result)) {
508
- result = result.filter(record => {
509
- if (!record.workTime) return true
510
- try {
511
- return (WorkTimeValidator.isWorkNow({workTime: record.workTime})).workNow
512
- } catch (error) {
513
- sails.log.error("Graphql > helper > error: ",error)
514
- }
515
- });
611
+ if (auth.userId && UserDevice.checkSession(auth.sessionId, auth.userId, { lastIP: "IP", userAgent: context.connectionParams["user-agent"] })) {
612
+ if (modelName.toLowerCase() === "user") {
613
+ criteria["id"] = auth.userId
614
+ } else {
615
+ criteria["user"] = auth.userId
616
+ }
617
+ } else {
618
+ throw 'Authorization failed'
516
619
  }
517
- return result;
518
- };
620
+ }
519
621
 
520
- return;
521
- default:
522
- // empty
523
- break;
524
- }
622
+ let result: any = null;
623
+
624
+
625
+ result = (await sails.models[modelname].findOne({ id: parent.id }).populate(key))[key];
626
+ if (result && sails.models[modelAttribute[modelRelationType]].attributes.sortOrder) {
627
+ result.sort((a, b) => a.sortOrder - b.sortOrder);
628
+ }
629
+
630
+ if (!result) result = []
631
+
632
+ // TODO: this need only for support legacy patching (discount)
633
+ if (result && result.length) {
634
+ result.forEach(item => {
635
+ emitter.emit(
636
+ `http-api:before-send-${modelAttribute.collection.toLowerCase()}`,
637
+ item
638
+ );
639
+ });
640
+ }
641
+
642
+ if (sails.models[modelAttribute[modelRelationType]].attributes.worktime && Array.isArray(result) && result.length > 0) {
643
+ result = result.filter(record => {
644
+ if (!record.worktime) return true
645
+ try {
646
+ return (WorkTimeValidator.isWorkNow({ worktime: record.worktime })).workNow
647
+ } catch (error) {
648
+ sails.log.error("Graphql > helper > error: ", error)
649
+ }
650
+ });
651
+ }
652
+
653
+ return result;
654
+ };
655
+
656
+ return;
657
+ default:
658
+ // empty
659
+ break;
525
660
  }
661
+ }
526
662
 
527
- resolvers[key] = async (parent, args, context) => {
528
- return parent && parent[key];
529
- };
530
- });
663
+ resolvers[key] = async (parent, args, context) => {
664
+ return parent && parent[key];
665
+ };
666
+ });
531
667
 
532
- console.log(modelName,resolvers)
533
- modelsResolvers[modelName] = resolvers;
668
+ modelsResolvers[modelName] = resolvers;
534
669
 
535
670
 
536
671
  // Subscription resolver
@@ -538,7 +673,7 @@ function addModelResolver(modelname) {
538
673
  models.add(modelname);
539
674
  const methodName = `${firstLetterToLowerCase(modelName)}`;
540
675
  let subscription = {
541
- def: `""" Generated """ ${methodName}(criteria: Json): ${modelName}`,
676
+ def: `""" [autogenerated] ${isAuthRequired(modelname) ? '\n[auth required]' : ''} """ ${methodName}(criteria: Json): ${modelName} `,
542
677
  fn: {
543
678
  subscribe: withFilter(
544
679
  (rootValue, args, context, info) =>
@@ -546,38 +681,42 @@ function addModelResolver(modelname) {
546
681
  async (payload, args, context, info) => {
547
682
 
548
683
  // For User models
549
- if (sails.models[modelname].attributes.user) {
550
- if (userAuth) {
551
- let user = await userAuth(
552
- context.connectionParams.authorization
553
- );
554
- if (user.id === payload.user){
555
- if (args.criteria) {
556
- checkCriteria(payload, args.criteria)
557
- } else {
558
- return true;
559
- }
560
- };
684
+ if (sails.models[modelname].attributes.user || modelname === 'user') {
685
+
686
+ let auth = await JWTAuth.verify(
687
+ context.connectionParams.authorization
688
+ );
689
+
690
+ if (!args.criteria) {
691
+ args.criteria = {}
692
+ }
693
+
694
+ if (auth.userId) {
695
+ if (modelName.toLowerCase() === "user") {
696
+ args.criteria.id = auth.userId
697
+ } else {
698
+ args.criteria.user = auth.userId
699
+ }
561
700
  } else {
562
- return false;
701
+ throw 'Authorization failed'
563
702
  }
564
703
  }
565
704
 
566
705
  return checkCriteria(payload, args.criteria)
567
-
706
+
568
707
  // Filter by waterline criteria
569
- function checkCriteria(payload: any, criteria: any): boolean{
708
+ function checkCriteria(payload: any, criteria: any): boolean {
570
709
 
571
710
  // For id's array
572
- if (Array.isArray(criteria) || typeof criteria === "string"){
573
- return (WLCriteria(payload, { where: { id: criteria }}).results).length > 0
711
+ if (Array.isArray(criteria) || typeof criteria === "string") {
712
+ return (WLCriteria(payload, { where: { id: criteria } }).results).length > 0
574
713
  }
575
714
 
576
715
  // Where cause
577
- if ( typeof criteria === 'object' && !Array.isArray(criteria) && criteria !== null ) {
716
+ if (typeof criteria === 'object' && !Array.isArray(criteria) && criteria !== null) {
578
717
  return (WLCriteria(payload, { where: criteria }).results).length > 0
579
718
  }
580
-
719
+
581
720
  return false
582
721
  }
583
722
 
@@ -605,23 +744,23 @@ function modelPublishExtend(modelname) {
605
744
  let modelName = sails.models[modelname].globalId;
606
745
 
607
746
  let afterCreate = sails.models[modelname].afterCreate;
608
- sails.models[modelname].afterCreate = async function (values, cb ) {
609
- await sails.models[modelname].publish(values.id);
610
- if (afterCreate) {
611
- afterCreate(values, cb);
612
- } else {
613
- cb();
614
- }
747
+ sails.models[modelname].afterCreate = async function (values, cb) {
748
+ await sails.models[modelname].publish(values.id);
749
+ if (afterCreate) {
750
+ afterCreate(values, cb);
751
+ } else {
752
+ cb();
753
+ }
615
754
  };
616
755
 
617
756
  let afterUpdate = sails.models[modelname].afterUpdate;
618
- sails.models[modelname].afterUpdate = async function (values, cb ) {
619
- await sails.models[modelname].publish(values.id);
620
- if (afterUpdate) {
621
- afterUpdate(values, cb);
622
- } else {
623
- cb();
624
- }
757
+ sails.models[modelname].afterUpdate = async function (values, cb) {
758
+ await sails.models[modelname].publish(values.id);
759
+ if (afterUpdate) {
760
+ afterUpdate(values, cb);
761
+ } else {
762
+ cb();
763
+ }
625
764
  };
626
765
 
627
766
  let modelPublishExtendObj = {
@@ -629,7 +768,7 @@ function modelPublishExtend(modelname) {
629
768
  let data = await sails.models[modelname].findOne(id);
630
769
  // `http-api:request-${modelAttribute.collection.toLowerCase()}model-list`,
631
770
 
632
- getEmitter().emit(`http-api:before-send-${modelname.toLowerCase()}`, data);
771
+ emitter.emit(`http-api:before-send-${modelname.toLowerCase()}`, data);
633
772
  sails.graphql.pubsub.publish(modelName, data);
634
773
  },
635
774
  };
@@ -637,6 +776,10 @@ function modelPublishExtend(modelname) {
637
776
  _.merge(sails.models[modelname], modelPublishExtendObj);
638
777
  }
639
778
 
779
+ function isAuthRequired(modelname: string): Boolean {
780
+ modelname = modelname.toLowerCase();
781
+ return sails.models[modelname].attributes.user !== undefined || modelname === 'user';
782
+ }
640
783
 
641
784
  export default {
642
785
  addModel,