@strapi/plugin-documentation 4.0.0-beta.2 → 4.0.0-beta.20

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 (70) hide show
  1. package/admin/src/components/FieldActionWrapper/index.js +14 -0
  2. package/admin/src/components/PluginIcon/index.js +12 -0
  3. package/admin/src/index.js +23 -11
  4. package/admin/src/pages/PluginPage/index.js +199 -0
  5. package/admin/src/pages/PluginPage/tests/index.test.js +873 -0
  6. package/admin/src/pages/PluginPage/tests/server.js +23 -0
  7. package/admin/src/pages/SettingsPage/index.js +181 -0
  8. package/admin/src/pages/SettingsPage/tests/index.test.js +612 -0
  9. package/admin/src/pages/SettingsPage/tests/server.js +18 -0
  10. package/admin/src/pages/{HomePage/utils → utils}/api.js +5 -4
  11. package/admin/src/pages/{HomePage/utils → utils}/schema.js +0 -0
  12. package/admin/src/pages/utils/useReactQuery.js +46 -0
  13. package/admin/src/translations/ar.json +0 -3
  14. package/admin/src/translations/cs.json +0 -3
  15. package/admin/src/translations/de.json +0 -3
  16. package/admin/src/translations/en.json +13 -3
  17. package/admin/src/translations/es.json +0 -3
  18. package/admin/src/translations/fr.json +0 -3
  19. package/admin/src/translations/id.json +0 -3
  20. package/admin/src/translations/it.json +0 -3
  21. package/admin/src/translations/ko.json +0 -3
  22. package/admin/src/translations/ms.json +0 -3
  23. package/admin/src/translations/nl.json +0 -3
  24. package/admin/src/translations/pl.json +0 -3
  25. package/admin/src/translations/pt-BR.json +0 -3
  26. package/admin/src/translations/pt.json +0 -3
  27. package/admin/src/translations/ru.json +0 -3
  28. package/admin/src/translations/sk.json +0 -3
  29. package/admin/src/translations/th.json +0 -3
  30. package/admin/src/translations/tr.json +0 -3
  31. package/admin/src/translations/uk.json +0 -3
  32. package/admin/src/translations/vi.json +0 -3
  33. package/admin/src/translations/zh-Hans.json +0 -3
  34. package/admin/src/translations/zh.json +0 -3
  35. package/package.json +26 -46
  36. package/server/bootstrap.js +22 -105
  37. package/server/config/default-config.js +12 -15
  38. package/server/config/index.js +10 -2
  39. package/server/controllers/documentation.js +49 -111
  40. package/server/index.js +17 -0
  41. package/server/middlewares/documentation.js +24 -55
  42. package/server/{policies/index-policy.js → middlewares/restrict-access.js} +2 -10
  43. package/{public → server/public}/index.html +0 -0
  44. package/{public → server/public}/login.html +0 -0
  45. package/server/register.js +11 -0
  46. package/server/routes/index.js +10 -17
  47. package/server/services/documentation.js +125 -1831
  48. package/server/utils/builders/build-api-endpoint-path.js +174 -0
  49. package/server/utils/builders/build-api-requests.js +41 -0
  50. package/server/utils/builders/build-api-responses.js +108 -0
  51. package/server/utils/builders/index.js +11 -0
  52. package/server/utils/clean-schema-attributes.js +205 -0
  53. package/server/utils/error-response.js +22 -0
  54. package/server/utils/get-schema-data.js +32 -0
  55. package/server/utils/query-params.js +84 -0
  56. package/strapi-server.js +1 -19
  57. package/admin/src/assets/images/logo.svg +0 -1
  58. package/admin/src/components/Block/components.js +0 -26
  59. package/admin/src/components/Block/index.js +0 -39
  60. package/admin/src/components/Copy/index.js +0 -36
  61. package/admin/src/components/Header/index.js +0 -72
  62. package/admin/src/components/Row/ButtonContainer.js +0 -67
  63. package/admin/src/components/Row/components.js +0 -83
  64. package/admin/src/components/Row/index.js +0 -51
  65. package/admin/src/pages/App/index.js +0 -52
  66. package/admin/src/pages/HomePage/components.js +0 -59
  67. package/admin/src/pages/HomePage/index.js +0 -175
  68. package/admin/src/pages/HomePage/useHomePage.js +0 -56
  69. package/server/policies/index.js +0 -7
  70. package/server/services/utils/forms.json +0 -29
@@ -8,6 +8,7 @@
8
8
 
9
9
  // Core dependencies.
10
10
  const path = require('path');
11
+ const bcrypt = require('bcryptjs');
11
12
 
12
13
  // Public dependencies.
13
14
  const fs = require('fs-extra');
@@ -17,15 +18,15 @@ const koaStatic = require('koa-static');
17
18
  module.exports = {
18
19
  async getInfos(ctx) {
19
20
  try {
20
- const service = strapi.plugins.documentation.services.documentation;
21
- const docVersions = service.retrieveDocumentationVersions();
22
- const form = await service.retrieveFrontForm();
21
+ const docService = strapi.plugin('documentation').service('documentation');
22
+ const docVersions = docService.getDocumentationVersions();
23
+ const documentationAccess = await docService.getDocumentationAccess();
23
24
 
24
25
  ctx.send({
25
26
  docVersions,
26
- currentVersion: service.getDocumentationVersion(),
27
- prefix: strapi.config.get('plugin.documentation.x-strapi-config').path,
28
- form,
27
+ currentVersion: docService.getDocumentationVersion(),
28
+ prefix: strapi.plugin('documentation').config('x-strapi-config').path,
29
+ documentationAccess,
29
30
  });
30
31
  } catch (err) {
31
32
  ctx.badRequest(null, err.message);
@@ -42,10 +43,13 @@ module.exports = {
42
43
  const version =
43
44
  major && minor && patch
44
45
  ? `${major}.${minor}.${patch}`
45
- : strapi.plugins.documentation.config.info.version;
46
+ : strapi
47
+ .plugin('documentation')
48
+ .service('documentation')
49
+ .getDocumentationVersion();
50
+
46
51
  const openAPISpecsPath = path.join(
47
- strapi.config.appPath,
48
- 'extensions',
52
+ strapi.dirs.extensions,
49
53
  'documentation',
50
54
  'documentation',
51
55
  version,
@@ -65,8 +69,7 @@ module.exports = {
65
69
 
66
70
  try {
67
71
  const layoutPath = path.resolve(
68
- strapi.config.appPath,
69
- 'extensions',
72
+ strapi.dirs.extensions,
70
73
  'documentation',
71
74
  'public',
72
75
  'index.html'
@@ -78,12 +81,7 @@ module.exports = {
78
81
  ctx.url = path.basename(`${ctx.url}/index.html`);
79
82
 
80
83
  try {
81
- const staticFolder = path.resolve(
82
- strapi.config.appPath,
83
- 'extensions',
84
- 'documentation',
85
- 'public'
86
- );
84
+ const staticFolder = path.resolve(strapi.dirs.extensions, 'documentation', 'public');
87
85
  return koaStatic(staticFolder)(ctx, next);
88
86
  } catch (e) {
89
87
  strapi.log.error(e);
@@ -118,8 +116,7 @@ module.exports = {
118
116
 
119
117
  try {
120
118
  const layoutPath = path.resolve(
121
- strapi.config.appPath,
122
- 'extensions',
119
+ strapi.dirs.extensions,
123
120
  'documentation',
124
121
  'public',
125
122
  'login.html'
@@ -130,12 +127,7 @@ module.exports = {
130
127
  ctx.url = path.basename(`${ctx.url}/login.html`);
131
128
 
132
129
  try {
133
- const staticFolder = path.resolve(
134
- strapi.config.appPath,
135
- 'extensions',
136
- 'documentation',
137
- 'public'
138
- );
130
+ const staticFolder = path.resolve(strapi.dirs.extensions, 'documentation', 'public');
139
131
  return koaStatic(staticFolder)(ctx, next);
140
132
  } catch (e) {
141
133
  strapi.log.error(e);
@@ -153,18 +145,19 @@ module.exports = {
153
145
  body: { password },
154
146
  } = ctx.request;
155
147
 
156
- const { password: storedPassword } = await strapi
148
+ const { password: hash } = await strapi
157
149
  .store({ type: 'plugin', name: 'documentation', key: 'config' })
158
150
  .get();
159
151
 
160
- const isValid = await strapi.plugins['users-permissions'].services.user.validatePassword(
161
- password,
162
- storedPassword
163
- );
152
+ const isValid = await bcrypt.compare(password, hash);
153
+
164
154
  let querystring = '?error=password';
165
155
 
166
156
  if (isValid) {
167
- ctx.session.documentation = password;
157
+ ctx.session.documentation = {
158
+ logged: true,
159
+ };
160
+
168
161
  querystring = '';
169
162
  }
170
163
 
@@ -176,126 +169,71 @@ module.exports = {
176
169
  },
177
170
 
178
171
  async regenerateDoc(ctx) {
179
- const service = strapi.plugins.documentation.services.documentation;
180
- const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
181
- const {
182
- request: {
183
- body: { version },
184
- admin,
185
- },
186
- } = ctx;
172
+ const { version } = ctx.request.body;
173
+
174
+ const service = strapi.service('plugin::documentation.documentation');
175
+
176
+ const documentationVersions = service.getDocumentationVersions().map(el => el.version);
187
177
 
188
178
  if (_.isEmpty(version)) {
189
- return ctx.badRequest(
190
- null,
191
- admin ? 'documentation.error.noVersion' : 'Please provide a version.'
192
- );
179
+ return ctx.badRequest('Please provide a version.');
193
180
  }
194
181
 
195
182
  if (!documentationVersions.includes(version)) {
196
- return ctx.badRequest(
197
- null,
198
- admin
199
- ? 'documentation.error.regenerateDoc.versionMissing'
200
- : 'The version you are trying to generate does not exist.'
201
- );
183
+ return ctx.badRequest('The version you are trying to generate does not exist.');
202
184
  }
203
185
 
204
186
  try {
205
187
  strapi.reload.isWatching = false;
206
- const fullDoc = service.generateFullDoc(version);
207
- const documentationPath = service.getMergedDocumentationPath(version);
208
- // Write the file
209
- fs.writeFileSync(
210
- path.resolve(documentationPath, 'full_documentation.json'),
211
- JSON.stringify(fullDoc, null, 2),
212
- 'utf8'
213
- );
188
+ await service.generateFullDoc(version);
214
189
  ctx.send({ ok: true });
215
- } catch (err) {
216
- ctx.badRequest(null, admin ? 'documentation.error.regenerateDoc' : 'An error occured');
217
190
  } finally {
218
191
  strapi.reload.isWatching = true;
219
192
  }
220
193
  },
221
194
 
222
195
  async deleteDoc(ctx) {
223
- strapi.reload.isWatching = false;
224
- const service = strapi.plugins.documentation.services.documentation;
225
- const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
196
+ const { version } = ctx.params;
226
197
 
227
- const {
228
- params: { version },
229
- request: { admin },
230
- } = ctx;
198
+ const service = strapi.service('plugin::documentation.documentation');
199
+
200
+ const documentationVersions = service.getDocumentationVersions().map(el => el.version);
231
201
 
232
202
  if (_.isEmpty(version)) {
233
- return ctx.badRequest(
234
- null,
235
- admin ? 'documentation.error.noVersion' : 'Please provide a version.'
236
- );
203
+ return ctx.badRequest('Please provide a version.');
237
204
  }
238
205
 
239
206
  if (!documentationVersions.includes(version)) {
240
- return ctx.badRequest(
241
- null,
242
- admin
243
- ? 'documentation.error.deleteDoc.versionMissing'
244
- : 'The version you are trying to delete does not exist.'
245
- );
207
+ return ctx.badRequest('The version you are trying to delete does not exist.');
246
208
  }
247
209
 
248
210
  try {
211
+ strapi.reload.isWatching = false;
249
212
  await service.deleteDocumentation(version);
250
213
  ctx.send({ ok: true });
251
- } catch (err) {
252
- ctx.badRequest(null, admin ? 'notification.error' : err.message);
253
214
  } finally {
254
215
  strapi.reload.isWatching = true;
255
216
  }
256
217
  },
257
218
 
258
219
  async updateSettings(ctx) {
259
- const {
260
- admin,
261
- body: { restrictedAccess, password },
262
- } = ctx.request;
263
-
264
- const usersPermService = strapi.plugins['users-permissions'].services;
220
+ const { restrictedAccess, password } = ctx.request.body;
265
221
 
266
222
  const pluginStore = strapi.store({ type: 'plugin', name: 'documentation' });
267
223
 
268
- const prevConfig = await pluginStore.get({ key: 'config' });
224
+ const config = {
225
+ restrictedAccess: Boolean(restrictedAccess),
226
+ };
269
227
 
270
- if (restrictedAccess && _.isEmpty(password)) {
271
- return ctx.badRequest(
272
- null,
273
- admin ? 'users-permissions.Auth.form.error.password.provide' : 'Please provide a password'
274
- );
275
- }
276
-
277
- const isNewPassword = !_.isEmpty(password) && password !== prevConfig.password;
278
-
279
- if (isNewPassword && usersPermService.user.isHashed(password)) {
280
- // Throw an error if the password selected by the user
281
- // contains more than two times the symbol '$'.
282
- return ctx.badRequest(
283
- null,
284
- admin
285
- ? 'users-permissions.Auth.form.error.password.format'
286
- : 'our password cannot contain more than three times the symbol `$`.'
287
- );
288
- }
228
+ if (restrictedAccess) {
229
+ if (_.isEmpty(password)) {
230
+ return ctx.badRequest('Please provide a password');
231
+ }
289
232
 
290
- if (isNewPassword) {
291
- prevConfig.password = await usersPermService.user.hashPassword({
292
- password,
293
- });
233
+ config.password = await bcrypt.hash(password, 10);
294
234
  }
295
235
 
296
- _.set(prevConfig, 'restrictedAccess', restrictedAccess);
297
-
298
- await pluginStore.set({ key: 'config', value: prevConfig });
236
+ await pluginStore.set({ key: 'config', value: config });
299
237
 
300
238
  return ctx.send({ ok: true });
301
239
  },
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const bootstrap = require('./bootstrap');
4
+ const services = require('./services');
5
+ const routes = require('./routes');
6
+ const controllers = require('./controllers');
7
+ const register = require('./register');
8
+ const config = require('./config');
9
+
10
+ module.exports = () => ({
11
+ bootstrap,
12
+ config,
13
+ routes,
14
+ controllers,
15
+ register,
16
+ services,
17
+ });
@@ -1,61 +1,30 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('path');
4
- const _ = require('lodash');
5
4
  const koaStatic = require('koa-static');
6
-
7
- const initialRoutes = [];
8
-
9
- // TODO: delete when refactoring documentation plugin for v4
10
- module.exports = {
11
- defaults: { documentation: { enabled: true } },
12
- load: {
13
- beforeInitialize() {
14
- strapi.config.middleware.load.before.push('documentation');
15
-
16
- initialRoutes.push(..._.cloneDeep(strapi.plugins.documentation.routes));
17
- },
18
-
19
- initialize() {
20
- const swaggerUi = require('swagger-ui-dist');
21
-
22
- // Find the plugins routes.
23
- strapi.plugins.documentation.routes = strapi.plugins.documentation.routes.map(
24
- (route, index) => {
25
- if (route.handler === 'Documentation.getInfos') {
26
- return route;
27
- }
28
-
29
- if (route.handler === 'Documentation.index' || route.path === '/login') {
30
- route.config.policies = initialRoutes[index].config.policies;
31
- }
32
-
33
- // Set prefix to empty to be able to customise it.
34
- if (strapi.config.has('plugins.documentation.x-strapi-config.path')) {
35
- route.config.prefix = '';
36
- route.path = `/${strapi.config.get('plugin.documentation.x-strapi-config').path}${
37
- route.path
38
- }`.replace('//', '/');
39
- }
40
-
41
- return route;
42
- }
43
- );
44
-
45
- strapi.server.routes([
46
- {
47
- method: 'GET',
48
- path: '/plugins/documentation/(.*)',
49
- async handler(ctx, next) {
50
- ctx.url = path.basename(ctx.url);
51
-
52
- return koaStatic(swaggerUi.getAbsoluteFSPath(), {
53
- maxage: strapi.config.middleware.settings.public.maxAge,
54
- defer: true,
55
- })(ctx, next);
56
- },
57
- },
58
- ]);
5
+ const session = require('koa-session');
6
+ const swaggerUi = require('swagger-ui-dist');
7
+
8
+ module.exports = async ({ strapi }) => {
9
+ const sessionConfig = strapi.config.get('plugin.documentation').session;
10
+ strapi.server.app.keys = sessionConfig.secretKeys;
11
+ strapi.server.app.use(session(sessionConfig, strapi.server.app));
12
+
13
+ strapi.server.routes([
14
+ {
15
+ method: 'GET',
16
+ path: '/plugins/documentation/(.*)',
17
+ async handler(ctx, next) {
18
+ ctx.url = path.basename(ctx.url);
19
+
20
+ return koaStatic(swaggerUi.getAbsoluteFSPath(), {
21
+ maxage: 86400000,
22
+ defer: true,
23
+ })(ctx, next);
24
+ },
25
+ config: {
26
+ auth: false,
27
+ },
59
28
  },
60
- },
29
+ ]);
61
30
  };
@@ -9,7 +9,7 @@ module.exports = async (ctx, next) => {
9
9
  return next();
10
10
  }
11
11
 
12
- if (!ctx.session.documentation) {
12
+ if (!ctx.session.documentation || !ctx.session.documentation.logged) {
13
13
  const querystring = ctx.querystring ? `?${ctx.querystring}` : '';
14
14
 
15
15
  return ctx.redirect(
@@ -18,15 +18,7 @@ module.exports = async (ctx, next) => {
18
18
  }/login${querystring}`
19
19
  );
20
20
  }
21
- const isValid = await strapi.plugins['users-permissions'].services.user.validatePassword(
22
- ctx.session.documentation,
23
- config.password
24
- );
25
-
26
- if (!isValid) {
27
- ctx.session.documentation = null;
28
- }
29
21
 
30
22
  // Execute the action.
31
- await next();
23
+ return next();
32
24
  };
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const registerDocumentationMiddleWare = require('./middlewares/documentation');
4
+
5
+ /**
6
+ * Register upload plugin
7
+ * @param {{ strapi: import('@strapi/strapi').Strapi }}
8
+ */
9
+ module.exports = async ({ strapi }) => {
10
+ await registerDocumentationMiddleWare({ strapi });
11
+ };
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+ const restrictAccess = require('../middlewares/restrict-access');
2
3
 
3
4
  module.exports = [
4
5
  {
@@ -6,10 +7,8 @@ module.exports = [
6
7
  path: '/',
7
8
  handler: 'documentation.index',
8
9
  config: {
9
- policies: [
10
- 'plugin::documentation.index',
11
- { name: 'admin::hasPermissions', options: { actions: ['plugin::documentation.read'] } },
12
- ],
10
+ auth: false,
11
+ middlewares: [restrictAccess],
13
12
  },
14
13
  },
15
14
  {
@@ -17,10 +16,8 @@ module.exports = [
17
16
  path: '/v:major(\\d+).:minor(\\d+).:patch(\\d+)',
18
17
  handler: 'documentation.index',
19
18
  config: {
20
- policies: [
21
- 'plugin::documentation.index',
22
- { name: 'admin::hasPermissions', options: { actions: ['plugin::documentation.read'] } },
23
- ],
19
+ auth: false,
20
+ middlewares: [restrictAccess],
24
21
  },
25
22
  },
26
23
  {
@@ -28,9 +25,7 @@ module.exports = [
28
25
  path: '/login',
29
26
  handler: 'documentation.loginView',
30
27
  config: {
31
- policies: [
32
- { name: 'admin::hasPermissions', options: { actions: ['plugin::documentation.read'] } },
33
- ],
28
+ auth: false,
34
29
  },
35
30
  },
36
31
  {
@@ -38,9 +33,7 @@ module.exports = [
38
33
  path: '/login',
39
34
  handler: 'documentation.login',
40
35
  config: {
41
- policies: [
42
- { name: 'admin::hasPermissions', options: { actions: ['plugin::documentation.read'] } },
43
- ],
36
+ auth: false,
44
37
  },
45
38
  },
46
39
  {
@@ -49,7 +42,7 @@ module.exports = [
49
42
  handler: 'documentation.getInfos',
50
43
  config: {
51
44
  policies: [
52
- { name: 'admin::hasPermissions', options: { actions: ['plugin::documentation.read'] } },
45
+ { name: 'admin::hasPermissions', config: { actions: ['plugin::documentation.read'] } },
53
46
  ],
54
47
  },
55
48
  },
@@ -61,7 +54,7 @@ module.exports = [
61
54
  policies: [
62
55
  {
63
56
  name: 'admin::hasPermissions',
64
- options: { actions: ['plugin::documentation.settings.regenerate'] },
57
+ config: { actions: ['plugin::documentation.settings.regenerate'] },
65
58
  },
66
59
  ],
67
60
  },
@@ -74,7 +67,7 @@ module.exports = [
74
67
  policies: [
75
68
  {
76
69
  name: 'admin::hasPermissions',
77
- options: { actions: ['plugin::documentation.settings.update'] },
70
+ config: { actions: ['plugin::documentation.settings.update'] },
78
71
  },
79
72
  ],
80
73
  },