mirror of
https://github.com/strapi/strapi.git
synced 2025-12-18 02:33:53 +00:00
[WIP] Read and update roles & permissions using database
This commit is contained in:
parent
b04a495bc4
commit
4aa28a196e
@ -27,10 +27,10 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
|||||||
|
|
||||||
// Roles that can't be deleted && modified
|
// Roles that can't be deleted && modified
|
||||||
// Don't delete this line
|
// Don't delete this line
|
||||||
protectedRoleIDs = ['0'];
|
protectedRoleIDs = ['root'];
|
||||||
|
|
||||||
// Roles that can't be deleted;
|
// Roles that can't be deleted;
|
||||||
undeletableIDs = ['1'];
|
undeletableIDs = ['guest'];
|
||||||
|
|
||||||
generateContent = () => {
|
generateContent = () => {
|
||||||
let icons = [
|
let icons = [
|
||||||
@ -46,11 +46,11 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
|||||||
|
|
||||||
switch (this.props.settingType) {
|
switch (this.props.settingType) {
|
||||||
case 'roles':
|
case 'roles':
|
||||||
if (includes(this.protectedRoleIDs, get(this.props.item, 'id').toString())) {
|
if (includes(this.protectedRoleIDs, get(this.props.item, 'type').toString())) {
|
||||||
icons = [];
|
icons = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includes(this.undeletableIDs, get(this.props.item, 'id').toString())) {
|
if (includes(this.undeletableIDs, get(this.props.item, 'type').toString())) {
|
||||||
icons = [{ icoType: 'pencil', onClick: this.handleClick }];
|
icons = [{ icoType: 'pencil', onClick: this.handleClick }];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
|||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
switch (this.props.settingType) {
|
switch (this.props.settingType) {
|
||||||
case 'roles': {
|
case 'roles': {
|
||||||
if (!includes(this.protectedRoleIDs, get(this.props.item, 'id').toString())) {
|
if (!includes(this.protectedRoleIDs, get(this.props.item, 'type').toString())) {
|
||||||
return router.push(`${router.location.pathname}/edit/${this.props.item.id}`);
|
return router.push(`${router.location.pathname}/edit/${this.props.item.id}`);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
{"actions":["content-manager.contentmanager.models","content-manager.contentmanager.find","content-manager.contentmanager.count","content-manager.contentmanager.findOne","content-manager.contentmanager.create","content-manager.contentmanager.update","content-manager.contentmanager.delete","content-manager.contentmanager.identity","content-type-builder.contenttypebuilder.getModels","content-type-builder.contenttypebuilder.getModel","content-type-builder.contenttypebuilder.getConnections","content-type-builder.contenttypebuilder.createModel","content-type-builder.contenttypebuilder.updateModel","content-type-builder.contenttypebuilder.deleteModel","content-type-builder.contenttypebuilder.autoReload","content-type-builder.contenttypebuilder.checkTableExists","content-type-builder.contenttypebuilder.identity","settings-manager.settingsmanager.menu","settings-manager.settingsmanager.environments","settings-manager.settingsmanager.languages","settings-manager.settingsmanager.databases","settings-manager.settingsmanager.database","settings-manager.settingsmanager.databaseModel","settings-manager.settingsmanager.get","settings-manager.settingsmanager.update","settings-manager.settingsmanager.createLanguage","settings-manager.settingsmanager.deleteLanguage","settings-manager.settingsmanager.createDatabase","settings-manager.settingsmanager.updateDatabase","settings-manager.settingsmanager.deleteDatabase","settings-manager.settingsmanager.autoReload","settings-manager.settingsmanager.identity","users-permissions.auth.callback","users-permissions.auth.changePassword","users-permissions.auth.forgotPassword","users-permissions.auth.register","users-permissions.auth.identity","users-permissions.user.find","users-permissions.user.me","users-permissions.user.findOne","users-permissions.user.create","users-permissions.user.update","users-permissions.user.destroy","users-permissions.user.identity","users-permissions.userspermissions.createRole","users-permissions.userspermissions.deleteProvider","users-permissions.userspermissions.deleteRole","users-permissions.userspermissions.getPermissions","users-permissions.userspermissions.getPolicies","users-permissions.userspermissions.getRole","users-permissions.userspermissions.getRoles","users-permissions.userspermissions.getRoutes","users-permissions.userspermissions.index","users-permissions.userspermissions.init","users-permissions.userspermissions.searchUsers","users-permissions.userspermissions.updateRole","users-permissions.userspermissions.identity"]}
|
||||||
@ -17,6 +17,7 @@ module.exports = cb => {
|
|||||||
if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) {
|
if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) {
|
||||||
try {
|
try {
|
||||||
const jwtSecret = uuid();
|
const jwtSecret = uuid();
|
||||||
|
|
||||||
fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'jwt.json'), JSON.stringify({
|
fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'jwt.json'), JSON.stringify({
|
||||||
jwtSecret
|
jwtSecret
|
||||||
}, null, 2), 'utf8');
|
}, null, 2), 'utf8');
|
||||||
@ -28,6 +29,6 @@ module.exports = cb => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
strapi.plugins['users-permissions'].services.userspermissions.syncSchema(() => {
|
strapi.plugins['users-permissions'].services.userspermissions.syncSchema(() => {
|
||||||
strapi.plugins['users-permissions'].services.userspermissions.updatePermissions(cb);
|
strapi.plugins['users-permissions'].services.userspermissions.initialize(cb);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
if (!ctx.state.user) {
|
if (!ctx.state.user) {
|
||||||
throw new Error('Authentication required.');
|
return ctx.unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
await next();
|
await next();
|
||||||
|
|||||||
@ -1,45 +1,54 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
const route = ctx.request.route;
|
let role;
|
||||||
let role = '1';
|
|
||||||
|
|
||||||
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
||||||
try {
|
try {
|
||||||
const tokenUser = await strapi.plugins['users-permissions'].services.jwt.getToken(ctx);
|
const token = await strapi.plugins['users-permissions'].services.jwt.getToken(ctx);
|
||||||
|
|
||||||
ctx.state.user = await strapi.plugins['users-permissions'].services.user.fetch(_.pick(tokenUser, ['_id', 'id']));
|
|
||||||
|
|
||||||
|
ctx.state.user = await strapi.query('user', 'users-permissions').findOne(_.pick(token, ['_id', 'id']), ['role'])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return ctx.unauthorized(err);
|
return ctx.unauthorized(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx.state.user) {
|
if (!ctx.state.user) {
|
||||||
return ctx.unauthorized('This user doesn\'t exit.');
|
return ctx.unauthorized(`User Not Found.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
role = ctx.state.user.role;
|
role = ctx.state.user.role;
|
||||||
|
|
||||||
if (role.toString() === '0') {
|
if (role.type === 'root') {
|
||||||
return await next();
|
return await next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const permission = _.get(strapi.plugins['users-permissions'].config, ['roles', role.toString(), 'permissions', route.plugin || 'application', 'controllers', route.controller, route.action]);
|
// Retrieve `guest` role.
|
||||||
|
if (!role) {
|
||||||
|
role = await strapi.query('role', 'users-permissions').findOne({ type: 'guest' }, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = ctx.request.route;
|
||||||
|
|
||||||
|
const permission = await strapi.query('permission', 'users-permissions').findOne({
|
||||||
|
role: role._id || role.id,
|
||||||
|
type: route.plugin || 'application',
|
||||||
|
controller: route.controller,
|
||||||
|
action: route.action,
|
||||||
|
enabled: true
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (!permission) {
|
if (!permission) {
|
||||||
return await next();
|
return ctx.unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permission.enabled && permission.policy) {
|
// Execute the policies.
|
||||||
try {
|
if (permission.policy) {
|
||||||
await strapi.plugins['users-permissions'].config.policies[permission.policy](ctx, next);
|
await strapi.plugins['users-permissions'].config.policies[permission.policy](ctx, next);
|
||||||
} catch (err) {
|
|
||||||
ctx.unauthorized(err);
|
|
||||||
}
|
}
|
||||||
} else if (permission.enabled) {
|
|
||||||
|
console.log("OKAY");
|
||||||
|
|
||||||
|
// Execute the action.
|
||||||
await next();
|
await next();
|
||||||
} else {
|
|
||||||
ctx.unauthorized('Access restricted for this action.');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
find: async function (params) {
|
find: async function (params = {}, populate) {
|
||||||
return this
|
return this
|
||||||
.find(params.where)
|
.find(params.where)
|
||||||
.limit(Number(params.limit))
|
.limit(Number(params.limit))
|
||||||
.sort(params.sort)
|
.sort(params.sort)
|
||||||
.skip(Number(params.skip))
|
.skip(Number(params.skip))
|
||||||
.populate(this.associations.map(x => x.alias).join(' '));
|
.populate(populate || this.associations.map(x => x.alias).join(' '))
|
||||||
|
.lean();
|
||||||
},
|
},
|
||||||
|
|
||||||
count: async function (params) {
|
count: async function (params = {}) {
|
||||||
return Number(await this
|
return Number(await this
|
||||||
.count());
|
.count(params));
|
||||||
},
|
},
|
||||||
|
|
||||||
findOne: async function (params) {
|
findOne: async function (params, populate) {
|
||||||
if (!params[this.primaryKey] && params.id) {
|
if (!params[this.primaryKey] && params.id) {
|
||||||
params[this.primaryKey] = params.id;
|
params[this.primaryKey] = params.id;
|
||||||
delete params.id;
|
delete params.id;
|
||||||
@ -25,12 +26,12 @@ module.exports = {
|
|||||||
|
|
||||||
return this
|
return this
|
||||||
.findOne(params)
|
.findOne(params)
|
||||||
.populate(this.associations.map(x => x.alias).join(' '));
|
.populate(populate || this.associations.map(x => x.alias).join(' '));
|
||||||
},
|
},
|
||||||
|
|
||||||
create: async function (params) {
|
create: async function (params) {
|
||||||
return this.create(Object.keys(params).reduce((acc, current) => {
|
return this.create(Object.keys(params).reduce((acc, current) => {
|
||||||
if (_.get(this._attributes, [current, 'type'])) {
|
if (_.get(this._attributes, [current, 'type']) || _.get(this._attributes, [current, 'model'])) {
|
||||||
acc[current] = params[current];
|
acc[current] = params[current];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,5 +88,20 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
createRole: async function (params) {
|
||||||
|
return this.
|
||||||
|
create(params);
|
||||||
|
},
|
||||||
|
|
||||||
|
addPermission: async function (params) {
|
||||||
|
return this
|
||||||
|
.create(params);
|
||||||
|
},
|
||||||
|
|
||||||
|
removePermission: async function (params) {
|
||||||
|
return this
|
||||||
|
.remove(params);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -159,15 +159,18 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First, check if the user is the first one to register as admin.
|
// First, check if the user is the first one to register as admin.
|
||||||
const adminUsers = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', { role: '0' }));
|
const hasAdmin = await strapi.query('user', 'users-permissions').count(strapi.utils.models.convertParams('user', { type: 'root' }));
|
||||||
|
|
||||||
// Check if the user is the first to register
|
// Check if the user is the first to register
|
||||||
if (adminUsers.length === 0) {
|
const role = hasAdmin < 1 ?
|
||||||
params.role = '0';
|
await strapi.query('role', 'users-permissions').findOne({ type: 'root' }, []):
|
||||||
} else {
|
await strapi.query('role', 'users-permissions').findOne({ type: 'guest' }, []);
|
||||||
params.role = '1';
|
|
||||||
|
if (!role) {
|
||||||
|
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.role.notFound' }] }] : 'Impossible to find the root role.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
params.role = role._id || role.id;
|
||||||
params.password = await strapi.plugins['users-permissions'].services.user.hashPassword(params);
|
params.password = await strapi.plugins['users-permissions'].services.user.hashPassword(params);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -90,10 +90,12 @@ module.exports = {
|
|||||||
|
|
||||||
getRoles: async (ctx) => {
|
getRoles: async (ctx) => {
|
||||||
try {
|
try {
|
||||||
|
console.log("coucou");
|
||||||
const roles = await strapi.plugins['users-permissions'].services.userspermissions.getRoles();
|
const roles = await strapi.plugins['users-permissions'].services.userspermissions.getRoles();
|
||||||
|
|
||||||
ctx.send({ roles });
|
ctx.send({ roles });
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
|
console.log(err);
|
||||||
ctx.badRequest(null, [{ messages: [{ id: 'Not found' }] }]);
|
ctx.badRequest(null, [{ messages: [{ id: 'Not found' }] }]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -118,7 +120,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
init: async (ctx) => {
|
init: async (ctx) => {
|
||||||
const hasAdmin = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', { role: '0' }));
|
const hasAdmin = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', { type: 'guest' }));
|
||||||
|
|
||||||
ctx.send({ hasAdmin: hasAdmin.length > 0 });
|
ctx.send({ hasAdmin: hasAdmin.length > 0 });
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lifecycle callbacks for the `User` model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Before saving a value.
|
||||||
|
// Fired before an `insert` or `update` query.
|
||||||
|
// beforeSave: async (model) => {},
|
||||||
|
|
||||||
|
// After saving a value.
|
||||||
|
// Fired after an `insert` or `update` query.
|
||||||
|
// afterSave: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before fetching all values.
|
||||||
|
// Fired before a `fetchAll` operation.
|
||||||
|
// beforeFetchAll: async (model) => {},
|
||||||
|
|
||||||
|
// After fetching all values.
|
||||||
|
// Fired after a `fetchAll` operation.
|
||||||
|
// afterFetchAll: async (model, results) => {},
|
||||||
|
|
||||||
|
// Fired before a `fetch` operation.
|
||||||
|
// beforeFetch: async (model) => {},
|
||||||
|
|
||||||
|
// After fetching a value.
|
||||||
|
// Fired after a `fetch` operation.
|
||||||
|
// afterFetch: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before creating a value.
|
||||||
|
// Fired before `insert` query.
|
||||||
|
// beforeCreate: async (model) => {},
|
||||||
|
|
||||||
|
// After creating a value.
|
||||||
|
// Fired after `insert` query.
|
||||||
|
// afterCreate: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before updating a value.
|
||||||
|
// Fired before an `update` query.
|
||||||
|
// beforeUpdate: async (model) => {},
|
||||||
|
|
||||||
|
// After updating a value.
|
||||||
|
// Fired after an `update` query.
|
||||||
|
// afterUpdate: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before destroying a value.
|
||||||
|
// Fired before a `delete` query.
|
||||||
|
// beforeDestroy: async (model) => {},
|
||||||
|
|
||||||
|
// After destroying a value.
|
||||||
|
// Fired after a `delete` query.
|
||||||
|
// afterDestroy: async (model, result) => {}
|
||||||
|
};
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"connection": "default",
|
||||||
|
"info": {
|
||||||
|
"name": "permission",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"controller": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"policy": {
|
||||||
|
"type": "json",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"model": "role",
|
||||||
|
"via": "permissions",
|
||||||
|
"plugin": "users-permissions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
packages/strapi-plugin-users-permissions/models/Role.js
Normal file
54
packages/strapi-plugin-users-permissions/models/Role.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lifecycle callbacks for the `User` model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Before saving a value.
|
||||||
|
// Fired before an `insert` or `update` query.
|
||||||
|
// beforeSave: async (model) => {},
|
||||||
|
|
||||||
|
// After saving a value.
|
||||||
|
// Fired after an `insert` or `update` query.
|
||||||
|
// afterSave: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before fetching all values.
|
||||||
|
// Fired before a `fetchAll` operation.
|
||||||
|
// beforeFetchAll: async (model) => {},
|
||||||
|
|
||||||
|
// After fetching all values.
|
||||||
|
// Fired after a `fetchAll` operation.
|
||||||
|
// afterFetchAll: async (model, results) => {},
|
||||||
|
|
||||||
|
// Fired before a `fetch` operation.
|
||||||
|
// beforeFetch: async (model) => {},
|
||||||
|
|
||||||
|
// After fetching a value.
|
||||||
|
// Fired after a `fetch` operation.
|
||||||
|
// afterFetch: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before creating a value.
|
||||||
|
// Fired before `insert` query.
|
||||||
|
// beforeCreate: async (model) => {},
|
||||||
|
|
||||||
|
// After creating a value.
|
||||||
|
// Fired after `insert` query.
|
||||||
|
// afterCreate: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before updating a value.
|
||||||
|
// Fired before an `update` query.
|
||||||
|
// beforeUpdate: async (model) => {},
|
||||||
|
|
||||||
|
// After updating a value.
|
||||||
|
// Fired after an `update` query.
|
||||||
|
// afterUpdate: async (model, result) => {},
|
||||||
|
|
||||||
|
// Before destroying a value.
|
||||||
|
// Fired before a `delete` query.
|
||||||
|
// beforeDestroy: async (model) => {},
|
||||||
|
|
||||||
|
// After destroying a value.
|
||||||
|
// Fired after a `delete` query.
|
||||||
|
// afterDestroy: async (model, result) => {}
|
||||||
|
};
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"connection": "default",
|
||||||
|
"info": {
|
||||||
|
"name": "role",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 3,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"unique": true
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"collection": "user",
|
||||||
|
"via": "role",
|
||||||
|
"plugin": "users-permissions"
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"collection": "permission",
|
||||||
|
"via": "role",
|
||||||
|
"plugin": "users-permissions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"collectionName": "",
|
"connection": "default",
|
||||||
"info": {
|
"info": {
|
||||||
"name": "user",
|
"name": "user",
|
||||||
"description": ""
|
"description": ""
|
||||||
@ -34,9 +34,10 @@
|
|||||||
"configurable": false
|
"configurable": false
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "integer",
|
"model": "role",
|
||||||
|
"via": "users",
|
||||||
|
"plugin": "users-permissions",
|
||||||
"configurable": false
|
"configurable": false
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"connection": "default"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const stringify = JSON.stringify;
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getActions: (plugins = []) => {
|
getActions: (plugins = [], withInfo = true) => {
|
||||||
const generateActions = (data) => (
|
const generateActions = (data) => (
|
||||||
Object.keys(data).reduce((acc, key) => {
|
Object.keys(data).reduce((acc, key) => {
|
||||||
acc[key] = { enabled: false, policy: '' };
|
acc[key] = { enabled: false, policy: '' };
|
||||||
@ -74,12 +73,20 @@ module.exports = {
|
|||||||
}, { controllers: {} });
|
}, { controllers: {} });
|
||||||
|
|
||||||
const pluginsPermissions = Object.keys(strapi.plugins).reduce((acc, key) => {
|
const pluginsPermissions = Object.keys(strapi.plugins).reduce((acc, key) => {
|
||||||
|
const initialState = {
|
||||||
|
controllers: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (withInfo) {
|
||||||
|
initialState.information = plugins.find(plugin => plugin.id === key) || {};
|
||||||
|
}
|
||||||
|
|
||||||
acc[key] = Object.keys(strapi.plugins[key].controllers).reduce((obj, k) => {
|
acc[key] = Object.keys(strapi.plugins[key].controllers).reduce((obj, k) => {
|
||||||
obj.controllers[k] = generateActions(strapi.plugins[key].controllers[k]);
|
obj.controllers[k] = generateActions(strapi.plugins[key].controllers[k]);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
}, { controllers: {}, information: plugins.find(plugin => plugin.id === key) || {} });
|
}, initialState);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
@ -108,111 +115,107 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getRoles: async () => {
|
getRoles: async () => {
|
||||||
const roles = strapi.plugins['users-permissions'].config.roles;
|
const roles = await strapi.query('role', 'users-permissions').find({ sort: 'name ASC' }, []);
|
||||||
const usersCount = await strapi.query('user', 'users-permissions').countByRoles();
|
|
||||||
const formattedRoles = Object.keys(roles).reduce((acc, key) => {
|
|
||||||
const role = _.pick(roles[key], ['name', 'description']);
|
|
||||||
|
|
||||||
_.set(role, 'id', key);
|
for (let i = 0; i < roles.length; ++i) {
|
||||||
_.set(role, 'nb_users', _.get(_.find(usersCount, { _id: parseFloat(key) }), 'total', 0));
|
role.nb_users = await strapi.query('user', 'users-permissions').count({ role: roles[i].id || roles[i]._id });
|
||||||
acc.push(role);
|
}
|
||||||
|
|
||||||
return acc;
|
return roles;
|
||||||
}, []);
|
|
||||||
|
|
||||||
return formattedRoles;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getRoutes: async () => {
|
getRoutes: async () => {
|
||||||
const apiRoutes = strapi.api ? Object.keys(strapi.api).reduce((acc, current) => {
|
const routes = Object.keys(strapi.api || {}).reduce((acc, current) => {
|
||||||
return acc.concat(strapi.api[current].config.routes);
|
return acc.concat(strapi.api[current].config.routes);
|
||||||
}, []) : [];
|
}, []);
|
||||||
|
|
||||||
const pluginsRoutes = Object.keys(strapi.plugins).reduce((acc, current) => {
|
const pluginsRoutes = Object.keys(strapi.plugins || {}).reduce((acc, current) => {
|
||||||
acc[current] = strapi.plugins[current].config.routes;
|
acc[current] = strapi.plugins[current].config.routes;
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return _.merge({ application: apiRoutes}, pluginsRoutes);
|
return _.merge({ application: routes }, pluginsRoutes);
|
||||||
},
|
},
|
||||||
|
|
||||||
getRoleConfigPath: () => (
|
updatePermissions: async function (cb) {
|
||||||
path.join(
|
const actions = strapi.plugins['users-permissions'].config.actions || [];
|
||||||
strapi.config.appPath,
|
|
||||||
'plugins',
|
|
||||||
'users-permissions',
|
|
||||||
'config',
|
|
||||||
'roles.json',
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
updateData: (data, diff = 'unset') => {
|
// Aggregate first level actions.
|
||||||
const dataToCompare = strapi.plugins['users-permissions'].services.userspermissions.getActions();
|
const appActions = Object.keys(strapi.api || {}).reduce((acc, api) => {
|
||||||
|
Object.keys(strapi.api[api].controllers)
|
||||||
|
.map(controller => {
|
||||||
|
const actions = Object.keys(strapi.api[api].controllers[controller])
|
||||||
|
.map(action => `application.${controller}.${action}`);
|
||||||
|
|
||||||
_.forEach(data, (roleData, roleId) => {
|
acc = acc.concat(actions);
|
||||||
const obj = diff === 'unset' ? roleData.permissions : dataToCompare;
|
|
||||||
|
|
||||||
_.forEach(obj, (pluginData, pluginName) => {
|
|
||||||
_.forEach(pluginData.controllers, (controllerActions, controllerName) => {
|
|
||||||
_.forEach(controllerActions, (actionData, actionName) => {
|
|
||||||
if (diff === 'unset') {
|
|
||||||
if (!_.get(dataToCompare, [pluginName, 'controllers', controllerName])) {
|
|
||||||
_.unset(data, [roleId, 'permissions', pluginName, 'controllers', controllerName]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_.get(dataToCompare, [pluginName, 'controllers', controllerName, actionName])) {
|
|
||||||
_.unset(data, [roleId, 'permissions', pluginName, 'controllers', controllerName, actionName]);
|
|
||||||
}
|
|
||||||
} else if (!_.get(data, [roleId, 'permissions', pluginName, 'controllers', controllerName, actionName])) {
|
|
||||||
const isCallback = actionName === 'callback' && controllerName === 'auth' && pluginName === 'users-permissions' && roleId === '1';
|
|
||||||
const isRegister = actionName === 'register' && controllerName === 'auth' && pluginName === 'users-permissions' && roleId === '1';
|
|
||||||
const isPassword = actionName === 'forgotPassword' && controllerName === 'auth' && pluginName === 'users-permissions' && roleId === '1';
|
|
||||||
const isNewPassword = actionName === 'changePassword' && controllerName === 'auth' && pluginName === 'users-permissions' && roleId === '1';
|
|
||||||
const isInit = actionName === 'init' && controllerName === 'userspermissions';
|
|
||||||
const isMe = actionName === 'me' && controllerName === 'user' && pluginName === 'users-permissions';
|
|
||||||
const enabled = isCallback || isRegister || roleId === '0' || isInit || isPassword || isNewPassword || isMe;
|
|
||||||
|
|
||||||
_.set(data, [roleId, 'permissions', pluginName, 'controllers', controllerName, actionName], { enabled, policy: '' })
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return acc;
|
||||||
},
|
}, []);
|
||||||
|
|
||||||
updatePermissions: async (cb) => {
|
// Aggregate plugins' actions.
|
||||||
const appActions = module.exports.getActions();
|
const pluginsActions = Object.keys(strapi.plugins).reduce((acc, plugin) => {
|
||||||
const writePermissions = module.exports.writePermissions;
|
Object.keys(strapi.plugins[plugin].controllers)
|
||||||
const currentRoles = strapi.plugins['users-permissions'].config.roles || {
|
.map(controller => {
|
||||||
'0': {
|
const actions = Object.keys(strapi.plugins[plugin].controllers[controller])
|
||||||
description: '',
|
.map(action => `${plugin}.${controller}.${action}`);
|
||||||
name: 'Administrator',
|
|
||||||
permissions: {
|
acc = acc.concat(actions);
|
||||||
application: {
|
});
|
||||||
controllers: {},
|
|
||||||
},
|
return acc;
|
||||||
},
|
}, []);
|
||||||
},
|
|
||||||
'1': {
|
// Merge array into one.
|
||||||
description: '',
|
const currentActions = appActions.concat(pluginsActions);
|
||||||
name: 'Guest',
|
// Count permissions available.
|
||||||
permissions: {
|
const permissions = await strapi.query('permission', 'users-permissions').count();
|
||||||
application: {
|
|
||||||
controllers: {},
|
// Compare to know if actions have been added or removed from controllers.
|
||||||
},
|
if (!_.isEqual(actions, currentActions) || permissions < 1) {
|
||||||
},
|
const splitted = (str) => {
|
||||||
},
|
const [type, controller, action] = str.split('.');
|
||||||
|
|
||||||
|
return { type, controller, action };
|
||||||
};
|
};
|
||||||
|
|
||||||
const remove = await module.exports.updateData(_.cloneDeep(currentRoles));
|
const defaultPolicy = (obj, role) => {
|
||||||
const added = await module.exports.updateData(_.cloneDeep(remove), 'set');
|
const isCallback = obj.action === 'callback' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'guest';
|
||||||
|
const isRegister = obj.action === 'register' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'guest';
|
||||||
|
const isPassword = obj.action === 'forgotPassword' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'guest';
|
||||||
|
const isNewPassword = obj.action === 'changePassword' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'guest';
|
||||||
|
const isInit = obj.action === 'init' && obj.controller === 'userspermissions';
|
||||||
|
const isMe = obj.action === 'me' && obj.controller === 'user' && obj.type === 'users-permissions';
|
||||||
|
const enabled = isCallback || isRegister || role.type === 'root' || isInit || isPassword || isNewPassword || isMe;
|
||||||
|
|
||||||
if (!_.isEqual(currentRoles, added)) {
|
return Object.assign(obj, { enabled, policy: '' });
|
||||||
writePermissions(added);
|
};
|
||||||
|
|
||||||
|
// Retrieve roles
|
||||||
|
const roles = await strapi.query('role', 'users-permissions').find();
|
||||||
|
|
||||||
|
// We have to know the difference to add or remove
|
||||||
|
// the permissions entries in the database.
|
||||||
|
const toRemove = _.difference(actions, currentActions).map(splitted);
|
||||||
|
const toAdd = (permissions < 1 ? currentActions : _.difference(currentActions, actions))
|
||||||
|
.map(splitted);
|
||||||
|
|
||||||
|
// Execute request to update entries in database for each role.
|
||||||
|
await Promise.all(
|
||||||
|
roles.map(role =>
|
||||||
|
Promise.all(
|
||||||
|
toAdd
|
||||||
|
.map(action => defaultPolicy(action, role))
|
||||||
|
.map(action => strapi.query('permission', 'users-permissions')
|
||||||
|
.addPermission(Object.assign(action, { role: role.id || role._id }))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Promise.all(toRemove.map(action => strapi.query('permission', 'users-permissions').removePermission(action)))
|
||||||
|
);
|
||||||
|
|
||||||
|
this.writeActions(currentActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
@ -220,11 +223,40 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initialize: async function (cb) {
|
||||||
|
const roles = await strapi.query('role', 'users-permissions').count();
|
||||||
|
|
||||||
|
// It's has been already initialized.
|
||||||
|
if (roles > 0) {
|
||||||
|
return await this.updatePermissions(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create two first default roles.
|
||||||
|
await Promise.all([
|
||||||
|
strapi.query('role', 'users-permissions').createRole({
|
||||||
|
name: 'Administrator',
|
||||||
|
description: 'These users have all access in the project.',
|
||||||
|
type: 'root'
|
||||||
|
}),
|
||||||
|
strapi.query('role', 'users-permissions').createRole({
|
||||||
|
name: 'Guest',
|
||||||
|
description: 'Default role given to unauthenticated user.',
|
||||||
|
type: 'guest'
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await this.updatePermissions(cb);
|
||||||
|
},
|
||||||
|
|
||||||
updateRole: async (roleId, body) => {
|
updateRole: async (roleId, body) => {
|
||||||
const appRoles = strapi.plugins['users-permissions'].config.roles
|
const appRoles = strapi.plugins['users-permissions'].config.roles
|
||||||
const updatedRole = _.pick(body, ['name', 'description', 'permissions']);
|
const updatedRole = _.pick(body, ['name', 'description', 'permissions']);
|
||||||
_.set(appRoles, [roleId], updatedRole);
|
_.set(appRoles, [roleId], updatedRole);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - Call request.
|
||||||
|
// Role.update()
|
||||||
|
|
||||||
module.exports.writePermissions(appRoles);
|
module.exports.writePermissions(appRoles);
|
||||||
|
|
||||||
const currentUsers = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', {
|
const currentUsers = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', {
|
||||||
@ -248,11 +280,13 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
writePermissions: (data) => {
|
writeActions: (data) => {
|
||||||
const roleConfigPath = module.exports.getRoleConfigPath();
|
const actionsPath = path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'actions.json');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(roleConfigPath, stringify({ roles: data }, null, 2), 'utf8');
|
// Rewrite actions.json file.
|
||||||
|
fs.writeFileSync(actionsPath, JSON.stringify({ actions: data }), 'utf8');
|
||||||
|
// Set value to AST to avoid restart.
|
||||||
_.set(strapi.plugins['users-permissions'], 'config.roles', data);
|
_.set(strapi.plugins['users-permissions'], 'config.roles', data);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
strapi.log.error(err);
|
strapi.log.error(err);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user