@budibase/worker 2.1.40-alpha.4 → 2.1.41

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 (208) hide show
  1. package/package.json +24 -14
  2. package/{src/tests/jestSetup.ts → scripts/jestSetup.js} +3 -12
  3. package/scripts/localdomain.js +7 -33
  4. package/src/api/controllers/global/auth.ts +43 -51
  5. package/src/api/controllers/global/{configs.ts → configs.js} +114 -119
  6. package/src/api/controllers/global/{email.ts → email.js} +5 -6
  7. package/src/api/controllers/global/roles.js +68 -0
  8. package/src/api/controllers/global/self.ts +2 -2
  9. package/src/api/controllers/global/users.ts +2 -4
  10. package/src/api/controllers/global/{workspaces.ts → workspaces.js} +18 -15
  11. package/src/api/controllers/system/{environment.ts → environment.js} +2 -3
  12. package/src/api/controllers/system/restore.ts +1 -1
  13. package/src/api/controllers/system/{status.ts → status.js} +3 -4
  14. package/src/api/controllers/system/tenants.ts +51 -8
  15. package/src/api/index.ts +8 -31
  16. package/src/api/routes/global/{auth.ts → auth.js} +48 -31
  17. package/src/api/routes/global/{configs.ts → configs.js} +23 -22
  18. package/src/api/routes/global/{email.ts → email.js} +10 -9
  19. package/src/api/routes/global/license.ts +1 -1
  20. package/src/api/routes/global/roles.js +12 -0
  21. package/src/api/routes/global/self.ts +2 -2
  22. package/src/api/routes/global/templates.ts +4 -4
  23. package/src/api/routes/global/tests/auth.spec.ts +64 -134
  24. package/src/api/routes/global/tests/configs.spec.ts +35 -34
  25. package/src/api/routes/global/tests/email.spec.ts +3 -4
  26. package/src/api/routes/global/tests/realEmail.spec.ts +3 -2
  27. package/src/api/routes/global/tests/self.spec.ts +4 -3
  28. package/src/api/routes/global/tests/users.spec.ts +59 -51
  29. package/src/api/routes/global/{users.ts → users.js} +32 -26
  30. package/src/api/routes/global/{workspaces.ts → workspaces.js} +10 -9
  31. package/src/api/routes/index.ts +1 -2
  32. package/src/api/routes/system/accounts.ts +1 -1
  33. package/src/api/routes/system/environment.js +8 -0
  34. package/src/api/routes/system/migrations.ts +1 -1
  35. package/src/api/routes/system/restore.ts +1 -1
  36. package/src/api/routes/system/status.js +8 -0
  37. package/src/api/routes/system/tenants.js +12 -0
  38. package/src/api/routes/system/tests/accounts.spec.ts +6 -5
  39. package/src/api/routes/validation/users.ts +3 -3
  40. package/src/constants/{index.ts → index.js} +64 -57
  41. package/src/constants/templates/{index.ts → index.js} +19 -23
  42. package/src/db/index.js +11 -0
  43. package/src/environment.ts +7 -9
  44. package/src/index.ts +16 -15
  45. package/src/middleware/{cloudRestricted.ts → cloudRestricted.js} +4 -5
  46. package/src/tests/TestConfiguration.ts +50 -99
  47. package/src/tests/api/accounts.ts +8 -5
  48. package/src/tests/api/auth.ts +6 -3
  49. package/src/tests/api/configs.ts +8 -15
  50. package/src/tests/api/email.ts +6 -3
  51. package/src/tests/api/index.ts +0 -15
  52. package/src/tests/api/self.ts +6 -11
  53. package/src/tests/api/users.ts +8 -40
  54. package/src/tests/controllers.js +7 -0
  55. package/src/tests/index.ts +1 -5
  56. package/src/tests/structures/accounts.ts +24 -0
  57. package/src/tests/structures/{configs.ts → configs.js} +11 -11
  58. package/src/tests/structures/index.ts +3 -5
  59. package/src/tests/structures/users.ts +0 -1
  60. package/src/utilities/appService.js +33 -0
  61. package/src/utilities/{email.ts → email.js} +45 -78
  62. package/src/utilities/fileSystem.js +5 -0
  63. package/src/utilities/{index.ts → index.js} +1 -1
  64. package/src/utilities/{redis.ts → redis.js} +24 -29
  65. package/src/utilities/templates.js +49 -0
  66. package/src/utilities/users.js +17 -0
  67. package/tsconfig.build.json +3 -2
  68. package/tsconfig.json +1 -3
  69. package/__mocks__/aws-sdk.ts +0 -15
  70. package/__mocks__/oauth.ts +0 -57
  71. package/coverage/clover.xml +0 -2153
  72. package/coverage/coverage-final.json +0 -78
  73. package/coverage/lcov-report/base.css +0 -224
  74. package/coverage/lcov-report/block-navigation.js +0 -87
  75. package/coverage/lcov-report/favicon.png +0 -0
  76. package/coverage/lcov-report/index.html +0 -431
  77. package/coverage/lcov-report/prettify.css +0 -1
  78. package/coverage/lcov-report/prettify.js +0 -2
  79. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  80. package/coverage/lcov-report/sorter.js +0 -196
  81. package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +0 -925
  82. package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +0 -1405
  83. package/coverage/lcov-report/src/api/controllers/global/email.ts.html +0 -196
  84. package/coverage/lcov-report/src/api/controllers/global/index.html +0 -236
  85. package/coverage/lcov-report/src/api/controllers/global/license.ts.html +0 -187
  86. package/coverage/lcov-report/src/api/controllers/global/roles.ts.html +0 -283
  87. package/coverage/lcov-report/src/api/controllers/global/self.ts.html +0 -577
  88. package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +0 -316
  89. package/coverage/lcov-report/src/api/controllers/global/users.ts.html +0 -796
  90. package/coverage/lcov-report/src/api/controllers/global/workspaces.ts.html +0 -244
  91. package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +0 -148
  92. package/coverage/lcov-report/src/api/controllers/system/environment.ts.html +0 -124
  93. package/coverage/lcov-report/src/api/controllers/system/index.html +0 -191
  94. package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +0 -124
  95. package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +0 -124
  96. package/coverage/lcov-report/src/api/controllers/system/status.ts.html +0 -133
  97. package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +0 -154
  98. package/coverage/lcov-report/src/api/index.html +0 -116
  99. package/coverage/lcov-report/src/api/index.ts.html +0 -583
  100. package/coverage/lcov-report/src/api/routes/global/auth.ts.html +0 -349
  101. package/coverage/lcov-report/src/api/routes/global/configs.ts.html +0 -457
  102. package/coverage/lcov-report/src/api/routes/global/email.ts.html +0 -193
  103. package/coverage/lcov-report/src/api/routes/global/index.html +0 -236
  104. package/coverage/lcov-report/src/api/routes/global/license.ts.html +0 -124
  105. package/coverage/lcov-report/src/api/routes/global/roles.ts.html +0 -133
  106. package/coverage/lcov-report/src/api/routes/global/self.ts.html +0 -139
  107. package/coverage/lcov-report/src/api/routes/global/templates.ts.html +0 -196
  108. package/coverage/lcov-report/src/api/routes/global/users.ts.html +0 -409
  109. package/coverage/lcov-report/src/api/routes/global/workspaces.ts.html +0 -196
  110. package/coverage/lcov-report/src/api/routes/index.html +0 -116
  111. package/coverage/lcov-report/src/api/routes/index.ts.html +0 -196
  112. package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +0 -142
  113. package/coverage/lcov-report/src/api/routes/system/environment.ts.html +0 -109
  114. package/coverage/lcov-report/src/api/routes/system/index.html +0 -191
  115. package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +0 -142
  116. package/coverage/lcov-report/src/api/routes/system/restore.ts.html +0 -109
  117. package/coverage/lcov-report/src/api/routes/system/status.ts.html +0 -109
  118. package/coverage/lcov-report/src/api/routes/system/tenants.ts.html +0 -124
  119. package/coverage/lcov-report/src/api/routes/validation/index.html +0 -131
  120. package/coverage/lcov-report/src/api/routes/validation/index.ts.html +0 -88
  121. package/coverage/lcov-report/src/api/routes/validation/users.ts.html +0 -235
  122. package/coverage/lcov-report/src/constants/index.html +0 -116
  123. package/coverage/lcov-report/src/constants/index.ts.html +0 -613
  124. package/coverage/lcov-report/src/constants/templates/index.html +0 -116
  125. package/coverage/lcov-report/src/constants/templates/index.ts.html +0 -316
  126. package/coverage/lcov-report/src/db/index.html +0 -116
  127. package/coverage/lcov-report/src/db/index.ts.html +0 -115
  128. package/coverage/lcov-report/src/environment.ts.html +0 -373
  129. package/coverage/lcov-report/src/index.html +0 -131
  130. package/coverage/lcov-report/src/index.ts.html +0 -394
  131. package/coverage/lcov-report/src/middleware/cloudRestricted.ts.html +0 -139
  132. package/coverage/lcov-report/src/middleware/index.html +0 -116
  133. package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +0 -145
  134. package/coverage/lcov-report/src/migrations/functions/index.html +0 -116
  135. package/coverage/lcov-report/src/migrations/index.html +0 -116
  136. package/coverage/lcov-report/src/migrations/index.ts.html +0 -271
  137. package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +0 -262
  138. package/coverage/lcov-report/src/sdk/accounts/index.html +0 -131
  139. package/coverage/lcov-report/src/sdk/accounts/index.ts.html +0 -88
  140. package/coverage/lcov-report/src/sdk/index.html +0 -116
  141. package/coverage/lcov-report/src/sdk/index.ts.html +0 -106
  142. package/coverage/lcov-report/src/sdk/users/events.ts.html +0 -577
  143. package/coverage/lcov-report/src/sdk/users/index.html +0 -146
  144. package/coverage/lcov-report/src/sdk/users/index.ts.html +0 -88
  145. package/coverage/lcov-report/src/sdk/users/users.ts.html +0 -1903
  146. package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1051
  147. package/coverage/lcov-report/src/tests/api/accounts.ts.html +0 -160
  148. package/coverage/lcov-report/src/tests/api/auth.ts.html +0 -220
  149. package/coverage/lcov-report/src/tests/api/base.ts.html +0 -133
  150. package/coverage/lcov-report/src/tests/api/configs.ts.html +0 -226
  151. package/coverage/lcov-report/src/tests/api/email.ts.html +0 -148
  152. package/coverage/lcov-report/src/tests/api/environment.ts.html +0 -130
  153. package/coverage/lcov-report/src/tests/api/index.html +0 -296
  154. package/coverage/lcov-report/src/tests/api/index.ts.html +0 -205
  155. package/coverage/lcov-report/src/tests/api/migrations.ts.html +0 -151
  156. package/coverage/lcov-report/src/tests/api/restore.ts.html +0 -127
  157. package/coverage/lcov-report/src/tests/api/self.ts.html +0 -163
  158. package/coverage/lcov-report/src/tests/api/status.ts.html +0 -121
  159. package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
  160. package/coverage/lcov-report/src/tests/api/users.ts.html +0 -511
  161. package/coverage/lcov-report/src/tests/controllers.ts.html +0 -100
  162. package/coverage/lcov-report/src/tests/index.html +0 -146
  163. package/coverage/lcov-report/src/tests/index.ts.html +0 -139
  164. package/coverage/lcov-report/src/tests/mocks/email.js.html +0 -115
  165. package/coverage/lcov-report/src/tests/mocks/index.html +0 -131
  166. package/coverage/lcov-report/src/tests/mocks/index.ts.html +0 -106
  167. package/coverage/lcov-report/src/tests/structures/configs.ts.html +0 -313
  168. package/coverage/lcov-report/src/tests/structures/groups.ts.html +0 -118
  169. package/coverage/lcov-report/src/tests/structures/index.html +0 -161
  170. package/coverage/lcov-report/src/tests/structures/index.ts.html +0 -151
  171. package/coverage/lcov-report/src/tests/structures/users.ts.html +0 -196
  172. package/coverage/lcov-report/src/utilities/appService.ts.html +0 -181
  173. package/coverage/lcov-report/src/utilities/email.ts.html +0 -850
  174. package/coverage/lcov-report/src/utilities/fileSystem.ts.html +0 -100
  175. package/coverage/lcov-report/src/utilities/index.html +0 -206
  176. package/coverage/lcov-report/src/utilities/index.ts.html +0 -112
  177. package/coverage/lcov-report/src/utilities/redis.ts.html +0 -424
  178. package/coverage/lcov-report/src/utilities/templates.ts.html +0 -232
  179. package/coverage/lcov-report/src/utilities/users.ts.html +0 -133
  180. package/coverage/lcov.info +0 -3958
  181. package/jest.config.ts +0 -29
  182. package/src/api/controllers/global/roles.ts +0 -66
  183. package/src/api/routes/global/roles.ts +0 -16
  184. package/src/api/routes/global/tests/license.spec.ts +0 -31
  185. package/src/api/routes/global/tests/roles.spec.ts +0 -27
  186. package/src/api/routes/global/tests/templates.spec.ts +0 -35
  187. package/src/api/routes/global/tests/workspaces.spec.ts +0 -29
  188. package/src/api/routes/system/environment.ts +0 -8
  189. package/src/api/routes/system/status.ts +0 -8
  190. package/src/api/routes/system/tenants.ts +0 -13
  191. package/src/api/routes/system/tests/environment.spec.ts +0 -29
  192. package/src/api/routes/system/tests/migrations.spec.ts +0 -63
  193. package/src/api/routes/system/tests/restore.spec.ts +0 -36
  194. package/src/api/routes/system/tests/status.spec.ts +0 -48
  195. package/src/api/routes/system/tests/tenants.spec.ts +0 -61
  196. package/src/db/index.ts +0 -10
  197. package/src/middleware/tests/tenancy.spec.ts +0 -73
  198. package/src/tests/api/base.ts +0 -16
  199. package/src/tests/api/environment.ts +0 -15
  200. package/src/tests/api/migrations.ts +0 -22
  201. package/src/tests/api/restore.ts +0 -14
  202. package/src/tests/api/status.ts +0 -12
  203. package/src/tests/api/tenants.ts +0 -15
  204. package/src/tests/controllers.ts +0 -5
  205. package/src/utilities/appService.ts +0 -32
  206. package/src/utilities/fileSystem.ts +0 -5
  207. package/src/utilities/templates.ts +0 -49
  208. package/src/utilities/users.ts +0 -16
@@ -1,850 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for src/utilities/email.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/utilities</a> email.ts</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">83.33% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>60/72</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">67.05% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>57/85</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">100% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>7/7</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">83.33% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>60/72</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 high'></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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">17x</span>
322
- <span class="cline-any cline-yes">17x</span>
323
- <span class="cline-any cline-yes">17x</span>
324
- <span class="cline-any cline-yes">17x</span>
325
- <span class="cline-any cline-yes">17x</span>
326
- <span class="cline-any cline-yes">17x</span>
327
- <span class="cline-any cline-neutral">&nbsp;</span>
328
- <span class="cline-any cline-yes">17x</span>
329
- <span class="cline-any cline-yes">17x</span>
330
- <span class="cline-any cline-neutral">&nbsp;</span>
331
- <span class="cline-any cline-neutral">&nbsp;</span>
332
- <span class="cline-any cline-neutral">&nbsp;</span>
333
- <span class="cline-any cline-neutral">&nbsp;</span>
334
- <span class="cline-any cline-neutral">&nbsp;</span>
335
- <span class="cline-any cline-neutral">&nbsp;</span>
336
- <span class="cline-any cline-neutral">&nbsp;</span>
337
- <span class="cline-any cline-neutral">&nbsp;</span>
338
- <span class="cline-any cline-neutral">&nbsp;</span>
339
- <span class="cline-any cline-neutral">&nbsp;</span>
340
- <span class="cline-any cline-neutral">&nbsp;</span>
341
- <span class="cline-any cline-neutral">&nbsp;</span>
342
- <span class="cline-any cline-neutral">&nbsp;</span>
343
- <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
352
- <span class="cline-any cline-yes">17x</span>
353
- <span class="cline-any cline-neutral">&nbsp;</span>
354
- <span class="cline-any cline-neutral">&nbsp;</span>
355
- <span class="cline-any cline-neutral">&nbsp;</span>
356
- <span class="cline-any cline-neutral">&nbsp;</span>
357
- <span class="cline-any cline-neutral">&nbsp;</span>
358
- <span class="cline-any cline-neutral">&nbsp;</span>
359
- <span class="cline-any cline-neutral">&nbsp;</span>
360
- <span class="cline-any cline-neutral">&nbsp;</span>
361
- <span class="cline-any cline-yes">22x</span>
362
- <span class="cline-any cline-neutral">&nbsp;</span>
363
- <span class="cline-any cline-yes">22x</span>
364
- <span class="cline-any cline-no">&nbsp;</span>
365
- <span class="cline-any cline-neutral">&nbsp;</span>
366
- <span class="cline-any cline-yes">22x</span>
367
- <span class="cline-any cline-yes">22x</span>
368
- <span class="cline-any cline-neutral">&nbsp;</span>
369
- <span class="cline-any cline-neutral">&nbsp;</span>
370
- <span class="cline-any cline-neutral">&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">22x</span>
374
- <span class="cline-any cline-neutral">&nbsp;</span>
375
- <span class="cline-any cline-neutral">&nbsp;</span>
376
- <span class="cline-any cline-yes">22x</span>
377
- <span class="cline-any cline-yes">3x</span>
378
- <span class="cline-any cline-neutral">&nbsp;</span>
379
- <span class="cline-any cline-neutral">&nbsp;</span>
380
- <span class="cline-any cline-no">&nbsp;</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-neutral">&nbsp;</span>
384
- <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
389
- <span class="cline-any cline-neutral">&nbsp;</span>
390
- <span class="cline-any cline-yes">22x</span>
391
- <span class="cline-any cline-neutral">&nbsp;</span>
392
- <span class="cline-any cline-neutral">&nbsp;</span>
393
- <span class="cline-any cline-neutral">&nbsp;</span>
394
- <span class="cline-any cline-neutral">&nbsp;</span>
395
- <span class="cline-any cline-neutral">&nbsp;</span>
396
- <span class="cline-any cline-neutral">&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-yes">7x</span>
400
- <span class="cline-any cline-neutral">&nbsp;</span>
401
- <span class="cline-any cline-yes">2x</span>
402
- <span class="cline-any cline-neutral">&nbsp;</span>
403
- <span class="cline-any cline-yes">5x</span>
404
- <span class="cline-any cline-neutral">&nbsp;</span>
405
- <span class="cline-any cline-no">&nbsp;</span>
406
- <span class="cline-any cline-neutral">&nbsp;</span>
407
- <span class="cline-any cline-neutral">&nbsp;</span>
408
- <span class="cline-any cline-neutral">&nbsp;</span>
409
- <span class="cline-any cline-neutral">&nbsp;</span>
410
- <span class="cline-any cline-neutral">&nbsp;</span>
411
- <span class="cline-any cline-neutral">&nbsp;</span>
412
- <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
420
- <span class="cline-any cline-neutral">&nbsp;</span>
421
- <span class="cline-any cline-neutral">&nbsp;</span>
422
- <span class="cline-any cline-neutral">&nbsp;</span>
423
- <span class="cline-any cline-neutral">&nbsp;</span>
424
- <span class="cline-any cline-neutral">&nbsp;</span>
425
- <span class="cline-any cline-yes">7x</span>
426
- <span class="cline-any cline-no">&nbsp;</span>
427
- <span class="cline-any cline-neutral">&nbsp;</span>
428
- <span class="cline-any cline-yes">7x</span>
429
- <span class="cline-any cline-neutral">&nbsp;</span>
430
- <span class="cline-any cline-neutral">&nbsp;</span>
431
- <span class="cline-any cline-neutral">&nbsp;</span>
432
- <span class="cline-any cline-yes">7x</span>
433
- <span class="cline-any cline-no">&nbsp;</span>
434
- <span class="cline-any cline-neutral">&nbsp;</span>
435
- <span class="cline-any cline-yes">7x</span>
436
- <span class="cline-any cline-yes">7x</span>
437
- <span class="cline-any cline-yes">7x</span>
438
- <span class="cline-any cline-yes">7x</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-yes">7x</span>
442
- <span class="cline-any cline-neutral">&nbsp;</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-yes">7x</span>
450
- <span class="cline-any cline-neutral">&nbsp;</span>
451
- <span class="cline-any cline-yes">7x</span>
452
- <span class="cline-any cline-neutral">&nbsp;</span>
453
- <span class="cline-any cline-neutral">&nbsp;</span>
454
- <span class="cline-any cline-neutral">&nbsp;</span>
455
- <span class="cline-any cline-neutral">&nbsp;</span>
456
- <span class="cline-any cline-neutral">&nbsp;</span>
457
- <span class="cline-any cline-neutral">&nbsp;</span>
458
- <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
463
- <span class="cline-any cline-neutral">&nbsp;</span>
464
- <span class="cline-any cline-neutral">&nbsp;</span>
465
- <span class="cline-any cline-neutral">&nbsp;</span>
466
- <span class="cline-any cline-neutral">&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-yes">9x</span>
470
- <span class="cline-any cline-neutral">&nbsp;</span>
471
- <span class="cline-any cline-neutral">&nbsp;</span>
472
- <span class="cline-any cline-yes">9x</span>
473
- <span class="cline-any cline-no">&nbsp;</span>
474
- <span class="cline-any cline-neutral">&nbsp;</span>
475
- <span class="cline-any cline-neutral">&nbsp;</span>
476
- <span class="cline-any cline-yes">9x</span>
477
- <span class="cline-any cline-neutral">&nbsp;</span>
478
- <span class="cline-any cline-yes">9x</span>
479
- <span class="cline-any cline-yes">9x</span>
480
- <span class="cline-any cline-neutral">&nbsp;</span>
481
- <span class="cline-any cline-neutral">&nbsp;</span>
482
- <span class="cline-any cline-neutral">&nbsp;</span>
483
- <span class="cline-any cline-no">&nbsp;</span>
484
- <span class="cline-any cline-no">&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-neutral">&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-neutral">&nbsp;</span>
496
- <span class="cline-any cline-neutral">&nbsp;</span>
497
- <span class="cline-any cline-neutral">&nbsp;</span>
498
- <span class="cline-any cline-neutral">&nbsp;</span>
499
- <span class="cline-any cline-neutral">&nbsp;</span>
500
- <span class="cline-any cline-neutral">&nbsp;</span>
501
- <span class="cline-any cline-yes">17x</span>
502
- <span class="cline-any cline-neutral">&nbsp;</span>
503
- <span class="cline-any cline-yes">2x</span>
504
- <span class="cline-any cline-no">&nbsp;</span>
505
- <span class="cline-any cline-neutral">&nbsp;</span>
506
- <span class="cline-any cline-yes">2x</span>
507
- <span class="cline-any cline-yes">2x</span>
508
- <span class="cline-any cline-yes">2x</span>
509
- <span class="cline-any cline-neutral">&nbsp;</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-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-yes">17x</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-yes">7x</span>
526
- <span class="cline-any cline-neutral">&nbsp;</span>
527
- <span class="cline-any cline-yes">7x</span>
528
- <span class="cline-any cline-yes">7x</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-yes">7x</span>
532
- <span class="cline-any cline-neutral">&nbsp;</span>
533
- <span class="cline-any cline-yes">7x</span>
534
- <span class="cline-any cline-neutral">&nbsp;</span>
535
- <span class="cline-any cline-yes">7x</span>
536
- <span class="cline-any cline-yes">7x</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-yes">7x</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-neutral">&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-neutral">&nbsp;</span>
546
- <span class="cline-any cline-neutral">&nbsp;</span>
547
- <span class="cline-any cline-yes">7x</span>
548
- <span class="cline-any cline-neutral">&nbsp;</span>
549
- <span class="cline-any cline-neutral">&nbsp;</span>
550
- <span class="cline-any cline-neutral">&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-yes">7x</span>
555
- <span class="cline-any cline-yes">7x</span>
556
- <span class="cline-any cline-neutral">&nbsp;</span>
557
- <span class="cline-any cline-neutral">&nbsp;</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-yes">7x</span>
561
- <span class="cline-any cline-yes">7x</span>
562
- <span class="cline-any cline-no">&nbsp;</span>
563
- <span class="cline-any cline-neutral">&nbsp;</span>
564
- <span class="cline-any cline-yes">7x</span>
565
- <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
570
- <span class="cline-any cline-neutral">&nbsp;</span>
571
- <span class="cline-any cline-neutral">&nbsp;</span>
572
- <span class="cline-any cline-yes">17x</span>
573
- <span class="cline-any cline-yes">15x</span>
574
- <span class="cline-any cline-yes">15x</span>
575
- <span class="cline-any cline-neutral">&nbsp;</span>
576
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import env from "../environment"
577
- import { EmailTemplatePurpose, TemplateType, Config } from "../constants"
578
- import { getTemplateByPurpose } from "../constants/templates"
579
- import { getSettingsTemplateContext } from "./templates"
580
- import { processString } from "@budibase/string-templates"
581
- import { getResetPasswordCode, getInviteCode } from "./redis"
582
- import { User, Database } from "@budibase/types"
583
- import { tenancy, db as dbCore } from "@budibase/backend-core"
584
- const nodemailer = require("nodemailer")
585
- &nbsp;
586
- type SendEmailOpts = {
587
- // workspaceId If finer grain controls being used then this will lookup config for workspace.
588
- workspaceId?: string
589
- // user If sending to an existing user the object can be provided, this is used in the context.
590
- user: User
591
- // from If sending from an address that is not what is configured in the SMTP config.
592
- from?: string
593
- // contents If sending a custom email then can supply contents which will be added to it.
594
- contents?: string
595
- // subject A custom subject can be specified if the config one is not desired.
596
- subject?: string
597
- // info Pass in a structure of information to be stored alongside the invitation.
598
- info?: any
599
- cc?: boolean
600
- bcc?: boolean
601
- automation?: boolean
602
- }
603
- &nbsp;
604
- const TEST_MODE = false
605
- const TYPE = TemplateType.EMAIL
606
- &nbsp;
607
- const FULL_EMAIL_PURPOSES = [
608
- EmailTemplatePurpose.INVITATION,
609
- EmailTemplatePurpose.PASSWORD_RECOVERY,
610
- EmailTemplatePurpose.WELCOME,
611
- EmailTemplatePurpose.CUSTOM,
612
- ]
613
- &nbsp;
614
- function createSMTPTransport(config: any) {
615
- let options: any
616
- let secure = config.secure
617
- // default it if not specified
618
- <span class="missing-if-branch" title="if path not taken" >I</span>if (secure == null) {
619
- <span class="cstat-no" title="statement not covered" > secure = config.port === 465</span>
620
- }
621
- if (!TEST_MODE) {
622
- options = {
623
- port: config.port,
624
- host: config.host,
625
- secure: secure,
626
- auth: config.auth,
627
- }
628
- options.tls = {
629
- rejectUnauthorized: false,
630
- }
631
- if (config.connectionTimeout) {
632
- options.connectionTimeout = config.connectionTimeout
633
- }
634
- } else <span class="missing-if-branch" title="else path not taken" >E</span>{
635
- <span class="cstat-no" title="statement not covered" > options = {</span>
636
- port: 587,
637
- host: "smtp.ethereal.email",
638
- secure: false,
639
- auth: {
640
- user: "don.bahringer@ethereal.email",
641
- pass: "yCKSH8rWyUPbnhGYk9",
642
- },
643
- }
644
- }
645
- return nodemailer.createTransport(options)
646
- }
647
- &nbsp;
648
- async function getLinkCode(
649
- purpose: EmailTemplatePurpose,
650
- email: string,
651
- user: User,
652
- info: any = null
653
- ) {
654
- switch (purpose) {
655
- case EmailTemplatePurpose.PASSWORD_RECOVERY:
656
- return getResetPasswordCode(user._id!, info)
657
- case EmailTemplatePurpose.INVITATION:
658
- return getInviteCode(email, info)
659
- <span class="branch-2 cbranch-no" title="branch not covered" > default:</span>
660
- <span class="cstat-no" title="statement not covered" > return null</span>
661
- }
662
- }
663
- &nbsp;
664
- /**
665
- * Builds an email using handlebars and the templates found in the system (default or otherwise).
666
- * @param {string} purpose the purpose of the email being built, e.g. invitation, password reset.
667
- * @param {string} email the address which it is being sent to for contextual purposes.
668
- * @param {object} context the context which is being used for building the email (hbs context).
669
- * @param {object|null} user if being sent to an existing user then the object can be provided for context.
670
- * @param {string|null} contents if using a custom template can supply contents for context.
671
- * @return {Promise&lt;string&gt;} returns the built email HTML if all provided parameters were valid.
672
- */
673
- async function buildEmail(
674
- purpose: EmailTemplatePurpose,
675
- email: string,
676
- context: any,
677
- { user, contents }: any = <span class="branch-0 cbranch-no" title="branch not covered" >{}</span>
678
- ) {
679
- // this isn't a full email
680
- <span class="missing-if-branch" title="if path not taken" >I</span>if (FULL_EMAIL_PURPOSES.indexOf(purpose) === -1) {
681
- <span class="cstat-no" title="statement not covered" > throw `Unable to build an email of type ${purpose}`</span>
682
- }
683
- let [base, body] = await Promise.all([
684
- getTemplateByPurpose(TYPE, EmailTemplatePurpose.BASE),
685
- getTemplateByPurpose(TYPE, purpose),
686
- ])
687
- <span class="missing-if-branch" title="if path not taken" >I</span>if (!base || !body) {
688
- <span class="cstat-no" title="statement not covered" > throw "Unable to build email, missing base components"</span>
689
- }
690
- base = base.contents
691
- body = body.contents
692
- let name = user ? user.name : undefined
693
- <span class="missing-if-branch" title="if path not taken" >I</span>if (user &amp;&amp; !name &amp;&amp; user.firstName) {
694
- <span class="cstat-no" title="statement not covered" > name = user.lastName ? `${user.firstName} ${user.lastName}` : user.firstName</span>
695
- }
696
- context = {
697
- ...context,
698
- contents,
699
- email,
700
- name,
701
- user: user || {},
702
- }
703
- &nbsp;
704
- body = await processString(body, context)
705
- // this should now be the complete email HTML
706
- return processString(base, {
707
- ...context,
708
- body,
709
- })
710
- }
711
- &nbsp;
712
- /**
713
- * Utility function for finding most valid SMTP configuration.
714
- * @param {object} db The CouchDB database which is to be looked up within.
715
- * @param {string|null} workspaceId If using finer grain control of configs a workspace can be used.
716
- * @param {boolean|null} automation Whether or not the configuration is being fetched for an email automation.
717
- * @return {Promise&lt;object|null&gt;} returns the SMTP configuration if it exists
718
- */
719
- async function getSmtpConfiguration(
720
- db: Database,
721
- workspaceId?: string,
722
- automation?: boolean
723
- ) {
724
- const params: any = {
725
- type: Config.SMTP,
726
- }
727
- <span class="missing-if-branch" title="if path not taken" >I</span>if (workspaceId) {
728
- <span class="cstat-no" title="statement not covered" > params.workspace = workspaceId</span>
729
- }
730
- &nbsp;
731
- const customConfig = await dbCore.getScopedConfig(db, params)
732
- &nbsp;
733
- if (customConfig) {
734
- return customConfig
735
- }
736
- &nbsp;
737
- // Use an SMTP fallback configuration from env variables
738
- <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!automation &amp;&amp; env.SMTP_FALLBACK_ENABLED) {</span>
739
- <span class="cstat-no" title="statement not covered" > return {</span>
740
- port: env.SMTP_PORT,
741
- host: env.SMTP_HOST,
742
- secure: false,
743
- from: env.SMTP_FROM_ADDRESS,
744
- auth: {
745
- user: env.SMTP_USER,
746
- pass: env.SMTP_PASSWORD,
747
- },
748
- }
749
- }
750
- }
751
- &nbsp;
752
- /**
753
- * Checks if a SMTP config exists based on passed in parameters.
754
- * @return {Promise&lt;boolean&gt;} returns true if there is a configuration that can be used.
755
- */
756
- export async function isEmailConfigured(workspaceId?: string) {
757
- // when "testing" or smtp fallback is enabled simply return true
758
- <span class="missing-if-branch" title="if path not taken" >I</span>if (TEST_MODE || env.SMTP_FALLBACK_ENABLED) {
759
- <span class="cstat-no" title="statement not covered" > return true</span>
760
- }
761
- const db = tenancy.getGlobalDB()
762
- const config = await getSmtpConfiguration(db, workspaceId)
763
- return config != null
764
- }
765
- &nbsp;
766
- /**
767
- * Given an email address and an email purpose this will retrieve the SMTP configuration and
768
- * send an email using it.
769
- * @param {string} email The email address to send to.
770
- * @param {string} purpose The purpose of the email being sent (e.g. reset password).
771
- * @param {object} opts The options for sending the email.
772
- * @return {Promise&lt;object&gt;} returns details about the attempt to send email, e.g. if it is successful; based on
773
- * nodemailer response.
774
- */
775
- export async function sendEmail(
776
- email: string,
777
- purpose: EmailTemplatePurpose,
778
- opts: SendEmailOpts
779
- ) {
780
- const db = tenancy.getGlobalDB()
781
- let config =
782
- (await getSmtpConfiguration(db, opts<span class="branch-0 cbranch-no" title="branch not covered" >?.w</span>orkspaceId, opts<span class="branch-0 cbranch-no" title="branch not covered" >?.a</span>utomation)) || <span class="branch-1 cbranch-no" title="branch not covered" >{}</span>
783
- <span class="missing-if-branch" title="if path not taken" >I</span>if (Object.keys(config).length === 0 &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >!TEST_MODE)</span> {
784
- <span class="cstat-no" title="statement not covered" > throw "Unable to find SMTP configuration."</span>
785
- }
786
- const transport = createSMTPTransport(config)
787
- // if there is a link code needed this will retrieve it
788
- const code = await getLinkCode(purpose, email, opts.user, opts<span class="branch-0 cbranch-no" title="branch not covered" >?.i</span>nfo)
789
- let context
790
- if (code) {
791
- context = await getSettingsTemplateContext(purpose, code)
792
- }
793
- &nbsp;
794
- let message: any = {
795
- from: opts<span class="branch-0 cbranch-no" title="branch not covered" >?.f</span>rom || config.from,
796
- html: await buildEmail(purpose, email, context, {
797
- user: opts<span class="branch-0 cbranch-no" title="branch not covered" >?.u</span>ser,
798
- contents: opts<span class="branch-0 cbranch-no" title="branch not covered" >?.c</span>ontents,
799
- }),
800
- }
801
- &nbsp;
802
- message = {
803
- ...message,
804
- to: email,
805
- cc: opts<span class="branch-0 cbranch-no" title="branch not covered" >?.c</span>c,
806
- bcc: opts<span class="branch-0 cbranch-no" title="branch not covered" >?.b</span>cc,
807
- }
808
- &nbsp;
809
- if (opts<span class="branch-0 cbranch-no" title="branch not covered" >?.s</span>ubject || config.subject) {
810
- message.subject = await processString(
811
- opts<span class="branch-0 cbranch-no" title="branch not covered" >?.s</span>ubject || config.subject,
812
- context
813
- )
814
- }
815
- const response = await transport.sendMail(message)
816
- <span class="missing-if-branch" title="if path not taken" >I</span>if (TEST_MODE) {
817
- <span class="cstat-no" title="statement not covered" > console.log("Test email URL: " + nodemailer.getTestMessageUrl(response))</span>
818
- }
819
- return response
820
- }
821
- &nbsp;
822
- /**
823
- * Given an SMTP configuration this runs it through nodemailer to see if it is in fact functional.
824
- * @param {object} config an SMTP configuration - this is based on the nodemailer API.
825
- * @return {Promise&lt;boolean&gt;} returns true if the configuration is valid.
826
- */
827
- export async function verifyConfig(config: any) {
828
- const transport = createSMTPTransport(config)
829
- await transport.verify()
830
- }
831
- &nbsp;</pre></td></tr></table></pre>
832
-
833
- <div class='push'></div><!-- for sticky footer -->
834
- </div><!-- /wrapper -->
835
- <div class='footer quiet pad2 space-top1 center small'>
836
- Code coverage generated by
837
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
838
- at Tue Nov 29 2022 22:22:07 GMT+0000 (Coordinated Universal Time)
839
- </div>
840
- <script src="../../prettify.js"></script>
841
- <script>
842
- window.onload = function () {
843
- prettyPrint();
844
- };
845
- </script>
846
- <script src="../../sorter.js"></script>
847
- <script src="../../block-navigation.js"></script>
848
- </body>
849
- </html>
850
-