@budibase/worker 2.1.31 → 2.1.32-alpha.1

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 (182) hide show
  1. package/__mocks__/aws-sdk.ts +15 -0
  2. package/__mocks__/oauth.ts +57 -0
  3. package/coverage/clover.xml +2160 -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 +913 -0
  14. package/coverage/lcov-report/src/api/controllers/global/configs.js.html +1390 -0
  15. package/coverage/lcov-report/src/api/controllers/global/email.js.html +193 -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.js.html +289 -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 +796 -0
  22. package/coverage/lcov-report/src/api/controllers/global/workspaces.js.html +253 -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.js.html +349 -0
  33. package/coverage/lcov-report/src/api/routes/global/configs.js.html +460 -0
  34. package/coverage/lcov-report/src/api/routes/global/email.js.html +196 -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.js.html +121 -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.js.html +403 -0
  41. package/coverage/lcov-report/src/api/routes/global/workspaces.js.html +199 -0
  42. package/coverage/lcov-report/src/api/routes/index.html +116 -0
  43. package/coverage/lcov-report/src/api/routes/index.ts.html +193 -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.js.html +304 -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 +364 -0
  61. package/coverage/lcov-report/src/index.html +131 -0
  62. package/coverage/lcov-report/src/index.ts.html +397 -0
  63. package/coverage/lcov-report/src/middleware/cloudRestricted.js.html +136 -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 +1903 -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.js.html +106 -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.js.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.js.html +184 -0
  105. package/coverage/lcov-report/src/utilities/email.ts.html +850 -0
  106. package/coverage/lcov-report/src/utilities/fileSystem.js.html +100 -0
  107. package/coverage/lcov-report/src/utilities/index.html +206 -0
  108. package/coverage/lcov-report/src/utilities/index.js.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.js.html +136 -0
  112. package/coverage/lcov.info +3986 -0
  113. package/jest.config.ts +29 -0
  114. package/package.json +13 -23
  115. package/scripts/localdomain.js +33 -7
  116. package/src/api/controllers/global/auth.ts +35 -31
  117. package/src/api/controllers/global/configs.js +17 -17
  118. package/src/api/controllers/global/self.ts +2 -2
  119. package/src/api/controllers/global/users.ts +3 -1
  120. package/src/api/controllers/system/{environment.js → environment.ts} +3 -2
  121. package/src/api/controllers/system/{status.js → status.ts} +4 -3
  122. package/src/api/controllers/system/tenants.ts +8 -51
  123. package/src/api/index.ts +29 -6
  124. package/src/api/routes/global/auth.js +22 -39
  125. package/src/api/routes/global/configs.js +9 -9
  126. package/src/api/routes/global/templates.ts +2 -2
  127. package/src/api/routes/global/tests/auth.spec.ts +134 -64
  128. package/src/api/routes/global/tests/configs.spec.ts +34 -35
  129. package/src/api/routes/global/tests/email.spec.ts +4 -3
  130. package/src/api/routes/global/tests/license.spec.ts +31 -0
  131. package/src/api/routes/global/tests/realEmail.spec.ts +2 -3
  132. package/src/api/routes/global/tests/roles.spec.ts +27 -0
  133. package/src/api/routes/global/tests/self.spec.ts +3 -4
  134. package/src/api/routes/global/tests/templates.spec.ts +35 -0
  135. package/src/api/routes/global/tests/users.spec.ts +51 -43
  136. package/src/api/routes/global/tests/workspaces.spec.ts +29 -0
  137. package/src/api/routes/system/environment.ts +8 -0
  138. package/src/api/routes/system/status.ts +8 -0
  139. package/src/api/routes/system/tenants.ts +13 -0
  140. package/src/api/routes/system/tests/accounts.spec.ts +5 -6
  141. package/src/api/routes/system/tests/environment.spec.ts +29 -0
  142. package/src/api/routes/system/tests/migrations.spec.ts +63 -0
  143. package/src/api/routes/system/tests/restore.spec.ts +36 -0
  144. package/src/api/routes/system/tests/status.spec.ts +48 -0
  145. package/src/api/routes/system/tests/tenants.spec.ts +61 -0
  146. package/src/constants/{index.js → index.ts} +57 -64
  147. package/src/constants/templates/index.js +2 -2
  148. package/src/db/index.ts +10 -0
  149. package/src/index.ts +1 -1
  150. package/src/middleware/cloudRestricted.js +2 -2
  151. package/src/middleware/tests/tenancy.spec.ts +73 -0
  152. package/src/tests/TestConfiguration.ts +98 -49
  153. package/src/tests/api/accounts.ts +5 -8
  154. package/src/tests/api/auth.ts +3 -6
  155. package/src/tests/api/base.ts +16 -0
  156. package/src/tests/api/configs.ts +15 -8
  157. package/src/tests/api/email.ts +3 -6
  158. package/src/tests/api/environment.ts +15 -0
  159. package/src/tests/api/index.ts +15 -0
  160. package/src/tests/api/migrations.ts +22 -0
  161. package/src/tests/api/restore.ts +14 -0
  162. package/src/tests/api/self.ts +11 -6
  163. package/src/tests/api/status.ts +12 -0
  164. package/src/tests/api/tenants.ts +15 -0
  165. package/src/tests/api/users.ts +38 -6
  166. package/src/tests/index.ts +5 -1
  167. package/{scripts/jestSetup.js → src/tests/jestSetup.ts} +12 -3
  168. package/src/tests/structures/configs.js +6 -6
  169. package/src/tests/structures/index.ts +4 -2
  170. package/src/tests/structures/users.ts +1 -0
  171. package/src/utilities/appService.js +3 -3
  172. package/src/utilities/{email.js → email.ts} +78 -45
  173. package/src/utilities/{redis.js → redis.ts} +29 -24
  174. package/src/utilities/templates.ts +49 -0
  175. package/tsconfig.build.json +2 -2
  176. package/tsconfig.json +3 -1
  177. package/src/api/routes/system/environment.js +0 -8
  178. package/src/api/routes/system/status.js +0 -8
  179. package/src/api/routes/system/tenants.js +0 -12
  180. package/src/db/index.js +0 -11
  181. package/src/tests/structures/accounts.ts +0 -24
  182. package/src/utilities/templates.js +0 -49
@@ -0,0 +1,913 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/api/controllers/global/auth.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> auth.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">64.51% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>100/155</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">36.36% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>8/22</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">48.83% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>21/43</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">61.47% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>75/122</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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">17x</span>
343
+ <span class="cline-any cline-yes">17x</span>
344
+ <span class="cline-any cline-neutral">&nbsp;</span>
345
+ <span class="cline-any cline-neutral">&nbsp;</span>
346
+ <span class="cline-any cline-neutral">&nbsp;</span>
347
+ <span class="cline-any cline-neutral">&nbsp;</span>
348
+ <span class="cline-any cline-neutral">&nbsp;</span>
349
+ <span class="cline-any cline-yes">17x</span>
350
+ <span class="cline-any cline-yes">17x</span>
351
+ <span class="cline-any cline-yes">17x</span>
352
+ <span class="cline-any cline-yes">17x</span>
353
+ <span class="cline-any cline-yes">17x</span>
354
+ <span class="cline-any cline-neutral">&nbsp;</span>
355
+ <span class="cline-any cline-yes">17x</span>
356
+ <span class="cline-any cline-yes">17x</span>
357
+ <span class="cline-any cline-yes">17x</span>
358
+ <span class="cline-any cline-neutral">&nbsp;</span>
359
+ <span class="cline-any cline-yes">17x</span>
360
+ <span class="cline-any cline-no">&nbsp;</span>
361
+ <span class="cline-any cline-neutral">&nbsp;</span>
362
+ <span class="cline-any cline-neutral">&nbsp;</span>
363
+ <span class="cline-any cline-yes">17x</span>
364
+ <span class="cline-any cline-yes">3x</span>
365
+ <span class="cline-any cline-neutral">&nbsp;</span>
366
+ <span class="cline-any cline-neutral">&nbsp;</span>
367
+ <span class="cline-any cline-neutral">&nbsp;</span>
368
+ <span class="cline-any cline-yes">1x</span>
369
+ <span class="cline-any cline-no">&nbsp;</span>
370
+ <span class="cline-any cline-no">&nbsp;</span>
371
+ <span class="cline-any cline-neutral">&nbsp;</span>
372
+ <span class="cline-any cline-neutral">&nbsp;</span>
373
+ <span class="cline-any cline-yes">1x</span>
374
+ <span class="cline-any cline-no">&nbsp;</span>
375
+ <span class="cline-any cline-neutral">&nbsp;</span>
376
+ <span class="cline-any cline-neutral">&nbsp;</span>
377
+ <span class="cline-any cline-neutral">&nbsp;</span>
378
+ <span class="cline-any cline-yes">1x</span>
379
+ <span class="cline-any cline-neutral">&nbsp;</span>
380
+ <span class="cline-any cline-yes">1x</span>
381
+ <span class="cline-any cline-neutral">&nbsp;</span>
382
+ <span class="cline-any cline-neutral">&nbsp;</span>
383
+ <span class="cline-any cline-yes">1x</span>
384
+ <span class="cline-any cline-no">&nbsp;</span>
385
+ <span class="cline-any cline-neutral">&nbsp;</span>
386
+ <span class="cline-any cline-neutral">&nbsp;</span>
387
+ <span class="cline-any cline-neutral">&nbsp;</span>
388
+ <span class="cline-any cline-yes">17x</span>
389
+ <span class="cline-any cline-no">&nbsp;</span>
390
+ <span class="cline-any cline-neutral">&nbsp;</span>
391
+ <span class="cline-any cline-no">&nbsp;</span>
392
+ <span class="cline-any cline-no">&nbsp;</span>
393
+ <span class="cline-any cline-no">&nbsp;</span>
394
+ <span class="cline-any cline-no">&nbsp;</span>
395
+ <span class="cline-any cline-neutral">&nbsp;</span>
396
+ <span class="cline-any cline-no">&nbsp;</span>
397
+ <span class="cline-any cline-neutral">&nbsp;</span>
398
+ <span class="cline-any cline-neutral">&nbsp;</span>
399
+ <span class="cline-any cline-neutral">&nbsp;</span>
400
+ <span class="cline-any cline-neutral">&nbsp;</span>
401
+ <span class="cline-any cline-yes">17x</span>
402
+ <span class="cline-any cline-no">&nbsp;</span>
403
+ <span class="cline-any cline-no">&nbsp;</span>
404
+ <span class="cline-any cline-no">&nbsp;</span>
405
+ <span class="cline-any cline-neutral">&nbsp;</span>
406
+ <span class="cline-any cline-neutral">&nbsp;</span>
407
+ <span class="cline-any cline-yes">17x</span>
408
+ <span class="cline-any cline-no">&nbsp;</span>
409
+ <span class="cline-any cline-no">&nbsp;</span>
410
+ <span class="cline-any cline-neutral">&nbsp;</span>
411
+ <span class="cline-any cline-no">&nbsp;</span>
412
+ <span class="cline-any cline-no">&nbsp;</span>
413
+ <span class="cline-any cline-neutral">&nbsp;</span>
414
+ <span class="cline-any cline-neutral">&nbsp;</span>
415
+ <span class="cline-any cline-neutral">&nbsp;</span>
416
+ <span class="cline-any cline-neutral">&nbsp;</span>
417
+ <span class="cline-any cline-neutral">&nbsp;</span>
418
+ <span class="cline-any cline-neutral">&nbsp;</span>
419
+ <span class="cline-any cline-yes">17x</span>
420
+ <span class="cline-any cline-yes">2x</span>
421
+ <span class="cline-any cline-yes">2x</span>
422
+ <span class="cline-any cline-yes">2x</span>
423
+ <span class="cline-any cline-no">&nbsp;</span>
424
+ <span class="cline-any cline-neutral">&nbsp;</span>
425
+ <span class="cline-any cline-neutral">&nbsp;</span>
426
+ <span class="cline-any cline-neutral">&nbsp;</span>
427
+ <span class="cline-any cline-neutral">&nbsp;</span>
428
+ <span class="cline-any cline-yes">2x</span>
429
+ <span class="cline-any cline-yes">2x</span>
430
+ <span class="cline-any cline-neutral">&nbsp;</span>
431
+ <span class="cline-any cline-yes">2x</span>
432
+ <span class="cline-any cline-yes">2x</span>
433
+ <span class="cline-any cline-neutral">&nbsp;</span>
434
+ <span class="cline-any cline-neutral">&nbsp;</span>
435
+ <span class="cline-any cline-neutral">&nbsp;</span>
436
+ <span class="cline-any cline-yes">2x</span>
437
+ <span class="cline-any cline-neutral">&nbsp;</span>
438
+ <span class="cline-any cline-neutral">&nbsp;</span>
439
+ <span class="cline-any cline-no">&nbsp;</span>
440
+ <span class="cline-any cline-neutral">&nbsp;</span>
441
+ <span class="cline-any cline-neutral">&nbsp;</span>
442
+ <span class="cline-any cline-yes">2x</span>
443
+ <span class="cline-any cline-neutral">&nbsp;</span>
444
+ <span class="cline-any cline-neutral">&nbsp;</span>
445
+ <span class="cline-any cline-neutral">&nbsp;</span>
446
+ <span class="cline-any cline-neutral">&nbsp;</span>
447
+ <span class="cline-any cline-neutral">&nbsp;</span>
448
+ <span class="cline-any cline-neutral">&nbsp;</span>
449
+ <span class="cline-any cline-neutral">&nbsp;</span>
450
+ <span class="cline-any cline-yes">17x</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-yes">1x</span>
454
+ <span class="cline-any cline-yes">1x</span>
455
+ <span class="cline-any cline-yes">1x</span>
456
+ <span class="cline-any cline-yes">1x</span>
457
+ <span class="cline-any cline-yes">1x</span>
458
+ <span class="cline-any cline-yes">1x</span>
459
+ <span class="cline-any cline-neutral">&nbsp;</span>
460
+ <span class="cline-any cline-neutral">&nbsp;</span>
461
+ <span class="cline-any cline-neutral">&nbsp;</span>
462
+ <span class="cline-any cline-yes">1x</span>
463
+ <span class="cline-any cline-yes">1x</span>
464
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
468
+ <span class="cline-any cline-neutral">&nbsp;</span>
469
+ <span class="cline-any cline-neutral">&nbsp;</span>
470
+ <span class="cline-any cline-yes">17x</span>
471
+ <span class="cline-any cline-yes">1x</span>
472
+ <span class="cline-any cline-yes">1x</span>
473
+ <span class="cline-any cline-neutral">&nbsp;</span>
474
+ <span class="cline-any cline-yes">1x</span>
475
+ <span class="cline-any cline-neutral">&nbsp;</span>
476
+ <span class="cline-any cline-neutral">&nbsp;</span>
477
+ <span class="cline-any cline-yes">17x</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-neutral">&nbsp;</span>
482
+ <span class="cline-any cline-no">&nbsp;</span>
483
+ <span class="cline-any cline-neutral">&nbsp;</span>
484
+ <span class="cline-any cline-neutral">&nbsp;</span>
485
+ <span class="cline-any cline-neutral">&nbsp;</span>
486
+ <span class="cline-any cline-neutral">&nbsp;</span>
487
+ <span class="cline-any cline-neutral">&nbsp;</span>
488
+ <span class="cline-any cline-neutral">&nbsp;</span>
489
+ <span class="cline-any cline-neutral">&nbsp;</span>
490
+ <span class="cline-any cline-neutral">&nbsp;</span>
491
+ <span class="cline-any cline-neutral">&nbsp;</span>
492
+ <span class="cline-any cline-no">&nbsp;</span>
493
+ <span class="cline-any cline-neutral">&nbsp;</span>
494
+ <span class="cline-any cline-neutral">&nbsp;</span>
495
+ <span class="cline-any cline-yes">17x</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-no">&nbsp;</span>
499
+ <span class="cline-any cline-no">&nbsp;</span>
500
+ <span class="cline-any cline-no">&nbsp;</span>
501
+ <span class="cline-any cline-neutral">&nbsp;</span>
502
+ <span class="cline-any cline-neutral">&nbsp;</span>
503
+ <span class="cline-any cline-neutral">&nbsp;</span>
504
+ <span class="cline-any cline-neutral">&nbsp;</span>
505
+ <span class="cline-any cline-neutral">&nbsp;</span>
506
+ <span class="cline-any cline-neutral">&nbsp;</span>
507
+ <span class="cline-any cline-yes">17x</span>
508
+ <span class="cline-any cline-no">&nbsp;</span>
509
+ <span class="cline-any cline-neutral">&nbsp;</span>
510
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
515
+ <span class="cline-any cline-no">&nbsp;</span>
516
+ <span class="cline-any cline-neutral">&nbsp;</span>
517
+ <span class="cline-any cline-neutral">&nbsp;</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-no">&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">17x</span>
529
+ <span class="cline-any cline-no">&nbsp;</span>
530
+ <span class="cline-any cline-neutral">&nbsp;</span>
531
+ <span class="cline-any cline-no">&nbsp;</span>
532
+ <span class="cline-any cline-neutral">&nbsp;</span>
533
+ <span class="cline-any cline-neutral">&nbsp;</span>
534
+ <span class="cline-any cline-neutral">&nbsp;</span>
535
+ <span class="cline-any cline-no">&nbsp;</span>
536
+ <span class="cline-any cline-no">&nbsp;</span>
537
+ <span class="cline-any cline-neutral">&nbsp;</span>
538
+ <span class="cline-any cline-neutral">&nbsp;</span>
539
+ <span class="cline-any cline-neutral">&nbsp;</span>
540
+ <span class="cline-any cline-neutral">&nbsp;</span>
541
+ <span class="cline-any cline-neutral">&nbsp;</span>
542
+ <span class="cline-any cline-no">&nbsp;</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-no">&nbsp;</span>
546
+ <span class="cline-any cline-no">&nbsp;</span>
547
+ <span class="cline-any cline-no">&nbsp;</span>
548
+ <span class="cline-any cline-no">&nbsp;</span>
549
+ <span class="cline-any cline-neutral">&nbsp;</span>
550
+ <span class="cline-any cline-no">&nbsp;</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-neutral">&nbsp;</span>
554
+ <span class="cline-any cline-neutral">&nbsp;</span>
555
+ <span class="cline-any cline-yes">17x</span>
556
+ <span class="cline-any cline-yes">3x</span>
557
+ <span class="cline-any cline-yes">3x</span>
558
+ <span class="cline-any cline-neutral">&nbsp;</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">3x</span>
563
+ <span class="cline-any cline-yes">3x</span>
564
+ <span class="cline-any cline-neutral">&nbsp;</span>
565
+ <span class="cline-any cline-neutral">&nbsp;</span>
566
+ <span class="cline-any cline-yes">3x</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-neutral">&nbsp;</span>
570
+ <span class="cline-any cline-yes">3x</span>
571
+ <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
576
+ <span class="cline-any cline-neutral">&nbsp;</span>
577
+ <span class="cline-any cline-yes">17x</span>
578
+ <span class="cline-any cline-yes">2x</span>
579
+ <span class="cline-any cline-yes">2x</span>
580
+ <span class="cline-any cline-neutral">&nbsp;</span>
581
+ <span class="cline-any cline-yes">2x</span>
582
+ <span class="cline-any cline-neutral">&nbsp;</span>
583
+ <span class="cline-any cline-yes">2x</span>
584
+ <span class="cline-any cline-yes">2x</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-neutral">&nbsp;</span>
588
+ <span class="cline-any cline-neutral">&nbsp;</span>
589
+ <span class="cline-any cline-yes">2x</span>
590
+ <span class="cline-any cline-neutral">&nbsp;</span>
591
+ <span class="cline-any cline-neutral">&nbsp;</span>
592
+ <span class="cline-any cline-yes">2x</span>
593
+ <span class="cline-any cline-neutral">&nbsp;</span>
594
+ <span class="cline-any cline-neutral">&nbsp;</span>
595
+ <span class="cline-any cline-neutral">&nbsp;</span>
596
+ <span class="cline-any cline-yes">2x</span>
597
+ <span class="cline-any cline-neutral">&nbsp;</span>
598
+ <span class="cline-any cline-neutral">&nbsp;</span>
599
+ <span class="cline-any cline-neutral">&nbsp;</span>
600
+ <span class="cline-any cline-neutral">&nbsp;</span>
601
+ <span class="cline-any cline-neutral">&nbsp;</span>
602
+ <span class="cline-any cline-yes">17x</span>
603
+ <span class="cline-any cline-yes">1x</span>
604
+ <span class="cline-any cline-yes">1x</span>
605
+ <span class="cline-any cline-neutral">&nbsp;</span>
606
+ <span class="cline-any cline-yes">1x</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-yes">1x</span>
612
+ <span class="cline-any cline-yes">1x</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-neutral">&nbsp;</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import core from "@budibase/backend-core"
619
+ import {
620
+ events,
621
+ users as usersCore,
622
+ context,
623
+ tenancy,
624
+ } from "@budibase/backend-core"
625
+ import { Config, EmailTemplatePurpose } from "../../../constants"
626
+ import { sendEmail, isEmailConfigured } from "../../../utilities/email"
627
+ import { checkResetPasswordCode } from "../../../utilities/redis"
628
+ import env from "../../../environment"
629
+ import sdk from "../../../sdk"
630
+ import { User } from "@budibase/types"
631
+ const { setCookie, getCookie, clearCookie, hash, platformLogout } = core.utils
632
+ const { Cookie, Header } = core.constants
633
+ const { passport, ssoCallbackUrl, google, oidc } = core.auth
634
+ &nbsp;
635
+ export const googleCallbackUrl = <span class="fstat-no" title="function not covered" >async (c</span>onfig: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
636
+ <span class="cstat-no" title="statement not covered" > return ssoCallbackUrl(tenancy.getGlobalDB(), config, "google")</span>
637
+ }
638
+ &nbsp;
639
+ export const oidcCallbackUrl = async (config: any) =&gt; {
640
+ return ssoCallbackUrl(tenancy.getGlobalDB(), config, "oidc")
641
+ }
642
+ &nbsp;
643
+ async function authInternal(ctx: any, user: any, err = <span class="branch-0 cbranch-no" title="branch not covered" >null,</span> info = <span class="branch-0 cbranch-no" title="branch not covered" >null)</span> {
644
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (err) {
645
+ <span class="cstat-no" title="statement not covered" > console.error("Authentication error", err)</span>
646
+ <span class="cstat-no" title="statement not covered" > return ctx.throw(403, info ? info : "Unauthorized")</span>
647
+ }
648
+ &nbsp;
649
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!user) {
650
+ <span class="cstat-no" title="statement not covered" > return ctx.throw(403, info ? info : "Unauthorized")</span>
651
+ }
652
+ &nbsp;
653
+ // set a cookie for browser access
654
+ setCookie(ctx, user.token, Cookie.Auth, { sign: false })
655
+ // set the token in a header as well for APIs
656
+ ctx.set(Header.TOKEN, user.token)
657
+ // get rid of any app cookies on login
658
+ // have to check test because this breaks cypress
659
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!env.isTest()) {
660
+ <span class="cstat-no" title="statement not covered" > clearCookie(ctx, Cookie.CurrentApp)</span>
661
+ }
662
+ }
663
+ &nbsp;
664
+ export const authenticate = <span class="fstat-no" title="function not covered" >async (c</span>tx: any, next: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
665
+ <span class="cstat-no" title="statement not covered" > return passport.authenticate(</span>
666
+ "local",
667
+ <span class="fstat-no" title="function not covered" > async (e</span>rr: any, user: User, info: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
668
+ <span class="cstat-no" title="statement not covered" > await authInternal(ctx, user, err, info)</span>
669
+ <span class="cstat-no" title="statement not covered" > await context.identity.doInUserContext(user, <span class="fstat-no" title="function not covered" >async () =</span>&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span></span>
670
+ <span class="cstat-no" title="statement not covered" > await events.auth.login("local")</span>
671
+ })
672
+ <span class="cstat-no" title="statement not covered" > ctx.status = 200</span>
673
+ }
674
+ )(ctx, next)
675
+ }
676
+ &nbsp;
677
+ export const setInitInfo = <span class="fstat-no" title="function not covered" >(c</span>tx: any) =&gt; {
678
+ const initInfo = <span class="cstat-no" title="statement not covered" >ctx.request.body</span>
679
+ <span class="cstat-no" title="statement not covered" > setCookie(ctx, initInfo, Cookie.Init)</span>
680
+ <span class="cstat-no" title="statement not covered" > ctx.status = 200</span>
681
+ }
682
+ &nbsp;
683
+ export const getInitInfo = <span class="fstat-no" title="function not covered" >(c</span>tx: any) =&gt; {
684
+ <span class="cstat-no" title="statement not covered" > try {</span>
685
+ <span class="cstat-no" title="statement not covered" > ctx.body = getCookie(ctx, Cookie.Init) || {}</span>
686
+ } catch (err) {
687
+ <span class="cstat-no" title="statement not covered" > clearCookie(ctx, Cookie.Init)</span>
688
+ <span class="cstat-no" title="statement not covered" > ctx.body = {}</span>
689
+ }
690
+ }
691
+ &nbsp;
692
+ /**
693
+ * Reset the user password, used as part of a forgotten password flow.
694
+ */
695
+ export const reset = async (ctx: any) =&gt; {
696
+ const { email } = ctx.request.body
697
+ const configured = await isEmailConfigured()
698
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!configured) {
699
+ <span class="cstat-no" title="statement not covered" > ctx.throw(</span>
700
+ 400,
701
+ "Please contact your platform administrator, SMTP is not configured."
702
+ )
703
+ }
704
+ try {
705
+ const user = (await usersCore.getGlobalUserByEmail(email)) as User
706
+ // only if user exists, don't error though if they don't
707
+ if (user) {
708
+ await sendEmail(email, EmailTemplatePurpose.PASSWORD_RECOVERY, {
709
+ user,
710
+ subject: "{{ company }} platform password reset",
711
+ })
712
+ await events.user.passwordResetRequested(user)
713
+ }
714
+ } catch (err) {
715
+ <span class="cstat-no" title="statement not covered" > console.log(err)</span>
716
+ // don't throw any kind of error to the user, this might give away something
717
+ }
718
+ ctx.body = {
719
+ message: "Please check your email for a reset link.",
720
+ }
721
+ }
722
+ &nbsp;
723
+ /**
724
+ * Perform the user password update if the provided reset code is valid.
725
+ */
726
+ export const resetUpdate = async (ctx: any) =&gt; {
727
+ const { resetCode, password } = ctx.request.body
728
+ try {
729
+ const { userId } = await checkResetPasswordCode(resetCode)
730
+ const db = tenancy.getGlobalDB()
731
+ const user = await db.get(userId)
732
+ user.password = await hash(password)
733
+ await db.put(user)
734
+ ctx.body = {
735
+ message: "password reset successfully.",
736
+ }
737
+ // remove password from the user before sending events
738
+ delete user.password
739
+ await events.user.passwordReset(user)
740
+ } catch (err) {
741
+ <span class="cstat-no" title="statement not covered" > console.error(err)</span>
742
+ <span class="cstat-no" title="statement not covered" > ctx.throw(400, "Cannot reset password.")</span>
743
+ }
744
+ }
745
+ &nbsp;
746
+ export const logout = async (ctx: any) =&gt; {
747
+ if (ctx.user &amp;&amp; ctx.user._id) {
748
+ await platformLogout({ ctx, userId: ctx.user._id })
749
+ }
750
+ ctx.body = { message: "User logged out." }
751
+ }
752
+ &nbsp;
753
+ export const datasourcePreAuth = <span class="fstat-no" title="function not covered" >async (c</span>tx: any, next: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
754
+ const provider = <span class="cstat-no" title="statement not covered" >ctx.params.provider</span>
755
+ const middleware = <span class="cstat-no" title="statement not covered" >require(`@budibase/backend-core/middleware`)</span>
756
+ const handler = <span class="cstat-no" title="statement not covered" >middleware.datasource[provider]</span>
757
+ &nbsp;
758
+ <span class="cstat-no" title="statement not covered" > setCookie(</span>
759
+ ctx,
760
+ {
761
+ provider,
762
+ appId: ctx.query.appId,
763
+ datasourceId: ctx.query.datasourceId,
764
+ },
765
+ Cookie.DatasourceAuth
766
+ )
767
+ &nbsp;
768
+ <span class="cstat-no" title="statement not covered" > return handler.preAuth(passport, ctx, next)</span>
769
+ }
770
+ &nbsp;
771
+ export const datasourceAuth = <span class="fstat-no" title="function not covered" >async (c</span>tx: any, next: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
772
+ const authStateCookie = <span class="cstat-no" title="statement not covered" >getCookie(ctx, Cookie.DatasourceAuth)</span>
773
+ const provider = <span class="cstat-no" title="statement not covered" >authStateCookie.provider</span>
774
+ const middleware = <span class="cstat-no" title="statement not covered" >require(`@budibase/backend-core/middleware`)</span>
775
+ const handler = <span class="cstat-no" title="statement not covered" >middleware.datasource[provider]</span>
776
+ <span class="cstat-no" title="statement not covered" > return handler.postAuth(passport, ctx, next)</span>
777
+ }
778
+ &nbsp;
779
+ /**
780
+ * The initial call that google authentication makes to take you to the google login screen.
781
+ * On a successful login, you will be redirected to the googleAuth callback route.
782
+ */
783
+ export const googlePreAuth = <span class="fstat-no" title="function not covered" >async (c</span>tx: any, next: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
784
+ const db = <span class="cstat-no" title="statement not covered" >tenancy.getGlobalDB()</span>
785
+ &nbsp;
786
+ const config = <span class="cstat-no" title="statement not covered" >await core.db.getScopedConfig(db, {</span>
787
+ type: Config.GOOGLE,
788
+ workspace: ctx.query.workspace,
789
+ })
790
+ let callbackUrl = <span class="cstat-no" title="statement not covered" >await exports.googleCallbackUrl(config)</span>
791
+ const strategy = <span class="cstat-no" title="statement not covered" >await google.strategyFactory(</span>
792
+ config,
793
+ callbackUrl,
794
+ sdk.users.save
795
+ )
796
+ &nbsp;
797
+ <span class="cstat-no" title="statement not covered" > return passport.authenticate(strategy, {</span>
798
+ scope: ["profile", "email"],
799
+ accessType: "offline",
800
+ prompt: "consent",
801
+ })(ctx, next)
802
+ }
803
+ &nbsp;
804
+ export const googleAuth = <span class="fstat-no" title="function not covered" >async (c</span>tx: any, next: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
805
+ const db = <span class="cstat-no" title="statement not covered" >tenancy.getGlobalDB()</span>
806
+ &nbsp;
807
+ const config = <span class="cstat-no" title="statement not covered" >await core.db.getScopedConfig(db, {</span>
808
+ type: Config.GOOGLE,
809
+ workspace: ctx.query.workspace,
810
+ })
811
+ const callbackUrl = <span class="cstat-no" title="statement not covered" >await exports.googleCallbackUrl(config)</span>
812
+ const strategy = <span class="cstat-no" title="statement not covered" >await google.strategyFactory(</span>
813
+ config,
814
+ callbackUrl,
815
+ sdk.users.save
816
+ )
817
+ &nbsp;
818
+ <span class="cstat-no" title="statement not covered" > return passport.authenticate(</span>
819
+ strategy,
820
+ { successRedirect: "/", failureRedirect: "/error" },
821
+ <span class="fstat-no" title="function not covered" > async (e</span>rr: any, user: User, info: any) =&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span>
822
+ <span class="cstat-no" title="statement not covered" > await authInternal(ctx, user, err, info)</span>
823
+ <span class="cstat-no" title="statement not covered" > await context.identity.doInUserContext(user, <span class="fstat-no" title="function not covered" >async () =</span>&gt;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" > {</span></span></span>
824
+ <span class="cstat-no" title="statement not covered" > await events.auth.login("google-internal")</span>
825
+ })
826
+ <span class="cstat-no" title="statement not covered" > ctx.redirect("/")</span>
827
+ }
828
+ )(ctx, next)
829
+ }
830
+ &nbsp;
831
+ export const oidcStrategyFactory = async (ctx: any, configId: any) =&gt; {
832
+ const db = tenancy.getGlobalDB()
833
+ const config = await core.db.getScopedConfig(db, {
834
+ type: Config.OIDC,
835
+ group: ctx.query.group,
836
+ })
837
+ &nbsp;
838
+ const chosenConfig = config.configs.filter((c: any) =&gt; c.uuid === configId)[0]
839
+ let callbackUrl = await exports.oidcCallbackUrl(chosenConfig)
840
+ &nbsp;
841
+ //Remote Config
842
+ const enrichedConfig = await oidc.fetchStrategyConfig(
843
+ chosenConfig,
844
+ callbackUrl
845
+ )
846
+ return oidc.strategyFactory(enrichedConfig, sdk.users.save)
847
+ }
848
+ &nbsp;
849
+ /**
850
+ * The initial call that OIDC authentication makes to take you to the configured OIDC login screen.
851
+ * On a successful login, you will be redirected to the oidcAuth callback route.
852
+ */
853
+ export const oidcPreAuth = async (ctx: any, next: any) =&gt; {
854
+ const { configId } = ctx.params
855
+ const strategy = await oidcStrategyFactory(ctx, configId)
856
+ &nbsp;
857
+ setCookie(ctx, configId, Cookie.OIDC_CONFIG)
858
+ &nbsp;
859
+ const db = tenancy.getGlobalDB()
860
+ const config = await core.db.getScopedConfig(db, {
861
+ type: Config.OIDC,
862
+ group: ctx.query.group,
863
+ })
864
+ &nbsp;
865
+ const chosenConfig = config.configs.filter((c: any) =&gt; c.uuid === configId)[0]
866
+ &nbsp;
867
+ let authScopes =
868
+ chosenConfig.scopes<span class="branch-1 cbranch-no" title="branch not covered" >?.length </span>&gt; 0
869
+ ? <span class="branch-0 cbranch-no" title="branch not covered" >chosenConfig.scopes</span>
870
+ : ["profile", "email", "offline_access"]
871
+ &nbsp;
872
+ return passport.authenticate(strategy, {
873
+ // required 'openid' scope is added by oidc strategy factory
874
+ scope: authScopes,
875
+ })(ctx, next)
876
+ }
877
+ &nbsp;
878
+ export const oidcAuth = async (ctx: any, next: any) =&gt; {
879
+ const configId = getCookie(ctx, Cookie.OIDC_CONFIG)
880
+ const strategy = await oidcStrategyFactory(ctx, configId)
881
+ &nbsp;
882
+ return passport.authenticate(
883
+ strategy,
884
+ { successRedirect: "/", failureRedirect: "/error" },
885
+ async (err: any, user: any, info: any) =&gt; {
886
+ await authInternal(ctx, user, err, info)
887
+ await context.identity.doInUserContext(user, async () =&gt; {
888
+ await events.auth.login("oidc")
889
+ })
890
+ ctx.redirect("/")
891
+ }
892
+ )(ctx, next)
893
+ }
894
+ &nbsp;</pre></td></tr></table></pre>
895
+
896
+ <div class='push'></div><!-- for sticky footer -->
897
+ </div><!-- /wrapper -->
898
+ <div class='footer quiet pad2 space-top1 center small'>
899
+ Code coverage generated by
900
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
901
+ at Mon Nov 21 2022 15:53:33 GMT+0000 (Coordinated Universal Time)
902
+ </div>
903
+ <script src="../../../../prettify.js"></script>
904
+ <script>
905
+ window.onload = function () {
906
+ prettyPrint();
907
+ };
908
+ </script>
909
+ <script src="../../../../sorter.js"></script>
910
+ <script src="../../../../block-navigation.js"></script>
911
+ </body>
912
+ </html>
913
+