mirror of
https://github.com/strapi/strapi.git
synced 2025-12-26 22:54:31 +00:00
Init auth
This commit is contained in:
parent
3b41a627a4
commit
7aa012da32
@ -18,6 +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 createUpdateNotifier = require('./utils/update-notifier');
|
||||
const createStartupLogger = require('./utils/startup-logger');
|
||||
const ee = require('./utils/ee');
|
||||
@ -52,6 +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.isLoaded = false;
|
||||
this.reload = this.reload();
|
||||
@ -388,7 +390,7 @@ class Strapi {
|
||||
await execLifecycle(this.config.get(configPath));
|
||||
|
||||
// admin
|
||||
await this.admin[lifecycleName]();
|
||||
await this.admin[lifecycleName](this);
|
||||
}
|
||||
|
||||
getModel(uid) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const { toLower } = require('lodash/fp');
|
||||
|
||||
module.exports = strapi => {
|
||||
const registerAdminRoutes = () => {
|
||||
@ -52,6 +53,15 @@ module.exports = strapi => {
|
||||
// pass meta down to compose endpoint
|
||||
router.type = 'content-api';
|
||||
router.routes.forEach(route => {
|
||||
if (typeof route.handler === 'string') {
|
||||
const [controller, action] = route.handler.split('.');
|
||||
_.defaultsDeep(route.config, {
|
||||
auth: {
|
||||
scope: `application.${toLower(controller)}.${toLower(action)}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
route.info = { apiName };
|
||||
});
|
||||
|
||||
|
||||
53
packages/core/strapi/lib/services/content-api/index.js
Normal file
53
packages/core/strapi/lib/services/content-api/index.js
Normal file
@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
const { strict: assert } = require('assert');
|
||||
const { has } = require('lodash/fp');
|
||||
|
||||
const INVALID_STRATEGY_MSG =
|
||||
'Invalid auth strategy. Expecting an object with properties {name: string, authenticate: 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);
|
||||
};
|
||||
|
||||
const createAuthentication = () => {
|
||||
const strategies = [];
|
||||
|
||||
return {
|
||||
register(strategy) {
|
||||
validStrategy(strategy);
|
||||
strategies.push(strategy);
|
||||
|
||||
return () => {
|
||||
strategies.splice(strategies.indexOf(strategy), 1);
|
||||
};
|
||||
},
|
||||
async authenticate(ctx) {
|
||||
for (const strategy of strategies) {
|
||||
const result = await strategy.authenticate(ctx);
|
||||
|
||||
const { authenticated = false, credentials, scope } = result || {};
|
||||
|
||||
if (authenticated) {
|
||||
ctx.state.auth = {
|
||||
isAuthenticated: authenticated,
|
||||
scope,
|
||||
credentials,
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = () => {
|
||||
return {
|
||||
auth: createAuthentication(),
|
||||
};
|
||||
};
|
||||
@ -28,6 +28,10 @@ const authPolicy = (ctx, next) => {
|
||||
}
|
||||
|
||||
if (!has('auth.scope', config)) {
|
||||
return ctx.unauthorized();
|
||||
}
|
||||
|
||||
if (config.auth.scope === '*') {
|
||||
// just requires authentication
|
||||
return next();
|
||||
}
|
||||
@ -52,10 +56,8 @@ const createContentAPI = strapi => {
|
||||
const api = createAPI(strapi, opts);
|
||||
|
||||
// implement auth providers
|
||||
api.use((ctx, next) => {
|
||||
ctx.state.auth = {
|
||||
isAuthenticated: true,
|
||||
};
|
||||
api.use(async (ctx, next) => {
|
||||
await strapi.container.get('content-api').auth.authenticate(ctx);
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
@ -44,8 +44,8 @@ const createServer = strapi => {
|
||||
const httpServer = createHTTPServer(strapi, app);
|
||||
|
||||
const apis = {
|
||||
admin: createAdminAPI(strapi),
|
||||
'content-api': createContentAPI(strapi),
|
||||
admin: createAdminAPI(strapi),
|
||||
};
|
||||
|
||||
// init health check
|
||||
|
||||
@ -63,8 +63,7 @@ const validateRouteConfig = routeConfig => {
|
||||
stripUnknown: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new Error('Invalid route config');
|
||||
throw new Error('Invalid route config', error.message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
23
packages/plugins/users-permissions/server/index.js
Normal file
23
packages/plugins/users-permissions/server/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
const register = require('./register');
|
||||
const bootstrap = require('./bootstrap');
|
||||
const contentTypes = require('./content-types');
|
||||
const policies = require('./policies');
|
||||
const services = require('./services');
|
||||
const routes = require('./routes');
|
||||
const controllers = require('./controllers');
|
||||
const middlewares = require('./middlewares');
|
||||
const config = require('./config');
|
||||
|
||||
module.exports = () => ({
|
||||
register,
|
||||
bootstrap,
|
||||
config,
|
||||
routes,
|
||||
controllers,
|
||||
middlewares,
|
||||
contentTypes,
|
||||
policies,
|
||||
services,
|
||||
});
|
||||
92
packages/plugins/users-permissions/server/register.js
Normal file
92
packages/plugins/users-permissions/server/register.js
Normal file
@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
|
||||
const { map } = require('lodash/fp');
|
||||
|
||||
const { getService } = require('./utils');
|
||||
|
||||
const getAdvancedSettings = () => {
|
||||
return strapi
|
||||
.store({
|
||||
environment: '',
|
||||
type: 'plugin',
|
||||
name: 'users-permissions',
|
||||
})
|
||||
.get({ key: 'advanced' });
|
||||
};
|
||||
|
||||
const permissionToScope = permission => {
|
||||
// missing apiName type
|
||||
return `${permission.type}.${permission.controller}.${permission.action}`;
|
||||
};
|
||||
|
||||
module.exports = strapi => {
|
||||
strapi.container.get('content-api').auth.register({
|
||||
name: 'users-permissions',
|
||||
async authenticate(ctx) {
|
||||
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
||||
try {
|
||||
const { id } = await getService('jwt').getToken(ctx);
|
||||
|
||||
if (id === undefined) {
|
||||
throw new Error('Invalid token: Token did not contain required fields');
|
||||
}
|
||||
|
||||
// fetch authenticated user
|
||||
const user = await getService('user').fetchAuthenticatedUser(id);
|
||||
|
||||
if (user) {
|
||||
const permissions = await strapi
|
||||
.query('plugin::users-permissions.permission')
|
||||
.findMany({
|
||||
where: {
|
||||
role: user.role.id,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
authenticated: true,
|
||||
credentials: user,
|
||||
scope: map(permissionToScope, permissions),
|
||||
};
|
||||
}
|
||||
} 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 };
|
||||
}
|
||||
}
|
||||
|
||||
const publicPermissions = await strapi
|
||||
.query('plugin::users-permissions.permission')
|
||||
.findMany({
|
||||
where: {
|
||||
role: { type: 'public' },
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (publicPermissions.length === 0) {
|
||||
return { authenticated: false };
|
||||
}
|
||||
|
||||
return {
|
||||
authenticated: true,
|
||||
credentials: null,
|
||||
scope: map(permissionToScope, publicPermissions),
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -202,24 +202,24 @@ module.exports = {
|
||||
prefix: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/auth/local',
|
||||
handler: 'auth.callback',
|
||||
config: {
|
||||
policies: ['plugin::users-permissions.rateLimit'],
|
||||
prefix: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/auth/local/register',
|
||||
handler: 'auth.register',
|
||||
config: {
|
||||
policies: ['plugin::users-permissions.rateLimit'],
|
||||
prefix: '',
|
||||
},
|
||||
},
|
||||
// {
|
||||
// method: 'POST',
|
||||
// path: '/auth/local',
|
||||
// handler: 'auth.callback',
|
||||
// config: {
|
||||
// policies: ['plugin::users-permissions.rateLimit'],
|
||||
// prefix: '',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// method: 'POST',
|
||||
// path: '/auth/local/register',
|
||||
// handler: 'auth.register',
|
||||
// config: {
|
||||
// policies: ['plugin::users-permissions.rateLimit'],
|
||||
// prefix: '',
|
||||
// },
|
||||
// },
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/auth/:provider/callback',
|
||||
|
||||
@ -2,22 +2,27 @@
|
||||
|
||||
module.exports = {
|
||||
type: 'content-api',
|
||||
// TODO:
|
||||
routes: [
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/users/count',
|
||||
handler: 'user.count',
|
||||
method: 'POST',
|
||||
path: '/auth/local',
|
||||
handler: 'auth.callback',
|
||||
config: {
|
||||
auth: { public: true },
|
||||
policies: ['plugin::users-permissions.rateLimit'],
|
||||
prefix: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/users',
|
||||
handler: 'user.find',
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/users/me',
|
||||
handler: 'user.me',
|
||||
method: 'POST',
|
||||
path: '/auth/local/register',
|
||||
handler: 'auth.register',
|
||||
config: {
|
||||
auth: { public: true },
|
||||
policies: ['plugin::users-permissions.rateLimit'],
|
||||
prefix: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
// TODO: add connection / auto registration routes
|
||||
};
|
||||
|
||||
@ -1,21 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
const bootstrap = require('./server/bootstrap');
|
||||
const contentTypes = require('./server/content-types');
|
||||
const policies = require('./server/policies');
|
||||
const services = require('./server/services');
|
||||
const routes = require('./server/routes');
|
||||
const controllers = require('./server/controllers');
|
||||
const middlewares = require('./server/middlewares');
|
||||
const config = require('./server/config');
|
||||
|
||||
module.exports = () => ({
|
||||
bootstrap,
|
||||
config,
|
||||
routes,
|
||||
controllers,
|
||||
middlewares,
|
||||
contentTypes,
|
||||
policies,
|
||||
services,
|
||||
});
|
||||
module.exports = require('./server');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user