2018-12-06 18:03:56 +01:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Documentation.js controller
|
|
|
|
*
|
|
|
|
* @description: A set of functions called "actions" of the `documentation` plugin.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Core dependencies.
|
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
// Public dependencies.
|
2019-05-06 11:54:15 +02:00
|
|
|
const fs = require('fs-extra');
|
2018-12-06 18:03:56 +01:00
|
|
|
const cheerio = require('cheerio');
|
|
|
|
const _ = require('lodash');
|
2019-06-08 18:50:07 +02:00
|
|
|
const koaStatic = require('koa-static');
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
module.exports = {
|
2019-06-08 18:50:07 +02:00
|
|
|
getInfos: async ctx => {
|
2018-12-06 18:03:56 +01:00
|
|
|
try {
|
|
|
|
const service = strapi.plugins.documentation.services.documentation;
|
|
|
|
const docVersions = service.retrieveDocumentationVersions();
|
|
|
|
const form = await service.retrieveFrontForm();
|
2019-04-15 18:57:58 +02:00
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
ctx.send({
|
|
|
|
docVersions,
|
|
|
|
currentVersion: service.getDocumentationVersion(),
|
2020-05-08 13:50:00 +02:00
|
|
|
prefix: strapi.plugins.documentation.config['x-strapi-config'].path,
|
2019-06-08 18:50:07 +02:00
|
|
|
form,
|
|
|
|
});
|
|
|
|
} catch (err) {
|
2018-12-06 18:03:56 +01:00
|
|
|
ctx.badRequest(null, err.message);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-04-15 18:57:58 +02:00
|
|
|
async index(ctx, next) {
|
2018-12-06 18:03:56 +01:00
|
|
|
try {
|
|
|
|
/**
|
|
|
|
* We don't expose the specs using koa-static or something else due to security reasons.
|
|
|
|
* That's why, we need to read the file localy and send the specs through it when we serve the Swagger UI.
|
|
|
|
*/
|
|
|
|
const { major, minor, patch } = ctx.params;
|
2019-06-08 18:50:07 +02:00
|
|
|
const version =
|
|
|
|
major && minor && patch
|
|
|
|
? `${major}.${minor}.${patch}`
|
|
|
|
: strapi.plugins.documentation.config.info.version;
|
|
|
|
const openAPISpecsPath = path.join(
|
|
|
|
strapi.config.appPath,
|
|
|
|
'extensions',
|
|
|
|
'documentation',
|
|
|
|
'documentation',
|
|
|
|
version,
|
|
|
|
'full_documentation.json'
|
|
|
|
);
|
2019-04-15 18:57:58 +02:00
|
|
|
|
|
|
|
try {
|
2018-12-06 18:03:56 +01:00
|
|
|
const documentation = fs.readFileSync(openAPISpecsPath, 'utf8');
|
2020-05-08 13:50:00 +02:00
|
|
|
const layout = fs.readFileSync(
|
|
|
|
path.resolve(__dirname, '..', 'public', 'index.html'),
|
|
|
|
'utf8'
|
|
|
|
);
|
|
|
|
const filledLayout = _.template(layout)({
|
|
|
|
backendUrl: strapi.config.server.url,
|
|
|
|
spec: JSON.stringify(JSON.parse(documentation)),
|
|
|
|
});
|
2019-04-15 18:57:58 +02:00
|
|
|
|
2018-12-06 18:03:56 +01:00
|
|
|
try {
|
2019-06-08 18:50:07 +02:00
|
|
|
const layoutPath = path.resolve(
|
|
|
|
strapi.config.appPath,
|
|
|
|
'extensions',
|
|
|
|
'documentation',
|
|
|
|
'public',
|
|
|
|
'index.html'
|
|
|
|
);
|
2019-05-06 11:54:15 +02:00
|
|
|
await fs.ensureFile(layoutPath);
|
2020-05-08 13:50:00 +02:00
|
|
|
await fs.writeFile(layoutPath, filledLayout);
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
// Serve the file.
|
|
|
|
ctx.url = path.basename(`${ctx.url}/index.html`);
|
|
|
|
|
|
|
|
try {
|
2019-06-08 18:50:07 +02:00
|
|
|
const staticFolder = path.resolve(
|
|
|
|
strapi.config.appPath,
|
|
|
|
'extensions',
|
|
|
|
'documentation',
|
|
|
|
'public'
|
|
|
|
);
|
|
|
|
return await koaStatic(staticFolder)(ctx, next);
|
2018-12-06 18:03:56 +01:00
|
|
|
} catch (e) {
|
2019-04-15 18:57:58 +02:00
|
|
|
strapi.log.error(e);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
2019-06-08 18:50:07 +02:00
|
|
|
} catch (e) {
|
2019-04-15 18:57:58 +02:00
|
|
|
strapi.log.error(e);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2019-04-15 18:57:58 +02:00
|
|
|
strapi.log.error(e);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2019-04-15 18:57:58 +02:00
|
|
|
strapi.log.error(e);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-04-15 18:57:58 +02:00
|
|
|
async loginView(ctx, next) {
|
2018-12-06 18:03:56 +01:00
|
|
|
const { error } = ctx.query;
|
|
|
|
|
|
|
|
try {
|
2020-05-08 13:50:00 +02:00
|
|
|
const layout = fs.readFileSync(path.join(__dirname, '..', 'public', 'login.html'));
|
|
|
|
const filledLayout = _.template(layout)({
|
|
|
|
actionUrl: `${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}/login`,
|
|
|
|
});
|
|
|
|
const $ = cheerio.load(filledLayout);
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
$('.error').text(_.isEmpty(error) ? '' : 'Wrong password...');
|
|
|
|
|
|
|
|
try {
|
2019-06-08 18:50:07 +02:00
|
|
|
const layoutPath = path.resolve(
|
|
|
|
strapi.config.appPath,
|
|
|
|
'extensions',
|
|
|
|
'documentation',
|
|
|
|
'public',
|
|
|
|
'login.html'
|
|
|
|
);
|
2019-05-06 11:54:15 +02:00
|
|
|
await fs.ensureFile(layoutPath);
|
|
|
|
await fs.writeFile(layoutPath, $.html());
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
ctx.url = path.basename(`${ctx.url}/login.html`);
|
2019-04-15 18:57:58 +02:00
|
|
|
|
|
|
|
try {
|
2019-06-08 18:50:07 +02:00
|
|
|
const staticFolder = path.resolve(
|
|
|
|
strapi.config.appPath,
|
|
|
|
'extensions',
|
|
|
|
'documentation',
|
|
|
|
'public'
|
|
|
|
);
|
|
|
|
return await koaStatic(staticFolder)(ctx, next);
|
2019-04-15 18:57:58 +02:00
|
|
|
} catch (e) {
|
|
|
|
strapi.log.error(e);
|
|
|
|
}
|
2018-12-06 18:03:56 +01:00
|
|
|
} catch (e) {
|
2019-04-15 18:57:58 +02:00
|
|
|
strapi.log.error(e);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2019-04-15 18:57:58 +02:00
|
|
|
strapi.log.error(e);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
async login(ctx) {
|
|
|
|
const {
|
|
|
|
body: { password },
|
|
|
|
} = ctx.request;
|
|
|
|
|
|
|
|
const { password: storedPassword } = await strapi
|
|
|
|
.store({
|
|
|
|
environment: '',
|
|
|
|
type: 'plugin',
|
|
|
|
name: 'documentation',
|
|
|
|
key: 'config',
|
|
|
|
})
|
|
|
|
.get();
|
|
|
|
|
2020-09-01 20:33:37 +05:30
|
|
|
const isValid = await strapi.plugins['users-permissions'].services.user.validatePassword(
|
2020-05-08 13:50:00 +02:00
|
|
|
password,
|
|
|
|
storedPassword
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
let querystring = '?error=password';
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
ctx.session.documentation = password;
|
|
|
|
querystring = '';
|
|
|
|
}
|
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
ctx.redirect(
|
2020-05-08 13:50:00 +02:00
|
|
|
`${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}${querystring}`
|
2019-06-08 18:50:07 +02:00
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
},
|
2019-04-15 18:57:58 +02:00
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
regenerateDoc: async ctx => {
|
2018-12-06 18:03:56 +01:00
|
|
|
const service = strapi.plugins.documentation.services.documentation;
|
2020-05-08 13:50:00 +02:00
|
|
|
const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
|
2019-06-08 18:50:07 +02:00
|
|
|
const {
|
|
|
|
request: {
|
|
|
|
body: { version },
|
|
|
|
admin,
|
|
|
|
},
|
|
|
|
} = ctx;
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
if (_.isEmpty(version)) {
|
2019-06-08 18:50:07 +02:00
|
|
|
return ctx.badRequest(
|
|
|
|
null,
|
|
|
|
admin ? 'documentation.error.noVersion' : 'Please provide a version.'
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!documentationVersions.includes(version)) {
|
2019-06-08 18:50:07 +02:00
|
|
|
return ctx.badRequest(
|
|
|
|
null,
|
|
|
|
admin
|
|
|
|
? 'documentation.error.regenerateDoc.versionMissing'
|
|
|
|
: 'The version you are trying to generate does not exist.'
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
strapi.reload.isWatching = false;
|
|
|
|
const fullDoc = service.generateFullDoc(version);
|
|
|
|
const documentationPath = service.getMergedDocumentationPath(version);
|
|
|
|
// Write the file
|
2019-06-08 18:50:07 +02:00
|
|
|
fs.writeFileSync(
|
|
|
|
path.resolve(documentationPath, 'full_documentation.json'),
|
|
|
|
JSON.stringify(fullDoc, null, 2),
|
|
|
|
'utf8'
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
ctx.send({ ok: true });
|
2019-06-08 18:50:07 +02:00
|
|
|
} catch (err) {
|
2020-05-08 13:50:00 +02:00
|
|
|
ctx.badRequest(null, admin ? 'documentation.error.regenerateDoc' : 'An error occured');
|
2018-12-06 18:03:56 +01:00
|
|
|
} finally {
|
|
|
|
strapi.reload.isWatching = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
deleteDoc: async ctx => {
|
2018-12-06 18:03:56 +01:00
|
|
|
strapi.reload.isWatching = false;
|
|
|
|
const service = strapi.plugins.documentation.services.documentation;
|
2020-05-08 13:50:00 +02:00
|
|
|
const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
|
2021-05-04 17:21:15 +02:00
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
const {
|
2021-05-04 17:21:15 +02:00
|
|
|
params: { version },
|
|
|
|
request: { admin },
|
2019-06-08 18:50:07 +02:00
|
|
|
} = ctx;
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
if (_.isEmpty(version)) {
|
2019-06-08 18:50:07 +02:00
|
|
|
return ctx.badRequest(
|
|
|
|
null,
|
|
|
|
admin ? 'documentation.error.noVersion' : 'Please provide a version.'
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!documentationVersions.includes(version)) {
|
2019-06-08 18:50:07 +02:00
|
|
|
return ctx.badRequest(
|
|
|
|
null,
|
|
|
|
admin
|
|
|
|
? 'documentation.error.deleteDoc.versionMissing'
|
|
|
|
: 'The version you are trying to delete does not exist.'
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
await service.deleteDocumentation(version);
|
|
|
|
ctx.send({ ok: true });
|
2019-06-08 18:50:07 +02:00
|
|
|
} catch (err) {
|
2018-12-06 18:03:56 +01:00
|
|
|
ctx.badRequest(null, admin ? 'notification.error' : err.message);
|
|
|
|
} finally {
|
|
|
|
strapi.reload.isWatching = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-06-08 18:50:07 +02:00
|
|
|
updateSettings: async ctx => {
|
|
|
|
const {
|
|
|
|
admin,
|
|
|
|
body: { restrictedAccess, password },
|
|
|
|
} = ctx.request;
|
2018-12-06 18:03:56 +01:00
|
|
|
const usersPermService = strapi.plugins['users-permissions'].services;
|
|
|
|
const pluginStore = strapi.store({
|
|
|
|
environment: '',
|
|
|
|
type: 'plugin',
|
|
|
|
name: 'documentation',
|
|
|
|
});
|
|
|
|
const prevConfig = await pluginStore.get({ key: 'config' });
|
|
|
|
|
|
|
|
if (restrictedAccess && _.isEmpty(password)) {
|
2019-06-08 18:50:07 +02:00
|
|
|
return ctx.badRequest(
|
|
|
|
null,
|
2020-05-08 13:50:00 +02:00
|
|
|
admin ? 'users-permissions.Auth.form.error.password.provide' : 'Please provide a password'
|
2019-06-08 18:50:07 +02:00
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
|
2020-05-08 13:50:00 +02:00
|
|
|
const isNewPassword = !_.isEmpty(password) && password !== prevConfig.password;
|
2018-12-06 18:03:56 +01:00
|
|
|
|
|
|
|
if (isNewPassword && usersPermService.user.isHashed(password)) {
|
|
|
|
// Throw an error if the password selected by the user
|
|
|
|
// contains more than two times the symbol '$'.
|
2019-06-08 18:50:07 +02:00
|
|
|
return ctx.badRequest(
|
|
|
|
null,
|
|
|
|
admin
|
|
|
|
? 'users-permissions.Auth.form.error.password.format'
|
|
|
|
: 'our password cannot contain more than three times the symbol `$`.'
|
|
|
|
);
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isNewPassword) {
|
2019-06-08 18:50:07 +02:00
|
|
|
prevConfig.password = await usersPermService.user.hashPassword({
|
|
|
|
password,
|
|
|
|
});
|
2018-12-06 18:03:56 +01:00
|
|
|
}
|
2019-04-15 18:57:58 +02:00
|
|
|
|
2018-12-06 18:03:56 +01:00
|
|
|
_.set(prevConfig, 'restrictedAccess', restrictedAccess);
|
2019-04-15 18:57:58 +02:00
|
|
|
|
2018-12-06 18:03:56 +01:00
|
|
|
await pluginStore.set({ key: 'config', value: prevConfig });
|
|
|
|
|
|
|
|
return ctx.send({ ok: true });
|
|
|
|
},
|
|
|
|
};
|