@akemona-org/strapi-plugin-documentation 3.7.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.
Files changed (64) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +170 -0
  3. package/admin/src/assets/images/logo.svg +1 -0
  4. package/admin/src/components/Block/components.js +26 -0
  5. package/admin/src/components/Block/index.js +39 -0
  6. package/admin/src/components/Row/ButtonContainer.js +53 -0
  7. package/admin/src/components/Row/components.js +83 -0
  8. package/admin/src/components/Row/index.js +57 -0
  9. package/admin/src/containers/App/index.js +30 -0
  10. package/admin/src/containers/HomePage/actions.js +72 -0
  11. package/admin/src/containers/HomePage/components.js +59 -0
  12. package/admin/src/containers/HomePage/constants.js +14 -0
  13. package/admin/src/containers/HomePage/index.js +283 -0
  14. package/admin/src/containers/HomePage/reducer.js +49 -0
  15. package/admin/src/containers/HomePage/saga.js +126 -0
  16. package/admin/src/containers/HomePage/selectors.js +34 -0
  17. package/admin/src/containers/Initializer/index.js +28 -0
  18. package/admin/src/containers/Initializer/tests/index.test.js +21 -0
  19. package/admin/src/index.js +57 -0
  20. package/admin/src/lifecycles.js +13 -0
  21. package/admin/src/permissions.js +19 -0
  22. package/admin/src/pluginId.js +5 -0
  23. package/admin/src/reducers.js +8 -0
  24. package/admin/src/translations/ar.json +23 -0
  25. package/admin/src/translations/cs.json +24 -0
  26. package/admin/src/translations/de.json +30 -0
  27. package/admin/src/translations/en.json +31 -0
  28. package/admin/src/translations/es.json +27 -0
  29. package/admin/src/translations/fr.json +29 -0
  30. package/admin/src/translations/id.json +28 -0
  31. package/admin/src/translations/index.js +49 -0
  32. package/admin/src/translations/it.json +29 -0
  33. package/admin/src/translations/ko.json +24 -0
  34. package/admin/src/translations/ms.json +26 -0
  35. package/admin/src/translations/nl.json +24 -0
  36. package/admin/src/translations/pl.json +27 -0
  37. package/admin/src/translations/pt-BR.json +24 -0
  38. package/admin/src/translations/pt.json +24 -0
  39. package/admin/src/translations/ru.json +31 -0
  40. package/admin/src/translations/sk.json +27 -0
  41. package/admin/src/translations/th.json +27 -0
  42. package/admin/src/translations/tr.json +23 -0
  43. package/admin/src/translations/uk.json +26 -0
  44. package/admin/src/translations/vi.json +27 -0
  45. package/admin/src/translations/zh-Hans.json +31 -0
  46. package/admin/src/translations/zh.json +27 -0
  47. package/admin/src/utils/getTrad.js +5 -0
  48. package/admin/src/utils/openWithNewTab.js +20 -0
  49. package/config/functions/bootstrap.js +138 -0
  50. package/config/policies/index.js +35 -0
  51. package/config/routes.json +74 -0
  52. package/config/settings.json +46 -0
  53. package/controllers/Documentation.js +303 -0
  54. package/middlewares/documentation/defaults.json +5 -0
  55. package/middlewares/documentation/index.js +59 -0
  56. package/package.json +89 -0
  57. package/public/index.html +57 -0
  58. package/public/login.html +135 -0
  59. package/services/Documentation.js +1861 -0
  60. package/services/Token.js +31 -0
  61. package/services/utils/components.json +25 -0
  62. package/services/utils/forms.json +29 -0
  63. package/services/utils/parametersOptions.json +134 -0
  64. package/services/utils/unknownComponent.json +11 -0
@@ -0,0 +1,31 @@
1
+ {
2
+ "components.Row.generatedDate": "上一个生成的版本",
3
+ "components.Row.open": "打开",
4
+ "components.Row.regenerate": "重新生成",
5
+ "containers.HomePage.Block.title": "版本号",
6
+ "containers.HomePage.Button.open": "打开API文档",
7
+ "containers.HomePage.Button.update": "更新",
8
+ "containers.HomePage.PluginHeader.description": "配置API文档插件",
9
+ "containers.HomePage.PluginHeader.title": "API文档设置",
10
+ "containers.HomePage.PopUpWarning.confirm": "确定",
11
+ "containers.HomePage.PopUpWarning.message": "您确定要删除此版本吗?",
12
+ "containers.HomePage.copied": "令牌已被复制到粘贴板",
13
+ "containers.HomePage.form.jwtToken": "获取您的 JWT 令牌",
14
+ "containers.HomePage.form.jwtToken.description": "复制此令牌,并用它在 Swagger 中发出请求",
15
+ "containers.HomePage.form.password": "密码",
16
+ "containers.HomePage.form.password.inputDescription": "设置访问所需的密码",
17
+ "containers.HomePage.form.restrictedAccess": "限制访问",
18
+ "containers.HomePage.form.restrictedAccess.inputDescription": "将文档端点设为私有。默认情况下,访问是公开的。",
19
+ "containers.HomePage.form.showGeneratedFiles": "显示生成的文件",
20
+ "containers.HomePage.form.showGeneratedFiles.inputDescription": "当您想要覆盖生成的文档的时候很有用。 \n该插件将生成按型号和插件拆分的文件。 \n通过启用此选项,可以更轻松地自定义文档",
21
+ "error.deleteDoc.versionMissing": "您尝试删除的版本不存在。",
22
+ "error.noVersion": "需要一个版本",
23
+ "error.regenerateDoc": "重新生成文件时发生错误",
24
+ "error.regenerateDoc.versionMissing": "您尝试重新生成的版本不存在",
25
+ "notification.update.success": "设置更新成功",
26
+ "notification.delete.success": "API文档已删除",
27
+ "notification.generate.success": "API文档已生成",
28
+ "plugin.name": "OpenAPI文档",
29
+ "plugin.description.long": "创建一个 OpenAPI 文档,并通过 SWAGGER UI 直接查看。",
30
+ "plugin.description.short": "创建一个 OpenAPI 文档,并通过 SWAGGER UI 直接查看。"
31
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "components.Row.generatedDate": "最後產生的時間",
3
+ "components.Row.open": "開啟",
4
+ "components.Row.regenerate": "重新產生",
5
+ "containers.HomePage.Block.title": "版本",
6
+ "containers.HomePage.Button.open": "打開文件資料",
7
+ "containers.HomePage.Button.update": "更新",
8
+ "containers.HomePage.PluginHeader.description": "配置文件資料擴充套件設定",
9
+ "containers.HomePage.PluginHeader.title": "文件資料 - 設定",
10
+ "containers.HomePage.PopUpWarning.confirm": "我了解了",
11
+ "containers.HomePage.PopUpWarning.message": "你確定要刪除這個版本嗎?",
12
+ "containers.HomePage.copied": "Token 已經複製到剪貼簿",
13
+ "containers.HomePage.form.jwtToken": "存取你的 jwt token",
14
+ "containers.HomePage.form.jwtToken.description": "複製這個token並於swagger中使用於發出請求",
15
+ "containers.HomePage.form.password": "密碼",
16
+ "containers.HomePage.form.password.inputDescription": "設定密碼存取權限",
17
+ "containers.HomePage.form.restrictedAccess": "存取受到限制",
18
+ "containers.HomePage.form.restrictedAccess.inputDescription": "將endpoints設定為私密的. 預設是對外公開的",
19
+ "containers.HomePage.form.showGeneratedFiles": "顯示產生的檔案",
20
+ "containers.HomePage.form.showGeneratedFiles.inputDescription": "用於覆寫產生的文件檔案時. \n擴充套件會依照model及plugin分別產生檔案. \n啟用這個選項將會方便你客製化文件資料",
21
+ "error.deleteDoc.versionMissing": "你想刪除的版本不存在",
22
+ "error.noVersion": "版本是必填欄位",
23
+ "error.regenerateDoc": "重新產生文件資料時發生了錯誤",
24
+ "error.regenerateDoc.versionMissing": "你想產生的版本不存在",
25
+ "notification.update.success": "更新設定成功",
26
+ "plugin.name": "文件資料"
27
+ }
@@ -0,0 +1,5 @@
1
+ import pluginId from '../pluginId';
2
+
3
+ const getTrad = id => `${pluginId}.${id}`;
4
+
5
+ export default getTrad;
@@ -0,0 +1,20 @@
1
+ import { startsWith } from 'lodash';
2
+
3
+ const openWithNewTab = path => {
4
+ const url = (() => {
5
+ if (startsWith(path, '/')) {
6
+ return `${strapi.backendURL}${path}`;
7
+ }
8
+ if (startsWith(path, 'https') || startsWith(path, 'http')) {
9
+ return path;
10
+ }
11
+
12
+ return `${strapi.backendURL}/${path}`;
13
+ })();
14
+
15
+ window.open(url, '_blank');
16
+
17
+ return window.focus();
18
+ };
19
+
20
+ export default openWithNewTab;
@@ -0,0 +1,138 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const _ = require('lodash');
6
+
7
+ module.exports = async () => {
8
+ // Check if the plugin users-permissions is installed because the documentation needs it
9
+ if (Object.keys(strapi.plugins).indexOf('users-permissions') === -1) {
10
+ throw new Error(
11
+ 'In order to make the documentation plugin works the users-permissions one is required'
12
+ );
13
+ }
14
+
15
+ const pluginStore = strapi.store({
16
+ environment: '',
17
+ type: 'plugin',
18
+ name: 'documentation',
19
+ });
20
+ const restrictedAccess = await pluginStore.get({ key: 'config' });
21
+
22
+ if (!restrictedAccess) {
23
+ pluginStore.set({ key: 'config', value: { restrictedAccess: false } });
24
+ }
25
+
26
+ let shouldUpdateFullDoc = false;
27
+ const services = strapi.plugins['documentation'].services.documentation;
28
+ // Generate plugins' documentation
29
+ const pluginsWithDocumentationNeeded = services.getPluginsWithDocumentationNeeded();
30
+ pluginsWithDocumentationNeeded.forEach(plugin => {
31
+ const isDocExisting = services.checkIfPluginDocumentationFolderExists(plugin);
32
+
33
+ if (!isDocExisting) {
34
+ services.createDocumentationDirectory(services.getPluginDocumentationPath(plugin));
35
+ // create the overrides directory
36
+ services.createDocumentationDirectory(services.getPluginOverrideDocumentationPath(plugin));
37
+ services.createPluginDocumentationFile(plugin);
38
+ shouldUpdateFullDoc = true;
39
+ } else {
40
+ const needToUpdatePluginDoc = services.checkIfPluginDocNeedsUpdate(plugin);
41
+
42
+ if (needToUpdatePluginDoc) {
43
+ services.createPluginDocumentationFile(plugin);
44
+ shouldUpdateFullDoc = true;
45
+ }
46
+ }
47
+ });
48
+
49
+ // Retrieve all the apis from the apis directory
50
+ const apis = services.getApis();
51
+ // Generate APIS' documentation
52
+ apis.forEach(api => {
53
+ const isDocExisting = services.checkIfDocumentationFolderExists(api);
54
+
55
+ if (!isDocExisting) {
56
+ // If the documentation directory doesn't exist create it
57
+ services.createDocumentationDirectory(services.getDocumentationPath(api));
58
+ // Create the overrides directory
59
+ services.createDocumentationDirectory(services.getDocumentationOverridesPath(api));
60
+ // Create the documentation files per version
61
+ services.createDocumentationFile(api); // Then create the {api}.json documentation file
62
+ shouldUpdateFullDoc = true;
63
+ } else {
64
+ const needToUpdateAPIDoc = services.checkIfAPIDocNeedsUpdate(api);
65
+
66
+ if (needToUpdateAPIDoc) {
67
+ services.createDocumentationFile(api);
68
+ shouldUpdateFullDoc = true;
69
+ }
70
+ }
71
+ });
72
+
73
+ const fullDoc = services.generateFullDoc();
74
+ // Verify that the correct documentation folder exists in the documentation plugin
75
+ const isMergedDocumentationExists = services.checkIfMergedDocumentationFolderExists();
76
+ const documentationPath = services.getMergedDocumentationPath();
77
+
78
+ if (isMergedDocumentationExists) {
79
+ /**
80
+ * Retrieve all tags from the documentation and join them
81
+ * @param {Object} documentation
82
+ * @returns {String}
83
+ */
84
+ const getDocTagsToString = documentation => {
85
+ return _.get(documentation, 'tags', [])
86
+ .map(tag => {
87
+ return tag.name.toLowerCase();
88
+ })
89
+ .sort((a, b) => a - b)
90
+ .join('.');
91
+ };
92
+ const oldDoc = require(path.resolve(documentationPath, 'full_documentation.json'));
93
+ const oldDocTags = getDocTagsToString(oldDoc);
94
+ const currentDocTags = getDocTagsToString(fullDoc);
95
+
96
+ // If the tags are different (an api has been deleted) we need to rebuild the documentation
97
+ if (oldDocTags !== currentDocTags) {
98
+ shouldUpdateFullDoc = true;
99
+ }
100
+ }
101
+
102
+ if (!isMergedDocumentationExists || shouldUpdateFullDoc) {
103
+ // Create the folder
104
+ services.createDocumentationDirectory(documentationPath);
105
+ // Write the file
106
+ fs.writeFileSync(
107
+ path.resolve(documentationPath, 'full_documentation.json'),
108
+ JSON.stringify(fullDoc, null, 2),
109
+ 'utf8'
110
+ );
111
+ }
112
+
113
+ // Add permissions
114
+ const actions = [
115
+ {
116
+ section: 'plugins',
117
+ displayName: 'Access the Documentation',
118
+ uid: 'read',
119
+ pluginName: 'documentation',
120
+ },
121
+ {
122
+ section: 'plugins',
123
+ displayName: 'Update and delete',
124
+ uid: 'settings.update',
125
+ subCategory: 'settings',
126
+ pluginName: 'documentation',
127
+ },
128
+ {
129
+ section: 'plugins',
130
+ displayName: 'Regenerate',
131
+ uid: 'settings.regenerate',
132
+ subCategory: 'settings',
133
+ pluginName: 'documentation',
134
+ },
135
+ ];
136
+
137
+ await strapi.admin.services.permission.actionProvider.registerMany(actions);
138
+ };
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ module.exports = async (ctx, next) => {
4
+ const pluginStore = strapi.store({
5
+ environment: '',
6
+ type: 'plugin',
7
+ name: 'documentation',
8
+ });
9
+ const config = await pluginStore.get({ key: 'config' });
10
+
11
+ const redirectToLogin = () => {
12
+ const querystring = ctx.querystring ? `?${ctx.querystring}` : '';
13
+ ctx.redirect(
14
+ `${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}/login${querystring}`
15
+ );
16
+ };
17
+
18
+ if (!config.restrictedAccess) {
19
+ return await next();
20
+ }
21
+
22
+ if (!ctx.session.token) {
23
+ return redirectToLogin();
24
+ }
25
+
26
+ const isValid = await strapi.plugins['documentation'].services.token.validate(ctx.session.token);
27
+
28
+ if (!isValid) {
29
+ ctx.session.token = null;
30
+ return redirectToLogin();
31
+ }
32
+
33
+ // Execute the action.
34
+ await next();
35
+ };
@@ -0,0 +1,74 @@
1
+ {
2
+ "routes": [
3
+ {
4
+ "method": "GET",
5
+ "path": "/",
6
+ "handler": "Documentation.index",
7
+ "config": {
8
+ "policies": [
9
+ "plugins::documentation.index",
10
+ ["admin::hasPermissions", ["plugins::documentation.read"]]
11
+ ]
12
+ }
13
+ },
14
+ {
15
+ "method": "GET",
16
+ "path": "/v:major(\\d+).:minor(\\d+).:patch(\\d+)",
17
+ "handler": "Documentation.index",
18
+ "config": {
19
+ "policies": [
20
+ "plugins::documentation.index",
21
+ ["admin::hasPermissions", ["plugins::documentation.read"]]
22
+ ]
23
+ }
24
+ },
25
+ {
26
+ "method": "GET",
27
+ "path": "/login",
28
+ "handler": "Documentation.loginView",
29
+ "config": {
30
+ "policies": [["admin::hasPermissions", ["plugins::documentation.read"]]]
31
+ }
32
+ },
33
+ {
34
+ "method": "POST",
35
+ "path": "/login",
36
+ "handler": "Documentation.login",
37
+ "config": {
38
+ "policies": [["admin::hasPermissions", ["plugins::documentation.read"]]]
39
+ }
40
+ },
41
+ {
42
+ "method": "GET",
43
+ "path": "/getInfos",
44
+ "handler": "Documentation.getInfos",
45
+ "config": {
46
+ "policies": [["admin::hasPermissions", ["plugins::documentation.read"]]]
47
+ }
48
+ },
49
+ {
50
+ "method": "POST",
51
+ "path": "/regenerateDoc",
52
+ "handler": "Documentation.regenerateDoc",
53
+ "config": {
54
+ "policies": [["admin::hasPermissions", ["plugins::documentation.settings.regenerate"]]]
55
+ }
56
+ },
57
+ {
58
+ "method": "PUT",
59
+ "path": "/updateSettings",
60
+ "handler": "Documentation.updateSettings",
61
+ "config": {
62
+ "policies": [["admin::hasPermissions", ["plugins::documentation.settings.update"]]]
63
+ }
64
+ },
65
+ {
66
+ "method": "DELETE",
67
+ "path": "/deleteDoc/:version",
68
+ "handler": "Documentation.deleteDoc",
69
+ "config": {
70
+ "policies": []
71
+ }
72
+ }
73
+ ]
74
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "version": "1.0.0",
5
+ "title": "DOCUMENTATION",
6
+ "description": "",
7
+ "termsOfService": "YOUR_TERMS_OF_SERVICE_URL",
8
+ "contact": {
9
+ "name": "TEAM",
10
+ "email": "contact-email@something.io",
11
+ "url": "mywebsite.io"
12
+ },
13
+ "license": {
14
+ "name": "Apache 2.0",
15
+ "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
16
+ }
17
+ },
18
+ "x-strapi-config": {
19
+ "path": "/documentation",
20
+ "showGeneratedFiles": true,
21
+ "generateDefaultResponse": true
22
+ },
23
+ "servers": [
24
+ {
25
+ "url": "http://localhost:1337",
26
+ "description": "Development server"
27
+ },
28
+ {
29
+ "url": "YOUR_STAGING_SERVER",
30
+ "description": "Staging server"
31
+ },
32
+ {
33
+ "url": "YOUR_PRODUCTION_SERVER",
34
+ "description": "Production server"
35
+ }
36
+ ],
37
+ "externalDocs": {
38
+ "description": "Find out more",
39
+ "url": "https://strapi.akemona.com/documentation/developer-docs/latest/getting-started/introduction.html"
40
+ },
41
+ "security": [
42
+ {
43
+ "bearerAuth": []
44
+ }
45
+ ]
46
+ }
@@ -0,0 +1,303 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Documentation.js controller
5
+ *
6
+ * @description: A set of functions called "actions" of the `documentation` plugin.
7
+ */
8
+
9
+ // Core dependencies.
10
+ const path = require('path');
11
+
12
+ // Public dependencies.
13
+ const fs = require('fs-extra');
14
+ const cheerio = require('cheerio');
15
+ const _ = require('lodash');
16
+ const koaStatic = require('koa-static');
17
+
18
+ module.exports = {
19
+ getInfos: async ctx => {
20
+ try {
21
+ const service = strapi.plugins.documentation.services.documentation;
22
+ const docVersions = service.retrieveDocumentationVersions();
23
+ const form = await service.retrieveFrontForm();
24
+
25
+ ctx.send({
26
+ docVersions,
27
+ currentVersion: service.getDocumentationVersion(),
28
+ prefix: strapi.plugins.documentation.config['x-strapi-config'].path,
29
+ form,
30
+ });
31
+ } catch (err) {
32
+ ctx.badRequest(null, err.message);
33
+ }
34
+ },
35
+
36
+ async index(ctx, next) {
37
+ try {
38
+ /**
39
+ * We don't expose the specs using koa-static or something else due to security reasons.
40
+ * That's why, we need to read the file localy and send the specs through it when we serve the Swagger UI.
41
+ */
42
+ const { major, minor, patch } = ctx.params;
43
+ const version =
44
+ major && minor && patch
45
+ ? `${major}.${minor}.${patch}`
46
+ : strapi.plugins.documentation.config.info.version;
47
+ const openAPISpecsPath = path.join(
48
+ strapi.config.appPath,
49
+ 'extensions',
50
+ 'documentation',
51
+ 'documentation',
52
+ version,
53
+ 'full_documentation.json'
54
+ );
55
+
56
+ try {
57
+ const documentation = fs.readFileSync(openAPISpecsPath, 'utf8');
58
+ const layout = fs.readFileSync(
59
+ path.resolve(__dirname, '..', 'public', 'index.html'),
60
+ 'utf8'
61
+ );
62
+ const filledLayout = _.template(layout)({
63
+ backendUrl: strapi.config.server.url,
64
+ spec: JSON.stringify(JSON.parse(documentation)),
65
+ });
66
+
67
+ try {
68
+ const layoutPath = path.resolve(
69
+ strapi.config.appPath,
70
+ 'extensions',
71
+ 'documentation',
72
+ 'public',
73
+ 'index.html'
74
+ );
75
+ await fs.ensureFile(layoutPath);
76
+ await fs.writeFile(layoutPath, filledLayout);
77
+
78
+ // Serve the file.
79
+ ctx.url = path.basename(`${ctx.url}/index.html`);
80
+
81
+ try {
82
+ const staticFolder = path.resolve(
83
+ strapi.config.appPath,
84
+ 'extensions',
85
+ 'documentation',
86
+ 'public'
87
+ );
88
+ return await koaStatic(staticFolder)(ctx, next);
89
+ } catch (e) {
90
+ strapi.log.error(e);
91
+ }
92
+ } catch (e) {
93
+ strapi.log.error(e);
94
+ }
95
+ } catch (e) {
96
+ strapi.log.error(e);
97
+ }
98
+ } catch (e) {
99
+ strapi.log.error(e);
100
+ }
101
+ },
102
+
103
+ async loginView(ctx, next) {
104
+ const { error } = ctx.query;
105
+
106
+ try {
107
+ const layout = fs.readFileSync(path.join(__dirname, '..', 'public', 'login.html'));
108
+ const filledLayout = _.template(layout)({
109
+ actionUrl: `${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}/login`,
110
+ });
111
+ const $ = cheerio.load(filledLayout);
112
+
113
+ $('.error').text(_.isEmpty(error) ? '' : 'Wrong password...');
114
+
115
+ try {
116
+ const layoutPath = path.resolve(
117
+ strapi.config.appPath,
118
+ 'extensions',
119
+ 'documentation',
120
+ 'public',
121
+ 'login.html'
122
+ );
123
+ await fs.ensureFile(layoutPath);
124
+ await fs.writeFile(layoutPath, $.html());
125
+
126
+ ctx.url = path.basename(`${ctx.url}/login.html`);
127
+
128
+ try {
129
+ const staticFolder = path.resolve(
130
+ strapi.config.appPath,
131
+ 'extensions',
132
+ 'documentation',
133
+ 'public'
134
+ );
135
+ return await koaStatic(staticFolder)(ctx, next);
136
+ } catch (e) {
137
+ strapi.log.error(e);
138
+ }
139
+ } catch (e) {
140
+ strapi.log.error(e);
141
+ }
142
+ } catch (e) {
143
+ strapi.log.error(e);
144
+ }
145
+ },
146
+
147
+ async login(ctx) {
148
+ const {
149
+ body: { password },
150
+ } = ctx.request;
151
+
152
+ const { password: storedPassword } = await strapi
153
+ .store({
154
+ environment: '',
155
+ type: 'plugin',
156
+ name: 'documentation',
157
+ key: 'config',
158
+ })
159
+ .get();
160
+
161
+ const isValid = await strapi.plugins['users-permissions'].services.user.validatePassword(
162
+ password,
163
+ storedPassword
164
+ );
165
+ let querystring = '?error=password';
166
+
167
+ if (isValid) {
168
+ ctx.session.token = await strapi.plugins['documentation'].services.token.create();
169
+ querystring = '';
170
+ }
171
+
172
+ ctx.redirect(
173
+ `${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}${querystring}`
174
+ );
175
+ },
176
+
177
+ regenerateDoc: async ctx => {
178
+ const service = strapi.plugins.documentation.services.documentation;
179
+ const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
180
+ const {
181
+ request: {
182
+ body: { version },
183
+ admin,
184
+ },
185
+ } = ctx;
186
+
187
+ if (_.isEmpty(version)) {
188
+ return ctx.badRequest(
189
+ null,
190
+ admin ? 'documentation.error.noVersion' : 'Please provide a version.'
191
+ );
192
+ }
193
+
194
+ if (!documentationVersions.includes(version)) {
195
+ return ctx.badRequest(
196
+ null,
197
+ admin
198
+ ? 'documentation.error.regenerateDoc.versionMissing'
199
+ : 'The version you are trying to generate does not exist.'
200
+ );
201
+ }
202
+
203
+ try {
204
+ strapi.reload.isWatching = false;
205
+ const fullDoc = service.generateFullDoc(version);
206
+ const documentationPath = service.getMergedDocumentationPath(version);
207
+ // Write the file
208
+ fs.writeFileSync(
209
+ path.resolve(documentationPath, 'full_documentation.json'),
210
+ JSON.stringify(fullDoc, null, 2),
211
+ 'utf8'
212
+ );
213
+ ctx.send({ ok: true });
214
+ } catch (err) {
215
+ ctx.badRequest(null, admin ? 'documentation.error.regenerateDoc' : 'An error occured');
216
+ } finally {
217
+ strapi.reload.isWatching = true;
218
+ }
219
+ },
220
+
221
+ deleteDoc: async ctx => {
222
+ strapi.reload.isWatching = false;
223
+ const service = strapi.plugins.documentation.services.documentation;
224
+ const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
225
+ const {
226
+ request: {
227
+ params: { version },
228
+ admin,
229
+ },
230
+ } = ctx;
231
+
232
+ if (_.isEmpty(version)) {
233
+ return ctx.badRequest(
234
+ null,
235
+ admin ? 'documentation.error.noVersion' : 'Please provide a version.'
236
+ );
237
+ }
238
+
239
+ 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
+ );
246
+ }
247
+
248
+ try {
249
+ await service.deleteDocumentation(version);
250
+ ctx.send({ ok: true });
251
+ } catch (err) {
252
+ ctx.badRequest(null, admin ? 'notification.error' : err.message);
253
+ } finally {
254
+ strapi.reload.isWatching = true;
255
+ }
256
+ },
257
+
258
+ updateSettings: async ctx => {
259
+ const {
260
+ admin,
261
+ body: { restrictedAccess, password },
262
+ } = ctx.request;
263
+ const usersPermService = strapi.plugins['users-permissions'].services;
264
+ const pluginStore = strapi.store({
265
+ environment: '',
266
+ type: 'plugin',
267
+ name: 'documentation',
268
+ });
269
+ const prevConfig = await pluginStore.get({ key: 'config' });
270
+
271
+ if (restrictedAccess && _.isEmpty(password)) {
272
+ return ctx.badRequest(
273
+ null,
274
+ admin ? 'users-permissions.Auth.form.error.password.provide' : 'Please provide a password'
275
+ );
276
+ }
277
+
278
+ const isNewPassword = !_.isEmpty(password) && password !== prevConfig.password;
279
+
280
+ if (isNewPassword && usersPermService.user.isHashed(password)) {
281
+ // Throw an error if the password selected by the user
282
+ // contains more than two times the symbol '$'.
283
+ return ctx.badRequest(
284
+ null,
285
+ admin
286
+ ? 'users-permissions.Auth.form.error.password.format'
287
+ : 'our password cannot contain more than three times the symbol `$`.'
288
+ );
289
+ }
290
+
291
+ if (isNewPassword) {
292
+ prevConfig.password = await usersPermService.user.hashPassword({
293
+ password,
294
+ });
295
+ }
296
+
297
+ _.set(prevConfig, 'restrictedAccess', restrictedAccess);
298
+
299
+ await pluginStore.set({ key: 'config', value: prevConfig });
300
+
301
+ return ctx.send({ ok: true });
302
+ },
303
+ };
@@ -0,0 +1,5 @@
1
+ {
2
+ "documentation": {
3
+ "enabled": true
4
+ }
5
+ }