strapi-plugin-comments 2.1.0-beta.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,12 @@ const routes = [
7
7
  handler: "client.findAllInHierarchy",
8
8
  config: {
9
9
  policies: [],
10
+ description: "Find all comments related to configured Collection / Single Type and return them in a nested structure",
11
+ tag: {
12
+ plugin: "comments",
13
+ name: "Comments",
14
+ actionType: "find",
15
+ },
10
16
  },
11
17
  },
12
18
  {
@@ -15,6 +21,12 @@ const routes = [
15
21
  handler: "client.post",
16
22
  config: {
17
23
  policies: [],
24
+ description: "Post a comment against configured Collection / Single Type",
25
+ tag: {
26
+ plugin: "comments",
27
+ name: "Comments",
28
+ actionType: "create",
29
+ },
18
30
  },
19
31
  },
20
32
  {
@@ -23,6 +35,12 @@ const routes = [
23
35
  handler: "client.findAllFlat",
24
36
  config: {
25
37
  policies: [],
38
+ description: "Find all comments related to configured Collection / Single Type and return them in a flat structure for further processing",
39
+ tag: {
40
+ plugin: "comments",
41
+ name: "Comments",
42
+ actionType: "find",
43
+ },
26
44
  },
27
45
  },
28
46
  {
@@ -31,6 +49,12 @@ const routes = [
31
49
  handler: "client.put",
32
50
  config: {
33
51
  policies: [],
52
+ description: "Update comment related to configured Collection / Single Type if user is the author",
53
+ tag: {
54
+ plugin: "comments",
55
+ name: "Comments",
56
+ actionType: "update",
57
+ },
34
58
  },
35
59
  },
36
60
  {
@@ -39,14 +63,26 @@ const routes = [
39
63
  handler: "client.reportAbuse",
40
64
  config: {
41
65
  policies: [],
66
+ description: "Report an abuse against comment for configured Collection / Single Type",
67
+ tag: {
68
+ plugin: "comments",
69
+ name: "Comments",
70
+ actionType: "create",
71
+ },
42
72
  },
43
73
  },
44
74
  {
45
75
  method: "DELETE",
46
- path: "/:relationId/comment/:commentId",
76
+ path: "/:relation/comment/:commentId",
47
77
  handler: "client.removeComment",
48
78
  config: {
49
79
  policies: [],
80
+ description: "Remove comment related to configured Collection / Single Type if user is the author",
81
+ tag: {
82
+ plugin: "comments",
83
+ name: "Comments",
84
+ actionType: "delete",
85
+ },
50
86
  },
51
87
  },
52
88
  ];
@@ -7,6 +7,7 @@ const lodash_1 = require("lodash");
7
7
  const error_1 = __importDefault(require("./../utils/error"));
8
8
  const functions_2 = require("./utils/functions");
9
9
  const constants_1 = require("./../utils/constants");
10
+ const DEFAULT_AUTHOR_POPULATE = { avatar: true };
10
11
  module.exports = ({ strapi }) => ({
11
12
  getCommonService() {
12
13
  return (0, functions_1.getPluginService)("common");
@@ -97,7 +98,7 @@ module.exports = ({ strapi }) => ({
97
98
  .findMany({
98
99
  ...params,
99
100
  populate: {
100
- authorUser: true,
101
+ authorUser: { populate: DEFAULT_AUTHOR_POPULATE },
101
102
  threadOf: true,
102
103
  reports: {
103
104
  where: {
@@ -111,7 +112,7 @@ module.exports = ({ strapi }) => ({
111
112
  });
112
113
  const relatedEntities = await this.getCommonService().findRelatedEntitiesFor(entities);
113
114
  const result = entities
114
- .map((_) => (0, functions_2.filterOurResolvedReports)(this.getCommonService().sanitizeCommentEntity(_)))
115
+ .map((_) => (0, functions_2.filterOurResolvedReports)(this.getCommonService().sanitizeCommentEntity(_, DEFAULT_AUTHOR_POPULATE)))
115
116
  .map((_) => this.getCommonService().mergeRelatedEntityTo(_, relatedEntities));
116
117
  const pageCount = Math.floor(total / pageSize);
117
118
  return {
@@ -139,10 +140,14 @@ module.exports = ({ strapi }) => ({
139
140
  };
140
141
  const defaultPopulate = {
141
142
  populate: {
142
- authorUser: true,
143
+ authorUser: {
144
+ populate: DEFAULT_AUTHOR_POPULATE,
145
+ },
143
146
  threadOf: {
144
147
  populate: {
145
- authorUser: true,
148
+ authorUser: {
149
+ populate: DEFAULT_AUTHOR_POPULATE,
150
+ },
146
151
  ...reportsPopulation,
147
152
  },
148
153
  },
@@ -192,7 +197,7 @@ module.exports = ({ strapi }) => ({
192
197
  const selectedEntity = this.getCommonService().sanitizeCommentEntity({
193
198
  ...entity,
194
199
  threadOf: entity.threadOf || null,
195
- });
200
+ }, DEFAULT_AUTHOR_POPULATE);
196
201
  return {
197
202
  entity: relatedEntity,
198
203
  selected: selectedEntity,
@@ -11,13 +11,17 @@ module.exports = ({ strapi }) => ({
11
11
  getCommonService() {
12
12
  return (0, functions_1.getPluginService)("common");
13
13
  },
14
- async create(relation, data, user = undefined) {
14
+ async create(relation, data, user) {
15
15
  const { content, threadOf } = data;
16
16
  const singleRelationFulfilled = relation && constants_1.REGEX.relatedUid.test(relation);
17
17
  if (!singleRelationFulfilled) {
18
18
  throw new error_1.default(400, `Field "related" got incorrect format, use format like "api::<collection name>.<content type name>:<entity id>"`);
19
19
  }
20
20
  const [uid, relatedId] = await this.getCommonService().parseRelationString(relation);
21
+ const isEnabledCollection = await this.getCommonService().isEnabledCollection(uid);
22
+ if (!isEnabledCollection) {
23
+ throw new error_1.default(400, `Field "related" refer to not enabled collection. Please amend the plugin settings and try again`);
24
+ }
21
25
  const relatedEntity = await strapi.db
22
26
  .query(uid)
23
27
  .findOne(relatedId);
@@ -26,29 +30,32 @@ module.exports = ({ strapi }) => ({
26
30
  }
27
31
  const approvalFlow = await this.getCommonService().getConfig(constants_1.CONFIG_PARAMS.APPROVAL_FLOW, []);
28
32
  const isApprovalFlowEnabled = approvalFlow.includes(uid) || relatedEntity.requireCommentsApproval;
29
- const linkToThread = !(0, lodash_1.isNil)(threadOf)
30
- ? await this.getCommonService().findOne({
31
- id: threadOf,
32
- related: relation,
33
- })
34
- : undefined;
35
- const validContext = this.getCommonService().isValidUserContext(user);
36
- if (linkToThread === null) {
33
+ let linkToThread;
34
+ try {
35
+ linkToThread = !(0, lodash_1.isNil)(threadOf)
36
+ ? await this.getCommonService().findOne({
37
+ id: threadOf,
38
+ related: relation,
39
+ })
40
+ : null;
41
+ }
42
+ catch (e) {
37
43
  throw new error_1.default(400, "Thread does not exist");
38
44
  }
45
+ const validContext = this.getCommonService().isValidUserContext(user);
39
46
  if (!validContext) {
40
47
  throw (0, functions_2.resolveUserContextError)(user);
41
48
  }
42
49
  if ((await this.getCommonService().checkBadWords(content)) &&
43
50
  singleRelationFulfilled) {
44
- const { author = {}, ...rest } = data;
51
+ const { author, ...rest } = data;
45
52
  let authorData = {};
46
53
  if (validContext && user) {
47
54
  authorData = {
48
55
  authorUser: user?.id,
49
56
  };
50
57
  }
51
- else {
58
+ else if (author) {
52
59
  if (author.email && !constants_1.REGEX.email.test(author.email)) {
53
60
  throw new error_1.default(400, 'Field: "author.email". Author e-mail is not valid value. Check your payload');
54
61
  }
@@ -56,11 +63,11 @@ module.exports = ({ strapi }) => ({
56
63
  authorId: author.id,
57
64
  authorName: author.name,
58
65
  authorEmail: author.email,
59
- authorAvatar: author.avatar,
66
+ authorAvatar: (0, lodash_1.isString)(author.avatar) ? author.avatar : undefined,
60
67
  };
61
68
  }
62
- if (!(0, lodash_1.isEmpty)(authorData) &&
63
- !(authorData.authorId || authorData.authorUser)) {
69
+ const authorNotProperlyProvided = !(0, lodash_1.isEmpty)(authorData) && !(authorData.authorId || authorData.authorUser);
70
+ if ((0, lodash_1.isEmpty)(authorData) || authorNotProperlyProvided) {
64
71
  throw new error_1.default(400, `Not able to recognise author of a comment. Make sure you've provided "author" property in a payload or authenticated your request properly.`);
65
72
  }
66
73
  if (isApprovalFlowEnabled &&
@@ -85,12 +92,12 @@ module.exports = ({ strapi }) => ({
85
92
  });
86
93
  return this.getCommonService().sanitizeCommentEntity({
87
94
  ...entity,
88
- threadOf: !(0, lodash_1.isNil)(threadOf) ? linkToThread : null,
95
+ threadOf: linkToThread,
89
96
  });
90
97
  }
91
98
  throw new error_1.default(400, "No content received");
92
99
  },
93
- async update(id, relation, data, user = undefined) {
100
+ async update(id, relation, data, user) {
94
101
  const { content } = data;
95
102
  const singleRelationFulfilled = relation && constants_1.REGEX.relatedUid.test(relation);
96
103
  if (!singleRelationFulfilled) {
@@ -119,45 +126,50 @@ module.exports = ({ strapi }) => ({
119
126
  }
120
127
  throw new error_1.default(403, `You're not allowed to take an action on that entity. Make sure you've provided "author" property in a payload or authenticated your request properly.`);
121
128
  },
122
- async reportAbuse(id, relation, payload, user = undefined) {
129
+ async reportAbuse(id, relation, payload, user) {
123
130
  if (!this.getCommonService().isValidUserContext(user)) {
124
131
  throw (0, functions_2.resolveUserContextError)(user);
125
132
  }
126
133
  await this.getCommonService().parseRelationString(relation);
127
- const reportAgainstEntity = await this.getCommonService().findOne({
128
- id,
129
- related: relation,
130
- });
131
- if (reportAgainstEntity) {
132
- const entity = await strapi.db
133
- .query((0, functions_2.getModelUid)("comment-report"))
134
- .create({
135
- data: {
136
- ...payload,
137
- resolved: false,
138
- related: id,
139
- },
134
+ try {
135
+ const reportAgainstEntity = await this.getCommonService().findOne({
136
+ id,
137
+ related: relation,
140
138
  });
141
- if (entity) {
142
- const response = {
143
- ...entity,
144
- related: reportAgainstEntity,
145
- };
146
- try {
147
- await this.sendAbuseReportEmail(entity.reason, entity.content);
148
- return response;
139
+ if (reportAgainstEntity) {
140
+ const entity = await strapi.db
141
+ .query((0, functions_2.getModelUid)("comment-report"))
142
+ .create({
143
+ data: {
144
+ ...payload,
145
+ resolved: false,
146
+ related: id,
147
+ },
148
+ });
149
+ if (entity) {
150
+ const response = {
151
+ ...entity,
152
+ related: reportAgainstEntity,
153
+ };
154
+ try {
155
+ await this.sendAbuseReportEmail(entity.reason, entity.content);
156
+ return response;
157
+ }
158
+ catch (err) {
159
+ return response;
160
+ }
149
161
  }
150
- catch (err) {
151
- return response;
162
+ else {
163
+ throw new error_1.default(500, "Report cannot be created");
152
164
  }
153
165
  }
154
- else {
155
- throw new error_1.default(500, "Report cannot be created");
156
- }
166
+ throw new error_1.default(403, `You're not allowed to take an action on that entity. Make sure that comment exist or you've authenticated your request properly.`);
167
+ }
168
+ catch (e) {
169
+ throw new error_1.default(403, `You're not allowed to take an action on that entity. Make sure that comment exist or you've authenticated your request properly.`);
157
170
  }
158
- throw new error_1.default(403, `You're not allowed to take an action on that entity. Make sure that comment exist or you've authenticated your request properly.`);
159
171
  },
160
- async markAsRemoved(id, relation, authorId, user = undefined) {
172
+ async markAsRemoved(id, relation, authorId, user) {
161
173
  if (!this.getCommonService().isValidUserContext(user)) {
162
174
  throw (0, functions_2.resolveUserContextError)(user);
163
175
  }
@@ -32,9 +32,11 @@ module.exports = ({ strapi }) => ({
32
32
  const result = strapi.config.get(`plugin.comments${queryProp ? "." + queryProp : ""}`);
33
33
  return (0, lodash_1.isNil)(result) ? defaultValue : result;
34
34
  },
35
- async findAllFlat({ query = {}, populate = {}, sort, pagination }, relatedEntity = null) {
36
- const defaultPopulate = {
35
+ async findAllFlat({ query = {}, populate = {}, sort, pagination, fields, }, relatedEntity = null) {
36
+ const defaultSelect = ["id", "related"];
37
+ const populateClause = {
37
38
  authorUser: true,
39
+ ...((0, lodash_1.isObject)(populate) ? populate : {}),
38
40
  };
39
41
  let queryExtension = {};
40
42
  if (sort && ((0, lodash_1.isString)(sort) || (0, lodash_1.isArray)(sort))) {
@@ -48,6 +50,12 @@ module.exports = ({ strapi }) => ({
48
50
  }, {}),
49
51
  };
50
52
  }
53
+ if (!(0, lodash_1.isNil)(fields)) {
54
+ queryExtension = {
55
+ ...queryExtension,
56
+ select: (0, lodash_1.isArray)(fields) ? (0, lodash_1.uniq)([...fields, ...defaultSelect]) : fields,
57
+ };
58
+ }
51
59
  let meta = {};
52
60
  if (pagination && (0, lodash_1.isObject)(pagination)) {
53
61
  const parsedpagination = Object.keys(pagination).reduce((prev, curr) => ({
@@ -85,8 +93,7 @@ module.exports = ({ strapi }) => ({
85
93
  ...query,
86
94
  },
87
95
  populate: {
88
- ...defaultPopulate,
89
- ...populate,
96
+ ...populateClause,
90
97
  },
91
98
  ...queryExtension,
92
99
  });
@@ -137,12 +144,16 @@ module.exports = ({ strapi }) => ({
137
144
  const parsedThreadOf = (0, lodash_1.isString)(query.threadOf)
138
145
  ? (0, lodash_1.parseInt)(query.threadOf)
139
146
  : query.threadOf;
147
+ let authorUserPopulate = {};
148
+ if ((0, lodash_1.isObject)(populateClause?.authorUser)) {
149
+ authorUserPopulate = populateClause.authorUser;
150
+ }
140
151
  return this.sanitizeCommentEntity({
141
152
  ..._,
142
153
  threadOf: parsedThreadOf || _.threadOf || null,
143
154
  gotThread: (threadedItem?.itemsInTread || 0) > 0,
144
155
  threadFirstItemId: threadedItem?.firstThreadItemId,
145
- });
156
+ }, authorUserPopulate);
146
157
  });
147
158
  return {
148
159
  data: hasRelatedEntitiesToMap
@@ -151,8 +162,8 @@ module.exports = ({ strapi }) => ({
151
162
  ...((0, lodash_1.isEmpty)(meta) ? {} : { meta }),
152
163
  };
153
164
  },
154
- async findAllInHierarchy({ query, populate = {}, sort, startingFromId = null, dropBlockedThreads = false, }, relatedEntity) {
155
- const entities = await this.findAllFlat({ query, populate, sort }, relatedEntity);
165
+ async findAllInHierarchy({ query, populate = {}, sort, fields, startingFromId = null, dropBlockedThreads = false, }, relatedEntity) {
166
+ const entities = await this.findAllFlat({ query, populate, sort, fields }, relatedEntity);
156
167
  return (0, functions_1.buildNestedStructure)(entities?.data, startingFromId, "threadOf", dropBlockedThreads, false);
157
168
  },
158
169
  async findOne(criteria) {
@@ -222,14 +233,17 @@ module.exports = ({ strapi }) => ({
222
233
  return false;
223
234
  }
224
235
  },
225
- sanitizeCommentEntity(entity) {
236
+ sanitizeCommentEntity(entity, populate) {
237
+ const fieldsToPopulate = (0, lodash_1.isArray)(populate)
238
+ ? populate
239
+ : Object.keys(populate || {});
226
240
  return {
227
241
  ...(0, functions_1.buildAuthorModel)({
228
242
  ...entity,
229
243
  threadOf: (0, lodash_1.isObject)(entity.threadOf)
230
- ? (0, functions_1.buildAuthorModel)(entity.threadOf)
244
+ ? (0, functions_1.buildAuthorModel)(entity.threadOf, fieldsToPopulate)
231
245
  : entity.threadOf,
232
- }),
246
+ }, fieldsToPopulate),
233
247
  };
234
248
  },
235
249
  isValidUserContext(user) {
@@ -241,8 +255,9 @@ module.exports = ({ strapi }) => ({
241
255
  const relatedId = (0, lodash_1.isNumber)(parsedRelatedId)
242
256
  ? parsedRelatedId
243
257
  : relatedStringId;
258
+ const isEnabledCollection = await this.isEnabledCollection(uid);
244
259
  const enabledCollections = await this.getConfig(constants_1.CONFIG_PARAMS.ENABLED_COLLECTIONS, []);
245
- if (!enabledCollections.includes(uid)) {
260
+ if (!isEnabledCollection) {
246
261
  throw new error_1.default(403, `Action not allowed for collection '${uid}'. Use one of: ${enabledCollections.join(", ")}`);
247
262
  }
248
263
  return [uid, relatedId];
@@ -262,5 +277,9 @@ module.exports = ({ strapi }) => ({
262
277
  }
263
278
  return content;
264
279
  },
280
+ async isEnabledCollection(uid) {
281
+ const enabledCollections = await this.getConfig("enabledCollections", []);
282
+ return enabledCollections.includes(uid);
283
+ },
265
284
  });
266
285
  //# sourceMappingURL=common.js.map
@@ -7,7 +7,7 @@ export declare const getRelatedGroups: (related: string) => Array<string>;
7
7
  export declare const getModelUid: (name: string) => string;
8
8
  export declare const filterOurResolvedReports: (item: Comment) => Comment;
9
9
  export declare const convertContentTypeNameToSlug: (str: string) => string;
10
- export declare const buildAuthorModel: (item: Comment) => Comment;
10
+ export declare const buildAuthorModel: (item: Comment, fieldsToPopulate?: Array<string>) => Comment;
11
11
  export declare const buildConfigQueryProp: (prop?: undefined | string | Array<string>) => string;
12
12
  export declare const resolveUserContextError: (user: StrapiUser) => PluginError;
13
13
  //# sourceMappingURL=functions.d.ts.map
@@ -64,16 +64,21 @@ const convertContentTypeNameToSlug = (str) => {
64
64
  : plainConversion;
65
65
  };
66
66
  exports.convertContentTypeNameToSlug = convertContentTypeNameToSlug;
67
- const buildAuthorModel = (item) => {
67
+ const buildAuthorModel = (item, fieldsToPopulate = []) => {
68
68
  const { authorUser, authorId, authorName, authorEmail, authorAvatar, ...rest } = item;
69
69
  let author = {};
70
70
  if (authorUser) {
71
- author = {
71
+ author = fieldsToPopulate.reduce((prev, curr) => ({
72
+ ...prev,
73
+ [curr]: authorUser[curr],
74
+ }), {
72
75
  id: authorUser.id,
73
76
  name: authorUser.username,
74
77
  email: authorUser.email,
75
- avatar: authorUser.avatar,
76
- };
78
+ avatar: (0, lodash_1.isString)(authorUser.avatar) || (0, lodash_1.isObject)(authorUser.avatar)
79
+ ? authorUser.avatar
80
+ : undefined,
81
+ });
77
82
  }
78
83
  else if (authorId) {
79
84
  author = {