mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 16:29:34 +00:00
Merge pull request #10910 from strapi/v4/content-api
Move admin auth to global auth system
This commit is contained in:
commit
9c81dbea7f
@ -6,16 +6,19 @@ module.exports = {
|
||||
method: 'GET',
|
||||
path: '/providers',
|
||||
handler: 'authentication.getProviders',
|
||||
config: { auth: false },
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/connect/:provider',
|
||||
handler: 'authentication.providerLogin',
|
||||
config: { auth: false },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/connect/:provider',
|
||||
handler: 'authentication.providerLogin',
|
||||
config: { auth: false },
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
|
@ -31,9 +31,9 @@ module.exports = createPolicyFactory(
|
||||
);
|
||||
|
||||
return (ctx, next) => {
|
||||
const { userAbility: ability, isAuthenticatedAdmin } = ctx.state;
|
||||
const { userAbility: ability, isAuthenticated } = ctx.state;
|
||||
|
||||
if (!isAuthenticatedAdmin || !ability) {
|
||||
if (!isAuthenticated || !ability) {
|
||||
return next();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = (ctx, next) => {
|
||||
if (!ctx.state.isAuthenticatedAdmin) {
|
||||
if (!ctx.state.isAuthenticated) {
|
||||
return ctx.unauthorized();
|
||||
}
|
||||
|
||||
|
@ -3,56 +3,51 @@
|
||||
|
||||
// const permissionsFieldsToPropertiesMigration = require('../migrations/permissions-fields-to-properties');
|
||||
|
||||
/**
|
||||
* Tries to authenticated admin user and calls next.
|
||||
* @param {KoaContext} ctx
|
||||
* @param {Middleware} next
|
||||
* @returns {undefined}
|
||||
*/
|
||||
const authMiddleware = async (ctx, next) => {
|
||||
if (!ctx.request.header.authorization) {
|
||||
return next();
|
||||
}
|
||||
const adminAuthStrategy = {
|
||||
name: 'admin',
|
||||
async authenticate(ctx) {
|
||||
const { authorization } = ctx.request.header;
|
||||
|
||||
if (
|
||||
ctx.request.header.authorization &&
|
||||
ctx.request.header.authorization.split(' ')[0] === 'Bearer'
|
||||
) {
|
||||
const token = ctx.request.header.authorization.split(' ')[1];
|
||||
if (!authorization) {
|
||||
return { authenticated: false };
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (isValid) {
|
||||
const admin = await strapi
|
||||
const user = await strapi
|
||||
.query('admin::user')
|
||||
.findOne({ where: { id: payload.id }, populate: ['roles'] });
|
||||
|
||||
if (!admin || !(admin.isActive === true)) {
|
||||
return ctx.unauthorized('Invalid credentials');
|
||||
if (!user || !(user.isActive === true)) {
|
||||
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.user = admin;
|
||||
ctx.state.userAbility = await strapi.admin.services.permission.engine.generateUserAbility(
|
||||
admin
|
||||
);
|
||||
ctx.state.userAbility = userAbility;
|
||||
ctx.state.user = user;
|
||||
|
||||
ctx.state.isAuthenticatedAdmin = true;
|
||||
|
||||
return next();
|
||||
return { authenticated: true, credentials: user };
|
||||
}
|
||||
}
|
||||
|
||||
ctx.unauthorized('Invalid credentials');
|
||||
return { error: 'Invalid credentials' };
|
||||
},
|
||||
// async verify() {},
|
||||
};
|
||||
|
||||
module.exports = () => {
|
||||
const passportMiddleware = strapi.admin.services.passport.init();
|
||||
|
||||
strapi.server.api('admin').use(passportMiddleware);
|
||||
strapi.server.api('admin').use(authMiddleware);
|
||||
strapi.container.get('auth').register('admin', adminAuthStrategy);
|
||||
|
||||
// FIXME: to implement
|
||||
// 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';
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/init',
|
||||
handler: 'admin.init',
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
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'],
|
||||
},
|
||||
},
|
||||
];
|
||||
const admin = require('./admin');
|
||||
const authentication = require('./authentication');
|
||||
const permissions = require('./permissions');
|
||||
const users = require('./users');
|
||||
const roles = require('./roles');
|
||||
const webhooks = require('./webhooks');
|
||||
|
||||
module.exports = [...admin, ...authentication, ...permissions, ...users, ...roles, ...webhooks];
|
||||
|
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: [],
|
||||
},
|
||||
},
|
||||
];
|
@ -7,7 +7,9 @@ module.exports = {
|
||||
method: 'POST',
|
||||
path: '/',
|
||||
handler: 'email.send',
|
||||
config: {},
|
||||
config: {
|
||||
policies: ['admin::isAuthenticatedAdmin'],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
|
@ -18,7 +18,7 @@ const { createCoreStore, coreStoreModel } = require('./services/core-store');
|
||||
const createEntityService = require('./services/entity-service');
|
||||
const entityValidator = require('./services/entity-validator');
|
||||
const createTelemetry = require('./services/metrics');
|
||||
const createContentAPI = require('./services/content-api');
|
||||
const createAuth = require('./services/auth');
|
||||
const createUpdateNotifier = require('./utils/update-notifier');
|
||||
const createStartupLogger = require('./utils/startup-logger');
|
||||
const ee = require('./utils/ee');
|
||||
@ -53,7 +53,7 @@ class Strapi {
|
||||
this.container.register('modules', modulesRegistry(this));
|
||||
this.container.register('plugins', pluginsRegistry(this));
|
||||
this.container.register('apis', apisRegistry(this));
|
||||
this.container.register('content-api', createContentAPI(this));
|
||||
this.container.register('auth', createAuth(this));
|
||||
|
||||
this.isLoaded = false;
|
||||
this.reload = this.reload();
|
||||
|
@ -3,6 +3,7 @@
|
||||
const { uniq, difference, get, isUndefined, merge } = require('lodash');
|
||||
|
||||
const requiredMiddlewares = [
|
||||
'auth',
|
||||
'responses',
|
||||
'router',
|
||||
'logger',
|
||||
|
@ -67,11 +67,13 @@ module.exports = strapi => {
|
||||
method: 'GET',
|
||||
path: '/',
|
||||
handler: serveIndexPage,
|
||||
config: { auth: false },
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/index.html',
|
||||
handler: serveIndexPage,
|
||||
config: { auth: false },
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
@ -80,6 +82,7 @@ module.exports = strapi => {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
config: { auth: false },
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
@ -88,6 +91,7 @@ module.exports = strapi => {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
config: { auth: false },
|
||||
},
|
||||
]);
|
||||
}
|
||||
@ -118,6 +122,7 @@ module.exports = strapi => {
|
||||
serveAdmin,
|
||||
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 opts = {
|
||||
prefix: '', // '/admin';
|
||||
type: 'admin',
|
||||
};
|
||||
|
||||
return createAPI(strapi, opts);
|
||||
|
@ -5,11 +5,11 @@ const Router = require('@koa/router');
|
||||
const { createRouteManager } = require('./routing');
|
||||
|
||||
const createAPI = (strapi, opts = {}) => {
|
||||
const { prefix, defaultPolicies } = opts;
|
||||
const { prefix, type } = opts;
|
||||
|
||||
const api = new Router({ prefix });
|
||||
|
||||
const routeManager = createRouteManager(strapi, { defaultPolicies });
|
||||
const routeManager = createRouteManager(strapi, { type });
|
||||
|
||||
return {
|
||||
use(fn) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { toLower, castArray, trim } = require('lodash/fp');
|
||||
const { toLower, castArray, trim, prop } = require('lodash/fp');
|
||||
|
||||
const compose = require('koa-compose');
|
||||
const { resolveMiddlewares } = require('./middleware');
|
||||
@ -9,24 +9,64 @@ const { resolvePolicies } = require('./policy');
|
||||
const getMethod = route => trim(toLower(route.method));
|
||||
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;
|
||||
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 => {
|
||||
return (route, { pluginName, router, apiName }) => {
|
||||
const authenticate = createAuthenticateMiddleware(strapi);
|
||||
const authorize = createAuthorizeMiddleware(strapi);
|
||||
|
||||
return (route, { router }) => {
|
||||
try {
|
||||
const method = getMethod(route);
|
||||
const path = getPath(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([
|
||||
routeInfoMiddleware(route),
|
||||
createRouteInfoMiddleware(route),
|
||||
authenticate,
|
||||
authorize,
|
||||
...policies,
|
||||
...middlewares,
|
||||
...castArray(action),
|
||||
@ -52,7 +92,10 @@ const getController = (name, { pluginName, apiName }, strapi) => {
|
||||
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') {
|
||||
return handler;
|
||||
}
|
||||
|
@ -1,50 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const { prop } = require('lodash/fp');
|
||||
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 opts = {
|
||||
prefix: strapi.config.get('api.prefix', '/api'),
|
||||
defaultPolicies: [createAuthPolicy(strapi)],
|
||||
type: 'content-api',
|
||||
};
|
||||
|
||||
const api = createAPI(strapi, opts);
|
||||
|
||||
// implement auth providers
|
||||
api.use((ctx, next) => {
|
||||
return strapi.container.get('content-api').auth.authenticate(ctx, next);
|
||||
});
|
||||
|
||||
return api;
|
||||
return createAPI(strapi, opts);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
@ -8,13 +8,9 @@ const { createRouteManager } = require('./routing');
|
||||
const { createAdminAPI } = require('./admin-api');
|
||||
const { createContentAPI } = require('./content-api');
|
||||
|
||||
const healthCheck = async (ctx, next) => {
|
||||
if (ctx.request.url === '/_health' && ['HEAD', 'GET'].includes(ctx.request.method)) {
|
||||
ctx.set('strapi', 'You are so French!');
|
||||
ctx.status = 204;
|
||||
} else {
|
||||
await next();
|
||||
}
|
||||
const healthCheck = async ctx => {
|
||||
ctx.set('strapi', 'You are so French!');
|
||||
ctx.status = 204;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -49,7 +45,7 @@ const createServer = strapi => {
|
||||
};
|
||||
|
||||
// init health check
|
||||
app.use(healthCheck);
|
||||
router.all('/_health', healthCheck);
|
||||
|
||||
const state = {
|
||||
mounted: false,
|
||||
|
@ -7,10 +7,14 @@ const { bodyPolicy } = policy;
|
||||
|
||||
const getPoliciesConfig = propOr([], 'config.policies');
|
||||
|
||||
const resolvePolicies = (route, opts = {}) => {
|
||||
const resolvePolicies = route => {
|
||||
const { pluginName, apiName } = route.info || {};
|
||||
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];
|
||||
};
|
||||
|
||||
|
@ -69,20 +69,16 @@ const validateRouteConfig = routeConfig => {
|
||||
};
|
||||
|
||||
const createRouteManager = (strapi, opts = {}) => {
|
||||
const { type } = opts;
|
||||
|
||||
const composeEndpoint = createEndpointComposer(strapi);
|
||||
|
||||
const createRoute = (route, router) => {
|
||||
validateRouteConfig(route);
|
||||
|
||||
if (opts.defaultPolicies) {
|
||||
if (has('config.policies', route)) {
|
||||
route.config.policies.unshift(...opts.defaultPolicies);
|
||||
} else {
|
||||
_.set(route, 'config.policies', [...opts.defaultPolicies]);
|
||||
}
|
||||
}
|
||||
_.set(route, 'info.type', type || 'admin');
|
||||
|
||||
composeEndpoint(route, { ...route.info, router });
|
||||
composeEndpoint(route, { router });
|
||||
};
|
||||
|
||||
const addRoutes = (routes, router) => {
|
||||
|
@ -32,6 +32,7 @@ module.exports = {
|
||||
method: 'GET',
|
||||
path: '/uploads/(.*)',
|
||||
handler: [range, koaStatic(staticDir, { defer: true, ...localServerConfig })],
|
||||
config: { auth: false },
|
||||
},
|
||||
]);
|
||||
},
|
||||
|
@ -20,34 +20,34 @@ const authenticate = async ctx => {
|
||||
const { id } = await getService('jwt').getToken(ctx);
|
||||
|
||||
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
|
||||
const user = await getService('user').fetchAuthenticatedUser(id);
|
||||
|
||||
if (user) {
|
||||
return {
|
||||
authenticated: true,
|
||||
credentials: user,
|
||||
};
|
||||
if (!user) {
|
||||
return { error: 'Invalid credentials' };
|
||||
}
|
||||
|
||||
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) {
|
||||
return { authenticated: false };
|
||||
}
|
||||
|
||||
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 };
|
||||
return { error: 'Invalid credentials' };
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ const authenticate = async ctx => {
|
||||
};
|
||||
|
||||
const verify = async (auth, config) => {
|
||||
const { errors } = strapi.container.get('content-api');
|
||||
const { errors } = strapi.container.get('auth');
|
||||
|
||||
const { credentials: user } = auth;
|
||||
|
||||
|
@ -3,5 +3,5 @@
|
||||
const authStrategy = require('./auth/strategy');
|
||||
|
||||
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 instance = strapi(options);
|
||||
|
||||
await instance.load();
|
||||
|
||||
instance.container.get('content-api').auth.register({
|
||||
name: 'test-strategy',
|
||||
instance.container.get('auth').register('content-api', {
|
||||
name: 'test-auth',
|
||||
authenticate() {
|
||||
return { authenticated: true };
|
||||
},
|
||||
@ -32,6 +30,8 @@ const createStrapiInstance = async ({ ensureSuperAdmin = true, logLevel = 'fatal
|
||||
},
|
||||
});
|
||||
|
||||
await instance.load();
|
||||
|
||||
instance.log.level = logLevel;
|
||||
|
||||
instance.server.mount();
|
||||
|
Loading…
x
Reference in New Issue
Block a user