@kalisio/kdk 2.6.3 → 2.6.5

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 (273) hide show
  1. package/core/api/hooks/hooks.model.js +1 -1
  2. package/extras/tours/pane.top.js +9 -0
  3. package/map/client/i18n/map_en.json +2 -1
  4. package/map/client/i18n/map_fr.json +2 -1
  5. package/package.json +1 -1
  6. package/test/api/core/test-log-2026-03-26.log +0 -0
  7. package/client/css/core.variables.scss +0 -72
  8. package/client/i18n/core_en.json +0 -744
  9. package/client/i18n/core_fr.json +0 -744
  10. package/client/i18n/map_en.json +0 -800
  11. package/client/i18n/map_fr.json +0 -800
  12. package/client/kdk.client.css +0 -47
  13. package/client/kdk.client.js +0 -41097
  14. package/client/kdk.client.map.css +0 -47
  15. package/client/kdk.client.map.js +0 -38182
  16. package/client/kdk.client.map.min.css +0 -1
  17. package/client/kdk.client.map.min.js +0 -27032
  18. package/client/kdk.client.min.css +0 -1
  19. package/client/kdk.client.min.js +0 -29074
  20. package/client/schemas/capture.create.json +0 -132
  21. package/client/schemas/catalog.update.json +0 -44
  22. package/client/schemas/messages.update.json +0 -16
  23. package/client/schemas/projects.create.json +0 -52
  24. package/client/schemas/projects.update.json +0 -52
  25. package/client/schemas/settings.update.json +0 -286
  26. package/client/schemas/tags.update.json +0 -35
  27. package/client/schemas/users.update-profile.json +0 -34
  28. package/coverage/base.css +0 -224
  29. package/coverage/block-navigation.js +0 -87
  30. package/coverage/core/api/application.js.html +0 -1864
  31. package/coverage/core/api/authentication.js.html +0 -907
  32. package/coverage/core/api/db.js.html +0 -817
  33. package/coverage/core/api/hooks/hooks.authentication.js.html +0 -139
  34. package/coverage/core/api/hooks/hooks.authorisations.js.html +0 -964
  35. package/coverage/core/api/hooks/hooks.logger.js.html +0 -163
  36. package/coverage/core/api/hooks/hooks.model.js.html +0 -967
  37. package/coverage/core/api/hooks/hooks.push.js.html +0 -268
  38. package/coverage/core/api/hooks/hooks.query.js.html +0 -910
  39. package/coverage/core/api/hooks/hooks.schemas.js.html +0 -298
  40. package/coverage/core/api/hooks/hooks.service.js.html +0 -319
  41. package/coverage/core/api/hooks/hooks.storage.js.html +0 -193
  42. package/coverage/core/api/hooks/hooks.tags.js.html +0 -253
  43. package/coverage/core/api/hooks/hooks.users.js.html +0 -676
  44. package/coverage/core/api/hooks/index.html +0 -281
  45. package/coverage/core/api/hooks/index.js.html +0 -115
  46. package/coverage/core/api/index.html +0 -176
  47. package/coverage/core/api/index.js.html +0 -148
  48. package/coverage/core/api/marshall.js.html +0 -448
  49. package/coverage/core/api/models/configurations.model.mongodb.js.html +0 -97
  50. package/coverage/core/api/models/index.html +0 -161
  51. package/coverage/core/api/models/messages.model.mongodb.js.html +0 -121
  52. package/coverage/core/api/models/tags.model.mongodb.js.html +0 -109
  53. package/coverage/core/api/models/users.model.mongodb.js.html +0 -115
  54. package/coverage/core/api/services/account/account.hooks.js.html +0 -208
  55. package/coverage/core/api/services/account/account.service.js.html +0 -436
  56. package/coverage/core/api/services/account/index.html +0 -131
  57. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  58. package/coverage/core/api/services/authorisations/authorisations.service.js.html +0 -520
  59. package/coverage/core/api/services/authorisations/index.html +0 -131
  60. package/coverage/core/api/services/configurations/configurations.hooks.js.html +0 -184
  61. package/coverage/core/api/services/configurations/index.html +0 -116
  62. package/coverage/core/api/services/databases/databases.hooks.js.html +0 -193
  63. package/coverage/core/api/services/databases/databases.service.js.html +0 -100
  64. package/coverage/core/api/services/databases/index.html +0 -131
  65. package/coverage/core/api/services/import-export/import-export.hooks.js.html +0 -184
  66. package/coverage/core/api/services/import-export/import-export.service.js.html +0 -118
  67. package/coverage/core/api/services/import-export/index.html +0 -131
  68. package/coverage/core/api/services/index.html +0 -116
  69. package/coverage/core/api/services/index.js.html +0 -727
  70. package/coverage/core/api/services/mailer/index.html +0 -131
  71. package/coverage/core/api/services/mailer/mailer.hooks.js.html +0 -190
  72. package/coverage/core/api/services/mailer/mailer.service.js.html +0 -118
  73. package/coverage/core/api/services/messages/index.html +0 -116
  74. package/coverage/core/api/services/messages/messages.hooks.js.html +0 -220
  75. package/coverage/core/api/services/push/index.html +0 -131
  76. package/coverage/core/api/services/push/push.hooks.js.html +0 -190
  77. package/coverage/core/api/services/push/push.service.js.html +0 -121
  78. package/coverage/core/api/services/storage/index.html +0 -131
  79. package/coverage/core/api/services/storage/storage.hooks.js.html +0 -190
  80. package/coverage/core/api/services/storage/storage.service.js.html +0 -172
  81. package/coverage/core/api/services/tags/index.html +0 -116
  82. package/coverage/core/api/services/tags/tags.hooks.js.html +0 -226
  83. package/coverage/core/api/services/users/index.html +0 -131
  84. package/coverage/core/api/services/users/users.hooks.js.html +0 -310
  85. package/coverage/core/api/services/users/users.service.js.html +0 -100
  86. package/coverage/core/common/errors.js.html +0 -88
  87. package/coverage/core/common/index.html +0 -191
  88. package/coverage/core/common/index.js.html +0 -115
  89. package/coverage/core/common/permissions.js.html +0 -742
  90. package/coverage/core/common/schema.js.html +0 -190
  91. package/coverage/core/common/utils.js.html +0 -226
  92. package/coverage/core/common/utils.offline.js.html +0 -199
  93. package/coverage/favicon.png +0 -0
  94. package/coverage/index.html +0 -506
  95. package/coverage/lcov-report/base.css +0 -224
  96. package/coverage/lcov-report/block-navigation.js +0 -87
  97. package/coverage/lcov-report/core/api/application.js.html +0 -1864
  98. package/coverage/lcov-report/core/api/authentication.js.html +0 -907
  99. package/coverage/lcov-report/core/api/db.js.html +0 -817
  100. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +0 -139
  101. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +0 -964
  102. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +0 -163
  103. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +0 -967
  104. package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +0 -268
  105. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +0 -910
  106. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +0 -298
  107. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +0 -319
  108. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +0 -193
  109. package/coverage/lcov-report/core/api/hooks/hooks.tags.js.html +0 -253
  110. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +0 -676
  111. package/coverage/lcov-report/core/api/hooks/index.html +0 -281
  112. package/coverage/lcov-report/core/api/hooks/index.js.html +0 -115
  113. package/coverage/lcov-report/core/api/index.html +0 -176
  114. package/coverage/lcov-report/core/api/index.js.html +0 -148
  115. package/coverage/lcov-report/core/api/marshall.js.html +0 -448
  116. package/coverage/lcov-report/core/api/models/configurations.model.mongodb.js.html +0 -97
  117. package/coverage/lcov-report/core/api/models/index.html +0 -161
  118. package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +0 -121
  119. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +0 -109
  120. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +0 -115
  121. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +0 -208
  122. package/coverage/lcov-report/core/api/services/account/account.service.js.html +0 -436
  123. package/coverage/lcov-report/core/api/services/account/index.html +0 -131
  124. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  125. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +0 -520
  126. package/coverage/lcov-report/core/api/services/authorisations/index.html +0 -131
  127. package/coverage/lcov-report/core/api/services/configurations/configurations.hooks.js.html +0 -184
  128. package/coverage/lcov-report/core/api/services/configurations/index.html +0 -116
  129. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +0 -193
  130. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +0 -100
  131. package/coverage/lcov-report/core/api/services/databases/index.html +0 -131
  132. package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +0 -184
  133. package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +0 -118
  134. package/coverage/lcov-report/core/api/services/import-export/index.html +0 -131
  135. package/coverage/lcov-report/core/api/services/index.html +0 -116
  136. package/coverage/lcov-report/core/api/services/index.js.html +0 -727
  137. package/coverage/lcov-report/core/api/services/mailer/index.html +0 -131
  138. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +0 -190
  139. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +0 -118
  140. package/coverage/lcov-report/core/api/services/messages/index.html +0 -116
  141. package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +0 -220
  142. package/coverage/lcov-report/core/api/services/push/index.html +0 -131
  143. package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +0 -190
  144. package/coverage/lcov-report/core/api/services/push/push.service.js.html +0 -121
  145. package/coverage/lcov-report/core/api/services/storage/index.html +0 -131
  146. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +0 -190
  147. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +0 -172
  148. package/coverage/lcov-report/core/api/services/tags/index.html +0 -116
  149. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +0 -226
  150. package/coverage/lcov-report/core/api/services/users/index.html +0 -131
  151. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +0 -310
  152. package/coverage/lcov-report/core/api/services/users/users.service.js.html +0 -100
  153. package/coverage/lcov-report/core/common/errors.js.html +0 -88
  154. package/coverage/lcov-report/core/common/index.html +0 -191
  155. package/coverage/lcov-report/core/common/index.js.html +0 -115
  156. package/coverage/lcov-report/core/common/permissions.js.html +0 -742
  157. package/coverage/lcov-report/core/common/schema.js.html +0 -190
  158. package/coverage/lcov-report/core/common/utils.js.html +0 -226
  159. package/coverage/lcov-report/core/common/utils.offline.js.html +0 -199
  160. package/coverage/lcov-report/favicon.png +0 -0
  161. package/coverage/lcov-report/index.html +0 -506
  162. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +0 -595
  163. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +0 -397
  164. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +0 -1309
  165. package/coverage/lcov-report/map/api/hooks/index.html +0 -161
  166. package/coverage/lcov-report/map/api/hooks/index.js.html +0 -94
  167. package/coverage/lcov-report/map/api/index.html +0 -131
  168. package/coverage/lcov-report/map/api/index.js.html +0 -139
  169. package/coverage/lcov-report/map/api/marshall.js.html +0 -178
  170. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +0 -106
  171. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +0 -202
  172. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +0 -196
  173. package/coverage/lcov-report/map/api/models/index.html +0 -176
  174. package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +0 -109
  175. package/coverage/lcov-report/map/api/models/styles.model.mongodb.js.html +0 -112
  176. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +0 -274
  177. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +0 -610
  178. package/coverage/lcov-report/map/api/services/alerts/index.html +0 -131
  179. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +0 -337
  180. package/coverage/lcov-report/map/api/services/catalog/index.html +0 -116
  181. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  182. package/coverage/lcov-report/map/api/services/daptiles/index.html +0 -116
  183. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +0 -316
  184. package/coverage/lcov-report/map/api/services/features/features.service.js.html +0 -544
  185. package/coverage/lcov-report/map/api/services/features/index.html +0 -131
  186. package/coverage/lcov-report/map/api/services/index.html +0 -116
  187. package/coverage/lcov-report/map/api/services/index.js.html +0 -1093
  188. package/coverage/lcov-report/map/api/services/projects/index.html +0 -116
  189. package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +0 -439
  190. package/coverage/lcov-report/map/api/services/styles/index.html +0 -116
  191. package/coverage/lcov-report/map/api/services/styles/styles.hooks.js.html +0 -211
  192. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +0 -466
  193. package/coverage/lcov-report/map/common/errors.js.html +0 -94
  194. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +0 -538
  195. package/coverage/lcov-report/map/common/grid.js.html +0 -1612
  196. package/coverage/lcov-report/map/common/index.html +0 -371
  197. package/coverage/lcov-report/map/common/index.js.html +0 -172
  198. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +0 -556
  199. package/coverage/lcov-report/map/common/moment-utils.js.html +0 -157
  200. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +0 -868
  201. package/coverage/lcov-report/map/common/opendap-utils.js.html +0 -823
  202. package/coverage/lcov-report/map/common/permissions.js.html +0 -130
  203. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +0 -418
  204. package/coverage/lcov-report/map/common/tms-utils.js.html +0 -271
  205. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +0 -364
  206. package/coverage/lcov-report/map/common/wcs-utils.js.html +0 -583
  207. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +0 -1033
  208. package/coverage/lcov-report/map/common/wfs-utils.js.html +0 -571
  209. package/coverage/lcov-report/map/common/wms-utils.js.html +0 -469
  210. package/coverage/lcov-report/map/common/wmts-utils.js.html +0 -544
  211. package/coverage/lcov-report/prettify.css +0 -1
  212. package/coverage/lcov-report/prettify.js +0 -2
  213. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  214. package/coverage/lcov-report/sorter.js +0 -196
  215. package/coverage/lcov.info +0 -11012
  216. package/coverage/map/api/hooks/hooks.catalog.js.html +0 -595
  217. package/coverage/map/api/hooks/hooks.features.js.html +0 -397
  218. package/coverage/map/api/hooks/hooks.query.js.html +0 -1309
  219. package/coverage/map/api/hooks/index.html +0 -161
  220. package/coverage/map/api/hooks/index.js.html +0 -94
  221. package/coverage/map/api/index.html +0 -131
  222. package/coverage/map/api/index.js.html +0 -139
  223. package/coverage/map/api/marshall.js.html +0 -178
  224. package/coverage/map/api/models/alerts.model.mongodb.js.html +0 -106
  225. package/coverage/map/api/models/catalog.model.mongodb.js.html +0 -202
  226. package/coverage/map/api/models/features.model.mongodb.js.html +0 -196
  227. package/coverage/map/api/models/index.html +0 -176
  228. package/coverage/map/api/models/projects.model.mongodb.js.html +0 -109
  229. package/coverage/map/api/models/styles.model.mongodb.js.html +0 -112
  230. package/coverage/map/api/services/alerts/alerts.hooks.js.html +0 -274
  231. package/coverage/map/api/services/alerts/alerts.service.js.html +0 -610
  232. package/coverage/map/api/services/alerts/index.html +0 -131
  233. package/coverage/map/api/services/catalog/catalog.hooks.js.html +0 -337
  234. package/coverage/map/api/services/catalog/index.html +0 -116
  235. package/coverage/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  236. package/coverage/map/api/services/daptiles/index.html +0 -116
  237. package/coverage/map/api/services/features/features.hooks.js.html +0 -316
  238. package/coverage/map/api/services/features/features.service.js.html +0 -544
  239. package/coverage/map/api/services/features/index.html +0 -131
  240. package/coverage/map/api/services/index.html +0 -116
  241. package/coverage/map/api/services/index.js.html +0 -1093
  242. package/coverage/map/api/services/projects/index.html +0 -116
  243. package/coverage/map/api/services/projects/projects.hooks.js.html +0 -439
  244. package/coverage/map/api/services/styles/index.html +0 -116
  245. package/coverage/map/api/services/styles/styles.hooks.js.html +0 -211
  246. package/coverage/map/common/dynamic-grid-source.js.html +0 -466
  247. package/coverage/map/common/errors.js.html +0 -94
  248. package/coverage/map/common/geotiff-grid-source.js.html +0 -538
  249. package/coverage/map/common/grid.js.html +0 -1612
  250. package/coverage/map/common/index.html +0 -371
  251. package/coverage/map/common/index.js.html +0 -172
  252. package/coverage/map/common/meteo-model-grid-source.js.html +0 -556
  253. package/coverage/map/common/moment-utils.js.html +0 -157
  254. package/coverage/map/common/opendap-grid-source.js.html +0 -868
  255. package/coverage/map/common/opendap-utils.js.html +0 -823
  256. package/coverage/map/common/permissions.js.html +0 -130
  257. package/coverage/map/common/time-based-grid-source.js.html +0 -418
  258. package/coverage/map/common/tms-utils.js.html +0 -271
  259. package/coverage/map/common/wcs-grid-source.js.html +0 -364
  260. package/coverage/map/common/wcs-utils.js.html +0 -583
  261. package/coverage/map/common/weacast-grid-source.js.html +0 -1033
  262. package/coverage/map/common/wfs-utils.js.html +0 -571
  263. package/coverage/map/common/wms-utils.js.html +0 -469
  264. package/coverage/map/common/wmts-utils.js.html +0 -544
  265. package/coverage/prettify.css +0 -1
  266. package/coverage/prettify.js +0 -2
  267. package/coverage/sort-arrow-sprite.png +0 -0
  268. package/coverage/sorter.js +0 -196
  269. package/coverage/tmp/coverage-222524-1765963609350-0.json +0 -1
  270. package/coverage/tmp/coverage-222536-1765963609335-0.json +0 -1
  271. package/coverage/tmp/coverage-222547-1765963609324-0.json +0 -1
  272. package/coverage/tmp/coverage-222559-1765963609309-0.json +0 -1
  273. package/coverage/tmp/coverage-222566-1765963609278-0.json +0 -1
@@ -1,742 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for core/common/permissions.js</title>
7
- <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../../prettify.css" />
9
- <link rel="stylesheet" href="../../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
- <meta name="viewport" content="width=device-width, initial-scale=1" />
12
- <style type='text/css'>
13
- .coverage-summary .sorter {
14
- background-image: url(../../sort-arrow-sprite.png);
15
- }
16
- </style>
17
- </head>
18
-
19
- <body>
20
- <div class='wrapper'>
21
- <div class='pad1'>
22
- <h1><a href="../../index.html">All files</a> / <a href="index.html">core/common</a> permissions.js</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">66.21% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>145/219</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">72.22% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>13/18</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">35.29% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>6/17</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">66.21% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>145/219</span>
50
- </div>
51
-
52
-
53
- </div>
54
- <p class="quiet">
55
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
- </p>
57
- <template id="filterTemplate">
58
- <div class="quiet">
59
- Filter:
60
- <input oninput="onInput()" type="search" id="fileSearch">
61
- </div>
62
- </template>
63
- </div>
64
- <div class='status-line medium'></div>
65
- <pre><table class="coverage">
66
- <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
- <a name='L2'></a><a href='#L2'>2</a>
68
- <a name='L3'></a><a href='#L3'>3</a>
69
- <a name='L4'></a><a href='#L4'>4</a>
70
- <a name='L5'></a><a href='#L5'>5</a>
71
- <a name='L6'></a><a href='#L6'>6</a>
72
- <a name='L7'></a><a href='#L7'>7</a>
73
- <a name='L8'></a><a href='#L8'>8</a>
74
- <a name='L9'></a><a href='#L9'>9</a>
75
- <a name='L10'></a><a href='#L10'>10</a>
76
- <a name='L11'></a><a href='#L11'>11</a>
77
- <a name='L12'></a><a href='#L12'>12</a>
78
- <a name='L13'></a><a href='#L13'>13</a>
79
- <a name='L14'></a><a href='#L14'>14</a>
80
- <a name='L15'></a><a href='#L15'>15</a>
81
- <a name='L16'></a><a href='#L16'>16</a>
82
- <a name='L17'></a><a href='#L17'>17</a>
83
- <a name='L18'></a><a href='#L18'>18</a>
84
- <a name='L19'></a><a href='#L19'>19</a>
85
- <a name='L20'></a><a href='#L20'>20</a>
86
- <a name='L21'></a><a href='#L21'>21</a>
87
- <a name='L22'></a><a href='#L22'>22</a>
88
- <a name='L23'></a><a href='#L23'>23</a>
89
- <a name='L24'></a><a href='#L24'>24</a>
90
- <a name='L25'></a><a href='#L25'>25</a>
91
- <a name='L26'></a><a href='#L26'>26</a>
92
- <a name='L27'></a><a href='#L27'>27</a>
93
- <a name='L28'></a><a href='#L28'>28</a>
94
- <a name='L29'></a><a href='#L29'>29</a>
95
- <a name='L30'></a><a href='#L30'>30</a>
96
- <a name='L31'></a><a href='#L31'>31</a>
97
- <a name='L32'></a><a href='#L32'>32</a>
98
- <a name='L33'></a><a href='#L33'>33</a>
99
- <a name='L34'></a><a href='#L34'>34</a>
100
- <a name='L35'></a><a href='#L35'>35</a>
101
- <a name='L36'></a><a href='#L36'>36</a>
102
- <a name='L37'></a><a href='#L37'>37</a>
103
- <a name='L38'></a><a href='#L38'>38</a>
104
- <a name='L39'></a><a href='#L39'>39</a>
105
- <a name='L40'></a><a href='#L40'>40</a>
106
- <a name='L41'></a><a href='#L41'>41</a>
107
- <a name='L42'></a><a href='#L42'>42</a>
108
- <a name='L43'></a><a href='#L43'>43</a>
109
- <a name='L44'></a><a href='#L44'>44</a>
110
- <a name='L45'></a><a href='#L45'>45</a>
111
- <a name='L46'></a><a href='#L46'>46</a>
112
- <a name='L47'></a><a href='#L47'>47</a>
113
- <a name='L48'></a><a href='#L48'>48</a>
114
- <a name='L49'></a><a href='#L49'>49</a>
115
- <a name='L50'></a><a href='#L50'>50</a>
116
- <a name='L51'></a><a href='#L51'>51</a>
117
- <a name='L52'></a><a href='#L52'>52</a>
118
- <a name='L53'></a><a href='#L53'>53</a>
119
- <a name='L54'></a><a href='#L54'>54</a>
120
- <a name='L55'></a><a href='#L55'>55</a>
121
- <a name='L56'></a><a href='#L56'>56</a>
122
- <a name='L57'></a><a href='#L57'>57</a>
123
- <a name='L58'></a><a href='#L58'>58</a>
124
- <a name='L59'></a><a href='#L59'>59</a>
125
- <a name='L60'></a><a href='#L60'>60</a>
126
- <a name='L61'></a><a href='#L61'>61</a>
127
- <a name='L62'></a><a href='#L62'>62</a>
128
- <a name='L63'></a><a href='#L63'>63</a>
129
- <a name='L64'></a><a href='#L64'>64</a>
130
- <a name='L65'></a><a href='#L65'>65</a>
131
- <a name='L66'></a><a href='#L66'>66</a>
132
- <a name='L67'></a><a href='#L67'>67</a>
133
- <a name='L68'></a><a href='#L68'>68</a>
134
- <a name='L69'></a><a href='#L69'>69</a>
135
- <a name='L70'></a><a href='#L70'>70</a>
136
- <a name='L71'></a><a href='#L71'>71</a>
137
- <a name='L72'></a><a href='#L72'>72</a>
138
- <a name='L73'></a><a href='#L73'>73</a>
139
- <a name='L74'></a><a href='#L74'>74</a>
140
- <a name='L75'></a><a href='#L75'>75</a>
141
- <a name='L76'></a><a href='#L76'>76</a>
142
- <a name='L77'></a><a href='#L77'>77</a>
143
- <a name='L78'></a><a href='#L78'>78</a>
144
- <a name='L79'></a><a href='#L79'>79</a>
145
- <a name='L80'></a><a href='#L80'>80</a>
146
- <a name='L81'></a><a href='#L81'>81</a>
147
- <a name='L82'></a><a href='#L82'>82</a>
148
- <a name='L83'></a><a href='#L83'>83</a>
149
- <a name='L84'></a><a href='#L84'>84</a>
150
- <a name='L85'></a><a href='#L85'>85</a>
151
- <a name='L86'></a><a href='#L86'>86</a>
152
- <a name='L87'></a><a href='#L87'>87</a>
153
- <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a>
173
- <a name='L108'></a><a href='#L108'>108</a>
174
- <a name='L109'></a><a href='#L109'>109</a>
175
- <a name='L110'></a><a href='#L110'>110</a>
176
- <a name='L111'></a><a href='#L111'>111</a>
177
- <a name='L112'></a><a href='#L112'>112</a>
178
- <a name='L113'></a><a href='#L113'>113</a>
179
- <a name='L114'></a><a href='#L114'>114</a>
180
- <a name='L115'></a><a href='#L115'>115</a>
181
- <a name='L116'></a><a href='#L116'>116</a>
182
- <a name='L117'></a><a href='#L117'>117</a>
183
- <a name='L118'></a><a href='#L118'>118</a>
184
- <a name='L119'></a><a href='#L119'>119</a>
185
- <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a>
187
- <a name='L122'></a><a href='#L122'>122</a>
188
- <a name='L123'></a><a href='#L123'>123</a>
189
- <a name='L124'></a><a href='#L124'>124</a>
190
- <a name='L125'></a><a href='#L125'>125</a>
191
- <a name='L126'></a><a href='#L126'>126</a>
192
- <a name='L127'></a><a href='#L127'>127</a>
193
- <a name='L128'></a><a href='#L128'>128</a>
194
- <a name='L129'></a><a href='#L129'>129</a>
195
- <a name='L130'></a><a href='#L130'>130</a>
196
- <a name='L131'></a><a href='#L131'>131</a>
197
- <a name='L132'></a><a href='#L132'>132</a>
198
- <a name='L133'></a><a href='#L133'>133</a>
199
- <a name='L134'></a><a href='#L134'>134</a>
200
- <a name='L135'></a><a href='#L135'>135</a>
201
- <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a>
217
- <a name='L152'></a><a href='#L152'>152</a>
218
- <a name='L153'></a><a href='#L153'>153</a>
219
- <a name='L154'></a><a href='#L154'>154</a>
220
- <a name='L155'></a><a href='#L155'>155</a>
221
- <a name='L156'></a><a href='#L156'>156</a>
222
- <a name='L157'></a><a href='#L157'>157</a>
223
- <a name='L158'></a><a href='#L158'>158</a>
224
- <a name='L159'></a><a href='#L159'>159</a>
225
- <a name='L160'></a><a href='#L160'>160</a>
226
- <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a>
228
- <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a>
230
- <a name='L165'></a><a href='#L165'>165</a>
231
- <a name='L166'></a><a href='#L166'>166</a>
232
- <a name='L167'></a><a href='#L167'>167</a>
233
- <a name='L168'></a><a href='#L168'>168</a>
234
- <a name='L169'></a><a href='#L169'>169</a>
235
- <a name='L170'></a><a href='#L170'>170</a>
236
- <a name='L171'></a><a href='#L171'>171</a>
237
- <a name='L172'></a><a href='#L172'>172</a>
238
- <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a>
240
- <a name='L175'></a><a href='#L175'>175</a>
241
- <a name='L176'></a><a href='#L176'>176</a>
242
- <a name='L177'></a><a href='#L177'>177</a>
243
- <a name='L178'></a><a href='#L178'>178</a>
244
- <a name='L179'></a><a href='#L179'>179</a>
245
- <a name='L180'></a><a href='#L180'>180</a>
246
- <a name='L181'></a><a href='#L181'>181</a>
247
- <a name='L182'></a><a href='#L182'>182</a>
248
- <a name='L183'></a><a href='#L183'>183</a>
249
- <a name='L184'></a><a href='#L184'>184</a>
250
- <a name='L185'></a><a href='#L185'>185</a>
251
- <a name='L186'></a><a href='#L186'>186</a>
252
- <a name='L187'></a><a href='#L187'>187</a>
253
- <a name='L188'></a><a href='#L188'>188</a>
254
- <a name='L189'></a><a href='#L189'>189</a>
255
- <a name='L190'></a><a href='#L190'>190</a>
256
- <a name='L191'></a><a href='#L191'>191</a>
257
- <a name='L192'></a><a href='#L192'>192</a>
258
- <a name='L193'></a><a href='#L193'>193</a>
259
- <a name='L194'></a><a href='#L194'>194</a>
260
- <a name='L195'></a><a href='#L195'>195</a>
261
- <a name='L196'></a><a href='#L196'>196</a>
262
- <a name='L197'></a><a href='#L197'>197</a>
263
- <a name='L198'></a><a href='#L198'>198</a>
264
- <a name='L199'></a><a href='#L199'>199</a>
265
- <a name='L200'></a><a href='#L200'>200</a>
266
- <a name='L201'></a><a href='#L201'>201</a>
267
- <a name='L202'></a><a href='#L202'>202</a>
268
- <a name='L203'></a><a href='#L203'>203</a>
269
- <a name='L204'></a><a href='#L204'>204</a>
270
- <a name='L205'></a><a href='#L205'>205</a>
271
- <a name='L206'></a><a href='#L206'>206</a>
272
- <a name='L207'></a><a href='#L207'>207</a>
273
- <a name='L208'></a><a href='#L208'>208</a>
274
- <a name='L209'></a><a href='#L209'>209</a>
275
- <a name='L210'></a><a href='#L210'>210</a>
276
- <a name='L211'></a><a href='#L211'>211</a>
277
- <a name='L212'></a><a href='#L212'>212</a>
278
- <a name='L213'></a><a href='#L213'>213</a>
279
- <a name='L214'></a><a href='#L214'>214</a>
280
- <a name='L215'></a><a href='#L215'>215</a>
281
- <a name='L216'></a><a href='#L216'>216</a>
282
- <a name='L217'></a><a href='#L217'>217</a>
283
- <a name='L218'></a><a href='#L218'>218</a>
284
- <a name='L219'></a><a href='#L219'>219</a>
285
- <a name='L220'></a><a href='#L220'>220</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
286
- <span class="cline-any cline-yes">1x</span>
287
- <span class="cline-any cline-yes">1x</span>
288
- <span class="cline-any cline-yes">1x</span>
289
- <span class="cline-any cline-yes">1x</span>
290
- <span class="cline-any cline-yes">1x</span>
291
- <span class="cline-any cline-yes">1x</span>
292
- <span class="cline-any cline-yes">1x</span>
293
- <span class="cline-any cline-yes">1x</span>
294
- <span class="cline-any cline-yes">1x</span>
295
- <span class="cline-any cline-yes">1x</span>
296
- <span class="cline-any cline-yes">1x</span>
297
- <span class="cline-any cline-yes">1x</span>
298
- <span class="cline-any cline-yes">1x</span>
299
- <span class="cline-any cline-yes">1x</span>
300
- <span class="cline-any cline-yes">1x</span>
301
- <span class="cline-any cline-yes">1x</span>
302
- <span class="cline-any cline-yes">1x</span>
303
- <span class="cline-any cline-yes">1x</span>
304
- <span class="cline-any cline-yes">1x</span>
305
- <span class="cline-any cline-yes">1x</span>
306
- <span class="cline-any cline-yes">1x</span>
307
- <span class="cline-any cline-yes">1x</span>
308
- <span class="cline-any cline-yes">1x</span>
309
- <span class="cline-any cline-yes">1x</span>
310
- <span class="cline-any cline-yes">1x</span>
311
- <span class="cline-any cline-yes">1x</span>
312
- <span class="cline-any cline-yes">1x</span>
313
- <span class="cline-any cline-yes">1x</span>
314
- <span class="cline-any cline-yes">1x</span>
315
- <span class="cline-any cline-yes">1x</span>
316
- <span class="cline-any cline-yes">1x</span>
317
- <span class="cline-any cline-no">&nbsp;</span>
318
- <span class="cline-any cline-no">&nbsp;</span>
319
- <span class="cline-any cline-no">&nbsp;</span>
320
- <span class="cline-any cline-no">&nbsp;</span>
321
- <span class="cline-any cline-no">&nbsp;</span>
322
- <span class="cline-any cline-no">&nbsp;</span>
323
- <span class="cline-any cline-no">&nbsp;</span>
324
- <span class="cline-any cline-no">&nbsp;</span>
325
- <span class="cline-any cline-no">&nbsp;</span>
326
- <span class="cline-any cline-no">&nbsp;</span>
327
- <span class="cline-any cline-no">&nbsp;</span>
328
- <span class="cline-any cline-no">&nbsp;</span>
329
- <span class="cline-any cline-no">&nbsp;</span>
330
- <span class="cline-any cline-yes">1x</span>
331
- <span class="cline-any cline-yes">1x</span>
332
- <span class="cline-any cline-yes">1x</span>
333
- <span class="cline-any cline-yes">23x</span>
334
- <span class="cline-any cline-yes">23x</span>
335
- <span class="cline-any cline-yes">23x</span>
336
- <span class="cline-any cline-yes">23x</span>
337
- <span class="cline-any cline-yes">23x</span>
338
- <span class="cline-any cline-yes">23x</span>
339
- <span class="cline-any cline-yes">23x</span>
340
- <span class="cline-any cline-yes">23x</span>
341
- <span class="cline-any cline-yes">23x</span>
342
- <span class="cline-any cline-yes">23x</span>
343
- <span class="cline-any cline-yes">23x</span>
344
- <span class="cline-any cline-yes">23x</span>
345
- <span class="cline-any cline-yes">23x</span>
346
- <span class="cline-any cline-yes">23x</span>
347
- <span class="cline-any cline-yes">23x</span>
348
- <span class="cline-any cline-yes">23x</span>
349
- <span class="cline-any cline-yes">22x</span>
350
- <span class="cline-any cline-yes">22x</span>
351
- <span class="cline-any cline-yes">22x</span>
352
- <span class="cline-any cline-yes">22x</span>
353
- <span class="cline-any cline-yes">22x</span>
354
- <span class="cline-any cline-yes">22x</span>
355
- <span class="cline-any cline-yes">22x</span>
356
- <span class="cline-any cline-yes">22x</span>
357
- <span class="cline-any cline-yes">22x</span>
358
- <span class="cline-any cline-yes">22x</span>
359
- <span class="cline-any cline-yes">22x</span>
360
- <span class="cline-any cline-yes">22x</span>
361
- <span class="cline-any cline-yes">22x</span>
362
- <span class="cline-any cline-yes">22x</span>
363
- <span class="cline-any cline-yes">22x</span>
364
- <span class="cline-any cline-yes">22x</span>
365
- <span class="cline-any cline-yes">22x</span>
366
- <span class="cline-any cline-yes">22x</span>
367
- <span class="cline-any cline-yes">22x</span>
368
- <span class="cline-any cline-yes">23x</span>
369
- <span class="cline-any cline-yes">1x</span>
370
- <span class="cline-any cline-yes">1x</span>
371
- <span class="cline-any cline-yes">1x</span>
372
- <span class="cline-any cline-yes">23x</span>
373
- <span class="cline-any cline-yes">23x</span>
374
- <span class="cline-any cline-yes">23x</span>
375
- <span class="cline-any cline-yes">23x</span>
376
- <span class="cline-any cline-yes">23x</span>
377
- <span class="cline-any cline-yes">23x</span>
378
- <span class="cline-any cline-yes">23x</span>
379
- <span class="cline-any cline-yes">23x</span>
380
- <span class="cline-any cline-yes">23x</span>
381
- <span class="cline-any cline-yes">23x</span>
382
- <span class="cline-any cline-yes">23x</span>
383
- <span class="cline-any cline-yes">3x</span>
384
- <span class="cline-any cline-no">&nbsp;</span>
385
- <span class="cline-any cline-no">&nbsp;</span>
386
- <span class="cline-any cline-yes">3x</span>
387
- <span class="cline-any cline-yes">23x</span>
388
- <span class="cline-any cline-yes">23x</span>
389
- <span class="cline-any cline-yes">23x</span>
390
- <span class="cline-any cline-yes">23x</span>
391
- <span class="cline-any cline-yes">1x</span>
392
- <span class="cline-any cline-yes">1x</span>
393
- <span class="cline-any cline-yes">5x</span>
394
- <span class="cline-any cline-yes">1x</span>
395
- <span class="cline-any cline-yes">1x</span>
396
- <span class="cline-any cline-yes">5x</span>
397
- <span class="cline-any cline-yes">1x</span>
398
- <span class="cline-any cline-yes">1x</span>
399
- <span class="cline-any cline-no">&nbsp;</span>
400
- <span class="cline-any cline-no">&nbsp;</span>
401
- <span class="cline-any cline-yes">1x</span>
402
- <span class="cline-any cline-yes">1x</span>
403
- <span class="cline-any cline-yes">4x</span>
404
- <span class="cline-any cline-yes">4x</span>
405
- <span class="cline-any cline-yes">4x</span>
406
- <span class="cline-any cline-yes">4x</span>
407
- <span class="cline-any cline-yes">4x</span>
408
- <span class="cline-any cline-yes">4x</span>
409
- <span class="cline-any cline-yes">4x</span>
410
- <span class="cline-any cline-yes">4x</span>
411
- <span class="cline-any cline-yes">4x</span>
412
- <span class="cline-any cline-yes">1x</span>
413
- <span class="cline-any cline-yes">4x</span>
414
- <span class="cline-any cline-yes">1x</span>
415
- <span class="cline-any cline-yes">1x</span>
416
- <span class="cline-any cline-yes">3x</span>
417
- <span class="cline-any cline-yes">3x</span>
418
- <span class="cline-any cline-yes">3x</span>
419
- <span class="cline-any cline-yes">3x</span>
420
- <span class="cline-any cline-yes">3x</span>
421
- <span class="cline-any cline-yes">3x</span>
422
- <span class="cline-any cline-yes">3x</span>
423
- <span class="cline-any cline-yes">3x</span>
424
- <span class="cline-any cline-yes">3x</span>
425
- <span class="cline-any cline-yes">3x</span>
426
- <span class="cline-any cline-yes">3x</span>
427
- <span class="cline-any cline-yes">1x</span>
428
- <span class="cline-any cline-yes">1x</span>
429
- <span class="cline-any cline-yes">1x</span>
430
- <span class="cline-any cline-no">&nbsp;</span>
431
- <span class="cline-any cline-no">&nbsp;</span>
432
- <span class="cline-any cline-no">&nbsp;</span>
433
- <span class="cline-any cline-no">&nbsp;</span>
434
- <span class="cline-any cline-no">&nbsp;</span>
435
- <span class="cline-any cline-no">&nbsp;</span>
436
- <span class="cline-any cline-no">&nbsp;</span>
437
- <span class="cline-any cline-no">&nbsp;</span>
438
- <span class="cline-any cline-no">&nbsp;</span>
439
- <span class="cline-any cline-no">&nbsp;</span>
440
- <span class="cline-any cline-no">&nbsp;</span>
441
- <span class="cline-any cline-no">&nbsp;</span>
442
- <span class="cline-any cline-no">&nbsp;</span>
443
- <span class="cline-any cline-no">&nbsp;</span>
444
- <span class="cline-any cline-no">&nbsp;</span>
445
- <span class="cline-any cline-no">&nbsp;</span>
446
- <span class="cline-any cline-no">&nbsp;</span>
447
- <span class="cline-any cline-no">&nbsp;</span>
448
- <span class="cline-any cline-no">&nbsp;</span>
449
- <span class="cline-any cline-yes">1x</span>
450
- <span class="cline-any cline-yes">1x</span>
451
- <span class="cline-any cline-yes">1x</span>
452
- <span class="cline-any cline-yes">1x</span>
453
- <span class="cline-any cline-no">&nbsp;</span>
454
- <span class="cline-any cline-no">&nbsp;</span>
455
- <span class="cline-any cline-no">&nbsp;</span>
456
- <span class="cline-any cline-no">&nbsp;</span>
457
- <span class="cline-any cline-no">&nbsp;</span>
458
- <span class="cline-any cline-no">&nbsp;</span>
459
- <span class="cline-any cline-no">&nbsp;</span>
460
- <span class="cline-any cline-yes">1x</span>
461
- <span class="cline-any cline-no">&nbsp;</span>
462
- <span class="cline-any cline-no">&nbsp;</span>
463
- <span class="cline-any cline-no">&nbsp;</span>
464
- <span class="cline-any cline-no">&nbsp;</span>
465
- <span class="cline-any cline-no">&nbsp;</span>
466
- <span class="cline-any cline-no">&nbsp;</span>
467
- <span class="cline-any cline-no">&nbsp;</span>
468
- <span class="cline-any cline-yes">1x</span>
469
- <span class="cline-any cline-yes">1x</span>
470
- <span class="cline-any cline-no">&nbsp;</span>
471
- <span class="cline-any cline-no">&nbsp;</span>
472
- <span class="cline-any cline-no">&nbsp;</span>
473
- <span class="cline-any cline-no">&nbsp;</span>
474
- <span class="cline-any cline-no">&nbsp;</span>
475
- <span class="cline-any cline-yes">1x</span>
476
- <span class="cline-any cline-yes">1x</span>
477
- <span class="cline-any cline-no">&nbsp;</span>
478
- <span class="cline-any cline-no">&nbsp;</span>
479
- <span class="cline-any cline-no">&nbsp;</span>
480
- <span class="cline-any cline-no">&nbsp;</span>
481
- <span class="cline-any cline-no">&nbsp;</span>
482
- <span class="cline-any cline-no">&nbsp;</span>
483
- <span class="cline-any cline-no">&nbsp;</span>
484
- <span class="cline-any cline-yes">1x</span>
485
- <span class="cline-any cline-yes">1x</span>
486
- <span class="cline-any cline-no">&nbsp;</span>
487
- <span class="cline-any cline-no">&nbsp;</span>
488
- <span class="cline-any cline-yes">1x</span>
489
- <span class="cline-any cline-yes">1x</span>
490
- <span class="cline-any cline-no">&nbsp;</span>
491
- <span class="cline-any cline-no">&nbsp;</span>
492
- <span class="cline-any cline-yes">1x</span>
493
- <span class="cline-any cline-yes">1x</span>
494
- <span class="cline-any cline-no">&nbsp;</span>
495
- <span class="cline-any cline-no">&nbsp;</span>
496
- <span class="cline-any cline-no">&nbsp;</span>
497
- <span class="cline-any cline-no">&nbsp;</span>
498
- <span class="cline-any cline-yes">1x</span>
499
- <span class="cline-any cline-yes">1x</span>
500
- <span class="cline-any cline-no">&nbsp;</span>
501
- <span class="cline-any cline-no">&nbsp;</span>
502
- <span class="cline-any cline-no">&nbsp;</span>
503
- <span class="cline-any cline-no">&nbsp;</span>
504
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import _ from 'lodash'
505
- import { AbilityBuilder, Ability, createAliasResolver } from '@casl/ability'
506
- import { toMongoQuery } from '@casl/mongoose'
507
- &nbsp;
508
- // Define some alias to simplify ability definitions
509
- const resolveAction = createAliasResolver({
510
- update: ['patch'],
511
- read: ['get', 'find'],
512
- remove: ['delete'],
513
- all: ['read', 'create', 'update', 'remove']
514
- })
515
- &nbsp;
516
- export const Roles = {
517
- member: 0,
518
- manager: 1,
519
- owner: 2
520
- }
521
- &nbsp;
522
- export const RoleNames = [
523
- 'member',
524
- 'manager',
525
- 'owner'
526
- ]
527
- &nbsp;
528
- // Hooks that can be added to customize abilities computation
529
- let hooks = []
530
- &nbsp;
531
- // Get the unique global symbol to store resource type / context on a resource object
532
- export const RESOURCE_TYPE = 'type'
533
- export const RESOURCE_TYPE_KEY = Symbol.for(RESOURCE_TYPE)
534
- &nbsp;
535
- export <span class="fstat-no" title="function not covered" >function defineResourceRules (subject, resource, resourceService, can) {</span>
536
- <span class="cstat-no" title="statement not covered" > const role = Roles[resource.permissions]</span>
537
- <span class="cstat-no" title="statement not covered" ></span>
538
- <span class="cstat-no" title="statement not covered" > if (role &gt;= Roles.member) {</span>
539
- <span class="cstat-no" title="statement not covered" > can('read', resourceService, { _id: resource._id })</span>
540
- <span class="cstat-no" title="statement not covered" > }</span>
541
- <span class="cstat-no" title="statement not covered" > if (role &gt;= Roles.manager) {</span>
542
- <span class="cstat-no" title="statement not covered" > can('update', resourceService, { _id: resource._id })</span>
543
- <span class="cstat-no" title="statement not covered" > can(['create', 'remove'], 'authorisations', { resource: resource._id })</span>
544
- <span class="cstat-no" title="statement not covered" > }</span>
545
- <span class="cstat-no" title="statement not covered" > if (role &gt;= Roles.owner) {</span>
546
- <span class="cstat-no" title="statement not covered" > can('remove', resourceService, { _id: resource._id })</span>
547
- <span class="cstat-no" title="statement not covered" > }</span>
548
- <span class="cstat-no" title="statement not covered" >}</span>
549
- &nbsp;
550
- // Hook computing default abilities for a given user
551
- export function defineUserAbilities (subject, can, cannot) {
552
- // Allow user registration
553
- can('service', 'users')
554
- can('create', 'users')
555
- // Verification email, reset password, etc.
556
- can('service', 'account')
557
- can(['create', 'verifyEmail'], 'account')
558
- // Allow import/export
559
- can('service', 'import-export')
560
- can('create', 'import-export')
561
- // Allow push registration
562
- can('service', 'push')
563
- can('create', 'push')
564
- // Allow tag management
565
- can('service', 'tags')
566
- can('read', 'tags')
567
- if (subject &amp;&amp; subject._id) {
568
- // Read user profiles for authorizing
569
- can('read', 'users')
570
- // Update user profile and destroy it
571
- can(['update', 'remove'], 'users', { _id: subject._id })
572
- // Access authorisation service, then rights will be granted on a per-resource basis
573
- can('service', 'authorisations')
574
- // Access storage service, then rights will be granted on a per-resource basis
575
- can('service', 'storage')
576
- // This is for the user avatar
577
- // take care that the storage service uses 'id' as input but produces _id as output
578
- can('create', 'storage', { id: 'avatars/' + subject._id.toString() })
579
- can('create', 'storage', { id: 'avatars/' + subject._id.toString() + '.thumbnail' })
580
- can(['createMultipartUpload', 'completeMultipartUpload', 'uploadPart', 'putObject'], 'storage', { id: 'avatars/' + subject._id.toString() })
581
- can(['createMultipartUpload', 'completeMultipartUpload', 'uploadPart', 'putObject'], 'storage', { id: 'avatars/' + subject._id.toString() + '.thumbnail' })
582
- can('remove', 'storage', { _id: 'avatars/' + subject._id.toString() })
583
- can('remove', 'storage', { _id: 'avatars/' + subject._id.toString() + '.thumbnail' })
584
- // Avatar is part of user profiles so that they can be read by any
585
- can('read', 'storage', { _id: { $regex: '^avatars/*' } })
586
- }
587
- }
588
- &nbsp;
589
- // Compute abilities for a given user
590
- export async function defineAbilities (subject, ...args) {
591
- const { build, can, cannot } = new AbilityBuilder(Ability)
592
- &nbsp;
593
- // Run registered hooks providing any additional arguments used to handle complex use cases
594
- await Promise.all(hooks.map(async hook =&gt; {
595
- await hook(subject, can, cannot, ...args)
596
- }))
597
- &nbsp;
598
- // CASL cannot infer the object type from the object itself so we need
599
- // to tell it how he can find the object type, i.e. service name.
600
- return build({
601
- detectSubjectType: resource =&gt; {
602
- if (!resource || typeof resource === 'string') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
603
- <span class="cstat-no" title="statement not covered" > return resource</span>
604
- <span class="cstat-no" title="statement not covered" > }</span>
605
- return resource[RESOURCE_TYPE_KEY]
606
- },
607
- resolveAction
608
- })
609
- }
610
- &nbsp;
611
- defineAbilities.registerHook = function (hook) {
612
- if (!hooks.includes(hook)) {
613
- hooks.push(hook)
614
- }
615
- }
616
- &nbsp;
617
- defineAbilities.unregisterHook = <span class="fstat-no" title="function not covered" >function (hook) {</span>
618
- <span class="cstat-no" title="statement not covered" > hooks = hooks.filter(registeredHook =&gt; registeredHook !== hook)</span>
619
- <span class="cstat-no" title="statement not covered" >}</span>
620
- &nbsp;
621
- export function hasServiceAbilities (abilities, service) {
622
- if (!abilities) <span class="branch-0 cbranch-no" title="branch not covered" >return false</span>
623
- // The unique identifier of a service is its path not its name.
624
- // Indeed we have for instance a 'groups' service in each context
625
- // Take care that in client we have the service path while on server we have the actual object
626
- const path = typeof service === 'string' <span class="branch-0 cbranch-no" title="branch not covered" >? service </span>: service.getPath()
627
- // */groups will allow to access any groups service in any context
628
- const allContextsPath = _.replace(path, /^.*\//, '*/')
629
- return abilities.can('service', path) ||
630
- abilities.can('service', `*/${path}`) ||
631
- abilities.can('service', allContextsPath)
632
- }
633
- &nbsp;
634
- export function hasResourceAbilities (abilities, operation, resourceType, context, resource) {
635
- if (!abilities) <span class="branch-0 cbranch-no" title="branch not covered" >return false</span>
636
- // Create a shallow copy adding context and type
637
- const object = Object.assign({}, resource)
638
- object[RESOURCE_TYPE_KEY] = resourceType
639
- // Add a virtual context to take it into account for object having no link to it
640
- if (context) <span class="branch-0 cbranch-no" title="branch not covered" >object.context = (typeof context === 'object' ? context._id.toString() : context.toString())</span>
641
- &nbsp;
642
- const result = abilities.can(operation, object)
643
- &nbsp;
644
- return result
645
- }
646
- &nbsp;
647
- // Utility function used to remove the virtual context from query
648
- export <span class="fstat-no" title="function not covered" >function removeContext (query) {</span>
649
- <span class="cstat-no" title="statement not covered" > _.forOwn(query, (value, key) =&gt; {</span>
650
- <span class="cstat-no" title="statement not covered" > // Process current attributes or recurse</span>
651
- <span class="cstat-no" title="statement not covered" > // Take care to nested fields like 'field._id'</span>
652
- <span class="cstat-no" title="statement not covered" > if (key === 'context') {</span>
653
- <span class="cstat-no" title="statement not covered" > delete query.context</span>
654
- <span class="cstat-no" title="statement not covered" > } else if (Array.isArray(value)) {</span>
655
- <span class="cstat-no" title="statement not covered" > value.forEach(item =&gt; removeContext(item))</span>
656
- <span class="cstat-no" title="statement not covered" > // Remove empty objects from array</span>
657
- <span class="cstat-no" title="statement not covered" > // _.remove(value, item =&gt; _.isEmpty(item))</span>
658
- <span class="cstat-no" title="statement not covered" > // Remove empty arrays from query</span>
659
- <span class="cstat-no" title="statement not covered" > if (_.isEmpty(value)) delete query[key]</span>
660
- <span class="cstat-no" title="statement not covered" > } else if (typeof value === 'object') {</span>
661
- <span class="cstat-no" title="statement not covered" > removeContext(value)</span>
662
- <span class="cstat-no" title="statement not covered" > // Remove empty objects from query</span>
663
- <span class="cstat-no" title="statement not covered" > if (_.isEmpty(value)) delete query[key]</span>
664
- <span class="cstat-no" title="statement not covered" > }</span>
665
- <span class="cstat-no" title="statement not covered" > })</span>
666
- <span class="cstat-no" title="statement not covered" > return query</span>
667
- <span class="cstat-no" title="statement not covered" >}</span>
668
- &nbsp;
669
- // Get the query used to filter the objects according to given abilities
670
- // A null query indicates that access should not be granted
671
- export <span class="fstat-no" title="function not covered" >function getQueryForAbilities (abilities, operation, resourceType) {</span>
672
- <span class="cstat-no" title="statement not covered" > if (!abilities) return null</span>
673
- <span class="cstat-no" title="statement not covered" ></span>
674
- <span class="cstat-no" title="statement not covered" > const query = toMongoQuery(abilities, resourceType, operation)</span>
675
- <span class="cstat-no" title="statement not covered" > // Remove any context to avoid taking it into account because it is not really stored on objects</span>
676
- <span class="cstat-no" title="statement not covered" > // We clone the object here because of references to the abilities rules (see https://github.com/kalisio/kdk/issues/384)</span>
677
- <span class="cstat-no" title="statement not covered" > return (query ? removeContext(_.cloneDeep(query)) : null)</span>
678
- <span class="cstat-no" title="statement not covered" >}</span>
679
- &nbsp;
680
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function buildSubjectsQueryForResource (resourceScope, resourceId, role) {</span></span>
681
- <span class="cstat-no" title="statement not covered" > const query = { [resourceScope]: { $elemMatch: { _id: resourceId } } }</span>
682
- <span class="cstat-no" title="statement not covered" > if (role) {</span>
683
- <span class="cstat-no" title="statement not covered" > _.set(query[resourceScope], '$elemMatch.permissions', (typeof role === 'string' ? role : RoleNames[role]))</span>
684
- <span class="cstat-no" title="statement not covered" > }</span>
685
- <span class="cstat-no" title="statement not covered" > return query</span>
686
- <span class="cstat-no" title="statement not covered" >}</span>
687
- &nbsp;
688
- export <span class="fstat-no" title="function not covered" >function findSubjectsForResource (subjectService, resourceScope, resourceId, role) {</span>
689
- <span class="cstat-no" title="statement not covered" > // Build the query</span>
690
- <span class="cstat-no" title="statement not covered" > const query = buildSubjectsQueryForResource(resourceScope, resourceId, role)</span>
691
- <span class="cstat-no" title="statement not covered" > // Execute the query</span>
692
- <span class="cstat-no" title="statement not covered" > return subjectService.find({ query })</span>
693
- <span class="cstat-no" title="statement not covered" >}</span>
694
- &nbsp;
695
- export <span class="fstat-no" title="function not covered" >function countSubjectsForResource (subjectService, resourceScope, resourceId, role) {</span>
696
- <span class="cstat-no" title="statement not covered" > // Build the query</span>
697
- <span class="cstat-no" title="statement not covered" > const query = buildSubjectsQueryForResource(resourceScope, resourceId, role)</span>
698
- <span class="cstat-no" title="statement not covered" > // Indicate we'd only like to count</span>
699
- <span class="cstat-no" title="statement not covered" > query.$limit = 0</span>
700
- <span class="cstat-no" title="statement not covered" > // Execute the query</span>
701
- <span class="cstat-no" title="statement not covered" > return subjectService.find({ query })</span>
702
- <span class="cstat-no" title="statement not covered" >}</span>
703
- &nbsp;
704
- export <span class="fstat-no" title="function not covered" >function isSeniorRole (roleName, juniorName) {</span>
705
- <span class="cstat-no" title="statement not covered" > return Roles[roleName] &gt;= Roles[juniorName]</span>
706
- <span class="cstat-no" title="statement not covered" >}</span>
707
- &nbsp;
708
- export <span class="fstat-no" title="function not covered" >function isJuniorRole (roleName, seniorName) {</span>
709
- <span class="cstat-no" title="statement not covered" > return Roles[roleName] &lt; Roles[seniorName]</span>
710
- <span class="cstat-no" title="statement not covered" >}</span>
711
- &nbsp;
712
- export <span class="fstat-no" title="function not covered" >function getSeniorRoles (roleName) {</span>
713
- <span class="cstat-no" title="statement not covered" > const seniorRoles = []</span>
714
- <span class="cstat-no" title="statement not covered" > _.forEach(Roles, role =&gt; { if (Roles[roleName] &lt; role) seniorRoles.push(RoleNames[role]) })</span>
715
- <span class="cstat-no" title="statement not covered" > return seniorRoles</span>
716
- <span class="cstat-no" title="statement not covered" >}</span>
717
- &nbsp;
718
- export <span class="fstat-no" title="function not covered" >function getJuniorRoles (roleName) {</span>
719
- <span class="cstat-no" title="statement not covered" > const juniorRoles = []</span>
720
- <span class="cstat-no" title="statement not covered" > _.forEach(Roles, role =&gt; { if (Roles[roleName] &gt;= role) juniorRoles.push(RoleNames[role]) })</span>
721
- <span class="cstat-no" title="statement not covered" > return juniorRoles</span>
722
- <span class="cstat-no" title="statement not covered" >}</span>
723
- &nbsp;</pre></td></tr></table></pre>
724
-
725
- <div class='push'></div><!-- for sticky footer -->
726
- </div><!-- /wrapper -->
727
- <div class='footer quiet pad2 space-top1 center small'>
728
- Code coverage generated by
729
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
730
- at 2025-12-17T09:26:49.744Z
731
- </div>
732
- <script src="../../prettify.js"></script>
733
- <script>
734
- window.onload = function () {
735
- prettyPrint();
736
- };
737
- </script>
738
- <script src="../../sorter.js"></script>
739
- <script src="../../block-navigation.js"></script>
740
- </body>
741
- </html>
742
-