2016-08-26 14:19:03 +02:00
|
|
|
'use strict';
|
|
|
|
|
2022-02-18 20:15:46 +01:00
|
|
|
const path = require('path');
|
2022-11-16 17:08:51 +01:00
|
|
|
|
2022-12-28 18:27:07 +01:00
|
|
|
const { map, values, sumBy, pipe, flatMap, propEq } = require('lodash/fp');
|
2019-04-30 18:01:59 +02:00
|
|
|
const execa = require('execa');
|
2018-03-23 12:44:17 +01:00
|
|
|
const _ = require('lodash');
|
2022-02-18 20:15:46 +01:00
|
|
|
const { exists } = require('fs-extra');
|
2022-09-29 17:35:18 +02:00
|
|
|
const { env } = require('@strapi/utils');
|
2021-10-20 17:30:05 +02:00
|
|
|
const { ValidationError } = require('@strapi/utils').errors;
|
2022-04-14 14:55:57 +02:00
|
|
|
const { isUsingTypeScript } = require('@strapi/typescript-utils');
|
2021-07-01 15:50:11 +02:00
|
|
|
// eslint-disable-next-line node/no-extraneous-require
|
2021-07-12 17:25:54 +02:00
|
|
|
const ee = require('@strapi/strapi/lib/utils/ee');
|
2021-07-01 15:50:11 +02:00
|
|
|
|
2022-04-06 09:09:04 +02:00
|
|
|
const {
|
|
|
|
validateUpdateProjectSettings,
|
|
|
|
validateUpdateProjectSettingsFiles,
|
2022-04-06 11:50:00 +02:00
|
|
|
validateUpdateProjectSettingsImagesDimensions,
|
2022-04-06 09:09:04 +02:00
|
|
|
} = require('../validation/project-settings');
|
2021-08-04 19:39:40 +02:00
|
|
|
const { getService } = require('../utils');
|
|
|
|
|
2020-01-07 14:15:16 +01:00
|
|
|
const PLUGIN_NAME_REGEX = /^[A-Za-z][A-Za-z0-9-_]+$/;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Validates a plugin name format
|
|
|
|
*/
|
2022-08-08 23:33:39 +02:00
|
|
|
const isValidPluginName = (plugin) => {
|
2020-03-06 19:16:23 +01:00
|
|
|
return _.isString(plugin) && !_.isEmpty(plugin) && PLUGIN_NAME_REGEX.test(plugin);
|
2020-01-07 14:15:16 +01:00
|
|
|
};
|
|
|
|
|
2016-08-26 14:19:03 +02:00
|
|
|
/**
|
|
|
|
* A set of functions called "actions" for `Admin`
|
|
|
|
*/
|
|
|
|
|
|
|
|
module.exports = {
|
2021-07-01 14:30:52 +02:00
|
|
|
// TODO very temporary to check the switch ee/ce
|
|
|
|
// When removing this we need to update the /admin/src/index.js file
|
|
|
|
// where we set the strapi.window.isEE value
|
|
|
|
async getProjectType() {
|
2021-07-12 17:25:54 +02:00
|
|
|
// FIXME
|
|
|
|
try {
|
|
|
|
return { data: { isEE: strapi.EE, features: ee.features.getEnabled() } };
|
|
|
|
} catch (err) {
|
|
|
|
return { data: { isEE: false, features: [] } };
|
|
|
|
}
|
2021-07-01 14:30:52 +02:00
|
|
|
},
|
|
|
|
|
2020-10-06 11:26:17 +02:00
|
|
|
async init() {
|
2022-03-30 10:25:18 +03:00
|
|
|
let uuid = strapi.config.get('uuid', false);
|
2021-07-28 15:32:21 +02:00
|
|
|
const hasAdmin = await getService('user').exists();
|
2022-04-20 16:11:43 +02:00
|
|
|
const { menuLogo } = await getService('project-settings').getProjectSettings();
|
2022-03-30 11:54:06 +03:00
|
|
|
// set to null if telemetryDisabled flag not avaialble in package.json
|
|
|
|
const telemetryDisabled = strapi.config.get('packageJsonStrapi.telemetryDisabled', null);
|
|
|
|
|
|
|
|
if (telemetryDisabled !== null && telemetryDisabled === true) {
|
|
|
|
uuid = false;
|
|
|
|
}
|
2020-10-06 11:26:17 +02:00
|
|
|
|
2022-04-20 16:11:43 +02:00
|
|
|
return {
|
|
|
|
data: {
|
|
|
|
uuid,
|
|
|
|
hasAdmin,
|
|
|
|
menuLogo: menuLogo ? menuLogo.url : null,
|
|
|
|
},
|
|
|
|
};
|
2020-10-06 11:26:17 +02:00
|
|
|
},
|
|
|
|
|
2022-04-20 15:52:58 +02:00
|
|
|
async getProjectSettings() {
|
|
|
|
return getService('project-settings').getProjectSettings();
|
|
|
|
},
|
|
|
|
|
2022-03-31 11:33:54 +02:00
|
|
|
async updateProjectSettings(ctx) {
|
2022-04-06 11:50:00 +02:00
|
|
|
const projectSettingsService = getService('project-settings');
|
|
|
|
|
2022-03-31 13:11:19 +02:00
|
|
|
const {
|
2022-04-06 09:09:04 +02:00
|
|
|
request: { files, body },
|
2022-03-31 13:11:19 +02:00
|
|
|
} = ctx;
|
|
|
|
|
2022-04-06 09:09:04 +02:00
|
|
|
await validateUpdateProjectSettings(body);
|
|
|
|
await validateUpdateProjectSettingsFiles(files);
|
2022-03-31 13:11:19 +02:00
|
|
|
|
2022-04-06 12:23:17 +02:00
|
|
|
const formatedFiles = await projectSettingsService.parseFilesData(files);
|
2022-04-06 11:50:00 +02:00
|
|
|
await validateUpdateProjectSettingsImagesDimensions(formatedFiles);
|
2022-04-04 15:09:08 +02:00
|
|
|
|
2022-04-15 09:58:35 +02:00
|
|
|
return projectSettingsService.updateProjectSettings({ ...body, ...formatedFiles });
|
2020-10-06 11:26:17 +02:00
|
|
|
},
|
|
|
|
|
2022-06-07 16:07:39 +02:00
|
|
|
async telemetryProperties(ctx) {
|
|
|
|
// If the telemetry is disabled, ignore the request and return early
|
|
|
|
if (strapi.telemetry.isDisabled) {
|
2022-06-07 16:19:24 +02:00
|
|
|
ctx.status = 204;
|
2022-06-07 16:07:39 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-14 14:55:57 +02:00
|
|
|
const useTypescriptOnServer = await isUsingTypeScript(strapi.dirs.app.root);
|
|
|
|
const useTypescriptOnAdmin = await isUsingTypeScript(
|
2022-04-13 15:41:39 +02:00
|
|
|
path.join(strapi.dirs.app.root, 'src', 'admin')
|
|
|
|
);
|
2022-09-30 11:40:05 +02:00
|
|
|
const isHostedOnStrapiCloud = env('STRAPI_HOSTING', null) === 'strapi.cloud';
|
2022-04-13 15:41:39 +02:00
|
|
|
|
2023-01-09 18:15:38 +01:00
|
|
|
const numberOfAllContentTypes = _.size(strapi.contentTypes);
|
2022-11-16 17:08:51 +01:00
|
|
|
const numberOfComponents = _.size(strapi.components);
|
2022-12-28 18:27:07 +01:00
|
|
|
|
|
|
|
const getNumberOfDynamicZones = () =>
|
|
|
|
pipe(
|
|
|
|
map('attributes'),
|
|
|
|
flatMap(values),
|
|
|
|
sumBy(propEq('type', 'dynamiczone'))
|
|
|
|
)(strapi.contentTypes);
|
2022-11-16 17:08:51 +01:00
|
|
|
|
2022-04-13 15:41:39 +02:00
|
|
|
return {
|
|
|
|
data: {
|
|
|
|
useTypescriptOnServer,
|
|
|
|
useTypescriptOnAdmin,
|
2022-09-29 18:12:05 +02:00
|
|
|
isHostedOnStrapiCloud,
|
2023-01-09 18:15:38 +01:00
|
|
|
numberOfAllContentTypes,
|
2022-11-16 17:08:51 +01:00
|
|
|
numberOfComponents,
|
2022-12-28 18:27:07 +01:00
|
|
|
numberOfDynamicZones: getNumberOfDynamicZones(),
|
2022-04-13 15:41:39 +02:00
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
2020-10-06 11:26:17 +02:00
|
|
|
async information() {
|
2021-09-01 19:55:16 +02:00
|
|
|
const currentEnvironment = strapi.config.get('environment');
|
2020-04-09 16:27:29 +02:00
|
|
|
const autoReload = strapi.config.get('autoReload', false);
|
|
|
|
const strapiVersion = strapi.config.get('info.strapi', null);
|
2022-06-23 14:39:48 +02:00
|
|
|
const dependencies = strapi.config.get('info.dependencies', {});
|
2022-08-16 14:00:45 +03:00
|
|
|
const projectId = strapi.config.get('uuid', null);
|
2020-10-06 11:26:17 +02:00
|
|
|
const nodeVersion = process.version;
|
|
|
|
const communityEdition = !strapi.EE;
|
2022-02-18 20:15:46 +01:00
|
|
|
const useYarn = await exists(path.join(process.cwd(), 'yarn.lock'));
|
2019-09-09 16:06:54 +02:00
|
|
|
|
2020-10-06 11:26:17 +02:00
|
|
|
return {
|
2022-02-18 18:53:03 +01:00
|
|
|
data: {
|
|
|
|
currentEnvironment,
|
|
|
|
autoReload,
|
|
|
|
strapiVersion,
|
2022-06-23 14:39:48 +02:00
|
|
|
dependencies,
|
2022-08-16 14:00:45 +03:00
|
|
|
projectId,
|
2022-02-18 18:53:03 +01:00
|
|
|
nodeVersion,
|
|
|
|
communityEdition,
|
2022-02-18 20:15:46 +01:00
|
|
|
useYarn,
|
2022-02-18 18:53:03 +01:00
|
|
|
},
|
2020-10-06 11:26:17 +02:00
|
|
|
};
|
2019-09-09 16:06:54 +02:00
|
|
|
},
|
|
|
|
|
2019-07-15 19:33:07 +02:00
|
|
|
async installPlugin(ctx) {
|
2017-12-16 17:35:16 +01:00
|
|
|
try {
|
2019-04-26 19:19:00 +02:00
|
|
|
const { plugin } = ctx.request.body;
|
2019-12-01 23:05:58 +01:00
|
|
|
|
2020-01-07 14:15:16 +01:00
|
|
|
if (!isValidPluginName(plugin)) {
|
2021-10-20 17:30:05 +02:00
|
|
|
throw new ValidationError('Invalid plugin name');
|
2019-12-01 23:05:58 +01:00
|
|
|
}
|
|
|
|
|
2017-12-16 17:35:16 +01:00
|
|
|
strapi.reload.isWatching = false;
|
|
|
|
|
|
|
|
strapi.log.info(`Installing ${plugin}...`);
|
2019-04-30 18:01:59 +02:00
|
|
|
await execa('npm', ['run', 'strapi', '--', 'install', plugin]);
|
2017-12-16 17:35:16 +01:00
|
|
|
|
|
|
|
ctx.send({ ok: true });
|
|
|
|
|
|
|
|
strapi.reload();
|
2019-04-02 22:45:21 +02:00
|
|
|
} catch (err) {
|
2017-12-16 17:35:16 +01:00
|
|
|
strapi.reload.isWatching = true;
|
2021-10-20 17:30:05 +02:00
|
|
|
throw err;
|
2017-12-16 17:35:16 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-07-15 19:33:07 +02:00
|
|
|
async plugins(ctx) {
|
2021-11-04 12:01:49 +01:00
|
|
|
const enabledPlugins = strapi.config.get('enabledPlugins');
|
|
|
|
|
|
|
|
const plugins = Object.entries(enabledPlugins).map(([key, plugin]) => ({
|
|
|
|
name: plugin.info.name || key,
|
|
|
|
displayName: plugin.info.displayName || plugin.info.name || key,
|
|
|
|
description: plugin.info.description || '',
|
2022-02-21 16:38:15 +01:00
|
|
|
packageName: plugin.info.packageName,
|
2021-11-04 12:01:49 +01:00
|
|
|
}));
|
|
|
|
|
2021-08-20 13:12:37 +02:00
|
|
|
ctx.send({ plugins });
|
2017-11-09 11:25:01 +01:00
|
|
|
},
|
|
|
|
|
2019-07-15 19:33:07 +02:00
|
|
|
async uninstallPlugin(ctx) {
|
2017-11-02 16:49:10 +01:00
|
|
|
try {
|
|
|
|
const { plugin } = ctx.params;
|
2019-12-01 23:05:58 +01:00
|
|
|
|
2020-01-07 14:15:16 +01:00
|
|
|
if (!isValidPluginName(plugin)) {
|
2021-10-20 17:30:05 +02:00
|
|
|
throw new ValidationError('Invalid plugin name');
|
2019-12-01 23:05:58 +01:00
|
|
|
}
|
|
|
|
|
2017-11-02 17:05:37 +01:00
|
|
|
strapi.reload.isWatching = false;
|
|
|
|
|
|
|
|
strapi.log.info(`Uninstalling ${plugin}...`);
|
2019-05-13 18:38:13 +02:00
|
|
|
await execa('npm', ['run', 'strapi', '--', 'uninstall', plugin, '-d']);
|
2017-11-02 17:05:37 +01:00
|
|
|
|
2017-11-02 16:49:10 +01:00
|
|
|
ctx.send({ ok: true });
|
2017-11-02 17:05:37 +01:00
|
|
|
|
|
|
|
strapi.reload();
|
2019-04-02 22:45:21 +02:00
|
|
|
} catch (err) {
|
2017-11-02 17:05:37 +01:00
|
|
|
strapi.reload.isWatching = true;
|
2021-10-20 17:30:05 +02:00
|
|
|
throw err;
|
2017-11-02 16:49:10 +01:00
|
|
|
}
|
2019-04-02 22:45:21 +02:00
|
|
|
},
|
2016-08-26 14:19:03 +02:00
|
|
|
};
|