@budibase/worker 2.1.45 → 2.1.46-alpha.0

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 (209) hide show
  1. package/__mocks__/aws-sdk.ts +15 -0
  2. package/__mocks__/oauth.ts +57 -0
  3. package/coverage/clover.xml +2167 -0
  4. package/coverage/coverage-final.json +78 -0
  5. package/coverage/lcov-report/base.css +224 -0
  6. package/coverage/lcov-report/block-navigation.js +87 -0
  7. package/coverage/lcov-report/favicon.png +0 -0
  8. package/coverage/lcov-report/index.html +431 -0
  9. package/coverage/lcov-report/prettify.css +1 -0
  10. package/coverage/lcov-report/prettify.js +2 -0
  11. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  12. package/coverage/lcov-report/sorter.js +196 -0
  13. package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +925 -0
  14. package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +1405 -0
  15. package/coverage/lcov-report/src/api/controllers/global/email.ts.html +196 -0
  16. package/coverage/lcov-report/src/api/controllers/global/index.html +236 -0
  17. package/coverage/lcov-report/src/api/controllers/global/license.ts.html +187 -0
  18. package/coverage/lcov-report/src/api/controllers/global/roles.ts.html +283 -0
  19. package/coverage/lcov-report/src/api/controllers/global/self.ts.html +577 -0
  20. package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +316 -0
  21. package/coverage/lcov-report/src/api/controllers/global/users.ts.html +799 -0
  22. package/coverage/lcov-report/src/api/controllers/global/workspaces.ts.html +244 -0
  23. package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +148 -0
  24. package/coverage/lcov-report/src/api/controllers/system/environment.ts.html +124 -0
  25. package/coverage/lcov-report/src/api/controllers/system/index.html +191 -0
  26. package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +124 -0
  27. package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +124 -0
  28. package/coverage/lcov-report/src/api/controllers/system/status.ts.html +133 -0
  29. package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +154 -0
  30. package/coverage/lcov-report/src/api/index.html +116 -0
  31. package/coverage/lcov-report/src/api/index.ts.html +583 -0
  32. package/coverage/lcov-report/src/api/routes/global/auth.ts.html +349 -0
  33. package/coverage/lcov-report/src/api/routes/global/configs.ts.html +457 -0
  34. package/coverage/lcov-report/src/api/routes/global/email.ts.html +193 -0
  35. package/coverage/lcov-report/src/api/routes/global/index.html +236 -0
  36. package/coverage/lcov-report/src/api/routes/global/license.ts.html +124 -0
  37. package/coverage/lcov-report/src/api/routes/global/roles.ts.html +133 -0
  38. package/coverage/lcov-report/src/api/routes/global/self.ts.html +139 -0
  39. package/coverage/lcov-report/src/api/routes/global/templates.ts.html +196 -0
  40. package/coverage/lcov-report/src/api/routes/global/users.ts.html +433 -0
  41. package/coverage/lcov-report/src/api/routes/global/workspaces.ts.html +196 -0
  42. package/coverage/lcov-report/src/api/routes/index.html +116 -0
  43. package/coverage/lcov-report/src/api/routes/index.ts.html +196 -0
  44. package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +142 -0
  45. package/coverage/lcov-report/src/api/routes/system/environment.ts.html +109 -0
  46. package/coverage/lcov-report/src/api/routes/system/index.html +191 -0
  47. package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +142 -0
  48. package/coverage/lcov-report/src/api/routes/system/restore.ts.html +109 -0
  49. package/coverage/lcov-report/src/api/routes/system/status.ts.html +109 -0
  50. package/coverage/lcov-report/src/api/routes/system/tenants.ts.html +124 -0
  51. package/coverage/lcov-report/src/api/routes/validation/index.html +131 -0
  52. package/coverage/lcov-report/src/api/routes/validation/index.ts.html +88 -0
  53. package/coverage/lcov-report/src/api/routes/validation/users.ts.html +235 -0
  54. package/coverage/lcov-report/src/constants/index.html +116 -0
  55. package/coverage/lcov-report/src/constants/index.ts.html +613 -0
  56. package/coverage/lcov-report/src/constants/templates/index.html +116 -0
  57. package/coverage/lcov-report/src/constants/templates/index.ts.html +316 -0
  58. package/coverage/lcov-report/src/db/index.html +116 -0
  59. package/coverage/lcov-report/src/db/index.ts.html +115 -0
  60. package/coverage/lcov-report/src/environment.ts.html +373 -0
  61. package/coverage/lcov-report/src/index.html +131 -0
  62. package/coverage/lcov-report/src/index.ts.html +394 -0
  63. package/coverage/lcov-report/src/middleware/cloudRestricted.ts.html +139 -0
  64. package/coverage/lcov-report/src/middleware/index.html +116 -0
  65. package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +145 -0
  66. package/coverage/lcov-report/src/migrations/functions/index.html +116 -0
  67. package/coverage/lcov-report/src/migrations/index.html +116 -0
  68. package/coverage/lcov-report/src/migrations/index.ts.html +271 -0
  69. package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +262 -0
  70. package/coverage/lcov-report/src/sdk/accounts/index.html +131 -0
  71. package/coverage/lcov-report/src/sdk/accounts/index.ts.html +88 -0
  72. package/coverage/lcov-report/src/sdk/index.html +116 -0
  73. package/coverage/lcov-report/src/sdk/index.ts.html +106 -0
  74. package/coverage/lcov-report/src/sdk/users/events.ts.html +577 -0
  75. package/coverage/lcov-report/src/sdk/users/index.html +146 -0
  76. package/coverage/lcov-report/src/sdk/users/index.ts.html +88 -0
  77. package/coverage/lcov-report/src/sdk/users/users.ts.html +1942 -0
  78. package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +1051 -0
  79. package/coverage/lcov-report/src/tests/api/accounts.ts.html +160 -0
  80. package/coverage/lcov-report/src/tests/api/auth.ts.html +220 -0
  81. package/coverage/lcov-report/src/tests/api/base.ts.html +133 -0
  82. package/coverage/lcov-report/src/tests/api/configs.ts.html +226 -0
  83. package/coverage/lcov-report/src/tests/api/email.ts.html +148 -0
  84. package/coverage/lcov-report/src/tests/api/environment.ts.html +130 -0
  85. package/coverage/lcov-report/src/tests/api/index.html +296 -0
  86. package/coverage/lcov-report/src/tests/api/index.ts.html +205 -0
  87. package/coverage/lcov-report/src/tests/api/migrations.ts.html +151 -0
  88. package/coverage/lcov-report/src/tests/api/restore.ts.html +127 -0
  89. package/coverage/lcov-report/src/tests/api/self.ts.html +163 -0
  90. package/coverage/lcov-report/src/tests/api/status.ts.html +121 -0
  91. package/coverage/lcov-report/src/tests/api/tenants.ts.html +130 -0
  92. package/coverage/lcov-report/src/tests/api/users.ts.html +511 -0
  93. package/coverage/lcov-report/src/tests/controllers.ts.html +100 -0
  94. package/coverage/lcov-report/src/tests/index.html +146 -0
  95. package/coverage/lcov-report/src/tests/index.ts.html +139 -0
  96. package/coverage/lcov-report/src/tests/mocks/email.js.html +115 -0
  97. package/coverage/lcov-report/src/tests/mocks/index.html +131 -0
  98. package/coverage/lcov-report/src/tests/mocks/index.ts.html +106 -0
  99. package/coverage/lcov-report/src/tests/structures/configs.ts.html +313 -0
  100. package/coverage/lcov-report/src/tests/structures/groups.ts.html +118 -0
  101. package/coverage/lcov-report/src/tests/structures/index.html +161 -0
  102. package/coverage/lcov-report/src/tests/structures/index.ts.html +151 -0
  103. package/coverage/lcov-report/src/tests/structures/users.ts.html +196 -0
  104. package/coverage/lcov-report/src/utilities/appService.ts.html +181 -0
  105. package/coverage/lcov-report/src/utilities/email.ts.html +850 -0
  106. package/coverage/lcov-report/src/utilities/fileSystem.ts.html +100 -0
  107. package/coverage/lcov-report/src/utilities/index.html +206 -0
  108. package/coverage/lcov-report/src/utilities/index.ts.html +112 -0
  109. package/coverage/lcov-report/src/utilities/redis.ts.html +424 -0
  110. package/coverage/lcov-report/src/utilities/templates.ts.html +232 -0
  111. package/coverage/lcov-report/src/utilities/users.ts.html +133 -0
  112. package/coverage/lcov.info +3989 -0
  113. package/jest.config.ts +29 -0
  114. package/package.json +14 -24
  115. package/scripts/localdomain.js +33 -7
  116. package/src/api/controllers/global/auth.ts +51 -43
  117. package/src/api/controllers/global/{configs.js → configs.ts} +119 -114
  118. package/src/api/controllers/global/{email.js → email.ts} +6 -5
  119. package/src/api/controllers/global/roles.ts +66 -0
  120. package/src/api/controllers/global/self.ts +2 -2
  121. package/src/api/controllers/global/users.ts +6 -3
  122. package/src/api/controllers/global/{workspaces.js → workspaces.ts} +15 -18
  123. package/src/api/controllers/system/{environment.js → environment.ts} +3 -2
  124. package/src/api/controllers/system/restore.ts +1 -1
  125. package/src/api/controllers/system/{status.js → status.ts} +4 -3
  126. package/src/api/controllers/system/tenants.ts +8 -51
  127. package/src/api/index.ts +31 -8
  128. package/src/api/routes/global/{auth.js → auth.ts} +31 -48
  129. package/src/api/routes/global/{configs.js → configs.ts} +22 -23
  130. package/src/api/routes/global/{email.js → email.ts} +9 -10
  131. package/src/api/routes/global/license.ts +1 -1
  132. package/src/api/routes/global/roles.ts +16 -0
  133. package/src/api/routes/global/self.ts +2 -2
  134. package/src/api/routes/global/templates.ts +4 -4
  135. package/src/api/routes/global/tests/auth.spec.ts +134 -64
  136. package/src/api/routes/global/tests/configs.spec.ts +34 -35
  137. package/src/api/routes/global/tests/email.spec.ts +4 -3
  138. package/src/api/routes/global/tests/license.spec.ts +31 -0
  139. package/src/api/routes/global/tests/realEmail.spec.ts +2 -3
  140. package/src/api/routes/global/tests/roles.spec.ts +27 -0
  141. package/src/api/routes/global/tests/self.spec.ts +3 -4
  142. package/src/api/routes/global/tests/templates.spec.ts +35 -0
  143. package/src/api/routes/global/tests/users.spec.ts +79 -46
  144. package/src/api/routes/global/tests/workspaces.spec.ts +29 -0
  145. package/src/api/routes/global/{users.js → users.ts} +28 -26
  146. package/src/api/routes/global/{workspaces.js → workspaces.ts} +9 -10
  147. package/src/api/routes/index.ts +2 -1
  148. package/src/api/routes/system/accounts.ts +1 -1
  149. package/src/api/routes/system/environment.ts +8 -0
  150. package/src/api/routes/system/migrations.ts +1 -1
  151. package/src/api/routes/system/restore.ts +1 -1
  152. package/src/api/routes/system/status.ts +8 -0
  153. package/src/api/routes/system/tenants.ts +13 -0
  154. package/src/api/routes/system/tests/accounts.spec.ts +5 -6
  155. package/src/api/routes/system/tests/environment.spec.ts +29 -0
  156. package/src/api/routes/system/tests/migrations.spec.ts +63 -0
  157. package/src/api/routes/system/tests/restore.spec.ts +36 -0
  158. package/src/api/routes/system/tests/status.spec.ts +48 -0
  159. package/src/api/routes/system/tests/tenants.spec.ts +61 -0
  160. package/src/api/routes/validation/users.ts +3 -3
  161. package/src/constants/{index.js → index.ts} +57 -64
  162. package/src/constants/templates/{index.js → index.ts} +23 -19
  163. package/src/db/index.ts +10 -0
  164. package/src/environment.ts +9 -7
  165. package/src/index.ts +15 -16
  166. package/src/middleware/{cloudRestricted.js → cloudRestricted.ts} +5 -4
  167. package/src/middleware/tests/tenancy.spec.ts +73 -0
  168. package/src/sdk/users/users.ts +28 -15
  169. package/src/tests/TestConfiguration.ts +99 -50
  170. package/src/tests/api/accounts.ts +5 -8
  171. package/src/tests/api/auth.ts +3 -6
  172. package/src/tests/api/base.ts +16 -0
  173. package/src/tests/api/configs.ts +15 -8
  174. package/src/tests/api/email.ts +3 -6
  175. package/src/tests/api/environment.ts +15 -0
  176. package/src/tests/api/index.ts +15 -0
  177. package/src/tests/api/migrations.ts +22 -0
  178. package/src/tests/api/restore.ts +14 -0
  179. package/src/tests/api/self.ts +11 -6
  180. package/src/tests/api/status.ts +12 -0
  181. package/src/tests/api/tenants.ts +15 -0
  182. package/src/tests/api/users.ts +38 -6
  183. package/src/tests/controllers.ts +5 -0
  184. package/src/tests/index.ts +5 -1
  185. package/{scripts/jestSetup.js → src/tests/jestSetup.ts} +12 -3
  186. package/src/tests/structures/{configs.js → configs.ts} +11 -11
  187. package/src/tests/structures/index.ts +5 -3
  188. package/src/tests/structures/users.ts +1 -0
  189. package/src/utilities/appService.ts +32 -0
  190. package/src/utilities/{email.js → email.ts} +78 -45
  191. package/src/utilities/fileSystem.ts +5 -0
  192. package/src/utilities/{index.js → index.ts} +1 -1
  193. package/src/utilities/{redis.js → redis.ts} +29 -24
  194. package/src/utilities/templates.ts +49 -0
  195. package/src/utilities/users.ts +16 -0
  196. package/tsconfig.build.json +2 -3
  197. package/tsconfig.json +3 -1
  198. package/src/api/controllers/global/roles.js +0 -68
  199. package/src/api/routes/global/roles.js +0 -12
  200. package/src/api/routes/system/environment.js +0 -8
  201. package/src/api/routes/system/status.js +0 -8
  202. package/src/api/routes/system/tenants.js +0 -12
  203. package/src/db/index.js +0 -11
  204. package/src/tests/controllers.js +0 -7
  205. package/src/tests/structures/accounts.ts +0 -24
  206. package/src/utilities/appService.js +0 -33
  207. package/src/utilities/fileSystem.js +0 -5
  208. package/src/utilities/templates.js +0 -49
  209. package/src/utilities/users.js +0 -17
@@ -0,0 +1,1405 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/api/controllers/global/configs.ts</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">src/api/controllers/global</a> configs.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">69.27% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>133/192</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">61.95% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>57/92</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">72% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>18/25</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">68.15% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>122/179</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>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">17x</span>
507
+ <span class="cline-any cline-yes">17x</span>
508
+ <span class="cline-any cline-yes">17x</span>
509
+ <span class="cline-any cline-yes">17x</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-neutral">&nbsp;</span>
512
+ <span class="cline-any cline-neutral">&nbsp;</span>
513
+ <span class="cline-any cline-neutral">&nbsp;</span>
514
+ <span class="cline-any cline-neutral">&nbsp;</span>
515
+ <span class="cline-any cline-neutral">&nbsp;</span>
516
+ <span class="cline-any cline-yes">17x</span>
517
+ <span class="cline-any cline-yes">17x</span>
518
+ <span class="cline-any cline-neutral">&nbsp;</span>
519
+ <span class="cline-any cline-neutral">&nbsp;</span>
520
+ <span class="cline-any cline-neutral">&nbsp;</span>
521
+ <span class="cline-any cline-neutral">&nbsp;</span>
522
+ <span class="cline-any cline-neutral">&nbsp;</span>
523
+ <span class="cline-any cline-neutral">&nbsp;</span>
524
+ <span class="cline-any cline-neutral">&nbsp;</span>
525
+ <span class="cline-any cline-neutral">&nbsp;</span>
526
+ <span class="cline-any cline-neutral">&nbsp;</span>
527
+ <span class="cline-any cline-neutral">&nbsp;</span>
528
+ <span class="cline-any cline-yes">41x</span>
529
+ <span class="cline-any cline-yes">41x</span>
530
+ <span class="cline-any cline-yes">41x</span>
531
+ <span class="cline-any cline-neutral">&nbsp;</span>
532
+ <span class="cline-any cline-neutral">&nbsp;</span>
533
+ <span class="cline-any cline-yes">41x</span>
534
+ <span class="cline-any cline-yes">6x</span>
535
+ <span class="cline-any cline-neutral">&nbsp;</span>
536
+ <span class="cline-any cline-neutral">&nbsp;</span>
537
+ <span class="cline-any cline-yes">41x</span>
538
+ <span class="cline-any cline-yes">41x</span>
539
+ <span class="cline-any cline-yes">35x</span>
540
+ <span class="cline-any cline-neutral">&nbsp;</span>
541
+ <span class="cline-any cline-yes">14x</span>
542
+ <span class="cline-any cline-yes">14x</span>
543
+ <span class="cline-any cline-neutral">&nbsp;</span>
544
+ <span class="cline-any cline-neutral">&nbsp;</span>
545
+ <span class="cline-any cline-yes">4x</span>
546
+ <span class="cline-any cline-yes">4x</span>
547
+ <span class="cline-any cline-yes">4x</span>
548
+ <span class="cline-any cline-yes">2x</span>
549
+ <span class="cline-any cline-neutral">&nbsp;</span>
550
+ <span class="cline-any cline-yes">4x</span>
551
+ <span class="cline-any cline-neutral">&nbsp;</span>
552
+ <span class="cline-any cline-neutral">&nbsp;</span>
553
+ <span class="cline-any cline-yes">6x</span>
554
+ <span class="cline-any cline-yes">6x</span>
555
+ <span class="cline-any cline-yes">6x</span>
556
+ <span class="cline-any cline-yes">4x</span>
557
+ <span class="cline-any cline-neutral">&nbsp;</span>
558
+ <span class="cline-any cline-yes">6x</span>
559
+ <span class="cline-any cline-neutral">&nbsp;</span>
560
+ <span class="cline-any cline-neutral">&nbsp;</span>
561
+ <span class="cline-any cline-neutral">&nbsp;</span>
562
+ <span class="cline-any cline-yes">11x</span>
563
+ <span class="cline-any cline-yes">11x</span>
564
+ <span class="cline-any cline-yes">11x</span>
565
+ <span class="cline-any cline-yes">1x</span>
566
+ <span class="cline-any cline-neutral">&nbsp;</span>
567
+ <span class="cline-any cline-neutral">&nbsp;</span>
568
+ <span class="cline-any cline-neutral">&nbsp;</span>
569
+ <span class="cline-any cline-yes">11x</span>
570
+ <span class="cline-any cline-yes">11x</span>
571
+ <span class="cline-any cline-yes">1x</span>
572
+ <span class="cline-any cline-neutral">&nbsp;</span>
573
+ <span class="cline-any cline-neutral">&nbsp;</span>
574
+ <span class="cline-any cline-neutral">&nbsp;</span>
575
+ <span class="cline-any cline-yes">11x</span>
576
+ <span class="cline-any cline-yes">11x</span>
577
+ <span class="cline-any cline-neutral">&nbsp;</span>
578
+ <span class="cline-any cline-neutral">&nbsp;</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-neutral">&nbsp;</span>
581
+ <span class="cline-any cline-yes">1x</span>
582
+ <span class="cline-any cline-neutral">&nbsp;</span>
583
+ <span class="cline-any cline-yes">11x</span>
584
+ <span class="cline-any cline-neutral">&nbsp;</span>
585
+ <span class="cline-any cline-neutral">&nbsp;</span>
586
+ <span class="cline-any cline-neutral">&nbsp;</span>
587
+ <span class="cline-any cline-yes">6x</span>
588
+ <span class="cline-any cline-neutral">&nbsp;</span>
589
+ <span class="cline-any cline-yes">1x</span>
590
+ <span class="cline-any cline-yes">1x</span>
591
+ <span class="cline-any cline-neutral">&nbsp;</span>
592
+ <span class="cline-any cline-neutral">&nbsp;</span>
593
+ <span class="cline-any cline-yes">2x</span>
594
+ <span class="cline-any cline-yes">2x</span>
595
+ <span class="cline-any cline-yes">2x</span>
596
+ <span class="cline-any cline-yes">1x</span>
597
+ <span class="cline-any cline-yes">1x</span>
598
+ <span class="cline-any cline-yes">1x</span>
599
+ <span class="cline-any cline-neutral">&nbsp;</span>
600
+ <span class="cline-any cline-yes">2x</span>
601
+ <span class="cline-any cline-neutral">&nbsp;</span>
602
+ <span class="cline-any cline-neutral">&nbsp;</span>
603
+ <span class="cline-any cline-yes">2x</span>
604
+ <span class="cline-any cline-yes">2x</span>
605
+ <span class="cline-any cline-yes">2x</span>
606
+ <span class="cline-any cline-neutral">&nbsp;</span>
607
+ <span class="cline-any cline-neutral">&nbsp;</span>
608
+ <span class="cline-any cline-neutral">&nbsp;</span>
609
+ <span class="cline-any cline-yes">1x</span>
610
+ <span class="cline-any cline-yes">1x</span>
611
+ <span class="cline-any cline-neutral">&nbsp;</span>
612
+ <span class="cline-any cline-neutral">&nbsp;</span>
613
+ <span class="cline-any cline-neutral">&nbsp;</span>
614
+ <span class="cline-any cline-yes">1x</span>
615
+ <span class="cline-any cline-neutral">&nbsp;</span>
616
+ <span class="cline-any cline-yes">2x</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-neutral">&nbsp;</span>
619
+ <span class="cline-any cline-neutral">&nbsp;</span>
620
+ <span class="cline-any cline-yes">1x</span>
621
+ <span class="cline-any cline-yes">1x</span>
622
+ <span class="cline-any cline-yes">1x</span>
623
+ <span class="cline-any cline-yes">1x</span>
624
+ <span class="cline-any cline-yes">1x</span>
625
+ <span class="cline-any cline-neutral">&nbsp;</span>
626
+ <span class="cline-any cline-neutral">&nbsp;</span>
627
+ <span class="cline-any cline-neutral">&nbsp;</span>
628
+ <span class="cline-any cline-yes">1x</span>
629
+ <span class="cline-any cline-yes">1x</span>
630
+ <span class="cline-any cline-yes">1x</span>
631
+ <span class="cline-any cline-yes">1x</span>
632
+ <span class="cline-any cline-neutral">&nbsp;</span>
633
+ <span class="cline-any cline-neutral">&nbsp;</span>
634
+ <span class="cline-any cline-neutral">&nbsp;</span>
635
+ <span class="cline-any cline-yes">1x</span>
636
+ <span class="cline-any cline-yes">1x</span>
637
+ <span class="cline-any cline-yes">1x</span>
638
+ <span class="cline-any cline-neutral">&nbsp;</span>
639
+ <span class="cline-any cline-neutral">&nbsp;</span>
640
+ <span class="cline-any cline-neutral">&nbsp;</span>
641
+ <span class="cline-any cline-neutral">&nbsp;</span>
642
+ <span class="cline-any cline-neutral">&nbsp;</span>
643
+ <span class="cline-any cline-yes">1x</span>
644
+ <span class="cline-any cline-neutral">&nbsp;</span>
645
+ <span class="cline-any cline-yes">1x</span>
646
+ <span class="cline-any cline-neutral">&nbsp;</span>
647
+ <span class="cline-any cline-neutral">&nbsp;</span>
648
+ <span class="cline-any cline-neutral">&nbsp;</span>
649
+ <span class="cline-any cline-neutral">&nbsp;</span>
650
+ <span class="cline-any cline-yes">41x</span>
651
+ <span class="cline-any cline-neutral">&nbsp;</span>
652
+ <span class="cline-any cline-neutral">&nbsp;</span>
653
+ <span class="cline-any cline-yes">17x</span>
654
+ <span class="cline-any cline-yes">41x</span>
655
+ <span class="cline-any cline-yes">41x</span>
656
+ <span class="cline-any cline-yes">41x</span>
657
+ <span class="cline-any cline-neutral">&nbsp;</span>
658
+ <span class="cline-any cline-yes">41x</span>
659
+ <span class="cline-any cline-yes">35x</span>
660
+ <span class="cline-any cline-neutral">&nbsp;</span>
661
+ <span class="cline-any cline-neutral">&nbsp;</span>
662
+ <span class="cline-any cline-neutral">&nbsp;</span>
663
+ <span class="cline-any cline-neutral">&nbsp;</span>
664
+ <span class="cline-any cline-neutral">&nbsp;</span>
665
+ <span class="cline-any cline-yes">41x</span>
666
+ <span class="cline-any cline-neutral">&nbsp;</span>
667
+ <span class="cline-any cline-yes">41x</span>
668
+ <span class="cline-any cline-neutral">&nbsp;</span>
669
+ <span class="cline-any cline-yes">15x</span>
670
+ <span class="cline-any cline-yes">12x</span>
671
+ <span class="cline-any cline-neutral">&nbsp;</span>
672
+ <span class="cline-any cline-neutral">&nbsp;</span>
673
+ <span class="cline-any cline-yes">3x</span>
674
+ <span class="cline-any cline-neutral">&nbsp;</span>
675
+ <span class="cline-any cline-neutral">&nbsp;</span>
676
+ <span class="cline-any cline-yes">38x</span>
677
+ <span class="cline-any cline-yes">38x</span>
678
+ <span class="cline-any cline-yes">38x</span>
679
+ <span class="cline-any cline-yes">38x</span>
680
+ <span class="cline-any cline-neutral">&nbsp;</span>
681
+ <span class="cline-any cline-yes">38x</span>
682
+ <span class="cline-any cline-yes">42x</span>
683
+ <span class="cline-any cline-neutral">&nbsp;</span>
684
+ <span class="cline-any cline-neutral">&nbsp;</span>
685
+ <span class="cline-any cline-yes">38x</span>
686
+ <span class="cline-any cline-neutral">&nbsp;</span>
687
+ <span class="cline-any cline-neutral">&nbsp;</span>
688
+ <span class="cline-any cline-neutral">&nbsp;</span>
689
+ <span class="cline-any cline-neutral">&nbsp;</span>
690
+ <span class="cline-any cline-neutral">&nbsp;</span>
691
+ <span class="cline-any cline-no">&nbsp;</span>
692
+ <span class="cline-any cline-neutral">&nbsp;</span>
693
+ <span class="cline-any cline-neutral">&nbsp;</span>
694
+ <span class="cline-any cline-neutral">&nbsp;</span>
695
+ <span class="cline-any cline-yes">17x</span>
696
+ <span class="cline-any cline-no">&nbsp;</span>
697
+ <span class="cline-any cline-no">&nbsp;</span>
698
+ <span class="cline-any cline-neutral">&nbsp;</span>
699
+ <span class="cline-any cline-neutral">&nbsp;</span>
700
+ <span class="cline-any cline-neutral">&nbsp;</span>
701
+ <span class="cline-any cline-neutral">&nbsp;</span>
702
+ <span class="cline-any cline-neutral">&nbsp;</span>
703
+ <span class="cline-any cline-neutral">&nbsp;</span>
704
+ <span class="cline-any cline-neutral">&nbsp;</span>
705
+ <span class="cline-any cline-no">&nbsp;</span>
706
+ <span class="cline-any cline-neutral">&nbsp;</span>
707
+ <span class="cline-any cline-neutral">&nbsp;</span>
708
+ <span class="cline-any cline-neutral">&nbsp;</span>
709
+ <span class="cline-any cline-neutral">&nbsp;</span>
710
+ <span class="cline-any cline-neutral">&nbsp;</span>
711
+ <span class="cline-any cline-neutral">&nbsp;</span>
712
+ <span class="cline-any cline-yes">17x</span>
713
+ <span class="cline-any cline-yes">36x</span>
714
+ <span class="cline-any cline-neutral">&nbsp;</span>
715
+ <span class="cline-any cline-yes">36x</span>
716
+ <span class="cline-any cline-yes">36x</span>
717
+ <span class="cline-any cline-no">&nbsp;</span>
718
+ <span class="cline-any cline-no">&nbsp;</span>
719
+ <span class="cline-any cline-no">&nbsp;</span>
720
+ <span class="cline-any cline-neutral">&nbsp;</span>
721
+ <span class="cline-any cline-no">&nbsp;</span>
722
+ <span class="cline-any cline-no">&nbsp;</span>
723
+ <span class="cline-any cline-neutral">&nbsp;</span>
724
+ <span class="cline-any cline-neutral">&nbsp;</span>
725
+ <span class="cline-any cline-neutral">&nbsp;</span>
726
+ <span class="cline-any cline-yes">36x</span>
727
+ <span class="cline-any cline-neutral">&nbsp;</span>
728
+ <span class="cline-any cline-yes">36x</span>
729
+ <span class="cline-any cline-neutral">&nbsp;</span>
730
+ <span class="cline-any cline-neutral">&nbsp;</span>
731
+ <span class="cline-any cline-neutral">&nbsp;</span>
732
+ <span class="cline-any cline-neutral">&nbsp;</span>
733
+ <span class="cline-any cline-neutral">&nbsp;</span>
734
+ <span class="cline-any cline-yes">36x</span>
735
+ <span class="cline-any cline-yes">27x</span>
736
+ <span class="cline-any cline-neutral">&nbsp;</span>
737
+ <span class="cline-any cline-neutral">&nbsp;</span>
738
+ <span class="cline-any cline-yes">9x</span>
739
+ <span class="cline-any cline-neutral">&nbsp;</span>
740
+ <span class="cline-any cline-neutral">&nbsp;</span>
741
+ <span class="cline-any cline-no">&nbsp;</span>
742
+ <span class="cline-any cline-neutral">&nbsp;</span>
743
+ <span class="cline-any cline-neutral">&nbsp;</span>
744
+ <span class="cline-any cline-neutral">&nbsp;</span>
745
+ <span class="cline-any cline-yes">17x</span>
746
+ <span class="cline-any cline-no">&nbsp;</span>
747
+ <span class="cline-any cline-no">&nbsp;</span>
748
+ <span class="cline-any cline-neutral">&nbsp;</span>
749
+ <span class="cline-any cline-no">&nbsp;</span>
750
+ <span class="cline-any cline-neutral">&nbsp;</span>
751
+ <span class="cline-any cline-neutral">&nbsp;</span>
752
+ <span class="cline-any cline-neutral">&nbsp;</span>
753
+ <span class="cline-any cline-no">&nbsp;</span>
754
+ <span class="cline-any cline-no">&nbsp;</span>
755
+ <span class="cline-any cline-neutral">&nbsp;</span>
756
+ <span class="cline-any cline-no">&nbsp;</span>
757
+ <span class="cline-any cline-neutral">&nbsp;</span>
758
+ <span class="cline-any cline-neutral">&nbsp;</span>
759
+ <span class="cline-any cline-neutral">&nbsp;</span>
760
+ <span class="cline-any cline-neutral">&nbsp;</span>
761
+ <span class="cline-any cline-neutral">&nbsp;</span>
762
+ <span class="cline-any cline-neutral">&nbsp;</span>
763
+ <span class="cline-any cline-no">&nbsp;</span>
764
+ <span class="cline-any cline-neutral">&nbsp;</span>
765
+ <span class="cline-any cline-neutral">&nbsp;</span>
766
+ <span class="cline-any cline-neutral">&nbsp;</span>
767
+ <span class="cline-any cline-yes">17x</span>
768
+ <span class="cline-any cline-no">&nbsp;</span>
769
+ <span class="cline-any cline-neutral">&nbsp;</span>
770
+ <span class="cline-any cline-no">&nbsp;</span>
771
+ <span class="cline-any cline-neutral">&nbsp;</span>
772
+ <span class="cline-any cline-no">&nbsp;</span>
773
+ <span class="cline-any cline-neutral">&nbsp;</span>
774
+ <span class="cline-any cline-neutral">&nbsp;</span>
775
+ <span class="cline-any cline-neutral">&nbsp;</span>
776
+ <span class="cline-any cline-no">&nbsp;</span>
777
+ <span class="cline-any cline-neutral">&nbsp;</span>
778
+ <span class="cline-any cline-neutral">&nbsp;</span>
779
+ <span class="cline-any cline-neutral">&nbsp;</span>
780
+ <span class="cline-any cline-no">&nbsp;</span>
781
+ <span class="cline-any cline-neutral">&nbsp;</span>
782
+ <span class="cline-any cline-neutral">&nbsp;</span>
783
+ <span class="cline-any cline-neutral">&nbsp;</span>
784
+ <span class="cline-any cline-neutral">&nbsp;</span>
785
+ <span class="cline-any cline-no">&nbsp;</span>
786
+ <span class="cline-any cline-no">&nbsp;</span>
787
+ <span class="cline-any cline-neutral">&nbsp;</span>
788
+ <span class="cline-any cline-neutral">&nbsp;</span>
789
+ <span class="cline-any cline-neutral">&nbsp;</span>
790
+ <span class="cline-any cline-no">&nbsp;</span>
791
+ <span class="cline-any cline-neutral">&nbsp;</span>
792
+ <span class="cline-any cline-neutral">&nbsp;</span>
793
+ <span class="cline-any cline-neutral">&nbsp;</span>
794
+ <span class="cline-any cline-no">&nbsp;</span>
795
+ <span class="cline-any cline-neutral">&nbsp;</span>
796
+ <span class="cline-any cline-no">&nbsp;</span>
797
+ <span class="cline-any cline-neutral">&nbsp;</span>
798
+ <span class="cline-any cline-neutral">&nbsp;</span>
799
+ <span class="cline-any cline-no">&nbsp;</span>
800
+ <span class="cline-any cline-neutral">&nbsp;</span>
801
+ <span class="cline-any cline-neutral">&nbsp;</span>
802
+ <span class="cline-any cline-neutral">&nbsp;</span>
803
+ <span class="cline-any cline-no">&nbsp;</span>
804
+ <span class="cline-any cline-no">&nbsp;</span>
805
+ <span class="cline-any cline-neutral">&nbsp;</span>
806
+ <span class="cline-any cline-neutral">&nbsp;</span>
807
+ <span class="cline-any cline-no">&nbsp;</span>
808
+ <span class="cline-any cline-no">&nbsp;</span>
809
+ <span class="cline-any cline-neutral">&nbsp;</span>
810
+ <span class="cline-any cline-no">&nbsp;</span>
811
+ <span class="cline-any cline-neutral">&nbsp;</span>
812
+ <span class="cline-any cline-neutral">&nbsp;</span>
813
+ <span class="cline-any cline-no">&nbsp;</span>
814
+ <span class="cline-any cline-neutral">&nbsp;</span>
815
+ <span class="cline-any cline-no">&nbsp;</span>
816
+ <span class="cline-any cline-neutral">&nbsp;</span>
817
+ <span class="cline-any cline-neutral">&nbsp;</span>
818
+ <span class="cline-any cline-neutral">&nbsp;</span>
819
+ <span class="cline-any cline-yes">17x</span>
820
+ <span class="cline-any cline-no">&nbsp;</span>
821
+ <span class="cline-any cline-no">&nbsp;</span>
822
+ <span class="cline-any cline-neutral">&nbsp;</span>
823
+ <span class="cline-any cline-no">&nbsp;</span>
824
+ <span class="cline-any cline-no">&nbsp;</span>
825
+ <span class="cline-any cline-neutral">&nbsp;</span>
826
+ <span class="cline-any cline-neutral">&nbsp;</span>
827
+ <span class="cline-any cline-no">&nbsp;</span>
828
+ <span class="cline-any cline-no">&nbsp;</span>
829
+ <span class="cline-any cline-neutral">&nbsp;</span>
830
+ <span class="cline-any cline-no">&nbsp;</span>
831
+ <span class="cline-any cline-neutral">&nbsp;</span>
832
+ <span class="cline-any cline-neutral">&nbsp;</span>
833
+ <span class="cline-any cline-neutral">&nbsp;</span>
834
+ <span class="cline-any cline-no">&nbsp;</span>
835
+ <span class="cline-any cline-no">&nbsp;</span>
836
+ <span class="cline-any cline-neutral">&nbsp;</span>
837
+ <span class="cline-any cline-no">&nbsp;</span>
838
+ <span class="cline-any cline-neutral">&nbsp;</span>
839
+ <span class="cline-any cline-neutral">&nbsp;</span>
840
+ <span class="cline-any cline-no">&nbsp;</span>
841
+ <span class="cline-any cline-neutral">&nbsp;</span>
842
+ <span class="cline-any cline-neutral">&nbsp;</span>
843
+ <span class="cline-any cline-neutral">&nbsp;</span>
844
+ <span class="cline-any cline-neutral">&nbsp;</span>
845
+ <span class="cline-any cline-neutral">&nbsp;</span>
846
+ <span class="cline-any cline-neutral">&nbsp;</span>
847
+ <span class="cline-any cline-neutral">&nbsp;</span>
848
+ <span class="cline-any cline-neutral">&nbsp;</span>
849
+ <span class="cline-any cline-no">&nbsp;</span>
850
+ <span class="cline-any cline-no">&nbsp;</span>
851
+ <span class="cline-any cline-no">&nbsp;</span>
852
+ <span class="cline-any cline-no">&nbsp;</span>
853
+ <span class="cline-any cline-neutral">&nbsp;</span>
854
+ <span class="cline-any cline-neutral">&nbsp;</span>
855
+ <span class="cline-any cline-neutral">&nbsp;</span>
856
+ <span class="cline-any cline-neutral">&nbsp;</span>
857
+ <span class="cline-any cline-neutral">&nbsp;</span>
858
+ <span class="cline-any cline-no">&nbsp;</span>
859
+ <span class="cline-any cline-no">&nbsp;</span>
860
+ <span class="cline-any cline-neutral">&nbsp;</span>
861
+ <span class="cline-any cline-no">&nbsp;</span>
862
+ <span class="cline-any cline-neutral">&nbsp;</span>
863
+ <span class="cline-any cline-neutral">&nbsp;</span>
864
+ <span class="cline-any cline-no">&nbsp;</span>
865
+ <span class="cline-any cline-neutral">&nbsp;</span>
866
+ <span class="cline-any cline-no">&nbsp;</span>
867
+ <span class="cline-any cline-neutral">&nbsp;</span>
868
+ <span class="cline-any cline-no">&nbsp;</span>
869
+ <span class="cline-any cline-neutral">&nbsp;</span>
870
+ <span class="cline-any cline-neutral">&nbsp;</span>
871
+ <span class="cline-any cline-neutral">&nbsp;</span>
872
+ <span class="cline-any cline-neutral">&nbsp;</span>
873
+ <span class="cline-any cline-neutral">&nbsp;</span>
874
+ <span class="cline-any cline-yes">17x</span>
875
+ <span class="cline-any cline-yes">36x</span>
876
+ <span class="cline-any cline-yes">36x</span>
877
+ <span class="cline-any cline-yes">36x</span>
878
+ <span class="cline-any cline-yes">36x</span>
879
+ <span class="cline-any cline-yes">23x</span>
880
+ <span class="cline-any cline-yes">23x</span>
881
+ <span class="cline-any cline-neutral">&nbsp;</span>
882
+ <span class="cline-any cline-yes">13x</span>
883
+ <span class="cline-any cline-neutral">&nbsp;</span>
884
+ <span class="cline-any cline-neutral">&nbsp;</span>
885
+ <span class="cline-any cline-neutral">&nbsp;</span>
886
+ <span class="cline-any cline-yes">17x</span>
887
+ <span class="cline-any cline-yes">4x</span>
888
+ <span class="cline-any cline-yes">4x</span>
889
+ <span class="cline-any cline-neutral">&nbsp;</span>
890
+ <span class="cline-any cline-yes">4x</span>
891
+ <span class="cline-any cline-yes">4x</span>
892
+ <span class="cline-any cline-neutral">&nbsp;</span>
893
+ <span class="cline-any cline-neutral">&nbsp;</span>
894
+ <span class="cline-any cline-yes">4x</span>
895
+ <span class="cline-any cline-yes">4x</span>
896
+ <span class="cline-any cline-yes">4x</span>
897
+ <span class="cline-any cline-neutral">&nbsp;</span>
898
+ <span class="cline-any cline-yes">4x</span>
899
+ <span class="cline-any cline-neutral">&nbsp;</span>
900
+ <span class="cline-any cline-neutral">&nbsp;</span>
901
+ <span class="cline-any cline-neutral">&nbsp;</span>
902
+ <span class="cline-any cline-yes">4x</span>
903
+ <span class="cline-any cline-neutral">&nbsp;</span>
904
+ <span class="cline-any cline-neutral">&nbsp;</span>
905
+ <span class="cline-any cline-neutral">&nbsp;</span>
906
+ <span class="cline-any cline-neutral">&nbsp;</span>
907
+ <span class="cline-any cline-yes">4x</span>
908
+ <span class="cline-any cline-neutral">&nbsp;</span>
909
+ <span class="cline-any cline-neutral">&nbsp;</span>
910
+ <span class="cline-any cline-neutral">&nbsp;</span>
911
+ <span class="cline-any cline-neutral">&nbsp;</span>
912
+ <span class="cline-any cline-yes">4x</span>
913
+ <span class="cline-any cline-neutral">&nbsp;</span>
914
+ <span class="cline-any cline-neutral">&nbsp;</span>
915
+ <span class="cline-any cline-neutral">&nbsp;</span>
916
+ <span class="cline-any cline-neutral">&nbsp;</span>
917
+ <span class="cline-any cline-yes">4x</span>
918
+ <span class="cline-any cline-yes">4x</span>
919
+ <span class="cline-any cline-neutral">&nbsp;</span>
920
+ <span class="cline-any cline-neutral">&nbsp;</span>
921
+ <span class="cline-any cline-neutral">&nbsp;</span>
922
+ <span class="cline-any cline-neutral">&nbsp;</span>
923
+ <span class="cline-any cline-neutral">&nbsp;</span>
924
+ <span class="cline-any cline-neutral">&nbsp;</span>
925
+ <span class="cline-any cline-neutral">&nbsp;</span>
926
+ <span class="cline-any cline-neutral">&nbsp;</span>
927
+ <span class="cline-any cline-neutral">&nbsp;</span>
928
+ <span class="cline-any cline-neutral">&nbsp;</span>
929
+ <span class="cline-any cline-neutral">&nbsp;</span>
930
+ <span class="cline-any cline-neutral">&nbsp;</span>
931
+ <span class="cline-any cline-neutral">&nbsp;</span>
932
+ <span class="cline-any cline-neutral">&nbsp;</span>
933
+ <span class="cline-any cline-neutral">&nbsp;</span>
934
+ <span class="cline-any cline-neutral">&nbsp;</span>
935
+ <span class="cline-any cline-neutral">&nbsp;</span>
936
+ <span class="cline-any cline-neutral">&nbsp;</span>
937
+ <span class="cline-any cline-neutral">&nbsp;</span>
938
+ <span class="cline-any cline-neutral">&nbsp;</span>
939
+ <span class="cline-any cline-neutral">&nbsp;</span>
940
+ <span class="cline-any cline-neutral">&nbsp;</span>
941
+ <span class="cline-any cline-neutral">&nbsp;</span>
942
+ <span class="cline-any cline-neutral">&nbsp;</span>
943
+ <span class="cline-any cline-no">&nbsp;</span>
944
+ <span class="cline-any cline-neutral">&nbsp;</span>
945
+ <span class="cline-any cline-neutral">&nbsp;</span>
946
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import * as email from "../../../utilities/email"
947
+ import env from "../../../environment"
948
+ import { googleCallbackUrl, oidcCallbackUrl } from "./auth"
949
+ import {
950
+ events,
951
+ cache,
952
+ objectStore,
953
+ tenancy,
954
+ db as dbCore,
955
+ } from "@budibase/backend-core"
956
+ import { checkAnyUserExists } from "../../../utilities/users"
957
+ import {
958
+ Database,
959
+ Config as ConfigDoc,
960
+ ConfigType,
961
+ SSOType,
962
+ GoogleConfig,
963
+ OIDCConfig,
964
+ SettingsConfig,
965
+ BBContext,
966
+ } from "@budibase/types"
967
+ &nbsp;
968
+ const getEventFns = async (db: Database, config: ConfigDoc) =&gt; {
969
+ const fns = []
970
+ const type = config.type
971
+ &nbsp;
972
+ let existing
973
+ if (config._id) {
974
+ existing = await db.get(config._id)
975
+ }
976
+ &nbsp;
977
+ const ssoType = type as SSOType
978
+ if (!existing) {
979
+ switch (config.type) {
980
+ case ConfigType.SMTP: {
981
+ fns.push(events.email.SMTPCreated)
982
+ break
983
+ }
984
+ case ConfigType.GOOGLE: {
985
+ const googleCfg = config as GoogleConfig
986
+ fns.push(() =&gt; events.auth.SSOCreated(ssoType))
987
+ if (googleCfg.config.activated) {
988
+ fns.push(() =&gt; events.auth.SSOActivated(ssoType))
989
+ }
990
+ break
991
+ }
992
+ case ConfigType.OIDC: {
993
+ const oidcCfg = config as OIDCConfig
994
+ fns.push(() =&gt; events.auth.SSOCreated(ssoType))
995
+ if (oidcCfg.config.configs[0].activated) {
996
+ fns.push(() =&gt; events.auth.SSOActivated(ssoType))
997
+ }
998
+ break
999
+ }
1000
+ case ConfigType.SETTINGS: {
1001
+ // company
1002
+ const settingsCfg = config as SettingsConfig
1003
+ const company = settingsCfg.config.company
1004
+ if (company &amp;&amp; company !== "Budibase") {
1005
+ fns.push(events.org.nameUpdated)
1006
+ }
1007
+ &nbsp;
1008
+ // logo
1009
+ const logoUrl = settingsCfg.config.logoUrl
1010
+ if (logoUrl) {
1011
+ fns.push(events.org.logoUpdated)
1012
+ }
1013
+ &nbsp;
1014
+ // platform url
1015
+ const platformUrl = settingsCfg.config.platformUrl
1016
+ if (
1017
+ platformUrl &amp;&amp;
1018
+ platformUrl !== "http://localhost:10000" &amp;&amp;
1019
+ env.SELF_HOSTED
1020
+ ) {
1021
+ fns.push(events.org.platformURLUpdated)
1022
+ }
1023
+ break
1024
+ }
1025
+ }
1026
+ } else {
1027
+ switch (config.type) {
1028
+ case ConfigType.SMTP: {
1029
+ fns.push(events.email.SMTPUpdated)
1030
+ break
1031
+ }
1032
+ case ConfigType.GOOGLE: {
1033
+ const googleCfg = config as GoogleConfig
1034
+ fns.push(() =&gt; events.auth.SSOUpdated(ssoType))
1035
+ if (!existing.config.activated &amp;&amp; googleCfg.config.activated) {
1036
+ fns.push(() =&gt; events.auth.SSOActivated(ssoType))
1037
+ } else if (existing.config.activated &amp;&amp; !googleCfg.config.activated) {
1038
+ fns.push(() =&gt; events.auth.SSODeactivated(ssoType))
1039
+ }
1040
+ break
1041
+ }
1042
+ case ConfigType.OIDC: {
1043
+ const oidcCfg = config as OIDCConfig
1044
+ fns.push(() =&gt; events.auth.SSOUpdated(ssoType))
1045
+ if (
1046
+ !existing.config.configs[0].activated &amp;&amp;
1047
+ oidcCfg.config.configs[0].activated
1048
+ ) {
1049
+ fns.push(() =&gt; events.auth.SSOActivated(ssoType))
1050
+ } else if (
1051
+ existing.config.configs[0].activated &amp;&amp;
1052
+ !oidcCfg.config.configs[0].activated
1053
+ ) {
1054
+ fns.push(() =&gt; events.auth.SSODeactivated(ssoType))
1055
+ }
1056
+ break
1057
+ }
1058
+ case ConfigType.SETTINGS: {
1059
+ // company
1060
+ const settingsCfg = config as SettingsConfig
1061
+ const existingCompany = existing.config.company
1062
+ const company = settingsCfg.config.company
1063
+ if (company &amp;&amp; company !== "Budibase" &amp;&amp; existingCompany !== company) {
1064
+ fns.push(events.org.nameUpdated)
1065
+ }
1066
+ &nbsp;
1067
+ // logo
1068
+ const existingLogoUrl = existing.config.logoUrl
1069
+ const logoUrl = settingsCfg.config.logoUrl
1070
+ if (logoUrl &amp;&amp; existingLogoUrl !== logoUrl) {
1071
+ fns.push(events.org.logoUpdated)
1072
+ }
1073
+ &nbsp;
1074
+ // platform url
1075
+ const existingPlatformUrl = existing.config.platformUrl
1076
+ const platformUrl = settingsCfg.config.platformUrl
1077
+ if (
1078
+ platformUrl &amp;&amp;
1079
+ platformUrl !== "http://localhost:10000" &amp;&amp;
1080
+ existingPlatformUrl !== platformUrl &amp;&amp;
1081
+ env.SELF_HOSTED
1082
+ ) {
1083
+ fns.push(events.org.platformURLUpdated)
1084
+ }
1085
+ break
1086
+ }
1087
+ }
1088
+ }
1089
+ &nbsp;
1090
+ return fns
1091
+ }
1092
+ &nbsp;
1093
+ export async function save(ctx: BBContext) {
1094
+ const db = tenancy.getGlobalDB()
1095
+ const { type, workspace, user, config } = ctx.request.body
1096
+ let eventFns = await getEventFns(db, ctx.request.body)
1097
+ // Config does not exist yet
1098
+ if (!ctx.request.body._id) {
1099
+ ctx.request.body._id = dbCore.generateConfigID({
1100
+ type,
1101
+ workspace,
1102
+ user,
1103
+ })
1104
+ }
1105
+ try {
1106
+ // verify the configuration
1107
+ switch (type) {
1108
+ case ConfigType.SMTP:
1109
+ await email.verifyConfig(config)
1110
+ break
1111
+ }
1112
+ } catch (err: any) {
1113
+ ctx.throw(400, err)
1114
+ }
1115
+ &nbsp;
1116
+ try {
1117
+ const response = await db.put(ctx.request.body)
1118
+ await cache.bustCache(cache.CacheKey.CHECKLIST)
1119
+ await cache.bustCache(cache.CacheKey.ANALYTICS_ENABLED)
1120
+ &nbsp;
1121
+ for (const fn of eventFns) {
1122
+ await fn()
1123
+ }
1124
+ &nbsp;
1125
+ ctx.body = {
1126
+ type,
1127
+ _id: response.id,
1128
+ _rev: response.rev,
1129
+ }
1130
+ } catch (err: any) {
1131
+ <span class="cstat-no" title="statement not covered" > ctx.throw(400, err)</span>
1132
+ }
1133
+ }
1134
+ &nbsp;
1135
+ export async function <span class="fstat-no" title="function not covered" >fetch(</span>ctx: BBContext) {
1136
+ const db = <span class="cstat-no" title="statement not covered" >tenancy.getGlobalDB()</span>
1137
+ const response = <span class="cstat-no" title="statement not covered" >await db.allDocs(</span>
1138
+ dbCore.getConfigParams(
1139
+ { type: ctx.params.type },
1140
+ {
1141
+ include_docs: true,
1142
+ }
1143
+ )
1144
+ )
1145
+ <span class="cstat-no" title="statement not covered" > ctx.body = response.rows.map(<span class="fstat-no" title="function not covered" >row </span>=&gt; <span class="cstat-no" title="statement not covered" >row.doc)</span></span>
1146
+ }
1147
+ &nbsp;
1148
+ /**
1149
+ * Gets the most granular config for a particular configuration type.
1150
+ * The hierarchy is type -&gt; workspace -&gt; user.
1151
+ */
1152
+ export async function find(ctx: BBContext) {
1153
+ const db = tenancy.getGlobalDB()
1154
+ &nbsp;
1155
+ const { userId, workspaceId } = ctx.query
1156
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (workspaceId &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >userId)</span> {
1157
+ const workspace = <span class="cstat-no" title="statement not covered" >await db.get(workspaceId as string)</span>
1158
+ const userInWorkspace = <span class="cstat-no" title="statement not covered" >workspace.users.some(</span>
1159
+ <span class="fstat-no" title="function not covered" > (w</span>orkspaceUser: any) =&gt; <span class="cstat-no" title="statement not covered" >workspaceUser === userId</span>
1160
+ )
1161
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!ctx.user!.admin &amp;&amp; !userInWorkspace) {</span>
1162
+ <span class="cstat-no" title="statement not covered" > ctx.throw(400, `User is not in specified workspace: ${workspace}.`)</span>
1163
+ }
1164
+ }
1165
+ &nbsp;
1166
+ try {
1167
+ // Find the config with the most granular scope based on context
1168
+ const scopedConfig = await dbCore.getScopedFullConfig(db, {
1169
+ type: ctx.params.type,
1170
+ user: userId,
1171
+ workspace: workspaceId,
1172
+ })
1173
+ &nbsp;
1174
+ if (scopedConfig) {
1175
+ ctx.body = scopedConfig
1176
+ } else {
1177
+ // don't throw an error, there simply is nothing to return
1178
+ ctx.body = {}
1179
+ }
1180
+ } catch (err: any) {
1181
+ <span class="cstat-no" title="statement not covered" > ctx.throw(err?.status || 400, err)</span>
1182
+ }
1183
+ }
1184
+ &nbsp;
1185
+ export async function <span class="fstat-no" title="function not covered" >publicOidc(</span>ctx: BBContext) {
1186
+ const db = <span class="cstat-no" title="statement not covered" >tenancy.getGlobalDB()</span>
1187
+ <span class="cstat-no" title="statement not covered" > try {</span>
1188
+ // Find the config with the most granular scope based on context
1189
+ const oidcConfig = <span class="cstat-no" title="statement not covered" >await dbCore.getScopedFullConfig(db, {</span>
1190
+ type: ConfigType.OIDC,
1191
+ })
1192
+ &nbsp;
1193
+ <span class="cstat-no" title="statement not covered" > if (!oidcConfig) {</span>
1194
+ <span class="cstat-no" title="statement not covered" > ctx.body = {}</span>
1195
+ } else {
1196
+ <span class="cstat-no" title="statement not covered" > ctx.body = oidcConfig.config.configs.map(<span class="fstat-no" title="function not covered" >(c</span>onfig: any) =&gt; (<span class="cstat-no" title="statement not covered" >{</span></span>
1197
+ logo: config.logo,
1198
+ name: config.name,
1199
+ uuid: config.uuid,
1200
+ }))
1201
+ }
1202
+ } catch (err: any) {
1203
+ <span class="cstat-no" title="statement not covered" > ctx.throw(err.status, err)</span>
1204
+ }
1205
+ }
1206
+ &nbsp;
1207
+ export async function <span class="fstat-no" title="function not covered" >publicSettings(</span>ctx: BBContext) {
1208
+ const db = <span class="cstat-no" title="statement not covered" >tenancy.getGlobalDB()</span>
1209
+ &nbsp;
1210
+ <span class="cstat-no" title="statement not covered" > try {</span>
1211
+ // Find the config with the most granular scope based on context
1212
+ const publicConfig = <span class="cstat-no" title="statement not covered" >await dbCore.getScopedFullConfig(db, {</span>
1213
+ type: ConfigType.SETTINGS,
1214
+ })
1215
+ &nbsp;
1216
+ const googleConfig = <span class="cstat-no" title="statement not covered" >await dbCore.getScopedFullConfig(db, {</span>
1217
+ type: ConfigType.GOOGLE,
1218
+ })
1219
+ &nbsp;
1220
+ const oidcConfig = <span class="cstat-no" title="statement not covered" >await dbCore.getScopedFullConfig(db, {</span>
1221
+ type: ConfigType.OIDC,
1222
+ })
1223
+ &nbsp;
1224
+ let config
1225
+ <span class="cstat-no" title="statement not covered" > if (!publicConfig) {</span>
1226
+ <span class="cstat-no" title="statement not covered" > config = {</span>
1227
+ config: {},
1228
+ }
1229
+ } else {
1230
+ <span class="cstat-no" title="statement not covered" > config = publicConfig</span>
1231
+ }
1232
+ &nbsp;
1233
+ // google button flag
1234
+ <span class="cstat-no" title="statement not covered" > if (googleConfig &amp;&amp; googleConfig.config) {</span>
1235
+ // activated by default for configs pre-activated flag
1236
+ <span class="cstat-no" title="statement not covered" > config.config.google =</span>
1237
+ googleConfig.config.activated == null || googleConfig.config.activated
1238
+ } else {
1239
+ <span class="cstat-no" title="statement not covered" > config.config.google = false</span>
1240
+ }
1241
+ &nbsp;
1242
+ // callback urls
1243
+ <span class="cstat-no" title="statement not covered" > config.config.oidcCallbackUrl = await oidcCallbackUrl()</span>
1244
+ <span class="cstat-no" title="statement not covered" > config.config.googleCallbackUrl = await googleCallbackUrl()</span>
1245
+ &nbsp;
1246
+ // oidc button flag
1247
+ <span class="cstat-no" title="statement not covered" > if (oidcConfig &amp;&amp; oidcConfig.config) {</span>
1248
+ <span class="cstat-no" title="statement not covered" > config.config.oidc = oidcConfig.config.configs[0].activated</span>
1249
+ } else {
1250
+ <span class="cstat-no" title="statement not covered" > config.config.oidc = false</span>
1251
+ }
1252
+ &nbsp;
1253
+ <span class="cstat-no" title="statement not covered" > ctx.body = config</span>
1254
+ } catch (err: any) {
1255
+ <span class="cstat-no" title="statement not covered" > ctx.throw(err.status, err)</span>
1256
+ }
1257
+ }
1258
+ &nbsp;
1259
+ export async function <span class="fstat-no" title="function not covered" >upload(</span>ctx: BBContext) {
1260
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (ctx.request.files == null || ctx.request.files.file.length &gt; 1) {</span>
1261
+ <span class="cstat-no" title="statement not covered" > ctx.throw(400, "One file must be uploaded.")</span>
1262
+ }
1263
+ const file = <span class="cstat-no" title="statement not covered" >ctx.request.files.file</span>
1264
+ const { type, name } = <span class="cstat-no" title="statement not covered" >ctx.params</span>
1265
+ &nbsp;
1266
+ let bucket
1267
+ <span class="cstat-no" title="statement not covered" > if (env.SELF_HOSTED) {</span>
1268
+ <span class="cstat-no" title="statement not covered" > bucket = objectStore.ObjectStoreBuckets.GLOBAL</span>
1269
+ } else {
1270
+ <span class="cstat-no" title="statement not covered" > bucket = objectStore.ObjectStoreBuckets.GLOBAL_CLOUD</span>
1271
+ }
1272
+ &nbsp;
1273
+ let key
1274
+ <span class="cstat-no" title="statement not covered" > if (env.MULTI_TENANCY) {</span>
1275
+ <span class="cstat-no" title="statement not covered" > key = `${tenancy.getTenantId()}/${type}/${name}`</span>
1276
+ } else {
1277
+ <span class="cstat-no" title="statement not covered" > key = `${type}/${name}`</span>
1278
+ }
1279
+ &nbsp;
1280
+ <span class="cstat-no" title="statement not covered" > await objectStore.upload({</span>
1281
+ bucket,
1282
+ filename: key,
1283
+ path: file.path,
1284
+ type: file.type,
1285
+ })
1286
+ &nbsp;
1287
+ // add to configuration structure
1288
+ // TODO: right now this only does a global level
1289
+ const db = <span class="cstat-no" title="statement not covered" >tenancy.getGlobalDB()</span>
1290
+ let cfgStructure = <span class="cstat-no" title="statement not covered" >await dbCore.getScopedFullConfig(db, { type })</span>
1291
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!cfgStructure) {</span>
1292
+ <span class="cstat-no" title="statement not covered" > cfgStructure = {</span>
1293
+ _id: dbCore.generateConfigID({ type }),
1294
+ config: {},
1295
+ }
1296
+ }
1297
+ let url
1298
+ <span class="cstat-no" title="statement not covered" > if (env.SELF_HOSTED) {</span>
1299
+ <span class="cstat-no" title="statement not covered" > url = `/${bucket}/${key}`</span>
1300
+ } else {
1301
+ <span class="cstat-no" title="statement not covered" > url = `${env.CDN_URL}/${key}`</span>
1302
+ }
1303
+ &nbsp;
1304
+ <span class="cstat-no" title="statement not covered" > cfgStructure.config[`${name}`] = url</span>
1305
+ // write back to db with url updated
1306
+ <span class="cstat-no" title="statement not covered" > await db.put(cfgStructure)</span>
1307
+ &nbsp;
1308
+ <span class="cstat-no" title="statement not covered" > ctx.body = {</span>
1309
+ message: "File has been uploaded and url stored to config.",
1310
+ url,
1311
+ }
1312
+ }
1313
+ &nbsp;
1314
+ export async function destroy(ctx: BBContext) {
1315
+ const db = tenancy.getGlobalDB()
1316
+ const { id, rev } = ctx.params
1317
+ try {
1318
+ await db.remove(id, rev)
1319
+ await cache.destroy(cache.CacheKey.CHECKLIST)
1320
+ ctx.body = { message: "Config deleted successfully" }
1321
+ } catch (err: any) {
1322
+ ctx.throw(err.status, err)
1323
+ }
1324
+ }
1325
+ &nbsp;
1326
+ export async function configChecklist(ctx: BBContext) {
1327
+ const db = tenancy.getGlobalDB()
1328
+ const tenantId = tenancy.getTenantId()
1329
+ &nbsp;
1330
+ try {
1331
+ ctx.body = await cache.withCache(
1332
+ cache.CacheKey.CHECKLIST,
1333
+ env.CHECKLIST_CACHE_TTL,
1334
+ async () =&gt; {
1335
+ let apps = []
1336
+ if (!env.MULTI_TENANCY || tenantId) {
1337
+ // Apps exist
1338
+ apps = await dbCore.getAllApps({ idsOnly: true, efficient: true })
1339
+ }
1340
+ &nbsp;
1341
+ // They have set up SMTP
1342
+ const smtpConfig = await dbCore.getScopedFullConfig(db, {
1343
+ type: ConfigType.SMTP,
1344
+ })
1345
+ &nbsp;
1346
+ // They have set up Google Auth
1347
+ const googleConfig = await dbCore.getScopedFullConfig(db, {
1348
+ type: ConfigType.GOOGLE,
1349
+ })
1350
+ &nbsp;
1351
+ // They have set up OIDC
1352
+ const oidcConfig = await dbCore.getScopedFullConfig(db, {
1353
+ type: ConfigType.OIDC,
1354
+ })
1355
+ &nbsp;
1356
+ // They have set up a global user
1357
+ const userExists = await checkAnyUserExists()
1358
+ return {
1359
+ apps: {
1360
+ checked: apps.length &gt; 0,
1361
+ label: "Create your first app",
1362
+ link: "/builder/portal/apps",
1363
+ },
1364
+ smtp: {
1365
+ checked: !!smtpConfig,
1366
+ label: "Set up email",
1367
+ link: "/builder/portal/manage/email",
1368
+ },
1369
+ adminUser: {
1370
+ checked: userExists,
1371
+ label: "Create your first user",
1372
+ link: "/builder/portal/manage/users",
1373
+ },
1374
+ sso: {
1375
+ checked: !!googleConfig || !!oidcConfig,
1376
+ label: "Set up single sign-on",
1377
+ link: "/builder/portal/manage/auth",
1378
+ },
1379
+ }
1380
+ }
1381
+ )
1382
+ } catch (err: any) {
1383
+ <span class="cstat-no" title="statement not covered" > ctx.throw(err.status, err)</span>
1384
+ }
1385
+ }
1386
+ &nbsp;</pre></td></tr></table></pre>
1387
+
1388
+ <div class='push'></div><!-- for sticky footer -->
1389
+ </div><!-- /wrapper -->
1390
+ <div class='footer quiet pad2 space-top1 center small'>
1391
+ Code coverage generated by
1392
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1393
+ at Fri Dec 09 2022 13:48:17 GMT+0000 (Coordinated Universal Time)
1394
+ </div>
1395
+ <script src="../../../../prettify.js"></script>
1396
+ <script>
1397
+ window.onload = function () {
1398
+ prettyPrint();
1399
+ };
1400
+ </script>
1401
+ <script src="../../../../sorter.js"></script>
1402
+ <script src="../../../../block-navigation.js"></script>
1403
+ </body>
1404
+ </html>
1405
+