mirror of
https://github.com/strapi/strapi.git
synced 2025-11-07 05:38:13 +00:00
Merge branch 'releases/v4' into v4/graphql-schema-generation-refactor
This commit is contained in:
commit
ee5e7a026f
@ -45,15 +45,6 @@ const SettingsPage = lazy(() =>
|
|||||||
import(/* webpackChunkName: "Admin_settingsPage" */ '../SettingsPage')
|
import(/* webpackChunkName: "Admin_settingsPage" */ '../SettingsPage')
|
||||||
);
|
);
|
||||||
|
|
||||||
const CTB = lazy(() =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "content-type-builder" */ '@strapi/plugin-content-type-builder/admin/src/pages/App'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const Upload = lazy(() =>
|
|
||||||
import(/* webpackChunkName: "upload" */ '@strapi/plugin-upload/admin/src/pages/App')
|
|
||||||
);
|
|
||||||
|
|
||||||
// Simple hook easier for testing
|
// Simple hook easier for testing
|
||||||
const useTrackUsage = () => {
|
const useTrackUsage = () => {
|
||||||
const { trackUsage } = useTracking();
|
const { trackUsage } = useTracking();
|
||||||
@ -100,8 +91,6 @@ const Admin = () => {
|
|||||||
<Route path="/me" component={ProfilePage} exact />
|
<Route path="/me" component={ProfilePage} exact />
|
||||||
|
|
||||||
<Route path="/content-manager" component={CM} />
|
<Route path="/content-manager" component={CM} />
|
||||||
<Route path="/plugins/content-type-builder" component={CTB} />
|
|
||||||
<Route path="/plugins/upload" component={Upload} />
|
|
||||||
{routes}
|
{routes}
|
||||||
<Route path="/settings/:settingId" component={SettingsPage} />
|
<Route path="/settings/:settingId" component={SettingsPage} />
|
||||||
<Route path="/settings" component={SettingsPage} exact />
|
<Route path="/settings" component={SettingsPage} exact />
|
||||||
|
|||||||
@ -9,14 +9,14 @@ import emailPlugin from '../../../email/admin/src';
|
|||||||
import uploadPlugin from '../../../upload/admin/src';
|
import uploadPlugin from '../../../upload/admin/src';
|
||||||
|
|
||||||
const plugins = {
|
const plugins = {
|
||||||
'@strapi/plugin-content-type-builder': ctbPlugin,
|
'content-type-builder': ctbPlugin,
|
||||||
'@strapi/plugin-documentation': documentationPlugin,
|
documentation: documentationPlugin,
|
||||||
'@strapi/plugin-i18n': i18nPlugin,
|
i18n: i18nPlugin,
|
||||||
'@strapi/plugin-email': emailPlugin,
|
email: emailPlugin,
|
||||||
'@strapi/plugin-upload': uploadPlugin,
|
upload: uploadPlugin,
|
||||||
'@strapi/plugin-graphql': graphqlPlugin,
|
graphql: graphqlPlugin,
|
||||||
'@strapi/plugin-sentry': sentryPlugin,
|
sentry: sentryPlugin,
|
||||||
'@strapi/plugin-users-permissions': usersPermissionsPlugin,
|
'users-permissions': usersPermissionsPlugin,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default plugins;
|
export default plugins;
|
||||||
|
|||||||
@ -6,16 +6,19 @@ module.exports = {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/providers',
|
path: '/providers',
|
||||||
handler: 'authentication.getProviders',
|
handler: 'authentication.getProviders',
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/connect/:provider',
|
path: '/connect/:provider',
|
||||||
handler: 'authentication.providerLogin',
|
handler: 'authentication.providerLogin',
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: '/connect/:provider',
|
path: '/connect/:provider',
|
||||||
handler: 'authentication.providerLogin',
|
handler: 'authentication.providerLogin',
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
/* eslint-disable no-useless-escape */
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
@ -34,9 +34,9 @@ function getCustomWebpackConfig(dir, config) {
|
|||||||
return webpackConfig;
|
return webpackConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function build({ dir, env, options, optimize }) {
|
async function build({ plugins, dir, env, options, optimize }) {
|
||||||
// Create the cache dir containing the front-end files.
|
// Create the cache dir containing the front-end files.
|
||||||
await createCacheDir(dir);
|
await createCacheDir({ dir, plugins });
|
||||||
|
|
||||||
const cacheDir = path.resolve(dir, '.cache');
|
const cacheDir = path.resolve(dir, '.cache');
|
||||||
const entry = path.resolve(cacheDir, 'admin', 'src');
|
const entry = path.resolve(cacheDir, 'admin', 'src');
|
||||||
@ -48,7 +48,18 @@ async function build({ dir, env, options, optimize }) {
|
|||||||
ceRoot: path.resolve(cacheDir, 'admin', 'src'),
|
ceRoot: path.resolve(cacheDir, 'admin', 'src'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = getCustomWebpackConfig(dir, { entry, dest, env, options, optimize, roots });
|
const pluginsPath = Object.keys(plugins).map(pluginName => plugins[pluginName].pathToPlugin);
|
||||||
|
|
||||||
|
const config = getCustomWebpackConfig(dir, {
|
||||||
|
entry,
|
||||||
|
pluginsPath,
|
||||||
|
cacheDir,
|
||||||
|
dest,
|
||||||
|
env,
|
||||||
|
options,
|
||||||
|
optimize,
|
||||||
|
roots,
|
||||||
|
});
|
||||||
|
|
||||||
const compiler = webpack(config);
|
const compiler = webpack(config);
|
||||||
|
|
||||||
@ -78,34 +89,28 @@ async function build({ dir, env, options, optimize }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createPluginsJs(plugins, localPlugins, dest) {
|
async function createPluginsJs(plugins, dest) {
|
||||||
const createPluginsArray = plugins =>
|
const pluginsArray = plugins.map(({ pathToPlugin, name }) => {
|
||||||
plugins.map(name => {
|
const shortName = _.camelCase(name);
|
||||||
const shortName = _.camelCase(name.replace(/^@strapi\/plugin-/i, ''));
|
return {
|
||||||
|
name,
|
||||||
return { name, shortName };
|
pathToPlugin: path.relative(path.resolve(dest, 'admin', 'src'), pathToPlugin),
|
||||||
});
|
shortName,
|
||||||
const appPluginsArray = createPluginsArray(plugins);
|
};
|
||||||
const localPluginsArray = createPluginsArray(localPlugins);
|
});
|
||||||
|
|
||||||
const content = `
|
const content = `
|
||||||
${appPluginsArray
|
${pluginsArray
|
||||||
.map(({ name, shortName }) => {
|
.map(({ pathToPlugin, shortName }) => {
|
||||||
const req = `'../../plugins/${name}/admin/src'`;
|
const req = `'${pathToPlugin}/admin/src'`;
|
||||||
|
|
||||||
return `import ${shortName} from ${req};`;
|
return `import ${shortName} from ${req};`;
|
||||||
})
|
})
|
||||||
.join('\n')}
|
.join('\n')}
|
||||||
${localPluginsArray
|
|
||||||
.map(({ name, shortName }) => {
|
|
||||||
const req = `'../../../plugins/${name}/admin/src'`;
|
|
||||||
|
|
||||||
return `import ${shortName} from ${req};`;
|
|
||||||
})
|
|
||||||
.join('\n')}
|
|
||||||
|
|
||||||
const plugins = {
|
const plugins = {
|
||||||
${[...appPluginsArray, ...localPluginsArray]
|
${[...pluginsArray]
|
||||||
.map(({ name, shortName }) => {
|
.map(({ name, shortName }) => {
|
||||||
return ` '${name}': ${shortName},`;
|
return ` '${name}': ${shortName},`;
|
||||||
})
|
})
|
||||||
@ -126,21 +131,6 @@ async function clean({ dir }) {
|
|||||||
fs.removeSync(cacheDir);
|
fs.removeSync(cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyPlugin(name, dest) {
|
|
||||||
const pkgFilePath = getPkgPath(name);
|
|
||||||
|
|
||||||
const resolveDepPath = (...args) => path.resolve(pkgFilePath, ...args);
|
|
||||||
const resolveDest = (...args) => path.resolve(dest, 'plugins', name, ...args);
|
|
||||||
|
|
||||||
const copy = (...args) => {
|
|
||||||
return fs.copy(resolveDepPath(...args), resolveDest(...args));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy the entire admin folder
|
|
||||||
await copy('admin');
|
|
||||||
await copy('package.json');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function copyAdmin(dest) {
|
async function copyAdmin(dest) {
|
||||||
const adminPath = getPkgPath('@strapi/admin');
|
const adminPath = getPkgPath('@strapi/admin');
|
||||||
|
|
||||||
@ -154,25 +144,16 @@ async function copyAdmin(dest) {
|
|||||||
await fs.copy(path.resolve(adminPath, 'package.json'), path.resolve(dest, 'package.json'));
|
await fs.copy(path.resolve(adminPath, 'package.json'), path.resolve(dest, 'package.json'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createCacheDir(dir) {
|
async function createCacheDir({ dir, plugins }) {
|
||||||
const cacheDir = path.resolve(dir, '.cache');
|
const cacheDir = path.resolve(dir, '.cache');
|
||||||
|
|
||||||
const pkgJSON = require(path.join(dir, 'package.json'));
|
const pluginsWithFront = Object.keys(plugins)
|
||||||
|
.filter(pluginName => {
|
||||||
const pluginsToCopy = Object.keys(pkgJSON.dependencies).filter(
|
const pluginInfo = plugins[pluginName];
|
||||||
dep =>
|
// TODO: use strapi-admin
|
||||||
dep.startsWith('@strapi/plugin') &&
|
return fs.existsSync(path.resolve(pluginInfo.pathToPlugin, 'admin', 'src', 'index.js'));
|
||||||
fs.existsSync(path.resolve(getPkgPath(dep), 'admin', 'src', 'index.js'))
|
})
|
||||||
);
|
.map(name => ({ name, ...plugins[name] }));
|
||||||
|
|
||||||
let localPluginsToCopy = [];
|
|
||||||
if (fs.existsSync(path.join(dir, 'plugins'))) {
|
|
||||||
localPluginsToCopy = fs
|
|
||||||
.readdirSync(path.join(dir, 'plugins'))
|
|
||||||
.filter(plugin =>
|
|
||||||
fs.existsSync(path.resolve(dir, 'plugins', plugin, 'admin', 'src', 'index.js'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create .cache dir
|
// create .cache dir
|
||||||
await fs.emptyDir(cacheDir);
|
await fs.emptyDir(cacheDir);
|
||||||
@ -180,9 +161,6 @@ async function createCacheDir(dir) {
|
|||||||
// copy admin core code
|
// copy admin core code
|
||||||
await copyAdmin(cacheDir);
|
await copyAdmin(cacheDir);
|
||||||
|
|
||||||
// copy plugins code
|
|
||||||
await Promise.all(pluginsToCopy.map(name => copyPlugin(name, cacheDir)));
|
|
||||||
|
|
||||||
// Copy app.js
|
// Copy app.js
|
||||||
const customAdminConfigFilePath = path.join(dir, 'admin', 'app.js');
|
const customAdminConfigFilePath = path.join(dir, 'admin', 'app.js');
|
||||||
|
|
||||||
@ -198,27 +176,30 @@ async function createCacheDir(dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create plugins.js with plugins requires
|
// create plugins.js with plugins requires
|
||||||
await createPluginsJs(pluginsToCopy, localPluginsToCopy, cacheDir);
|
await createPluginsJs(pluginsWithFront, cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function watchAdmin({ dir, host, port, browser, options }) {
|
async function watchAdmin({ plugins, dir, host, port, browser, options }) {
|
||||||
// Create the cache dir containing the front-end files.
|
// Create the cache dir containing the front-end files.
|
||||||
await createCacheDir(dir);
|
const cacheDir = path.join(dir, '.cache');
|
||||||
|
await createCacheDir({ dir, plugins });
|
||||||
|
|
||||||
const entry = path.join(dir, '.cache', 'admin', 'src');
|
const entry = path.join(cacheDir, 'admin', 'src');
|
||||||
const dest = path.join(dir, 'build');
|
const dest = path.join(dir, 'build');
|
||||||
const env = 'development';
|
const env = 'development';
|
||||||
|
|
||||||
const cacheDir = path.join(dir, '.cache');
|
|
||||||
|
|
||||||
// Roots for the @strapi/babel-plugin-switch-ee-ce
|
// Roots for the @strapi/babel-plugin-switch-ee-ce
|
||||||
const roots = {
|
const roots = {
|
||||||
eeRoot: path.resolve(cacheDir, 'ee', 'admin'),
|
eeRoot: path.resolve(cacheDir, 'ee', 'admin'),
|
||||||
ceRoot: path.resolve(cacheDir, 'admin', 'src'),
|
ceRoot: path.resolve(cacheDir, 'admin', 'src'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pluginsPath = Object.keys(plugins).map(pluginName => plugins[pluginName].pathToPlugin);
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
entry,
|
entry,
|
||||||
|
cacheDir,
|
||||||
|
pluginsPath,
|
||||||
dest,
|
dest,
|
||||||
env,
|
env,
|
||||||
port,
|
port,
|
||||||
|
|||||||
@ -11,6 +11,8 @@ const buildAdmin = async () => {
|
|||||||
const args = {
|
const args = {
|
||||||
entry,
|
entry,
|
||||||
dest,
|
dest,
|
||||||
|
cacheDir: __dirname,
|
||||||
|
pluginsPath: [path.resolve(__dirname, '../../../..')],
|
||||||
env: 'production',
|
env: 'production',
|
||||||
optimize: true,
|
optimize: true,
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@ -31,9 +31,9 @@ module.exports = createPolicyFactory(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (ctx, next) => {
|
return (ctx, next) => {
|
||||||
const { userAbility: ability, isAuthenticatedAdmin } = ctx.state;
|
const { userAbility: ability, isAuthenticated } = ctx.state;
|
||||||
|
|
||||||
if (!isAuthenticatedAdmin || !ability) {
|
if (!isAuthenticated || !ability) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = (ctx, next) => {
|
module.exports = (ctx, next) => {
|
||||||
if (!ctx.state.isAuthenticatedAdmin) {
|
if (!ctx.state.isAuthenticated) {
|
||||||
return ctx.unauthorized();
|
return ctx.unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,56 +3,51 @@
|
|||||||
|
|
||||||
// const permissionsFieldsToPropertiesMigration = require('../migrations/permissions-fields-to-properties');
|
// const permissionsFieldsToPropertiesMigration = require('../migrations/permissions-fields-to-properties');
|
||||||
|
|
||||||
/**
|
const adminAuthStrategy = {
|
||||||
* Tries to authenticated admin user and calls next.
|
name: 'admin',
|
||||||
* @param {KoaContext} ctx
|
async authenticate(ctx) {
|
||||||
* @param {Middleware} next
|
const { authorization } = ctx.request.header;
|
||||||
* @returns {undefined}
|
|
||||||
*/
|
|
||||||
const authMiddleware = async (ctx, next) => {
|
|
||||||
if (!ctx.request.header.authorization) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (!authorization) {
|
||||||
ctx.request.header.authorization &&
|
return { authenticated: false };
|
||||||
ctx.request.header.authorization.split(' ')[0] === 'Bearer'
|
}
|
||||||
) {
|
|
||||||
const token = ctx.request.header.authorization.split(' ')[1];
|
|
||||||
|
|
||||||
|
const parts = authorization.split(/\s+/);
|
||||||
|
|
||||||
|
if (parts[0] !== 'Bearer' || parts.length !== 2) {
|
||||||
|
return { authenticated: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = parts[1];
|
||||||
const { payload, isValid } = strapi.admin.services.token.decodeJwtToken(token);
|
const { payload, isValid } = strapi.admin.services.token.decodeJwtToken(token);
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
const admin = await strapi
|
const user = await strapi
|
||||||
.query('admin::user')
|
.query('admin::user')
|
||||||
.findOne({ where: { id: payload.id }, populate: ['roles'] });
|
.findOne({ where: { id: payload.id }, populate: ['roles'] });
|
||||||
|
|
||||||
if (!admin || !(admin.isActive === true)) {
|
if (!user || !(user.isActive === true)) {
|
||||||
return ctx.unauthorized('Invalid credentials');
|
return { error: 'Invalid credentials' };
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use simple user & isAuthenticated
|
const userAbility = await strapi.admin.services.permission.engine.generateUserAbility(user);
|
||||||
|
|
||||||
ctx.state.admin = admin;
|
ctx.state.userAbility = userAbility;
|
||||||
ctx.state.user = admin;
|
ctx.state.user = user;
|
||||||
ctx.state.userAbility = await strapi.admin.services.permission.engine.generateUserAbility(
|
|
||||||
admin
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.state.isAuthenticatedAdmin = true;
|
return { authenticated: true, credentials: user };
|
||||||
|
|
||||||
return next();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ctx.unauthorized('Invalid credentials');
|
return { error: 'Invalid credentials' };
|
||||||
|
},
|
||||||
|
// async verify() {},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = () => {
|
module.exports = () => {
|
||||||
const passportMiddleware = strapi.admin.services.passport.init();
|
const passportMiddleware = strapi.admin.services.passport.init();
|
||||||
|
|
||||||
strapi.server.api('admin').use(passportMiddleware);
|
strapi.server.api('admin').use(passportMiddleware);
|
||||||
strapi.server.api('admin').use(authMiddleware);
|
strapi.container.get('auth').register('admin', adminAuthStrategy);
|
||||||
|
|
||||||
// FIXME: to implement
|
// FIXME: to implement
|
||||||
// strapi.db.migrations.register(permissionsFieldsToPropertiesMigration);
|
// strapi.db.migrations.register(permissionsFieldsToPropertiesMigration);
|
||||||
|
|||||||
63
packages/core/admin/server/routes/admin.js
Normal file
63
packages/core/admin/server/routes/admin.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/init',
|
||||||
|
handler: 'admin.init',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/project-type',
|
||||||
|
handler: 'admin.getProjectType',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/information',
|
||||||
|
handler: 'admin.information',
|
||||||
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/plugins',
|
||||||
|
handler: 'admin.plugins',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::marketplace.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/plugins/install',
|
||||||
|
handler: 'admin.installPlugin',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{
|
||||||
|
name: 'admin::hasPermissions',
|
||||||
|
options: { actions: ['admin::marketplace.plugins.install'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'DELETE',
|
||||||
|
path: '/plugins/uninstall/:plugin',
|
||||||
|
handler: 'admin.uninstallPlugin',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{
|
||||||
|
name: 'admin::hasPermissions',
|
||||||
|
options: { actions: ['admin::marketplace.plugins.uninstall'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
46
packages/core/admin/server/routes/authentication.js
Normal file
46
packages/core/admin/server/routes/authentication.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/login',
|
||||||
|
handler: 'authentication.login',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/renew-token',
|
||||||
|
handler: 'authentication.renewToken',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/register-admin',
|
||||||
|
handler: 'authentication.registerAdmin',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/registration-info',
|
||||||
|
handler: 'authentication.registrationInfo',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/register',
|
||||||
|
handler: 'authentication.register',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/forgot-password',
|
||||||
|
handler: 'authentication.forgotPassword',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/reset-password',
|
||||||
|
handler: 'authentication.resetPassword',
|
||||||
|
config: { auth: false },
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -1,325 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = [
|
const admin = require('./admin');
|
||||||
{
|
const authentication = require('./authentication');
|
||||||
method: 'GET',
|
const permissions = require('./permissions');
|
||||||
path: '/init',
|
const users = require('./users');
|
||||||
handler: 'admin.init',
|
const roles = require('./roles');
|
||||||
},
|
const webhooks = require('./webhooks');
|
||||||
{
|
|
||||||
method: 'GET',
|
module.exports = [...admin, ...authentication, ...permissions, ...users, ...roles, ...webhooks];
|
||||||
path: '/project-type',
|
|
||||||
handler: 'admin.getProjectType',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/information',
|
|
||||||
handler: 'admin.information',
|
|
||||||
config: {
|
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/plugins',
|
|
||||||
handler: 'admin.plugins',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::marketplace.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/plugins/install',
|
|
||||||
handler: 'admin.installPlugin',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{
|
|
||||||
name: 'admin::hasPermissions',
|
|
||||||
options: { actions: ['admin::marketplace.plugins.install'] },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
path: '/plugins/uninstall/:plugin',
|
|
||||||
handler: 'admin.uninstallPlugin',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{
|
|
||||||
name: 'admin::hasPermissions',
|
|
||||||
options: { actions: ['admin::marketplace.plugins.uninstall'] },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/login',
|
|
||||||
handler: 'authentication.login',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/renew-token',
|
|
||||||
handler: 'authentication.renewToken',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/register-admin',
|
|
||||||
handler: 'authentication.registerAdmin',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/registration-info',
|
|
||||||
handler: 'authentication.registrationInfo',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/register',
|
|
||||||
handler: 'authentication.register',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/forgot-password',
|
|
||||||
handler: 'authentication.forgotPassword',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/reset-password',
|
|
||||||
handler: 'authentication.resetPassword',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/webhooks',
|
|
||||||
handler: 'Webhooks.listWebhooks',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/webhooks',
|
|
||||||
handler: 'Webhooks.createWebhook',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.create'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/webhooks/:id',
|
|
||||||
handler: 'Webhooks.getWebhook',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
path: '/webhooks/:id',
|
|
||||||
handler: 'Webhooks.updateWebhook',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.update'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
path: '/webhooks/:id',
|
|
||||||
handler: 'Webhooks.deleteWebhook',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.delete'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/webhooks/batch-delete',
|
|
||||||
handler: 'Webhooks.deleteWebhooks',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.delete'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/webhooks/:id/trigger',
|
|
||||||
handler: 'Webhooks.triggerWebhook',
|
|
||||||
config: {
|
|
||||||
policies: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/users/me',
|
|
||||||
handler: 'authenticated-user.getMe',
|
|
||||||
config: {
|
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
path: '/users/me',
|
|
||||||
handler: 'authenticated-user.updateMe',
|
|
||||||
config: {
|
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/users/me/permissions',
|
|
||||||
handler: 'authenticated-user.getOwnPermissions',
|
|
||||||
config: {
|
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/users',
|
|
||||||
handler: 'user.create',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.create'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/users',
|
|
||||||
handler: 'user.find',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/users/:id',
|
|
||||||
handler: 'user.findOne',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
path: '/users/:id',
|
|
||||||
handler: 'user.update',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.update'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
path: '/users/:id',
|
|
||||||
handler: 'user.deleteOne',
|
|
||||||
config: {
|
|
||||||
policies: [{ name: 'admin::hasPermissions', options: { actions: ['admin::users.delete'] } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/users/batch-delete',
|
|
||||||
handler: 'user.deleteMany',
|
|
||||||
config: {
|
|
||||||
policies: [{ name: 'admin::hasPermissions', options: { actions: ['admin::users.delete'] } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/roles/:id/permissions',
|
|
||||||
handler: 'role.getPermissions',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
path: '/roles/:id/permissions',
|
|
||||||
handler: 'role.updatePermissions',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.update'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/roles/:id',
|
|
||||||
handler: 'role.findOne',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/roles',
|
|
||||||
handler: 'role.findAll',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.read'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
path: '/roles/:id',
|
|
||||||
handler: 'role.update',
|
|
||||||
config: {
|
|
||||||
policies: [
|
|
||||||
'admin::isAuthenticatedAdmin',
|
|
||||||
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.update'] } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
path: '/permissions',
|
|
||||||
handler: 'permission.getAll',
|
|
||||||
config: {
|
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
path: '/permissions/check',
|
|
||||||
handler: 'permission.check',
|
|
||||||
config: {
|
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
20
packages/core/admin/server/routes/permissions.js
Normal file
20
packages/core/admin/server/routes/permissions.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/permissions',
|
||||||
|
handler: 'permission.getAll',
|
||||||
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/permissions/check',
|
||||||
|
handler: 'permission.check',
|
||||||
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
67
packages/core/admin/server/routes/roles.js
Normal file
67
packages/core/admin/server/routes/roles.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/users/batch-delete',
|
||||||
|
handler: 'user.deleteMany',
|
||||||
|
config: {
|
||||||
|
policies: [{ name: 'admin::hasPermissions', options: { actions: ['admin::users.delete'] } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/roles/:id/permissions',
|
||||||
|
handler: 'role.getPermissions',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
path: '/roles/:id/permissions',
|
||||||
|
handler: 'role.updatePermissions',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.update'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/roles/:id',
|
||||||
|
handler: 'role.findOne',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/roles',
|
||||||
|
handler: 'role.findAll',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
path: '/roles/:id',
|
||||||
|
handler: 'role.update',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::roles.update'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
88
packages/core/admin/server/routes/users.js
Normal file
88
packages/core/admin/server/routes/users.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/users/me',
|
||||||
|
handler: 'authenticated-user.getMe',
|
||||||
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
path: '/users/me',
|
||||||
|
handler: 'authenticated-user.updateMe',
|
||||||
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/users/me/permissions',
|
||||||
|
handler: 'authenticated-user.getOwnPermissions',
|
||||||
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/users',
|
||||||
|
handler: 'user.create',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.create'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/users',
|
||||||
|
handler: 'user.find',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/users/:id',
|
||||||
|
handler: 'user.findOne',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
path: '/users/:id',
|
||||||
|
handler: 'user.update',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::users.update'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'DELETE',
|
||||||
|
path: '/users/:id',
|
||||||
|
handler: 'user.deleteOne',
|
||||||
|
config: {
|
||||||
|
policies: [{ name: 'admin::hasPermissions', options: { actions: ['admin::users.delete'] } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/users/batch-delete',
|
||||||
|
handler: 'user.deleteMany',
|
||||||
|
config: {
|
||||||
|
policies: [{ name: 'admin::hasPermissions', options: { actions: ['admin::users.delete'] } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
78
packages/core/admin/server/routes/webhooks.js
Normal file
78
packages/core/admin/server/routes/webhooks.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/webhooks',
|
||||||
|
handler: 'Webhooks.listWebhooks',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/webhooks',
|
||||||
|
handler: 'Webhooks.createWebhook',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.create'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/webhooks/:id',
|
||||||
|
handler: 'Webhooks.getWebhook',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.read'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
path: '/webhooks/:id',
|
||||||
|
handler: 'Webhooks.updateWebhook',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.update'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'DELETE',
|
||||||
|
path: '/webhooks/:id',
|
||||||
|
handler: 'Webhooks.deleteWebhook',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.delete'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/webhooks/batch-delete',
|
||||||
|
handler: 'Webhooks.deleteWebhooks',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', options: { actions: ['admin::webhooks.delete'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/webhooks/:id/trigger',
|
||||||
|
handler: 'Webhooks.triggerWebhook',
|
||||||
|
config: {
|
||||||
|
policies: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -22,6 +22,8 @@ module.exports = () => {
|
|||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
entry,
|
entry,
|
||||||
|
cacheDir: __dirname,
|
||||||
|
pluginsPath: [path.resolve(__dirname, '../../..')],
|
||||||
dest,
|
dest,
|
||||||
env,
|
env,
|
||||||
options,
|
options,
|
||||||
|
|||||||
@ -13,6 +13,8 @@ const getClientEnvironment = require('./env');
|
|||||||
|
|
||||||
module.exports = ({
|
module.exports = ({
|
||||||
entry,
|
entry,
|
||||||
|
cacheDir,
|
||||||
|
pluginsPath,
|
||||||
dest,
|
dest,
|
||||||
env,
|
env,
|
||||||
optimize,
|
optimize,
|
||||||
@ -98,7 +100,7 @@ module.exports = ({
|
|||||||
{
|
{
|
||||||
test: /\.m?js$/,
|
test: /\.m?js$/,
|
||||||
// TODO remove when plugins are built separately
|
// TODO remove when plugins are built separately
|
||||||
exclude: /node_modules\/(?!(@strapi\/plugin-content-type-builder|@strapi\/plugin-upload)\/).*/,
|
include: [cacheDir, ...pluginsPath],
|
||||||
use: {
|
use: {
|
||||||
loader: require.resolve('babel-loader'),
|
loader: require.resolve('babel-loader'),
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@ -19,14 +19,22 @@ const name = pluginPkg.strapi.name;
|
|||||||
export default {
|
export default {
|
||||||
register(app) {
|
register(app) {
|
||||||
app.addReducers(reducers);
|
app.addReducers(reducers);
|
||||||
app.addCorePluginMenuLink({
|
|
||||||
|
app.addMenuLink({
|
||||||
to: `/plugins/${pluginId}`,
|
to: `/plugins/${pluginId}`,
|
||||||
icon,
|
icon,
|
||||||
intlLabel: {
|
intlLabel: {
|
||||||
id: `${pluginId}.plugin.name`,
|
id: `${pluginId}.plugin.name`,
|
||||||
defaultMessage: 'Content-Types Builder',
|
defaultMessage: 'Content Types Builder',
|
||||||
},
|
},
|
||||||
permissions: pluginPermissions.main,
|
permissions: pluginPermissions.main,
|
||||||
|
Component: async () => {
|
||||||
|
const component = await import(
|
||||||
|
/* webpackChunkName: "content-type-builder" */ './pages/App'
|
||||||
|
);
|
||||||
|
|
||||||
|
return component;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
app.registerPlugin({
|
app.registerPlugin({
|
||||||
|
|||||||
@ -7,7 +7,9 @@ module.exports = {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: '/',
|
path: '/',
|
||||||
handler: 'email.send',
|
handler: 'email.send',
|
||||||
config: {},
|
config: {
|
||||||
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@ -18,7 +18,7 @@ const { createCoreStore, coreStoreModel } = require('./services/core-store');
|
|||||||
const createEntityService = require('./services/entity-service');
|
const createEntityService = require('./services/entity-service');
|
||||||
const entityValidator = require('./services/entity-validator');
|
const entityValidator = require('./services/entity-validator');
|
||||||
const createTelemetry = require('./services/metrics');
|
const createTelemetry = require('./services/metrics');
|
||||||
const createContentAPI = require('./services/content-api');
|
const createAuth = require('./services/auth');
|
||||||
const createUpdateNotifier = require('./utils/update-notifier');
|
const createUpdateNotifier = require('./utils/update-notifier');
|
||||||
const createStartupLogger = require('./utils/startup-logger');
|
const createStartupLogger = require('./utils/startup-logger');
|
||||||
const ee = require('./utils/ee');
|
const ee = require('./utils/ee');
|
||||||
@ -53,7 +53,7 @@ class Strapi {
|
|||||||
this.container.register('modules', modulesRegistry(this));
|
this.container.register('modules', modulesRegistry(this));
|
||||||
this.container.register('plugins', pluginsRegistry(this));
|
this.container.register('plugins', pluginsRegistry(this));
|
||||||
this.container.register('apis', apisRegistry(this));
|
this.container.register('apis', apisRegistry(this));
|
||||||
this.container.register('content-api', createContentAPI(this));
|
this.container.register('auth', createAuth(this));
|
||||||
|
|
||||||
this.isLoaded = false;
|
this.isLoaded = false;
|
||||||
this.reload = this.reload();
|
this.reload = this.reload();
|
||||||
|
|||||||
@ -3,20 +3,30 @@ const { green } = require('chalk');
|
|||||||
|
|
||||||
const strapiAdmin = require('@strapi/admin');
|
const strapiAdmin = require('@strapi/admin');
|
||||||
const { getConfigUrls } = require('@strapi/utils');
|
const { getConfigUrls } = require('@strapi/utils');
|
||||||
const loadConfiguration = require('../core/app-configuration');
|
|
||||||
const ee = require('../utils/ee');
|
|
||||||
|
|
||||||
|
const ee = require('../utils/ee');
|
||||||
const addSlash = require('../utils/addSlash');
|
const addSlash = require('../utils/addSlash');
|
||||||
|
const strapi = require('../index');
|
||||||
|
const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `$ strapi build`
|
* `$ strapi build`
|
||||||
*/
|
*/
|
||||||
module.exports = async ({ clean, optimization }) => {
|
module.exports = async ({ clean, optimization }) => {
|
||||||
const dir = process.cwd();
|
const dir = process.cwd();
|
||||||
const config = loadConfiguration(dir);
|
|
||||||
|
|
||||||
const { serverUrl, adminPath } = getConfigUrls(config.server, true);
|
const strapiInstance = strapi({
|
||||||
|
dir,
|
||||||
|
autoReload: true,
|
||||||
|
serveAdminPanel: false,
|
||||||
|
});
|
||||||
|
|
||||||
console.log(`Building your admin UI with ${green(config.environment)} configuration ...`);
|
const plugins = await getEnabledPlugins(strapiInstance);
|
||||||
|
|
||||||
|
const env = strapiInstance.config.get('environment');
|
||||||
|
const { serverUrl, adminPath } = getConfigUrls(strapiInstance.config.get('server'), true);
|
||||||
|
|
||||||
|
console.log(`Building your admin UI with ${green(env)} configuration ...`);
|
||||||
|
|
||||||
if (clean) {
|
if (clean) {
|
||||||
await strapiAdmin.clean({ dir });
|
await strapiAdmin.clean({ dir });
|
||||||
@ -27,6 +37,7 @@ module.exports = async ({ clean, optimization }) => {
|
|||||||
return strapiAdmin
|
return strapiAdmin
|
||||||
.build({
|
.build({
|
||||||
dir,
|
dir,
|
||||||
|
plugins,
|
||||||
// front end build env is always production for now
|
// front end build env is always production for now
|
||||||
env: 'production',
|
env: 'production',
|
||||||
optimize: optimization,
|
optimize: optimization,
|
||||||
|
|||||||
@ -1,32 +1,42 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const strapiAdmin = require('@strapi/admin');
|
const strapiAdmin = require('@strapi/admin');
|
||||||
const { getOr } = require('lodash/fp');
|
|
||||||
const { getConfigUrls, getAbsoluteServerUrl } = require('@strapi/utils');
|
const { getConfigUrls, getAbsoluteServerUrl } = require('@strapi/utils');
|
||||||
const loadConfiguration = require('../core/app-configuration');
|
|
||||||
const ee = require('../utils/ee');
|
const ee = require('../utils/ee');
|
||||||
const addSlash = require('../utils/addSlash');
|
const addSlash = require('../utils/addSlash');
|
||||||
|
const strapi = require('../index');
|
||||||
|
const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins');
|
||||||
|
|
||||||
module.exports = async function({ browser }) {
|
module.exports = async function({ browser }) {
|
||||||
const dir = process.cwd();
|
const dir = process.cwd();
|
||||||
|
|
||||||
const config = loadConfiguration(dir);
|
const strapiInstance = strapi({
|
||||||
|
dir,
|
||||||
|
autoReload: true,
|
||||||
|
serveAdminPanel: false,
|
||||||
|
});
|
||||||
|
|
||||||
const { adminPath } = getConfigUrls(config.server, true);
|
const plugins = await getEnabledPlugins(strapiInstance);
|
||||||
|
|
||||||
const adminPort = getOr(8000, 'server.admin.port')(config);
|
const { adminPath } = getConfigUrls(strapiInstance.config.get('server'), true);
|
||||||
const adminHost = getOr('localhost', 'server.admin.host')(config);
|
|
||||||
const adminWatchIgnoreFiles = getOr([], 'server.admin.watchIgnoreFiles')(config);
|
const adminPort = strapiInstance.config.get('server.admin.port', 8000);
|
||||||
|
const adminHost = strapiInstance.config.get('server.admin.host', 'localhost');
|
||||||
|
const adminWatchIgnoreFiles = strapiInstance.config.get('server.admin.watchIgnoreFiles', []);
|
||||||
|
|
||||||
|
const backendURL = getAbsoluteServerUrl(strapiInstance.config, true);
|
||||||
|
|
||||||
ee({ dir });
|
ee({ dir });
|
||||||
|
|
||||||
strapiAdmin.watchAdmin({
|
strapiAdmin.watchAdmin({
|
||||||
dir,
|
dir,
|
||||||
|
plugins,
|
||||||
port: adminPort,
|
port: adminPort,
|
||||||
host: adminHost,
|
host: adminHost,
|
||||||
browser,
|
browser,
|
||||||
options: {
|
options: {
|
||||||
backend: getAbsoluteServerUrl(config, true),
|
backend: backendURL,
|
||||||
adminPath: addSlash(adminPath),
|
adminPath: addSlash(adminPath),
|
||||||
watchIgnoreFiles: adminWatchIgnoreFiles,
|
watchIgnoreFiles: adminWatchIgnoreFiles,
|
||||||
features: ee.isEE ? ee.features.getEnabled() : [],
|
features: ee.isEE ? ee.features.getEnabled() : [],
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
const { uniq, difference, get, isUndefined, merge } = require('lodash');
|
const { uniq, difference, get, isUndefined, merge } = require('lodash');
|
||||||
|
|
||||||
const requiredMiddlewares = [
|
const requiredMiddlewares = [
|
||||||
|
'auth',
|
||||||
'responses',
|
'responses',
|
||||||
'router',
|
'router',
|
||||||
'logger',
|
'logger',
|
||||||
|
|||||||
@ -67,11 +67,13 @@ module.exports = strapi => {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/',
|
path: '/',
|
||||||
handler: serveIndexPage,
|
handler: serveIndexPage,
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/index.html',
|
path: '/index.html',
|
||||||
handler: serveIndexPage,
|
handler: serveIndexPage,
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -80,6 +82,7 @@ module.exports = strapi => {
|
|||||||
maxage: maxAge,
|
maxage: maxAge,
|
||||||
defer: true,
|
defer: true,
|
||||||
}),
|
}),
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -88,6 +91,7 @@ module.exports = strapi => {
|
|||||||
maxage: maxAge,
|
maxage: maxAge,
|
||||||
defer: true,
|
defer: true,
|
||||||
}),
|
}),
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -118,6 +122,7 @@ module.exports = strapi => {
|
|||||||
serveAdmin,
|
serveAdmin,
|
||||||
serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' }),
|
serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' }),
|
||||||
],
|
],
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|||||||
92
packages/core/strapi/lib/services/auth/index.js
Normal file
92
packages/core/strapi/lib/services/auth/index.js
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { strict: assert } = require('assert');
|
||||||
|
const { has, prop } = require('lodash/fp');
|
||||||
|
|
||||||
|
class UnauthorizedError extends Error {}
|
||||||
|
class ForbiddenError extends Error {}
|
||||||
|
|
||||||
|
const INVALID_STRATEGY_MSG =
|
||||||
|
'Invalid auth strategy. Expecting an object with properties {name: string, authenticate: function, verify: function}';
|
||||||
|
|
||||||
|
const validStrategy = strategy => {
|
||||||
|
assert(has('authenticate', strategy), INVALID_STRATEGY_MSG);
|
||||||
|
assert(typeof strategy.authenticate === 'function', INVALID_STRATEGY_MSG);
|
||||||
|
|
||||||
|
if (has('verify', strategy)) {
|
||||||
|
assert(typeof strategy.verify === 'function', INVALID_STRATEGY_MSG);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAuthentication = () => {
|
||||||
|
const strategies = {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
errors: {
|
||||||
|
UnauthorizedError,
|
||||||
|
ForbiddenError,
|
||||||
|
},
|
||||||
|
register(type, strategy) {
|
||||||
|
validStrategy(strategy);
|
||||||
|
|
||||||
|
if (!strategies[type]) {
|
||||||
|
strategies[type] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
strategies[type].push(strategy);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
async authenticate(ctx, next) {
|
||||||
|
const { route } = ctx.state;
|
||||||
|
|
||||||
|
// use route strategy
|
||||||
|
const config = prop('config.auth', route);
|
||||||
|
|
||||||
|
if (config === false) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const strategiesToUse = strategies[route.info.type];
|
||||||
|
|
||||||
|
for (const strategy of strategiesToUse) {
|
||||||
|
const result = await strategy.authenticate(ctx);
|
||||||
|
|
||||||
|
const { authenticated = false, error = null, credentials } = result || {};
|
||||||
|
|
||||||
|
if (error !== null) {
|
||||||
|
return ctx.unauthorized(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authenticated) {
|
||||||
|
ctx.state.isAuthenticated = true;
|
||||||
|
ctx.state.auth = {
|
||||||
|
strategy,
|
||||||
|
credentials,
|
||||||
|
};
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.unauthorized('Missing credentials');
|
||||||
|
},
|
||||||
|
async verify(auth, config = {}) {
|
||||||
|
if (config === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!auth) {
|
||||||
|
throw new UnauthorizedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof auth.strategy.verify === 'function') {
|
||||||
|
return await auth.strategy.verify(auth, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = createAuthentication;
|
||||||
@ -1,71 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { strict: assert } = require('assert');
|
|
||||||
const { has } = require('lodash/fp');
|
|
||||||
|
|
||||||
class UnauthorizedError extends Error {}
|
|
||||||
class ForbiddenError extends Error {}
|
|
||||||
|
|
||||||
const INVALID_STRATEGY_MSG =
|
|
||||||
'Invalid auth strategy. Expecting an object with properties {name: string, authenticate: function, verify: function}';
|
|
||||||
|
|
||||||
const validStrategy = strategy => {
|
|
||||||
assert(has('name', strategy), INVALID_STRATEGY_MSG);
|
|
||||||
assert(typeof strategy.name === 'string', INVALID_STRATEGY_MSG);
|
|
||||||
|
|
||||||
assert(has('authenticate', strategy), INVALID_STRATEGY_MSG);
|
|
||||||
assert(typeof strategy.authenticate === 'function', INVALID_STRATEGY_MSG);
|
|
||||||
|
|
||||||
assert(has('verify', strategy), INVALID_STRATEGY_MSG);
|
|
||||||
assert(typeof strategy.verify === 'function', INVALID_STRATEGY_MSG);
|
|
||||||
};
|
|
||||||
|
|
||||||
const createAuthentication = () => {
|
|
||||||
const strategies = [];
|
|
||||||
|
|
||||||
return {
|
|
||||||
register(strategy) {
|
|
||||||
validStrategy(strategy);
|
|
||||||
strategies.push(strategy);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
strategies.splice(strategies.indexOf(strategy), 1);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
async authenticate(ctx, next) {
|
|
||||||
for (const strategy of strategies) {
|
|
||||||
const result = await strategy.authenticate(ctx);
|
|
||||||
|
|
||||||
const { authenticated = false, credentials } = result || {};
|
|
||||||
|
|
||||||
if (authenticated) {
|
|
||||||
ctx.state.auth = { strategy, credentials };
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
},
|
|
||||||
async verify(auth, config = {}) {
|
|
||||||
if (config.public) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!auth) {
|
|
||||||
throw new UnauthorizedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return await auth.strategy.verify(auth, config);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
return {
|
|
||||||
auth: createAuthentication(),
|
|
||||||
errors: {
|
|
||||||
UnauthorizedError,
|
|
||||||
ForbiddenError,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -5,6 +5,7 @@ const { createAPI } = require('./api');
|
|||||||
const createAdminAPI = strapi => {
|
const createAdminAPI = strapi => {
|
||||||
const opts = {
|
const opts = {
|
||||||
prefix: '', // '/admin';
|
prefix: '', // '/admin';
|
||||||
|
type: 'admin',
|
||||||
};
|
};
|
||||||
|
|
||||||
return createAPI(strapi, opts);
|
return createAPI(strapi, opts);
|
||||||
|
|||||||
@ -5,11 +5,11 @@ const Router = require('@koa/router');
|
|||||||
const { createRouteManager } = require('./routing');
|
const { createRouteManager } = require('./routing');
|
||||||
|
|
||||||
const createAPI = (strapi, opts = {}) => {
|
const createAPI = (strapi, opts = {}) => {
|
||||||
const { prefix, defaultPolicies } = opts;
|
const { prefix, type } = opts;
|
||||||
|
|
||||||
const api = new Router({ prefix });
|
const api = new Router({ prefix });
|
||||||
|
|
||||||
const routeManager = createRouteManager(strapi, { defaultPolicies });
|
const routeManager = createRouteManager(strapi, { type });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
use(fn) {
|
use(fn) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { toLower, castArray, trim } = require('lodash/fp');
|
const { toLower, castArray, trim, prop } = require('lodash/fp');
|
||||||
|
|
||||||
const compose = require('koa-compose');
|
const compose = require('koa-compose');
|
||||||
const { resolveMiddlewares } = require('./middleware');
|
const { resolveMiddlewares } = require('./middleware');
|
||||||
@ -9,24 +9,64 @@ const { resolvePolicies } = require('./policy');
|
|||||||
const getMethod = route => trim(toLower(route.method));
|
const getMethod = route => trim(toLower(route.method));
|
||||||
const getPath = route => trim(route.path);
|
const getPath = route => trim(route.path);
|
||||||
|
|
||||||
const routeInfoMiddleware = route => (ctx, next) => {
|
const createRouteInfoMiddleware = routeInfo => (ctx, next) => {
|
||||||
|
const route = {
|
||||||
|
...routeInfo,
|
||||||
|
config: routeInfo.config || {},
|
||||||
|
};
|
||||||
|
|
||||||
ctx.state.route = route;
|
ctx.state.route = route;
|
||||||
return next();
|
return next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAuthConfig = prop('config.auth');
|
||||||
|
|
||||||
|
const createAuthorizeMiddleware = strapi => async (ctx, next) => {
|
||||||
|
const { auth, route } = ctx.state;
|
||||||
|
|
||||||
|
const authService = strapi.container.get('auth');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await authService.verify(auth, getAuthConfig(route));
|
||||||
|
|
||||||
|
return next();
|
||||||
|
} catch (error) {
|
||||||
|
const { UnauthorizedError, ForbiddenError } = authService.errors;
|
||||||
|
|
||||||
|
if (error instanceof UnauthorizedError) {
|
||||||
|
return ctx.unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error instanceof ForbiddenError) {
|
||||||
|
return ctx.forbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAuthenticateMiddleware = strapi => async (ctx, next) => {
|
||||||
|
return strapi.container.get('auth').authenticate(ctx, next);
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = strapi => {
|
module.exports = strapi => {
|
||||||
return (route, { pluginName, router, apiName }) => {
|
const authenticate = createAuthenticateMiddleware(strapi);
|
||||||
|
const authorize = createAuthorizeMiddleware(strapi);
|
||||||
|
|
||||||
|
return (route, { router }) => {
|
||||||
try {
|
try {
|
||||||
const method = getMethod(route);
|
const method = getMethod(route);
|
||||||
const path = getPath(route);
|
const path = getPath(route);
|
||||||
|
|
||||||
const middlewares = resolveMiddlewares(route);
|
const middlewares = resolveMiddlewares(route);
|
||||||
const policies = resolvePolicies(route, { pluginName, apiName });
|
const policies = resolvePolicies(route);
|
||||||
|
|
||||||
const action = getAction(route, { pluginName, apiName }, strapi);
|
const action = getAction(route, strapi);
|
||||||
|
|
||||||
const routeHandler = compose([
|
const routeHandler = compose([
|
||||||
routeInfoMiddleware(route),
|
createRouteInfoMiddleware(route),
|
||||||
|
authenticate,
|
||||||
|
authorize,
|
||||||
...policies,
|
...policies,
|
||||||
...middlewares,
|
...middlewares,
|
||||||
...castArray(action),
|
...castArray(action),
|
||||||
@ -52,7 +92,10 @@ const getController = (name, { pluginName, apiName }, strapi) => {
|
|||||||
return strapi.controller(name);
|
return strapi.controller(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAction = ({ handler }, { pluginName, apiName }, strapi) => {
|
const getAction = (route, strapi) => {
|
||||||
|
const { handler, info = {} } = route;
|
||||||
|
const { pluginName, apiName } = info;
|
||||||
|
|
||||||
if (Array.isArray(handler) || typeof handler === 'function') {
|
if (Array.isArray(handler) || typeof handler === 'function') {
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,50 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { prop } = require('lodash/fp');
|
|
||||||
const { createAPI } = require('./api');
|
const { createAPI } = require('./api');
|
||||||
|
|
||||||
const getAuthConfig = prop('config.auth');
|
|
||||||
|
|
||||||
const createAuthPolicy = strapi => async (ctx, next) => {
|
|
||||||
const { auth, route } = ctx.state;
|
|
||||||
|
|
||||||
if (!route) {
|
|
||||||
return ctx.unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await strapi.container.get('content-api').auth.verify(auth, getAuthConfig(route));
|
|
||||||
|
|
||||||
return next();
|
|
||||||
} catch (error) {
|
|
||||||
const { errors } = strapi.container.get('content-api');
|
|
||||||
|
|
||||||
if (error instanceof errors.UnauthorizedError) {
|
|
||||||
return ctx.unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error instanceof errors.ForbiddenError) {
|
|
||||||
return ctx.forbidden();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const createContentAPI = strapi => {
|
const createContentAPI = strapi => {
|
||||||
const opts = {
|
const opts = {
|
||||||
prefix: strapi.config.get('api.prefix', '/api'),
|
prefix: strapi.config.get('api.prefix', '/api'),
|
||||||
defaultPolicies: [createAuthPolicy(strapi)],
|
type: 'content-api',
|
||||||
};
|
};
|
||||||
|
|
||||||
const api = createAPI(strapi, opts);
|
return createAPI(strapi, opts);
|
||||||
|
|
||||||
// implement auth providers
|
|
||||||
api.use((ctx, next) => {
|
|
||||||
return strapi.container.get('content-api').auth.authenticate(ctx, next);
|
|
||||||
});
|
|
||||||
|
|
||||||
return api;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@ -8,13 +8,9 @@ const { createRouteManager } = require('./routing');
|
|||||||
const { createAdminAPI } = require('./admin-api');
|
const { createAdminAPI } = require('./admin-api');
|
||||||
const { createContentAPI } = require('./content-api');
|
const { createContentAPI } = require('./content-api');
|
||||||
|
|
||||||
const healthCheck = async (ctx, next) => {
|
const healthCheck = async ctx => {
|
||||||
if (ctx.request.url === '/_health' && ['HEAD', 'GET'].includes(ctx.request.method)) {
|
ctx.set('strapi', 'You are so French!');
|
||||||
ctx.set('strapi', 'You are so French!');
|
ctx.status = 204;
|
||||||
ctx.status = 204;
|
|
||||||
} else {
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +45,7 @@ const createServer = strapi => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// init health check
|
// init health check
|
||||||
app.use(healthCheck);
|
router.all('/_health', healthCheck);
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
mounted: false,
|
mounted: false,
|
||||||
|
|||||||
@ -7,10 +7,14 @@ const { bodyPolicy } = policy;
|
|||||||
|
|
||||||
const getPoliciesConfig = propOr([], 'config.policies');
|
const getPoliciesConfig = propOr([], 'config.policies');
|
||||||
|
|
||||||
const resolvePolicies = (route, opts = {}) => {
|
const resolvePolicies = route => {
|
||||||
|
const { pluginName, apiName } = route.info || {};
|
||||||
const policiesConfig = getPoliciesConfig(route);
|
const policiesConfig = getPoliciesConfig(route);
|
||||||
|
|
||||||
const policies = policiesConfig.map(policyName => policy.get(policyName, opts));
|
const policies = policiesConfig.map(policyName => {
|
||||||
|
return policy.get(policyName, { pluginName, apiName });
|
||||||
|
});
|
||||||
|
|
||||||
return [...policies, bodyPolicy];
|
return [...policies, bodyPolicy];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -69,20 +69,16 @@ const validateRouteConfig = routeConfig => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createRouteManager = (strapi, opts = {}) => {
|
const createRouteManager = (strapi, opts = {}) => {
|
||||||
|
const { type } = opts;
|
||||||
|
|
||||||
const composeEndpoint = createEndpointComposer(strapi);
|
const composeEndpoint = createEndpointComposer(strapi);
|
||||||
|
|
||||||
const createRoute = (route, router) => {
|
const createRoute = (route, router) => {
|
||||||
validateRouteConfig(route);
|
validateRouteConfig(route);
|
||||||
|
|
||||||
if (opts.defaultPolicies) {
|
_.set(route, 'info.type', type || 'admin');
|
||||||
if (has('config.policies', route)) {
|
|
||||||
route.config.policies.unshift(...opts.defaultPolicies);
|
|
||||||
} else {
|
|
||||||
_.set(route, 'config.policies', [...opts.defaultPolicies]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
composeEndpoint(route, { ...route.info, router });
|
composeEndpoint(route, { router });
|
||||||
};
|
};
|
||||||
|
|
||||||
const addRoutes = (routes, router) => {
|
const addRoutes = (routes, router) => {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export default {
|
|||||||
// TODO update doc and guides
|
// TODO update doc and guides
|
||||||
app.addComponents({ name: 'media-library', Component: InputModalStepper });
|
app.addComponents({ name: 'media-library', Component: InputModalStepper });
|
||||||
|
|
||||||
app.addCorePluginMenuLink({
|
app.addMenuLink({
|
||||||
to: `/plugins/${pluginId}`,
|
to: `/plugins/${pluginId}`,
|
||||||
icon,
|
icon,
|
||||||
intlLabel: {
|
intlLabel: {
|
||||||
@ -32,6 +32,11 @@ export default {
|
|||||||
defaultMessage: 'Media Library',
|
defaultMessage: 'Media Library',
|
||||||
},
|
},
|
||||||
permissions: pluginPermissions.main,
|
permissions: pluginPermissions.main,
|
||||||
|
Component: async () => {
|
||||||
|
const component = await import(/* webpackChunkName: "upload" */ './pages/App');
|
||||||
|
|
||||||
|
return component;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO update guide
|
// TODO update guide
|
||||||
|
|||||||
@ -32,6 +32,7 @@ module.exports = {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/uploads/(.*)',
|
path: '/uploads/(.*)',
|
||||||
handler: [range, koaStatic(staticDir, { defer: true, ...localServerConfig })],
|
handler: [range, koaStatic(staticDir, { defer: true, ...localServerConfig })],
|
||||||
|
config: { auth: false },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -50,8 +50,6 @@ module.exports = (projectDirectory, cliArguments) => {
|
|||||||
installDependencies: true,
|
installDependencies: true,
|
||||||
strapiDependencies: [
|
strapiDependencies: [
|
||||||
'@strapi/strapi',
|
'@strapi/strapi',
|
||||||
'@strapi/admin',
|
|
||||||
'@strapi/utils',
|
|
||||||
'@strapi/plugin-users-permissions',
|
'@strapi/plugin-users-permissions',
|
||||||
'@strapi/plugin-i18n',
|
'@strapi/plugin-i18n',
|
||||||
],
|
],
|
||||||
|
|||||||
@ -20,34 +20,34 @@ const authenticate = async ctx => {
|
|||||||
const { id } = await getService('jwt').getToken(ctx);
|
const { id } = await getService('jwt').getToken(ctx);
|
||||||
|
|
||||||
if (id === undefined) {
|
if (id === undefined) {
|
||||||
throw new Error('Invalid token: Token did not contain required fields');
|
return { error: 'Invalid token: Token did not contain required fields' };
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch authenticated user
|
// fetch authenticated user
|
||||||
const user = await getService('user').fetchAuthenticatedUser(id);
|
const user = await getService('user').fetchAuthenticatedUser(id);
|
||||||
|
|
||||||
if (user) {
|
if (!user) {
|
||||||
return {
|
return { error: 'Invalid credentials' };
|
||||||
authenticated: true,
|
|
||||||
credentials: user,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const advancedSettings = await getAdvancedSettings();
|
||||||
|
|
||||||
|
if (advancedSettings.email_confirmation && !user.confirmed) {
|
||||||
|
return { error: 'Invalid credentials' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.blocked) {
|
||||||
|
return { error: 'Invalid credentials' };
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.state.user = user;
|
||||||
|
|
||||||
|
return {
|
||||||
|
authenticated: true,
|
||||||
|
credentials: user,
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { authenticated: false };
|
return { error: 'Invalid credentials' };
|
||||||
}
|
|
||||||
|
|
||||||
if (!ctx.state.user) {
|
|
||||||
return { authenticated: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
const advancedSettings = await getAdvancedSettings();
|
|
||||||
|
|
||||||
if (advancedSettings.email_confirmation && !ctx.state.user.confirmed) {
|
|
||||||
return { authenticated: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.state.user.blocked) {
|
|
||||||
return { authenticated: false };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ const authenticate = async ctx => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const verify = async (auth, config) => {
|
const verify = async (auth, config) => {
|
||||||
const { errors } = strapi.container.get('content-api');
|
const { errors } = strapi.container.get('auth');
|
||||||
|
|
||||||
const { credentials: user } = auth;
|
const { credentials: user } = auth;
|
||||||
|
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
const authStrategy = require('./auth/strategy');
|
const authStrategy = require('./auth/strategy');
|
||||||
|
|
||||||
module.exports = strapi => {
|
module.exports = strapi => {
|
||||||
strapi.container.get('content-api').auth.register(authStrategy);
|
strapi.container.get('auth').register('content-api', authStrategy);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -20,10 +20,8 @@ const createStrapiInstance = async ({ ensureSuperAdmin = true, logLevel = 'fatal
|
|||||||
const options = { dir: TEST_APP_URL };
|
const options = { dir: TEST_APP_URL };
|
||||||
const instance = strapi(options);
|
const instance = strapi(options);
|
||||||
|
|
||||||
await instance.load();
|
instance.container.get('auth').register('content-api', {
|
||||||
|
name: 'test-auth',
|
||||||
instance.container.get('content-api').auth.register({
|
|
||||||
name: 'test-strategy',
|
|
||||||
authenticate() {
|
authenticate() {
|
||||||
return { authenticated: true };
|
return { authenticated: true };
|
||||||
},
|
},
|
||||||
@ -32,6 +30,8 @@ const createStrapiInstance = async ({ ensureSuperAdmin = true, logLevel = 'fatal
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await instance.load();
|
||||||
|
|
||||||
instance.log.level = logLevel;
|
instance.log.level = logLevel;
|
||||||
|
|
||||||
instance.server.mount();
|
instance.server.mount();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user