@internetderdinge/api 1.229.0 → 1.229.2

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 (171) hide show
  1. package/dist/src/accounts/accounts.controller.js +89 -0
  2. package/dist/src/accounts/accounts.route.js +101 -0
  3. package/dist/src/accounts/accounts.schemas.js +12 -0
  4. package/dist/src/accounts/accounts.service.js +65 -0
  5. package/dist/src/accounts/accounts.validation.js +99 -0
  6. package/dist/src/accounts/auth0.service.js +188 -0
  7. package/dist/src/config/config.js +48 -0
  8. package/dist/src/config/logger.js +27 -0
  9. package/dist/src/config/morgan.js +16 -0
  10. package/dist/src/config/passport.cjs +28 -0
  11. package/dist/src/config/roles.js +11 -0
  12. package/dist/src/config/tokens.cjs +10 -0
  13. package/dist/src/devices/devices.controller.js +172 -0
  14. package/dist/src/devices/devices.model.js +94 -0
  15. package/dist/src/devices/devices.route.js +153 -0
  16. package/dist/src/devices/devices.schemas.js +84 -0
  17. package/dist/src/devices/devices.service.js +198 -0
  18. package/dist/src/devices/devices.types.js +1 -0
  19. package/dist/src/devices/devices.validation.js +257 -0
  20. package/dist/src/devicesNotifications/devicesNotifications.controller.js +69 -0
  21. package/dist/src/devicesNotifications/devicesNotifications.model.js +39 -0
  22. package/dist/src/devicesNotifications/devicesNotifications.route.js +124 -0
  23. package/dist/src/devicesNotifications/devicesNotifications.schemas.js +10 -0
  24. package/dist/src/devicesNotifications/devicesNotifications.service.js +181 -0
  25. package/dist/src/devicesNotifications/devicesNotifications.validation.js +46 -0
  26. package/dist/src/email/email.service.js +580 -0
  27. package/dist/src/files/upload.service.js +124 -0
  28. package/dist/src/i18n/i18n.js +38 -0
  29. package/dist/src/i18n/saveMissingLocalJsonBackend.js +53 -0
  30. package/dist/src/i18n/types.js +1 -0
  31. package/dist/src/index.js +48 -0
  32. package/dist/src/iotdevice/iotdevice.controller.js +96 -0
  33. package/dist/src/iotdevice/iotdevice.model.js +17 -0
  34. package/dist/src/iotdevice/iotdevice.route.js +143 -0
  35. package/dist/src/iotdevice/iotdevice.schemas.js +60 -0
  36. package/dist/src/iotdevice/iotdevice.service.js +579 -0
  37. package/dist/src/iotdevice/iotdevice.types.js +1 -0
  38. package/dist/src/iotdevice/iotdevice.validation.js +54 -0
  39. package/dist/src/middlewares/auth.js +75 -0
  40. package/dist/src/middlewares/checkJwt.cjs +17 -0
  41. package/dist/src/middlewares/error.js +36 -0
  42. package/dist/src/middlewares/mongooseValidations/ensureSameOrganization.js +13 -0
  43. package/dist/src/middlewares/rateLimiter.js +7 -0
  44. package/dist/src/middlewares/validate.js +18 -0
  45. package/dist/src/middlewares/validateAction.js +35 -0
  46. package/dist/src/middlewares/validateAdmin.js +18 -0
  47. package/dist/src/middlewares/validateAi.js +16 -0
  48. package/dist/src/middlewares/validateCurrentAuthUser.js +17 -0
  49. package/dist/src/middlewares/validateCurrentUser.js +20 -0
  50. package/dist/src/middlewares/validateDevice.js +98 -0
  51. package/dist/src/middlewares/validateDeviceUserOrganization.js +26 -0
  52. package/dist/src/middlewares/validateOrganization.js +63 -0
  53. package/dist/src/middlewares/validateQuerySearchUserAndOrganization.js +44 -0
  54. package/dist/src/middlewares/validateTokens.js +23 -0
  55. package/dist/src/middlewares/validateUser.js +38 -0
  56. package/dist/src/middlewares/validateZod.js +33 -0
  57. package/dist/src/models/plugins/index.js +4 -0
  58. package/dist/src/models/plugins/paginate.plugin.js +117 -0
  59. package/dist/src/models/plugins/paginateNew.plugin.js +185 -0
  60. package/dist/src/models/plugins/simplePopulate.js +16 -0
  61. package/dist/src/models/plugins/toJSON.plugin.js +35 -0
  62. package/dist/src/organizations/organizations.controller.js +64 -0
  63. package/dist/src/organizations/organizations.model.js +41 -0
  64. package/dist/src/organizations/organizations.route.js +98 -0
  65. package/dist/src/organizations/organizations.schemas.js +7 -0
  66. package/dist/src/organizations/organizations.service.js +59 -0
  67. package/dist/src/organizations/organizations.validation.js +62 -0
  68. package/dist/src/pdf/pdf.controller.js +24 -0
  69. package/dist/src/pdf/pdf.route.js +22 -0
  70. package/dist/src/pdf/pdf.schemas.js +6 -0
  71. package/dist/src/pdf/pdf.service.js +65 -0
  72. package/dist/src/pdf/pdf.validation.js +27 -0
  73. package/dist/src/tokens/tokens.controller.js +60 -0
  74. package/dist/src/tokens/tokens.model.js +17 -0
  75. package/dist/src/tokens/tokens.route.js +52 -0
  76. package/dist/src/tokens/tokens.schemas.js +14 -0
  77. package/dist/src/tokens/tokens.service.js +30 -0
  78. package/dist/src/tokens/tokens.validation.js +9 -0
  79. package/dist/src/types/routeSpec.js +1 -0
  80. package/dist/src/users/users.controller.js +147 -0
  81. package/dist/src/users/users.model.js +50 -0
  82. package/dist/src/users/users.route.js +137 -0
  83. package/dist/src/users/users.schemas.js +69 -0
  84. package/dist/src/users/users.service.js +295 -0
  85. package/dist/src/users/users.types.js +1 -0
  86. package/dist/src/users/users.validation.js +144 -0
  87. package/dist/src/utils/ApiError.js +16 -0
  88. package/dist/src/utils/buildRouterAndDocs.js +72 -0
  89. package/dist/src/utils/catchAsync.js +4 -0
  90. package/dist/src/utils/comparePapers.service.js +32 -0
  91. package/dist/src/utils/deviceUtils.js +63 -0
  92. package/dist/src/utils/filterOptions.js +24 -0
  93. package/dist/src/utils/medicationName.js +10 -0
  94. package/dist/src/utils/pick.js +16 -0
  95. package/dist/src/utils/registerOpenApi.js +67 -0
  96. package/dist/src/utils/urlUtils.js +15 -0
  97. package/dist/src/utils/userName.js +22 -0
  98. package/dist/src/utils/zValidations.js +143 -0
  99. package/dist/src/validations/auth.validation.cjs +53 -0
  100. package/dist/src/validations/custom.validation.js +19 -0
  101. package/dist/src/validations/index.cjs +3 -0
  102. package/dist/tsconfig.tsbuildinfo +1 -0
  103. package/package.json +97 -80
  104. package/scripts/release-and-sync-paperless.mjs +137 -0
  105. package/src/accounts/accounts.controller.ts +1 -0
  106. package/src/accounts/accounts.service.ts +1 -0
  107. package/src/accounts/accounts.validation.ts +8 -5
  108. package/src/accounts/auth0.service.ts +55 -28
  109. package/src/config/config.ts +6 -0
  110. package/src/config/logger.ts +15 -9
  111. package/src/devices/devices.controller.ts +7 -1
  112. package/src/devices/devices.model.ts +4 -1
  113. package/src/devices/devices.schemas.ts +11 -9
  114. package/src/devices/devices.service.ts +1 -0
  115. package/src/devices/devices.types.ts +1 -0
  116. package/src/devices/devices.validation.ts +93 -32
  117. package/src/devicesNotifications/devicesNotifications.controller.ts +57 -28
  118. package/src/devicesNotifications/devicesNotifications.model.ts +20 -12
  119. package/src/devicesNotifications/devicesNotifications.service.ts +35 -17
  120. package/src/files/upload.service.ts +52 -28
  121. package/src/i18n/i18n.ts +1 -1
  122. package/src/i18n/types.ts +1 -0
  123. package/src/index.ts +47 -0
  124. package/src/iotdevice/iotdevice.controller.ts +1 -0
  125. package/src/iotdevice/iotdevice.model.ts +6 -3
  126. package/src/iotdevice/iotdevice.route.ts +85 -76
  127. package/src/iotdevice/iotdevice.service.ts +4 -3
  128. package/src/iotdevice/iotdevice.types.ts +6 -0
  129. package/src/middlewares/auth.ts +2 -8
  130. package/src/middlewares/error.ts +26 -12
  131. package/src/middlewares/mongooseValidations/ensureSameOrganization.ts +4 -3
  132. package/src/middlewares/validateAi.ts +17 -9
  133. package/src/middlewares/validateDevice.ts +1 -0
  134. package/src/middlewares/validateDeviceUserOrganization.ts +1 -0
  135. package/src/middlewares/validateOrganization.ts +1 -1
  136. package/src/middlewares/validateQuerySearchUserAndOrganization.ts +1 -0
  137. package/src/middlewares/validateTokens.ts +2 -1
  138. package/src/middlewares/validateUser.ts +1 -0
  139. package/src/middlewares/validateZod.ts +5 -5
  140. package/src/models/plugins/index.ts +5 -4
  141. package/src/models/plugins/paginate.plugin.ts +26 -16
  142. package/src/models/plugins/paginateNew.plugin.ts +33 -21
  143. package/src/models/plugins/simplePopulate.ts +8 -3
  144. package/src/models/plugins/toJSON.plugin.ts +12 -5
  145. package/src/organizations/organizations.controller.ts +1 -2
  146. package/src/organizations/organizations.model.ts +4 -4
  147. package/src/organizations/organizations.route.ts +1 -1
  148. package/src/organizations/organizations.service.ts +15 -6
  149. package/src/organizations/organizations.validation.ts +1 -1
  150. package/src/pdf/pdf.controller.ts +18 -1
  151. package/src/pdf/pdf.service.ts +25 -16
  152. package/src/tokens/tokens.controller.ts +6 -8
  153. package/src/tokens/tokens.model.ts +3 -1
  154. package/src/tokens/tokens.service.ts +3 -2
  155. package/src/types/express.d.ts +17 -0
  156. package/src/types/mongoose.d.ts +22 -0
  157. package/src/users/users.controller.ts +8 -9
  158. package/src/users/users.model.ts +6 -5
  159. package/src/users/users.route.ts +0 -1
  160. package/src/users/users.service.ts +16 -0
  161. package/src/users/users.types.ts +1 -0
  162. package/src/users/users.validation.ts +6 -2
  163. package/src/utils/ApiError.ts +8 -1
  164. package/src/utils/buildRouterAndDocs.ts +57 -22
  165. package/src/utils/catchAsync.ts +27 -3
  166. package/src/utils/medicationName.ts +5 -4
  167. package/src/utils/pick.ts +5 -1
  168. package/src/utils/registerOpenApi.ts +75 -24
  169. package/src/utils/userName.ts +1 -0
  170. package/src/utils/zValidations.ts +98 -27
  171. package/tsconfig.json +13 -4
@@ -0,0 +1,580 @@
1
+ import AWS from 'aws-sdk';
2
+ import config from '../../src/config/config';
3
+ import i18n from '../../src/i18n/i18n';
4
+ function urlStartsWithHttp(url) {
5
+ return url.startsWith('http');
6
+ }
7
+ const button = ({ link, text, color = '#0076ff' }) => {
8
+ return `
9
+ <div><!--[if mso]>
10
+ <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="${link}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="15%" stroke="f" fillcolor="${color}">
11
+ <w:anchorlock/>
12
+ <center>
13
+ <![endif]-->
14
+ <a href="${link}"
15
+ style="background-color:${color};border-radius:4px;color:#ffffff;display:inline-block;font-family:sans-serif;font-size:15px;font-weight:bold;line-height:40px;text-align:center;text-decoration:none;width:200px;-webkit-text-size-adjust:none;">${text}</a>
16
+ <!--[if mso]>
17
+ </center>
18
+ </v:roundrect>
19
+ <![endif]--></div>
20
+ `;
21
+ };
22
+ const actionButton = ({ link, text, color = '#0076ff' }) => {
23
+ return `<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
24
+ <tr>
25
+ <td align="center">
26
+ <table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
27
+ <tr>
28
+ <td align="center">
29
+ <a href="${link}" class="f-fallback button" target="_blank">${text}</a>
30
+ </td>
31
+ </tr>
32
+ </table>
33
+ </td>
34
+ </tr>
35
+ </table>`;
36
+ };
37
+ export const sendEmail = async ({ title = 'Kein Titel', body = 'Kein Inhalt', url = '', domain = 'memo', image, email, actionButtonText, lng, }) => {
38
+ const interactive = '#0076ff';
39
+ AWS.config.update({
40
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
41
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
42
+ region: 'eu-central-1',
43
+ });
44
+ const actionButtonTextWithLanguage = i18n.t(actionButtonText || 'Go to Application', { lng });
45
+ const ses = new AWS.SES({ apiVersion: '2010-12-01' });
46
+ const toEmail = 'notifications@wirewire.de';
47
+ const base64ToName = Buffer.from(`Memo ${i18n.t('Notifications', { lng })}`).toString('base64');
48
+ const finalToName = `=?UTF-8?B?${base64ToName}?= <${toEmail}>`;
49
+ const params = {
50
+ Destination: {
51
+ ToAddresses: [email],
52
+ },
53
+ ConfigurationSetName: 'memo-transactional',
54
+ Message: {
55
+ Body: {
56
+ Html: {
57
+ Charset: 'UTF-8',
58
+ Data: `
59
+ <!DOCTYPE html>
60
+ <html>
61
+ <head>
62
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
63
+ <meta name="x-apple-disable-message-reformatting" />
64
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
65
+ <meta name="color-scheme" content="light dark" />
66
+ <meta name="supported-color-schemes" content="light dark" />
67
+ <title></title>
68
+ <style>
69
+ /* Base ------------------------------ */
70
+
71
+ @import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap");
72
+ body {
73
+ width: 100% !important;
74
+ height: 100%;
75
+ margin: 0;
76
+ -webkit-text-size-adjust: none;
77
+ }
78
+
79
+ a {
80
+ color: ${interactive};
81
+ }
82
+
83
+ a img {
84
+ border: none;
85
+ }
86
+
87
+ td {
88
+ word-break: break-word;
89
+ }
90
+
91
+ .preheader {
92
+ display: none !important;
93
+ visibility: hidden;
94
+ mso-hide: all;
95
+ font-size: 1px;
96
+ line-height: 1px;
97
+ max-height: 0;
98
+ max-width: 0;
99
+ opacity: 0;
100
+ overflow: hidden;
101
+ }
102
+ /* Type ------------------------------ */
103
+
104
+ body,
105
+ td,
106
+ th {
107
+ font-family: "Open Sans", Helvetica, Arial, sans-serif;
108
+ }
109
+
110
+ h1 {
111
+ margin-top: 0;
112
+ color: #333333;
113
+ font-size: 22px;
114
+ font-weight: bold;
115
+ }
116
+
117
+ h2 {
118
+ margin-top: 0;
119
+ color: #333333;
120
+ font-size: 16px;
121
+ font-weight: bold;
122
+ }
123
+
124
+ h3 {
125
+ margin-top: 0;
126
+ color: #333333;
127
+ font-size: 14px;
128
+ font-weight: bold;
129
+ }
130
+
131
+ td,
132
+ th {
133
+ font-size: 16px;
134
+ }
135
+
136
+ p,
137
+ ul,
138
+ ol,
139
+ blockquote {
140
+ margin: .4em 0 1.1875em;
141
+ font-size: 16px;
142
+ line-height: 1.625;
143
+ }
144
+
145
+ p.sub {
146
+ font-size: 13px;
147
+ }
148
+ /* Utilities ------------------------------ */
149
+
150
+ .align-right {
151
+ text-align: right;
152
+ }
153
+
154
+ .align-left {
155
+ text-align: left;
156
+ }
157
+
158
+ .align-center {
159
+ text-align: center;
160
+ }
161
+
162
+ .u-margin-bottom-none {
163
+ margin-bottom: 0;
164
+ }
165
+ /* Buttons ------------------------------ */
166
+
167
+ .button {
168
+ background-color: ${interactive};
169
+ border-top: 10px solid ${interactive};
170
+ border-right: 18px solid ${interactive};
171
+ border-bottom: 10px solid ${interactive};
172
+ border-left: 18px solid ${interactive};
173
+ display: inline-block;
174
+ color: #FFF !important;
175
+ text-decoration: none;
176
+ font-weight:bold;
177
+ border-radius: 4px;
178
+ /* box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16); */
179
+ -webkit-text-size-adjust: none;
180
+ box-sizing: border-box;
181
+ }
182
+
183
+ .button--green {
184
+ background-color: #22BC66;
185
+ border-top: 10px solid #22BC66;
186
+ border-right: 18px solid #22BC66;
187
+ border-bottom: 10px solid #22BC66;
188
+ border-left: 18px solid #22BC66;
189
+ }
190
+
191
+ .button--red {
192
+ background-color: #FF6136;
193
+ border-top: 10px solid #FF6136;
194
+ border-right: 18px solid #FF6136;
195
+ border-bottom: 10px solid #FF6136;
196
+ border-left: 18px solid #FF6136;
197
+ }
198
+
199
+ @media only screen and (max-width: 500px) {
200
+ .button {
201
+ width: 100% !important;
202
+ text-align: center !important;
203
+ }
204
+ }
205
+ /* Attribute list ------------------------------ */
206
+
207
+ .attributes {
208
+ margin: 0 0 21px;
209
+ }
210
+
211
+ .attributes_content {
212
+ background-color: #F4F4F7;
213
+ padding: 16px;
214
+ }
215
+
216
+ .attributes_item {
217
+ padding: 0;
218
+ }
219
+ /* Related Items ------------------------------ */
220
+
221
+ .related {
222
+ width: 100%;
223
+ margin: 0;
224
+ padding: 25px 0 0 0;
225
+ -premailer-width: 100%;
226
+ -premailer-cellpadding: 0;
227
+ -premailer-cellspacing: 0;
228
+ }
229
+
230
+ .related_item {
231
+ padding: 10px 0;
232
+ color: #CBCCCF;
233
+ font-size: 15px;
234
+ line-height: 18px;
235
+ }
236
+
237
+ .related_item-title {
238
+ display: block;
239
+ margin: .5em 0 0;
240
+ }
241
+
242
+ .related_item-thumb {
243
+ display: block;
244
+ padding-bottom: 10px;
245
+ }
246
+
247
+ .related_heading {
248
+ border-top: 1px solid #CBCCCF;
249
+ text-align: center;
250
+ padding: 25px 0 10px;
251
+ }
252
+ /* Discount Code ------------------------------ */
253
+
254
+ .discount {
255
+ width: 100%;
256
+ margin: 0;
257
+ padding: 24px;
258
+ -premailer-width: 100%;
259
+ -premailer-cellpadding: 0;
260
+ -premailer-cellspacing: 0;
261
+ background-color: #F4F4F7;
262
+ border: 2px dashed #CBCCCF;
263
+ }
264
+
265
+ .discount_heading {
266
+ text-align: center;
267
+ }
268
+
269
+ .discount_body {
270
+ text-align: center;
271
+ font-size: 15px;
272
+ }
273
+ /* Social Icons ------------------------------ */
274
+
275
+ .social {
276
+ width: auto;
277
+ }
278
+
279
+ .social td {
280
+ padding: 0;
281
+ width: auto;
282
+ }
283
+
284
+ .social_icon {
285
+ height: 20px;
286
+ margin: 0 8px 10px 8px;
287
+ padding: 0;
288
+ }
289
+ /* Data table ------------------------------ */
290
+
291
+ .purchase {
292
+ width: 100%;
293
+ margin: 0;
294
+ padding: 35px 0;
295
+ -premailer-width: 100%;
296
+ -premailer-cellpadding: 0;
297
+ -premailer-cellspacing: 0;
298
+ }
299
+
300
+ .purchase_content {
301
+ width: 100%;
302
+ margin: 0;
303
+ padding: 25px 0 0 0;
304
+ -premailer-width: 100%;
305
+ -premailer-cellpadding: 0;
306
+ -premailer-cellspacing: 0;
307
+ }
308
+
309
+ .purchase_item {
310
+ padding: 10px 0;
311
+ color: #51545E;
312
+ font-size: 15px;
313
+ line-height: 18px;
314
+ }
315
+
316
+ .purchase_heading {
317
+ padding-bottom: 8px;
318
+ border-bottom: 1px solid #EAEAEC;
319
+ }
320
+
321
+ .purchase_heading p {
322
+ margin: 0;
323
+ color: #85878E;
324
+ font-size: 12px;
325
+ }
326
+
327
+ .purchase_footer {
328
+ padding-top: 15px;
329
+ border-top: 1px solid #EAEAEC;
330
+ }
331
+
332
+ .purchase_total {
333
+ margin: 0;
334
+ text-align: right;
335
+ font-weight: bold;
336
+ color: #333333;
337
+ }
338
+
339
+ .purchase_total--label {
340
+ padding: 0 15px 0 0;
341
+ }
342
+
343
+ body {
344
+ background-color: #F2F4F6;
345
+ color: #51545E;
346
+ }
347
+
348
+ p {
349
+ color: #51545E;
350
+ }
351
+
352
+ .email-wrapper {
353
+ width: 100%;
354
+ margin: 0;
355
+ padding: 0;
356
+ -premailer-width: 100%;
357
+ -premailer-cellpadding: 0;
358
+ -premailer-cellspacing: 0;
359
+ background-color: #F2F4F6;
360
+ }
361
+
362
+ .email-image {
363
+ display: block;
364
+ width: 100px;
365
+ height: auto;
366
+ margin: auto;
367
+ margin-bottom: 20px;
368
+ }
369
+
370
+ .email-content {
371
+ width: 100%;
372
+ margin: 0;
373
+ padding: 0;
374
+ -premailer-width: 100%;
375
+ -premailer-cellpadding: 0;
376
+ -premailer-cellspacing: 0;
377
+ }
378
+ /* Masthead ----------------------- */
379
+
380
+ .email-masthead {
381
+ padding: 25px 0;
382
+ text-align: center;
383
+ }
384
+
385
+ .email-masthead_logo {
386
+ width: 94px;
387
+ }
388
+
389
+ .email-masthead_name {
390
+ font-size: 16px;
391
+ font-weight: normal;
392
+ color: #A8AAAF;
393
+ text-decoration: none;
394
+ text-shadow: 0 1px 0 white;
395
+ }
396
+ /* Body ------------------------------ */
397
+
398
+ .email-body {
399
+ width: 100%;
400
+ margin: 0;
401
+ padding: 0;
402
+ -premailer-width: 100%;
403
+ -premailer-cellpadding: 0;
404
+ -premailer-cellspacing: 0;
405
+ }
406
+
407
+ .email-body_inner {
408
+ width: 570px;
409
+ margin: 0 auto;
410
+ padding: 0;
411
+ -premailer-width: 570px;
412
+ -premailer-cellpadding: 0;
413
+ -premailer-cellspacing: 0;
414
+ background-color: #FFFFFF;
415
+ }
416
+
417
+ .email-footer {
418
+ width: 570px;
419
+ margin: 0 auto;
420
+ padding: 0;
421
+ -premailer-width: 570px;
422
+ -premailer-cellpadding: 0;
423
+ -premailer-cellspacing: 0;
424
+ text-align: center;
425
+ }
426
+
427
+ .email-footer p {
428
+ color: #A8AAAF;
429
+ }
430
+
431
+ .body-action {
432
+ width: 100%;
433
+ margin: 30px auto;
434
+ padding: 0;
435
+ -premailer-width: 100%;
436
+ -premailer-cellpadding: 0;
437
+ -premailer-cellspacing: 0;
438
+ text-align: center;
439
+ }
440
+
441
+ .callout {
442
+ color: #000;
443
+ background: #F2F4F6;
444
+ padding: 20px;
445
+ }
446
+
447
+ .body-sub {
448
+ margin-top: 25px;
449
+ padding-top: 25px;
450
+ border-top: 1px solid #EAEAEC;
451
+ }
452
+
453
+ .content-cell {
454
+ padding: 30px;
455
+ }
456
+ /*Media Queries ------------------------------ */
457
+
458
+ @media only screen and (max-width: 600px) {
459
+ .email-body_inner,
460
+ .email-footer {
461
+ width: 100% !important;
462
+ }
463
+ }
464
+
465
+ @media (prefers-color-scheme: dark) {
466
+ body,
467
+ .email-body,
468
+ .email-body_inner,
469
+ .email-content,
470
+ .email-wrapper,
471
+ .email-masthead,
472
+ .email-footer {
473
+ background-color: #333333 !important;
474
+ color: #FFF !important;
475
+ }
476
+ p,
477
+ ul,
478
+ ol,
479
+ blockquote,
480
+ h1,
481
+ h2,
482
+ h3,
483
+ span,
484
+ .purchase_item {
485
+ color: #FFF !important;
486
+ }
487
+ .attributes_content,
488
+ .discount {
489
+ background-color: #222 !important;
490
+ }
491
+ .email-masthead_name {
492
+ text-shadow: none !important;
493
+ }
494
+ }
495
+
496
+ :root {
497
+ color-scheme: light dark;
498
+ supported-color-schemes: light dark;
499
+ }
500
+ </style>
501
+ </head>
502
+ <body>
503
+ <span class="preheader">${body}</span>
504
+ <table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
505
+ <tr>
506
+ <td align="center">
507
+ <table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
508
+ <tr>
509
+ <td class="email-masthead">
510
+ <a href="https://${domain}.wirewire.de" class="f-fallback email-masthead_name">
511
+ ${domain === 'memo' ? 'ANABOX smart' : 'paperlesspaper'}
512
+ </a>
513
+ </td>
514
+ </tr>
515
+ <!-- Email Body -->
516
+ <tr>
517
+ <td class="email-body" width="570" cellpadding="0" cellspacing="0">
518
+ <table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
519
+ <!-- Body content -->
520
+ <tr>
521
+ <td class="content-cell align-center">
522
+ <div class="f-fallback">
523
+ ${image ? `<img class="email-image" src="${image}" alt="memo image" />` : ''}
524
+ <h1>${title}</h1>
525
+ <p>${body}</p>
526
+ <!-- Action -->
527
+ ${actionButton({
528
+ link: urlStartsWithHttp(url) ? url : `http://${domain}.wirewire.de${url}`,
529
+ text: actionButtonTextWithLanguage,
530
+ })}
531
+ </div>
532
+ </td>
533
+ </tr>
534
+ </table>
535
+ </td>
536
+ </tr>
537
+ <tr>
538
+ <td>
539
+ <table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
540
+ <tr>
541
+ <td class="content-cell" align="center">
542
+ <p class="f-fallback sub align-center">
543
+ ${domain === 'web' ? 'The Wire UG' : 'wirewire GmbH'}
544
+ <a href="http://${domain}.wirewire.de/account">Account</a>
545
+
546
+ ${config.env !== 'production' ? `<br/><br/>Environment: ${config.env}` : ''}
547
+ </p>
548
+ </td>
549
+ </tr>
550
+ </table>
551
+ </td>
552
+ </tr>
553
+ </table>
554
+ </td>
555
+ </tr>
556
+ </table>
557
+ </body>
558
+ </html>
559
+ `,
560
+ },
561
+ Text: {
562
+ Charset: 'UTF-8',
563
+ Data: `${title} ${body}`,
564
+ },
565
+ },
566
+ Subject: {
567
+ Charset: 'UTF-8',
568
+ Data: `${title} - Memo App`,
569
+ },
570
+ },
571
+ Source: finalToName,
572
+ };
573
+ try {
574
+ const data = await ses.sendEmail(params).promise();
575
+ console.log('Email submitted to SES', data);
576
+ }
577
+ catch (error) {
578
+ console.error(error);
579
+ }
580
+ };
@@ -0,0 +1,124 @@
1
+ // @ts-nocheck
2
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
3
+ import { Upload } from "@aws-sdk/lib-storage";
4
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
5
+ import multer from "multer";
6
+ import multerS3 from "multer-s3";
7
+ import fs from "fs";
8
+ import request from "request";
9
+ const s3 = new S3Client({
10
+ region: "eu-central-1",
11
+ credentials: {
12
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
13
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
14
+ },
15
+ });
16
+ export const getSignedFileUrl = async ({ fileName, bucket = process.env.AWS_S3_BUCKET_NAME, expiresIn = 7200, }) => {
17
+ const command = new GetObjectCommand({
18
+ Bucket: bucket,
19
+ Key: fileName,
20
+ });
21
+ const result = await getSignedUrl(s3, command, { expiresIn });
22
+ return result;
23
+ };
24
+ export const uploadImage = async ({ key, blob, }) => {
25
+ const target = {
26
+ Bucket: process.env.AWS_S3_BUCKET_NAME,
27
+ Key: key,
28
+ Body: blob,
29
+ };
30
+ try {
31
+ const parallelUploads3 = new Upload({
32
+ client: s3,
33
+ queueSize: 4,
34
+ leavePartsOnError: false,
35
+ params: target,
36
+ });
37
+ parallelUploads3.on("httpUploadProgress", (progress) => {
38
+ // console.log(progress);
39
+ });
40
+ await parallelUploads3.done();
41
+ }
42
+ catch (e) {
43
+ console.error(e);
44
+ }
45
+ return { hello: "xx" };
46
+ };
47
+ export const fileFilter = (req, file, cb) => {
48
+ if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
49
+ cb(null, true);
50
+ }
51
+ else {
52
+ cb(new Error("Invalid file type, only JPEG and PNG is allowed!"), false);
53
+ }
54
+ };
55
+ export const uploadFile = multer({
56
+ storage: multerS3({
57
+ s3: s3,
58
+ bucket: process.env.AWS_S3_BUCKET_NAME,
59
+ contentType: multerS3.AUTO_CONTENT_TYPE,
60
+ acl: "public-read",
61
+ metadata(req, file, cb) {
62
+ cb(null, { fieldName: file.fieldname });
63
+ },
64
+ key(req, file, cb) {
65
+ cb(null, `${Date.now().toString()}-${file.originalname}`);
66
+ },
67
+ }),
68
+ });
69
+ const getPhoto = async (photoId, res) => {
70
+ try {
71
+ const params = {
72
+ Bucket: process.env.AWS_S3_BUCKET_NAME,
73
+ Key: photoId,
74
+ };
75
+ await s3
76
+ .getObject(params)
77
+ .on("httpHeaders", function (statusCode, headers) {
78
+ res.set("Content-Length", headers["content-length"]);
79
+ res.set("Content-Type", headers["content-type"]);
80
+ this.response.httpResponse.createUnbufferedStream().pipe(res);
81
+ })
82
+ .send();
83
+ }
84
+ catch (e) {
85
+ throw new Error(`Could not retrieve file from S3: ${e.message}`);
86
+ }
87
+ };
88
+ const download = (uri, filename, callback) => {
89
+ request.head(uri, (err, res, body) => {
90
+ if (err) {
91
+ console.error(err);
92
+ return;
93
+ }
94
+ console.log("content-type:", res.headers["content-type"]);
95
+ console.log("content-length:", res.headers["content-length"]);
96
+ request(uri).pipe(fs.createWriteStream(filename)).on("close", callback);
97
+ });
98
+ };
99
+ const getPhotoFromUserImage = async (photoId, res) => {
100
+ try {
101
+ const params = {
102
+ Bucket: process.env.AWS_S3_BUCKET_NAME,
103
+ Key: photoId,
104
+ };
105
+ await s3
106
+ .getObject(params)
107
+ .on("httpHeaders", function (statusCode, headers) {
108
+ res.set("Content-Length", headers["content-length"]);
109
+ res.set("Content-Type", headers["content-type"]);
110
+ this.response.httpResponse.createUnbufferedStream().pipe(res);
111
+ })
112
+ .send();
113
+ }
114
+ catch (e) {
115
+ throw new Error(`Could not retrieve file from S3: ${e.message}`);
116
+ }
117
+ };
118
+ export default {
119
+ uploadFile,
120
+ uploadImage,
121
+ getPhoto,
122
+ getPhotoFromUserImage,
123
+ getSignedFileUrl,
124
+ };