strapi-plugin-comments 2.0.0-rc.2 → 2.0.3

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 (65) hide show
  1. package/.husky/pre-commit +4 -0
  2. package/README.md +53 -9
  3. package/__mocks__/initSetup.js +82 -0
  4. package/admin/src/components/ActionButton/styles.js +10 -0
  5. package/admin/src/components/DiscussionThread/index.js +2 -6
  6. package/admin/src/components/DiscussionThreadItem/index.js +25 -68
  7. package/admin/src/components/DiscussionThreadItem/styles.js +4 -79
  8. package/admin/src/components/DiscussionThreadItemActions/index.js +82 -40
  9. package/admin/src/components/DiscussionThreadItemActions/styles.js +1 -12
  10. package/admin/src/components/DiscussionThreadItemApprovalFlowActions/index.js +2 -3
  11. package/admin/src/components/DiscussionThreadItemFooter/index.js +47 -0
  12. package/admin/src/components/DiscussionThreadItemFooter/styles.js +13 -0
  13. package/admin/src/components/DiscussionThreadItemReviewAction/index.js +131 -0
  14. package/admin/src/components/IconButton/styles.js +14 -0
  15. package/admin/src/components/ReportsReviewModal/index.js +1 -1
  16. package/admin/src/components/ReportsReviewTable/index.js +12 -6
  17. package/admin/src/components/StatusBadge/index.js +17 -0
  18. package/admin/src/components/StatusBadge/styles.js +17 -0
  19. package/admin/src/hooks/useConfig.js +43 -0
  20. package/admin/src/index.js +31 -2
  21. package/admin/src/pages/Details/components/DetailsEntity/index.js +42 -24
  22. package/admin/src/pages/Details/components/DetailsFilters/index.js +8 -10
  23. package/admin/src/pages/Details/index.js +11 -17
  24. package/admin/src/pages/Discover/components/DiscoverTableRow/index.js +30 -67
  25. package/admin/src/pages/Settings/index.js +342 -0
  26. package/admin/src/pages/Settings/utils/api.js +50 -0
  27. package/admin/src/permissions.js +3 -0
  28. package/admin/src/translations/en.json +50 -16
  29. package/admin/src/utils/index.js +2 -1
  30. package/admin/src/utils/parseRegExp.js +10 -0
  31. package/admin/src/utils/resolveCommentStatus.js +4 -4
  32. package/package.json +12 -7
  33. package/server/bootstrap.js +24 -0
  34. package/server/config/index.js +1 -0
  35. package/server/controllers/admin.js +33 -8
  36. package/server/controllers/client.js +4 -4
  37. package/server/controllers/utils/__tests__/functions.test.js +2 -2
  38. package/server/controllers/utils/parsers.js +3 -1
  39. package/server/graphql/index.js +7 -8
  40. package/server/graphql/queries/findAllFlat.js +4 -2
  41. package/server/graphql/queries/findAllInHierarchy.js +3 -3
  42. package/server/graphql/resolvers-config.js +2 -4
  43. package/server/graphql/types/comment-nested.js +1 -0
  44. package/server/graphql/types/report-reason.js +10 -10
  45. package/server/register.js +1 -3
  46. package/server/routes/admin.js +24 -0
  47. package/server/services/__tests__/common.test.js +246 -0
  48. package/server/services/admin.js +60 -6
  49. package/server/services/client.js +13 -9
  50. package/server/services/common.js +86 -11
  51. package/server/services/utils/__tests__/functions.test.js +20 -73
  52. package/server/services/utils/functions.js +9 -17
  53. package/server/utils/__tests__/functions.test.js +17 -0
  54. package/server/utils/constants.js +10 -0
  55. package/strapi-server.js +12 -5
  56. package/.circleci/config.yml +0 -48
  57. package/.eslintrc +0 -35
  58. package/.github/pull_request_template.md +0 -13
  59. package/.nvmrc +0 -1
  60. package/admin/src/components/DiscussionThreadItemMeta/index.js +0 -42
  61. package/admin/src/components/DiscussionThreadItemWarnings/index.js +0 -147
  62. package/admin/src/components/DiscussionThreadItemWarnings/styles.js +0 -7
  63. package/codecov.yml +0 -4
  64. package/public/assets/logo.png +0 -0
  65. package/public/assets/preview.png +0 -0
@@ -10,6 +10,39 @@ module.exports = {
10
10
  return getPluginService(name);
11
11
  },
12
12
 
13
+ async config(ctx) {
14
+ try {
15
+ return await this.getService().config();
16
+ } catch (e) {
17
+ throwError(ctx, e);
18
+ }
19
+ },
20
+
21
+ async settingsConfig(ctx) {
22
+ try {
23
+ return this.getService().config(true);
24
+ } catch (e) {
25
+ throwError(ctx, e);
26
+ }
27
+ },
28
+
29
+ async settingsUpdateConfig(ctx) {
30
+ try {
31
+ const { request: { body } } = ctx;
32
+ return this.getService().updateConfig(body);
33
+ } catch (e) {
34
+ throwError(ctx, e);
35
+ }
36
+ },
37
+
38
+ async settingsRestoreConfig(ctx) {
39
+ try {
40
+ return this.getService().restoreConfig();
41
+ } catch (e) {
42
+ throwError(ctx, e);
43
+ }
44
+ },
45
+
13
46
  async findAll(ctx) {
14
47
  return this.getService()
15
48
  .findAll(ctx.query);
@@ -101,14 +134,6 @@ module.exports = {
101
134
  }
102
135
  },
103
136
 
104
- async config(ctx) {
105
- try {
106
- return await this.getService().config();
107
- } catch (e) {
108
- throwError(ctx, e);
109
- }
110
- },
111
-
112
137
  getContentsTypes() {
113
138
  return Object.entries(strapi.contentTypes)
114
139
  .filter(([, contentType]) => (
@@ -11,23 +11,23 @@ module.exports = {
11
11
  },
12
12
 
13
13
  async findAllFlat(ctx) {
14
- const { params = {}, query } = ctx;
14
+ const { params = {}, query, sort, pagination } = ctx;
15
15
  const { relation } = parseParams(params);
16
16
  try {
17
17
  return this.getService('common')
18
- .findAllFlat(flatInput(relation, query));
18
+ .findAllFlat(flatInput(relation, query, sort, pagination));
19
19
  } catch (e) {
20
20
  throwError(ctx, e);
21
21
  }
22
22
  },
23
23
 
24
24
  async findAllInHierarchy(ctx) {
25
- const { params = {}, query } = ctx;
25
+ const { params = {}, query, sort } = ctx;
26
26
  const { relation } = parseParams(params);
27
27
  try {
28
28
  return await this.getService('common')
29
29
  .findAllInHierarchy({
30
- ...flatInput(relation, query),
30
+ ...flatInput(relation, query, sort),
31
31
  dropBlockedThreads: true,
32
32
  });
33
33
  } catch (e) {
@@ -1,6 +1,6 @@
1
- const PluginError = require('../../../services/utils/error');
1
+ const PluginError = require('../../../utils/error');
2
2
  const ctx = require('koa/lib/context');
3
- const { parseParams, throwError } = require('../functions');
3
+ const { throwError } = require('../functions');
4
4
 
5
5
  jest.mock
6
6
 
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = {
4
- flatInput(relation, query) {
4
+ flatInput(relation, query, sort, pagination) {
5
5
  return {
6
6
  query: {
7
7
  ...query,
@@ -13,6 +13,8 @@ module.exports = {
13
13
  populate: { authorUser: true },
14
14
  },
15
15
  },
16
+ pagination,
17
+ sort,
16
18
  };
17
19
  },
18
20
 
@@ -6,17 +6,16 @@ const getMutations = require('./mutations');
6
6
  const getResolversConfig = require('./resolvers-config');
7
7
  const { getModelUid } = require('../services/utils/functions');
8
8
 
9
- module.exports = () => {
9
+ module.exports = async ({ strapi, config}) => {
10
10
  const extensionService = strapi.plugin('graphql').service('extension');
11
-
12
11
  extensionService.shadowCRUD(getModelUid('comment')).disable();
13
12
  extensionService.shadowCRUD(getModelUid('comment-report')).disable();
14
-
15
- extensionService.use(({ nexus }) => {
16
- const types = getTypes({ strapi, nexus });
17
- const queries = getQueries({ strapi, nexus });
18
- const mutations = getMutations({ strapi, nexus });
19
- const resolversConfig = getResolversConfig({ strapi });
13
+
14
+ extensionService.use(({ strapi, nexus }) => {
15
+ const types = getTypes({ strapi, nexus, config });
16
+ const queries = getQueries({ strapi, nexus, config });
17
+ const mutations = getMutations({ strapi, nexus, config });
18
+ const resolversConfig = getResolversConfig({ strapi, config });
20
19
 
21
20
  return {
22
21
  types: [types, queries, mutations],
@@ -18,11 +18,13 @@ module.exports = ({ strapi, nexus }) => {
18
18
  sort: args.SortArg,
19
19
  },
20
20
  async resolve(obj, args) {
21
- const { relation, filters } = args;
21
+ const { relation, filters, sort, pagination } = args;
22
22
  return await getPluginService('common')
23
23
  .findAllFlat(flatInput(
24
24
  relation,
25
- getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType)
25
+ getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType),
26
+ sort,
27
+ pagination
26
28
  ), undefined);
27
29
  },
28
30
  };
@@ -13,16 +13,16 @@ module.exports = ({ strapi, nexus }) => {
13
13
  type: nonNull(list('CommentNested')),
14
14
  args: {
15
15
  relation: nonNull(stringArg()),
16
- // filters: filtersArg,
17
16
  sort: args.SortArg,
18
17
  },
19
18
  async resolve(obj, args) {
20
- const { relation, filters } = args;
19
+ const { relation, filters, sort } = args;
21
20
  return await getPluginService('common')
22
21
  .findAllInHierarchy({
23
22
  ...flatInput(
24
23
  relation,
25
- getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType)
24
+ getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType),
25
+ sort
26
26
  ),
27
27
  dropBlockedThreads: true,
28
28
  });
@@ -1,9 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const { getPluginService } = require("../utils/functions");
4
-
5
- module.exports = () => {
6
- const auth = getPluginService('common').getConfig('gql.auth', false);
3
+ module.exports = ({ config }) => {
4
+ const { gql: { auth = false } = {}} = config;
7
5
  return {
8
6
  'Query.findAllFlat': { auth },
9
7
  'Query.findAllInHierarchy': { auth },
@@ -6,6 +6,7 @@ module.exports = ({ nexus }) => nexus.objectType({
6
6
  t.boolean("blocked")
7
7
  t.boolean("blockedThread")
8
8
  t.string("approvalStatus")
9
+ t.boolean("removed")
9
10
  t.field("threadOf", { type: 'CommentSingle' })
10
11
  t.list.field("children", { type: 'CommentNested' })
11
12
  t.field("author", { type: 'CommentAuthor' })
@@ -1,10 +1,10 @@
1
- const { getPluginService } = require("../../utils/functions");
2
-
3
-
4
- module.exports = ({ nexus }) => nexus.enumType({
5
- name: "ReportReason",
6
- description: 'Reason of abuse report',
7
- members: {
8
- ...getPluginService('common').getConfig('reportReasons', {})
9
- },
10
- })
1
+ module.exports = ({ nexus, config }) => {
2
+ const { reportReasons } = config;
3
+ return nexus.enumType({
4
+ name: "ReportReason",
5
+ description: 'Reason of abuse report',
6
+ members: {
7
+ ...reportReasons
8
+ },
9
+ })
10
+ };
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
3
  module.exports = ({ strapi }) => {
4
- if (strapi.plugin('graphql')) {
5
- require('./graphql')({ strapi });
6
- }
4
+ // register phase
7
5
  };
@@ -89,4 +89,28 @@ module.exports = [
89
89
  policies: [],
90
90
  },
91
91
  },
92
+ {
93
+ method: 'GET',
94
+ path: '/settings/config',
95
+ handler: 'admin.settingsConfig',
96
+ config: {
97
+ policies: [],
98
+ },
99
+ },
100
+ {
101
+ method: 'PUT',
102
+ path: '/settings/config',
103
+ handler: 'admin.settingsUpdateConfig',
104
+ config: {
105
+ policies: [],
106
+ },
107
+ },
108
+ {
109
+ method: 'DELETE',
110
+ path: '/settings/config',
111
+ handler: 'admin.settingsRestoreConfig',
112
+ config: {
113
+ policies: [],
114
+ },
115
+ },
92
116
  ];
@@ -0,0 +1,246 @@
1
+ const { CONFIG_PARAMS } = require('../../utils/constants');
2
+ const PluginError = require('../../utils/error');
3
+ const { getPluginService } = require('../../utils/functions');
4
+
5
+ jest.mock
6
+
7
+
8
+ const setup = function(config) {
9
+ Object.defineProperty(global, 'strapi', {
10
+ value: require('../../../__mocks__/initSetup')(config),
11
+ writable: true,
12
+ });
13
+ }
14
+
15
+ afterEach(() => {
16
+ Object.defineProperty(global, 'strapi', {});
17
+ })
18
+
19
+ describe('Test Comments service functions utils', () => {
20
+ describe('Get plugin store', () => {
21
+ beforeEach(() => setup());
22
+
23
+ test('Should return store', async () => {
24
+ const pluginStore = await getPluginService('common').getPluginStore();
25
+ expect(pluginStore).toHaveProperty('get');
26
+ expect(pluginStore).toHaveProperty('set');
27
+ expect(pluginStore).toHaveProperty('delete');
28
+ });
29
+ });
30
+
31
+ describe('Get plugin config', () => {
32
+ describe('Local config', () => {
33
+ beforeEach(() => setup({
34
+ test: 'sample',
35
+ }));
36
+
37
+ test('Should return config value', async () => {
38
+ const result = await getPluginService('common').getConfig('test');
39
+ expect(result).toEqual('sample');
40
+ });
41
+
42
+ test('Should return default config prop value if not set', async () => {
43
+ const result = await getPluginService('common').getConfig('another', 'defaultValue');
44
+ expect(result).toEqual('defaultValue');
45
+ });
46
+ });
47
+
48
+ describe('Store config', () => {
49
+ beforeEach(() => setup({
50
+ test: 'sample',
51
+ }, true));
52
+
53
+ test('Should return config value', async () => {
54
+ const result = await getPluginService('common').getConfig('test');
55
+ expect(result).toEqual('sample');
56
+ });
57
+
58
+ test('Should return default config prop value if not set', async () => {
59
+ const result = await getPluginService('common').getConfig('another', 'defaultValue');
60
+ expect(result).toEqual('defaultValue');
61
+ });
62
+ });
63
+ });
64
+
65
+ describe('Validate user context', () => {
66
+ beforeEach(() => setup());
67
+
68
+ test('Should context be valid', () => {
69
+ expect(getPluginService('common').isValidUserContext({ id: 1 })).toEqual(true);
70
+ });
71
+
72
+ test('Should context be invalid', () => {
73
+ expect(getPluginService('common').isValidUserContext({ })).toEqual(false);
74
+ });
75
+
76
+ test('Should use fallback', () => {
77
+ expect(getPluginService('common').isValidUserContext()).toEqual(true);
78
+ });
79
+ });
80
+
81
+ describe('Sanitize comments entity', () => {
82
+ beforeEach(() => setup());
83
+
84
+ const sample = {
85
+ id: 1,
86
+ content: 'Test text',
87
+ blocked: false,
88
+ removed: true,
89
+ };
90
+
91
+ const authorSample = {
92
+ id: 1,
93
+ username: 'Joe Doe',
94
+ email: 'test@example.com',
95
+ password: 'xxx',
96
+ };
97
+
98
+ const authorGenericSample = {
99
+ authorId: 1,
100
+ authorName: 'Joe Doe',
101
+ authorEmail: 'test@example.com',
102
+ };
103
+
104
+ const outputAuthorSample = {
105
+ id: 1,
106
+ name: 'Joe Doe',
107
+ email: 'test@example.com',
108
+ };
109
+
110
+ test('Should return exact the same value', () => {
111
+ const input = { ...sample };
112
+ const output = getPluginService('common').sanitizeCommentEntity(input);
113
+ expect(output).toHaveProperty('id', input.id);
114
+ expect(output).toHaveProperty('content', input.content);
115
+ expect(output).toHaveProperty('blocked', input.blocked);
116
+ expect(output).toHaveProperty('removed', input.removed);
117
+ });
118
+
119
+ test('Should return entity with \'author\' property for generic author', () => {
120
+ const input = {
121
+ ...sample,
122
+ ...authorGenericSample,
123
+ };
124
+ const output = getPluginService('common').sanitizeCommentEntity(input);
125
+
126
+ expect(output).toHaveProperty('author');
127
+ expect(output).toHaveProperty('author.id', input.authorId);
128
+ expect(output).toHaveProperty('author.id', outputAuthorSample.id);
129
+ expect(output).toHaveProperty('author.name', input.authorName);
130
+ expect(output).toHaveProperty('author.name', outputAuthorSample.name);
131
+ expect(output).toHaveProperty('author.email', input.authorEmail);
132
+ expect(output).toHaveProperty('author.email', outputAuthorSample.email);
133
+
134
+ expect(output).not.toHaveProperty('authorId');
135
+ expect(output).not.toHaveProperty('authorName');
136
+ expect(output).not.toHaveProperty('authorEmail');
137
+ });
138
+
139
+ test('Should return entity with \'author\' property for Strapi author', () => {
140
+ const input = {
141
+ ...sample,
142
+ authorUser: authorSample,
143
+ };
144
+ const output = getPluginService('common').sanitizeCommentEntity(input);
145
+
146
+ expect(output).toHaveProperty('author');
147
+ expect(output).toHaveProperty('author.id', input.authorUser.id);
148
+ expect(output).toHaveProperty('author.id', outputAuthorSample.id);
149
+ expect(output).toHaveProperty('author.name', input.authorUser.username);
150
+ expect(output).toHaveProperty('author.name', outputAuthorSample.name);
151
+ expect(output).toHaveProperty('author.email', input.authorUser.email);
152
+ expect(output).toHaveProperty('author.email', outputAuthorSample.email);
153
+
154
+ expect(output).not.toHaveProperty('authorUser');
155
+
156
+ expect(output).not.toHaveProperty('author.password');
157
+ });
158
+ });
159
+
160
+ describe('Bad Words filtering', () => {
161
+ beforeEach(() => setup());
162
+
163
+ const text = 'Lorem ipsum dolor sit fuck amet';
164
+
165
+ test('Should find bad words usage and throw error PluginError', async () => {
166
+ expect.assertions(7);
167
+ try {
168
+ await getPluginService('common').checkBadWords(text);
169
+ } catch (e) {
170
+ expect(await getPluginService('common').getConfig('badWords')).toEqual(undefined);
171
+ expect(e).toBeInstanceOf(PluginError);
172
+ expect(e).toHaveProperty('status', 400);
173
+ expect(e).toHaveProperty('name', 'Strapi:Plugin:Comments');
174
+ expect(e).toHaveProperty('message', 'Bad language used! Please polite your comment...');
175
+ expect(e).toHaveProperty('payload');
176
+ expect(e.payload).toEqual(expect.objectContaining({
177
+ content: {
178
+ original: text,
179
+ filtered: text.replace('fuck', '****'),
180
+ }
181
+ }));
182
+ }
183
+ });
184
+ });
185
+
186
+ describe('Bad Words filtering', () => {
187
+ beforeEach(() => setup({ badWords: false }));
188
+
189
+ const text = 'Lorem ipsum dolor sit fuck amet';
190
+
191
+ test('Should skip bad words filtering because of configuration change', async () => {
192
+ expect(await getPluginService('common').getConfig('badWords')).toEqual(false);
193
+ expect(await getPluginService('common').checkBadWords(text)).toEqual(text);
194
+ });
195
+ });
196
+
197
+ describe('Parse relation string (store config)', () => {
198
+ const [uid, id] = ['api::my-collection.my-content-type', '1'];
199
+ const validCollection = `${uid}:${id}`;
200
+
201
+ const [wrongUid, wrongId] = ['api::wrong.type', '2'];
202
+ const testCollection = `${wrongUid}:${wrongId}`;
203
+
204
+ describe('Store config', () => {
205
+ beforeEach(() => setup({ enabledCollections: [uid] }, true));
206
+
207
+ test('Should pass', async () => {
208
+ expect(await getPluginService('common').parseRelationString(validCollection));
209
+ expect(await getPluginService('common').getConfig(CONFIG_PARAMS.ENABLED_COLLECTIONS)).toContain(uid);
210
+ });
211
+
212
+ test('Should fail with 403', async () => {
213
+
214
+ try {
215
+ await getPluginService('common').parseRelationString(testCollection);
216
+ } catch(e) {
217
+ expect(await getPluginService('common').getConfig(CONFIG_PARAMS.ENABLED_COLLECTIONS)).toContain(uid);
218
+ expect(await getPluginService('common').getConfig(CONFIG_PARAMS.ENABLED_COLLECTIONS)).not.toContain(wrongUid);
219
+ expect(e).toBeInstanceOf(PluginError);
220
+ expect(e).toHaveProperty('status', 403);
221
+ }
222
+ });
223
+ });
224
+
225
+ describe('Local config', () => {
226
+ beforeEach(() => setup({ enabledCollections: [uid] }));
227
+
228
+ test('Should pass', async () => {
229
+ expect(await getPluginService('common').parseRelationString(validCollection));
230
+ expect(await getPluginService('common').getConfig(CONFIG_PARAMS.ENABLED_COLLECTIONS)).toContain(uid);
231
+ });
232
+
233
+ test('Should fail with 403', async () => {
234
+
235
+ try {
236
+ await getPluginService('common').parseRelationString(testCollection);
237
+ } catch(e) {
238
+ expect(await getPluginService('common').getConfig(CONFIG_PARAMS.ENABLED_COLLECTIONS)).toContain(uid);
239
+ expect(await getPluginService('common').getConfig(CONFIG_PARAMS.ENABLED_COLLECTIONS)).not.toContain(wrongUid);
240
+ expect(e).toBeInstanceOf(PluginError);
241
+ expect(e).toHaveProperty('status', 403);
242
+ }
243
+ });
244
+ });
245
+ });
246
+ });
@@ -21,19 +21,73 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
21
21
  },
22
22
 
23
23
  // Config
24
- async config() {
25
- const entryLabel = this.getCommonService().getConfig('entryLabel');
26
- const approvalFlow = this.getCommonService().getConfig('approvalFlow');
27
- return {
28
- entryLabel,
29
- approvalFlow,
24
+ async config(viaSettingsPage = false) {
25
+ const pluginStore = await this.getCommonService().getPluginStore();
26
+ const config = await pluginStore.get({ key: 'config' });
27
+ const additionalConfiguration = {
30
28
  regex: Object.keys(REGEX).reduce((prev, curr) => ({
31
29
  ...prev,
32
30
  [curr]: REGEX[curr].toString(),
33
31
  }), {}),
34
32
  };
33
+
34
+ const isGQLPluginEnabled = !isNil(strapi.plugin('graphql'));
35
+
36
+ if (config) {
37
+ return {
38
+ ...config,
39
+ ...additionalConfiguration,
40
+ isGQLPluginEnabled: viaSettingsPage ? isGQLPluginEnabled : undefined,
41
+ };
42
+ }
43
+
44
+ const entryLabel = this.getCommonService().getLocalConfig('entryLabel');
45
+ const approvalFlow = this.getCommonService().getLocalConfig('approvalFlow');
46
+ const reportReasons = this.getCommonService().getLocalConfig('reportReasons');
47
+ const result = {
48
+ entryLabel,
49
+ approvalFlow,
50
+ reportReasons,
51
+ ...additionalConfiguration,
52
+ };
53
+
54
+ if (viaSettingsPage) {
55
+ const enabledCollections = this.getCommonService().getLocalConfig('enabledCollections');
56
+ const moderatorRoles = this.getCommonService().getLocalConfig('moderatorRoles');
57
+ return {
58
+ ...result,
59
+ enabledCollections,
60
+ moderatorRoles,
61
+ isGQLPluginEnabled,
62
+ };
63
+ }
64
+
65
+ return result;
35
66
  },
36
67
 
68
+ async updateConfig(body) {
69
+ const pluginStore = await this.getCommonService().getPluginStore();
70
+
71
+ await pluginStore.set({ key: 'config', value: body });
72
+
73
+ return this.config();
74
+ },
75
+
76
+ async restoreConfig() {
77
+ const pluginStore = await this.getCommonService().getPluginStore();
78
+ const defaultConfig = this.getCommonService().getLocalConfig();
79
+
80
+ await pluginStore.delete({key: 'config'})
81
+ await pluginStore.set({
82
+ key: 'config',
83
+ value: {
84
+ ...defaultConfig,
85
+ }
86
+ });
87
+
88
+ return this.config();
89
+ },
90
+
37
91
  // Find all comments
38
92
  async findAll({ related, entity, ...query }) {
39
93
  const { _q, orderBy, pageSize = 10, page = 1, filters, ...rest } = parseParams(query);
@@ -8,10 +8,9 @@ const {
8
8
  isEqualEntity,
9
9
  getModelUid,
10
10
  getRelatedGroups,
11
- checkBadWords,
12
11
  resolveUserContextError,
13
12
  } = require('./utils/functions');
14
- const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
13
+ const { APPROVAL_STATUS, REGEX, CONFIG_PARAMS } = require('./../utils/constants')
15
14
 
16
15
  /**
17
16
  * Comments Plugin - Client services
@@ -32,16 +31,14 @@ module.exports = ({ strapi }) => ({
32
31
  throw new PluginError(400, `Field "related" got incorrect format, use format like "api::<collection name>.<content type name>:<entity id>"`);
33
32
  }
34
33
 
35
- const [ uid, relatedStringId ] = getRelatedGroups(relation);
36
- const parsedRelatedId = parseInt(relatedStringId);
37
- const relatedId = isNumber(parsedRelatedId) ? parsedRelatedId : relatedStringId;
34
+ const [ uid, relatedId ] = await this.getCommonService().parseRelationString(relation);
38
35
 
39
36
  const relatedEntity = await strapi.db.query(uid).findOne(relatedId);
40
37
  if (!relatedEntity) {
41
38
  throw new PluginError(400, `Relation for field "related" does not exist. Check your payload please.`);
42
39
  }
43
40
 
44
- const isApprovalFlowEnabled = this.getCommonService().getConfig('approvalFlow', []).includes(uid) ||
41
+ const isApprovalFlowEnabled = await this.getCommonService().getConfig(CONFIG_PARAMS.APPROVAL_FLOW, []).includes(uid) ||
45
42
  relatedEntity.requireCommentsApproval;
46
43
 
47
44
  const linkToThread = !isNil(threadOf) ? await this.getCommonService().findOne({
@@ -58,7 +55,7 @@ module.exports = ({ strapi }) => ({
58
55
  throw resolveUserContextError(user);
59
56
  }
60
57
 
61
- if (checkBadWords(content) && singleRelationFulfilled) {
58
+ if (await this.getCommonService().checkBadWords(content) && singleRelationFulfilled) {
62
59
  const { author = {}, ...rest } = data;
63
60
  let authorData = {};
64
61
  if (validContext && user) {
@@ -116,6 +113,8 @@ module.exports = ({ strapi }) => ({
116
113
  throw new PluginError(400, `Request property "relation" got incorrect format, use format like "api::<collection name>.<content type name>:<entity id>"`);
117
114
  }
118
115
 
116
+ await this.getCommonService().parseRelationString(relation);
117
+
119
118
  const existingEntity = await this.getCommonService().findOne({
120
119
  id,
121
120
  related: relation,
@@ -128,7 +127,7 @@ module.exports = ({ strapi }) => ({
128
127
  }
129
128
 
130
129
  if (isEqualEntity(existingEntity, data, user) && content) {
131
- if (checkBadWords(content)) {
130
+ if (await this.getCommonService().checkBadWords(content)) {
132
131
  const entity = await strapi.db.query(getModelUid('comment')).update({
133
132
  where: { id },
134
133
  data: { content },
@@ -145,6 +144,9 @@ module.exports = ({ strapi }) => ({
145
144
  if (!this.getCommonService().isValidUserContext(user)) {
146
145
  throw resolveUserContextError(user);
147
146
  }
147
+
148
+ await this.getCommonService().parseRelationString(relation);
149
+
148
150
  const reportAgainstEntity = await this.getCommonService().findOne({
149
151
  id,
150
152
  related: relation,
@@ -186,6 +188,8 @@ module.exports = ({ strapi }) => ({
186
188
  throw new PluginError(403, `You're not allowed to take an action on that entity. Make sure that you've provided proper "authorId" or authenticated your request properly.`);
187
189
  }
188
190
 
191
+ await this.getCommonService().parseRelationString(relation);
192
+
189
193
  let entity;
190
194
  try {
191
195
  const byAuthor = user?.id ? {
@@ -217,7 +221,7 @@ module.exports = ({ strapi }) => ({
217
221
  },
218
222
 
219
223
  async sendAbuseReportEmail(reason, content) {
220
- const rolesToBeNotified = this.getCommonService().getConfig('moderatorRoles') || ['strapi-super-admin'];
224
+ const rolesToBeNotified = await this.getCommonService().getConfig(CONFIG_PARAMS.MODERATOR_ROLES) || ['strapi-super-admin'];
221
225
 
222
226
  const adminUserModel = strapi.db.query('admin::user');
223
227
  const emails = await adminUserModel.findMany({