@plusscommunities/pluss-newsletter-aws-sharing 2.0.4-beta.0 → 2.0.4

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.
@@ -2,11 +2,12 @@ const uuid = require("uuid");
2
2
  const moment = require("moment");
3
3
  const initConfig = require("./initConfig");
4
4
  const { getRowId } = require("./common/helper");
5
+ const { isValidVideo } = require("./config/validVideoURLs");
5
6
  const generateJsonResponse = require("./common/helper/generateJsonResponse");
6
7
  const updateRef = require("./common/db/common/updateRef");
7
8
  const getRef = require("./common/db/common/getRef");
8
9
  const validateMasterAuth = require("./common/helper/auth/validateMasterAuth");
9
- const getSessionUser = require("./common/helper/auth/getSessionUser");
10
+ const getSessionUserFromReqAuthKey = require("@plusscommunities/pluss-core-aws/helper/auth/getSessionUserFromReqAuthKey");
10
11
  const getUserPreview = require("./common/helper/getUserPreview");
11
12
  const sendEmail = require("./common/helper/sendEmail");
12
13
  const newsletterSubmissionEmail = require("./common/templates/newsletterSubmissionEmail");
@@ -55,9 +56,21 @@ module.exports.addNewsletterEntry = (event, context, callback) => {
55
56
  data.update.IsFeaturedDate = null;
56
57
  }
57
58
 
59
+ if (data.update.Video) {
60
+ if (!isValidVideo(data.update.Video)) {
61
+ return callback(
62
+ null,
63
+ generateJsonResponse(400, {
64
+ message:
65
+ "The video URL is from a domain that is not recognized and therefore blocked for security reasons.",
66
+ })
67
+ );
68
+ }
69
+ }
70
+
58
71
  if (data.update.Notification) data.update.UnsentNotification = "X";
59
72
 
60
- getSessionUser(event.headers.authkey).then((uid) => {
73
+ getSessionUserFromReqAuthKey(event).then((uid) => {
61
74
  getUserPreview(uid).then((user) => {
62
75
  data.update.SubmittedBy = user;
63
76
  if (data.update.AuthorDisplay === "name") {
@@ -73,10 +86,8 @@ module.exports.addNewsletterEntry = (event, context, callback) => {
73
86
  console.error("Authorization not valid");
74
87
  callback(
75
88
  null,
76
- generateJsonResponse(422, {
77
- error: {
78
- message: "Authorization not valid.",
79
- },
89
+ generateJsonResponse(403, {
90
+ message: "Authorization not valid.",
80
91
  })
81
92
  );
82
93
  return;
@@ -95,7 +106,13 @@ module.exports.addNewsletterEntry = (event, context, callback) => {
95
106
  );
96
107
  })
97
108
  .catch((error) => {
98
- callback(null, generateJsonResponse(422, { error }));
109
+ console.log("error", error);
110
+ callback(
111
+ null,
112
+ generateJsonResponse(500, {
113
+ message: "Something went wrong.",
114
+ })
115
+ );
99
116
  });
100
117
  } else {
101
118
  updateRef(values.tableNameNewsletterSubmissions, data.update)
@@ -118,7 +135,13 @@ module.exports.addNewsletterEntry = (event, context, callback) => {
118
135
  );
119
136
  })
120
137
  .catch((error) => {
121
- callback(null, generateJsonResponse(422, { error }));
138
+ console.log("error", error);
139
+ callback(
140
+ null,
141
+ generateJsonResponse(500, {
142
+ message: "Something went wrong.",
143
+ })
144
+ );
122
145
  });
123
146
  }
124
147
  }
@@ -145,7 +168,13 @@ module.exports.addNewsletterEntry = (event, context, callback) => {
145
168
  );
146
169
  })
147
170
  .catch((error) => {
148
- callback(null, generateJsonResponse(422, { error }));
171
+ console.log("error", error);
172
+ callback(
173
+ null,
174
+ generateJsonResponse(500, {
175
+ message: "Something went wrong.",
176
+ })
177
+ );
149
178
  });
150
179
  }
151
180
  }
@@ -0,0 +1,46 @@
1
+ const _ = require("lodash");
2
+ const { log } = require("@plusscommunities/pluss-core-aws/helper");
3
+ const { getConfig } = require("@plusscommunities/pluss-core-aws/config");
4
+
5
+ const validVideoURLs = [
6
+ "youtube.com",
7
+ "youtu.be",
8
+ "vimeo.com",
9
+ `${process.env.tablePrefix}uploads.s3.ap-southeast-2.amazonaws.com`,
10
+ ];
11
+
12
+ /**
13
+ *
14
+ * @param {*} videoUrl Url of the video
15
+ * @returns {Boolean} true if the URL is valid. false if it should be blocked.
16
+ */
17
+ exports.isValidVideo = (videoUrl) => {
18
+ const logId = log("isValidVideo", "Start", videoUrl);
19
+ if (_.isEmpty(videoUrl)) {
20
+ log("isValidVideo", "Empty", videoUrl, logId);
21
+ return true;
22
+ }
23
+
24
+ const { featureConfig } = getConfig();
25
+ if (!featureConfig.limitVideoURLs) {
26
+ return true;
27
+ }
28
+ try {
29
+ const host = new URL(videoUrl.toLowerCase()).host;
30
+ log("isValidVideo", "host", host, logId);
31
+
32
+ return _.some(validVideoURLs, (validUrl) => {
33
+ log("isValidVideo", "validUrl", validUrl, logId);
34
+ log(
35
+ "isValidVideo",
36
+ "isValid",
37
+ host === validUrl || host === `www.${validUrl}`,
38
+ logId
39
+ );
40
+ return host === validUrl || host === `www.${validUrl}`;
41
+ });
42
+ } catch (e) {
43
+ log("isValidVideo", "Error", e, logId);
44
+ }
45
+ return false;
46
+ };
@@ -1,10 +1,12 @@
1
1
  const moment = require("moment");
2
2
  const initConfig = require("./initConfig");
3
+ const { isValidVideo } = require("./config/validVideoURLs");
3
4
  const generateJsonResponse = require("./common/helper/generateJsonResponse");
4
5
  const editRef = require("./common/db/common/editRef");
5
6
  const getRef = require("./common/db/common/getRef");
6
7
  const validateMasterAuth = require("./common/helper/auth/validateMasterAuth");
7
- const getUserPreviewFromHeader = require("./common/helper/getUserPreviewFromHeader");
8
+ const getSessionUserFromReqAuthKey = require("@plusscommunities/pluss-core-aws/helper/auth/getSessionUserFromReqAuthKey");
9
+ const getUserPreview = require("@plusscommunities/pluss-core-aws/helper/getUserPreview");
8
10
  const publishActivity = require("./common/db/activity/publishActivity");
9
11
  const { values } = require("./values.config");
10
12
 
@@ -21,15 +23,25 @@ module.exports.editNewsletterEntry = (event, context, callback) => {
21
23
  Number.MAX_SAFE_INTEGER - data.update.UnixTimestamp;
22
24
  }
23
25
 
26
+ if (data.update.Video) {
27
+ if (!isValidVideo(data.update.Video)) {
28
+ return callback(
29
+ null,
30
+ generateJsonResponse(400, {
31
+ message:
32
+ "The video URL is from a domain that is not recognized and therefore blocked for security reasons.",
33
+ })
34
+ );
35
+ }
36
+ }
37
+
24
38
  validateMasterAuth(event, values.permissionNewsletter).then((authorised) => {
25
39
  if (!authorised) {
26
40
  console.error("Authorization not valid");
27
41
  callback(
28
42
  null,
29
- generateJsonResponse(422, {
30
- error: {
31
- message: "Authorization not valid.",
32
- },
43
+ generateJsonResponse(403, {
44
+ message: "Authorization not valid.",
33
45
  })
34
46
  );
35
47
  return;
@@ -41,51 +53,55 @@ module.exports.editNewsletterEntry = (event, context, callback) => {
41
53
  return callback(
42
54
  null,
43
55
  generateJsonResponse(422, {
44
- error: {
45
- message: "Incorrect site.",
46
- },
56
+ message: "Incorrect site.",
47
57
  })
48
58
  );
49
59
  }
50
- getUserPreviewFromHeader(event.headers.authkey)
51
- .then((user) => {
52
- if (
53
- data.update.AuthorDisplay === "name" &&
54
- result.AuthorDisplay !== "name"
55
- ) {
56
- //list author if change was made
57
- data.update.Author = user;
58
- }
59
- data.update.Changed = moment.utc().unix();
60
- if (data.update.IsFeatured && !data.update.IsFeaturedDate) {
61
- data.update.IsFeaturedDate = moment.utc().unix();
62
- } else if (!data.update.IsFeatured) {
63
- data.update.IsFeaturedDate = null;
64
- }
60
+ getSessionUserFromReqAuthKey(event)
61
+ .then((uid) => {
62
+ getUserPreview(uid).then((user) => {
63
+ if (
64
+ data.update.AuthorDisplay === "name" &&
65
+ result.AuthorDisplay !== "name"
66
+ ) {
67
+ //list author if change was made
68
+ data.update.Author = user;
69
+ }
70
+ data.update.Changed = moment.utc().unix();
71
+ if (data.update.IsFeatured && !data.update.IsFeaturedDate) {
72
+ data.update.IsFeaturedDate = moment.utc().unix();
73
+ } else if (!data.update.IsFeatured) {
74
+ data.update.IsFeaturedDate = null;
75
+ }
65
76
 
66
- editRef(
67
- values.tableNameNewsletterEntries,
68
- "RowId",
69
- data.update.RowId,
70
- data.update
71
- ).then((result) => {
72
- publishActivity(
73
- values.activityEditNews,
74
- data.update.Site,
77
+ editRef(
78
+ values.tableNameNewsletterEntries,
79
+ "RowId",
75
80
  data.update.RowId,
76
- user,
77
- { title: data.update.Title }
81
+ data.update
82
+ ).then((result) => {
83
+ publishActivity(
84
+ values.activityEditNews,
85
+ data.update.Site,
86
+ data.update.RowId,
87
+ user,
88
+ { title: data.update.Title }
89
+ );
90
+ });
91
+ callback(
92
+ null,
93
+ generateJsonResponse(200, { success: true, update: result })
78
94
  );
95
+ return;
79
96
  });
97
+ })
98
+ .catch((error) => {
99
+ console.log(error);
80
100
  callback(
81
101
  null,
82
- generateJsonResponse(200, { success: true, map: result })
102
+ generateJsonResponse(500, { message: "Something went wrong." })
83
103
  );
84
104
  return;
85
- })
86
- .catch((error) => {
87
- callback(null, generateJsonResponse(422, { error }));
88
- return;
89
105
  });
90
106
  }
91
107
  );
package/feature.config.js CHANGED
@@ -13,3 +13,303 @@ exports.entity = {
13
13
  webPath: values.routeEntityPath,
14
14
  appPath: values.screenNewsletterPost,
15
15
  };
16
+
17
+ exports.serverless = {
18
+ name: values.serviceKey,
19
+ apis: [
20
+ {
21
+ name: "addNewsletterEntry",
22
+ file: "addNewsletterEntry",
23
+ function: "addNewsletterEntry",
24
+ memorySize: 1024,
25
+ timeout: 30,
26
+ path: "add",
27
+ method: "post",
28
+ headers: ["Content-Type", "authkey", "apikey"],
29
+ },
30
+ {
31
+ name: "editNewsletterEntry",
32
+ file: "editNewsletterEntry",
33
+ function: "editNewsletterEntry",
34
+ memorySize: 128,
35
+ timeout: 10,
36
+ path: "edit",
37
+ method: "post",
38
+ headers: ["Content-Type", "authkey", "apikey"],
39
+ },
40
+ {
41
+ name: "editNewsletterSubmission",
42
+ file: "editNewsletterSubmission",
43
+ function: "editNewsletterSubmission",
44
+ memorySize: 128,
45
+ timeout: 10,
46
+ path: "editSubmission",
47
+ method: "post",
48
+ headers: ["Content-Type", "authkey", "apikey"],
49
+ },
50
+ {
51
+ name: "getNewsletterEntry",
52
+ file: "getNewsletterEntry",
53
+ function: "getNewsletterEntry",
54
+ memorySize: 128,
55
+ timeout: 10,
56
+ path: "get/{id}",
57
+ method: "get",
58
+ headers: ["Content-Type", "authkey", "apikey"],
59
+ },
60
+ {
61
+ name: "getNews",
62
+ file: "getNews",
63
+ function: "getNews",
64
+ memorySize: 128,
65
+ timeout: 10,
66
+ path: "get2/{action}",
67
+ method: "get",
68
+ headers: ["Content-Type", "authkey", "apikey"],
69
+ },
70
+ {
71
+ name: "getNewsletterEntries",
72
+ file: "getNewsletterEntries",
73
+ function: "getNewsletterEntries",
74
+ memorySize: 1024,
75
+ timeout: 30,
76
+ path: "get",
77
+ method: "get",
78
+ headers: ["Content-Type", "authkey", "apikey"],
79
+ },
80
+ {
81
+ name: "getFeaturedNewsletterEntries",
82
+ file: "getFeaturedNewsletterEntries",
83
+ function: "getFeaturedNewsletterEntries",
84
+ memorySize: 128,
85
+ timeout: 10,
86
+ path: "getFeatured",
87
+ method: "get",
88
+ headers: ["Content-Type", "authkey", "apikey"],
89
+ },
90
+ {
91
+ name: "getRecentNewsletterEntries",
92
+ file: "getRecentNewsletterEntries",
93
+ function: "getRecentNewsletterEntries",
94
+ memorySize: 128,
95
+ timeout: 10,
96
+ path: "recent",
97
+ method: "get",
98
+ headers: ["Content-Type", "authkey", "apikey"],
99
+ },
100
+ {
101
+ name: "searchAvailableNews",
102
+ file: "searchAvailableNews",
103
+ function: "searchAvailableNews",
104
+ memorySize: 128,
105
+ timeout: 10,
106
+ path: "content/search",
107
+ method: "get",
108
+ headers: ["Content-Type", "authkey", "apikey"],
109
+ },
110
+ {
111
+ name: "getAvailableNews",
112
+ file: "getAvailableNews",
113
+ function: "getAvailableNews",
114
+ memorySize: 128,
115
+ timeout: 10,
116
+ path: "content/get",
117
+ method: "get",
118
+ headers: ["Content-Type", "authkey", "apikey"],
119
+ },
120
+ {
121
+ name: "getPublishedEntries",
122
+ file: "getPublishedEntries",
123
+ function: "getPublishedEntries",
124
+ memorySize: 128,
125
+ timeout: 10,
126
+ path: "content/specific",
127
+ method: "get",
128
+ headers: ["Content-Type", "authkey", "apikey"],
129
+ },
130
+ {
131
+ name: "getPublishedAvailableNews",
132
+ file: "getPublishedAvailableNews",
133
+ function: "getPublishedAvailableNews",
134
+ memorySize: 128,
135
+ timeout: 10,
136
+ path: "content/published",
137
+ method: "get",
138
+ headers: ["Content-Type", "authkey", "apikey"],
139
+ },
140
+ {
141
+ name: "deleteNewsletterEntry",
142
+ file: "deleteNewsletterEntry",
143
+ function: "deleteNewsletterEntry",
144
+ memorySize: 128,
145
+ timeout: 10,
146
+ path: "remove",
147
+ method: "post",
148
+ headers: ["Content-Type", "authkey", "apikey"],
149
+ },
150
+ {
151
+ name: "hasNewsletterAccess",
152
+ file: "hasNewsletterAccess",
153
+ function: "hasNewsletterAccess",
154
+ memorySize: 128,
155
+ timeout: 10,
156
+ path: "access",
157
+ method: "get",
158
+ headers: ["Content-Type", "authkey", "apikey"],
159
+ },
160
+ {
161
+ name: "getNewsletterSubmissions",
162
+ file: "getNewsletterSubmissions",
163
+ function: "getNewsletterSubmissions",
164
+ memorySize: 128,
165
+ timeout: 10,
166
+ path: "submissions/get",
167
+ method: "get",
168
+ headers: ["Content-Type", "authkey", "apikey"],
169
+ },
170
+ {
171
+ name: "getNewsletterSubmission",
172
+ file: "getNewsletterSubmission",
173
+ function: "getNewsletterSubmission",
174
+ memorySize: 128,
175
+ timeout: 10,
176
+ path: "submissions/get/{id}",
177
+ method: "get",
178
+ headers: ["Content-Type", "authkey", "apikey"],
179
+ },
180
+ {
181
+ name: "handleNewsletterSubmission",
182
+ file: "handleNewsletterSubmission",
183
+ function: "handleNewsletterSubmission",
184
+ memorySize: 128,
185
+ timeout: 10,
186
+ path: "submissions/handle",
187
+ method: "post",
188
+ headers: ["Content-Type", "authkey", "apikey"],
189
+ },
190
+ {
191
+ name: "getSubmissionCount",
192
+ file: "getSubmissionCount",
193
+ function: "getSubmissionCount",
194
+ memorySize: 128,
195
+ timeout: 10,
196
+ path: "submissions/count",
197
+ method: "get",
198
+ headers: ["Content-Type", "authkey", "apikey"],
199
+ },
200
+ {
201
+ name: "getTaggedNews",
202
+ file: "getTaggedNews",
203
+ function: "getTaggedNews",
204
+ memorySize: 128,
205
+ timeout: 10,
206
+ path: "tagged/get",
207
+ method: "get",
208
+ headers: ["Content-Type", "authkey", "apikey"],
209
+ },
210
+ ],
211
+ triggers: [
212
+ {
213
+ name: "newsletterChanged",
214
+ file: "newsletterChanged",
215
+ function: "newsletterChanged",
216
+ memorySize: 2048,
217
+ timeout: 30,
218
+ table: values.tableKeyNewsletterEntries,
219
+ },
220
+ ],
221
+ schedules: [
222
+ {
223
+ name: "watchNewsletter",
224
+ file: "watchNewsletter",
225
+ function: "watchNewsletter",
226
+ memorySize: "2048",
227
+ timeout: "300",
228
+ rate: "1/5 * * * ? *",
229
+ },
230
+ ],
231
+ tables: [
232
+ {
233
+ key: values.tableKeyNewsletterEntries,
234
+ name: values.tableNameNewsletterEntries,
235
+ attributes: [
236
+ { name: "RowId", type: "S" },
237
+ { name: "Site", type: "S" },
238
+ { name: "UnixTimestampReverse", type: "N" },
239
+ { name: "FeaturedExpiry", type: "N" },
240
+ { name: "SourceId", type: "S" },
241
+ { name: "UnsentNotification", type: "S" },
242
+ { name: "UnixTimestamp", type: "N" },
243
+ ],
244
+ id: "RowId",
245
+ indexes: [
246
+ {
247
+ name: "NewsletterEntriesSiteTimestampIndex",
248
+ keys: [
249
+ { name: "Site", type: "HASH" },
250
+ { name: "UnixTimestampReverse", type: "RANGE" },
251
+ ],
252
+ },
253
+ {
254
+ name: "NewsletterEntriesSiteFeaturedExpiryIndex",
255
+ keys: [
256
+ { name: "Site", type: "HASH" },
257
+ { name: "FeaturedExpiry", type: "RANGE" },
258
+ ],
259
+ },
260
+ {
261
+ name: "NewsletterEntriesSiteSourceIdIndex",
262
+ keys: [
263
+ { name: "Site", type: "HASH" },
264
+ { name: "SourceId", type: "RANGE" },
265
+ ],
266
+ },
267
+ {
268
+ name: "NewsletterEntriesUnsentNotiIndex",
269
+ keys: [
270
+ { name: "UnsentNotification", type: "HASH" },
271
+ { name: "UnixTimestamp", type: "RANGE" },
272
+ ],
273
+ },
274
+ ],
275
+ },
276
+ {
277
+ key: values.tableKeyNewsletterSubmissions,
278
+ name: values.tableNameNewsletterSubmissions,
279
+ attributes: [
280
+ { name: "RowId", type: "S" },
281
+ { name: "Site", type: "S" },
282
+ { name: "UnixTimestampReverse", type: "N" },
283
+ ],
284
+ id: "RowId",
285
+ indexes: [
286
+ {
287
+ name: "NewsletterSubmissionsSiteTimestampIndex",
288
+ keys: [
289
+ { name: "Site", type: "HASH" },
290
+ { name: "UnixTimestampReverse", type: "RANGE" },
291
+ ],
292
+ },
293
+ ],
294
+ },
295
+ {
296
+ key: values.tableKeyNewsletterUserEntries,
297
+ name: values.tableNameNewsletterUserEntries,
298
+ attributes: [
299
+ { name: "RowId", type: "S" },
300
+ { name: "UserId", type: "S" },
301
+ { name: "UnixTimestampReverse", type: "N" },
302
+ ],
303
+ id: "RowId",
304
+ indexes: [
305
+ {
306
+ name: "NewsletterUserEntriesUserIdTimestampIndex",
307
+ keys: [
308
+ { name: "UserId", type: "HASH" },
309
+ { name: "UnixTimestampReverse", type: "RANGE" },
310
+ ],
311
+ },
312
+ ],
313
+ },
314
+ ],
315
+ };