2017-11-06 11:14:43 +01:00
|
|
|
|
'use strict';
|
|
|
|
|
|
2017-11-17 14:22:59 +01:00
|
|
|
|
const fs = require('fs')
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const stringify = JSON.stringify;
|
2017-11-16 17:59:41 +01:00
|
|
|
|
const _ = require('lodash');
|
2018-01-05 16:19:53 +01:00
|
|
|
|
const request = require('request');
|
2017-12-07 18:16:18 +01:00
|
|
|
|
|
2017-11-06 11:14:43 +01:00
|
|
|
|
/**
|
|
|
|
|
* UsersPermissions.js service
|
|
|
|
|
*
|
|
|
|
|
* @description: A set of functions similar to controller's actions to avoid code duplication.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
2017-11-27 16:49:56 +01:00
|
|
|
|
createRole: (role) => {
|
2017-12-07 18:16:18 +01:00
|
|
|
|
const appRoles = strapi.plugins['users-permissions'].config.roles;
|
2017-12-08 14:40:42 +01:00
|
|
|
|
const highestId = Math.max(...Object.keys(appRoles).map(Number)) + 1;
|
2017-11-27 16:49:56 +01:00
|
|
|
|
const newRole = _.pick(role, ['name', 'description', 'permissions']);
|
|
|
|
|
|
2017-11-27 17:02:45 +01:00
|
|
|
|
_.set(appRoles, highestId.toString(), newRole);
|
2017-11-27 16:49:56 +01:00
|
|
|
|
|
2017-12-01 16:06:16 +01:00
|
|
|
|
_.forEach(role.users, (user) => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.updateUserRole(user, highestId);
|
2017-12-01 16:06:16 +01:00
|
|
|
|
});
|
|
|
|
|
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.writePermissions(appRoles);
|
2017-11-27 17:02:45 +01:00
|
|
|
|
},
|
|
|
|
|
|
2017-12-01 16:06:16 +01:00
|
|
|
|
deleteRole: async (roleId) => {
|
2017-12-07 18:16:18 +01:00
|
|
|
|
const appRoles = strapi.plugins['users-permissions'].config.roles
|
2017-11-27 17:50:51 +01:00
|
|
|
|
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.writePermissions(_.omit(appRoles, [roleId]));
|
2017-12-01 16:06:16 +01:00
|
|
|
|
|
|
|
|
|
const users = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', {
|
|
|
|
|
role: roleId
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
_.forEach(users, (user) => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.updateUserRole(user, '1');
|
2017-12-01 16:06:16 +01:00
|
|
|
|
});
|
2017-11-27 16:49:56 +01:00
|
|
|
|
},
|
|
|
|
|
|
2018-01-05 16:19:53 +01:00
|
|
|
|
getPlugins: (plugin, lang = 'en') => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
request({
|
|
|
|
|
uri: `https://marketplace.strapi.io/plugins?lang=${lang}`,
|
|
|
|
|
json: true,
|
|
|
|
|
headers: {
|
|
|
|
|
'cache-control': 'max-age=3600'
|
|
|
|
|
}
|
|
|
|
|
}, (err, response, body) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
return reject(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resolve(body);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getActions: (plugins = []) => {
|
2017-11-17 14:22:59 +01:00
|
|
|
|
const generateActions = (data) => (
|
|
|
|
|
Object.keys(data).reduce((acc, key) => {
|
|
|
|
|
acc[key] = { enabled: false, policy: '' };
|
2017-11-06 11:14:43 +01:00
|
|
|
|
|
2017-11-17 14:22:59 +01:00
|
|
|
|
return acc;
|
|
|
|
|
}, {}));
|
|
|
|
|
|
2017-11-17 17:49:50 +01:00
|
|
|
|
const appControllers = Object.keys(strapi.api || {}).reduce((acc, key) => {
|
2017-11-17 14:22:59 +01:00
|
|
|
|
acc.controllers[key] = generateActions(strapi.api[key].controllers[key]);
|
2017-11-16 17:59:41 +01:00
|
|
|
|
|
|
|
|
|
return acc;
|
2017-11-17 12:14:12 +01:00
|
|
|
|
}, { controllers: {} });
|
|
|
|
|
|
|
|
|
|
const pluginsPermissions = Object.keys(strapi.plugins).reduce((acc, key) => {
|
2017-11-20 14:35:24 +01:00
|
|
|
|
acc[key] = Object.keys(strapi.plugins[key].controllers).reduce((obj, k) => {
|
2017-11-17 14:22:59 +01:00
|
|
|
|
obj.controllers[k] = generateActions(strapi.plugins[key].controllers[k]);
|
2017-11-17 12:14:12 +01:00
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
2018-01-05 16:19:53 +01:00
|
|
|
|
}, { controllers: {}, information: plugins.find(plugin => plugin.id === key) || {} });
|
2017-11-17 12:14:12 +01:00
|
|
|
|
|
|
|
|
|
return acc;
|
|
|
|
|
}, {});
|
2017-11-16 17:59:41 +01:00
|
|
|
|
|
|
|
|
|
const permissions = {
|
|
|
|
|
application: {
|
|
|
|
|
controllers: appControllers.controllers,
|
2017-11-17 12:14:12 +01:00
|
|
|
|
},
|
2017-11-16 17:59:41 +01:00
|
|
|
|
};
|
|
|
|
|
|
2017-12-11 11:14:07 +01:00
|
|
|
|
return _.merge(permissions, pluginsPermissions);;
|
2017-11-17 16:36:57 +01:00
|
|
|
|
},
|
2017-11-17 14:22:59 +01:00
|
|
|
|
|
2018-01-05 16:19:53 +01:00
|
|
|
|
getRole: async (roleId, plugins) => {
|
|
|
|
|
const appRoles = strapi.plugins['users-permissions'].config.roles;
|
|
|
|
|
|
2017-11-30 16:52:28 +01:00
|
|
|
|
appRoles[roleId].users = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', { role: roleId }));
|
2017-11-27 17:50:51 +01:00
|
|
|
|
|
2018-01-05 16:19:53 +01:00
|
|
|
|
Object.keys(appRoles[roleId].permissions)
|
|
|
|
|
.filter(name => name !== 'application')
|
|
|
|
|
.map(name => {
|
|
|
|
|
appRoles[roleId].permissions[name].information = plugins.find(plugin => plugin.id === name) || {};
|
|
|
|
|
});
|
|
|
|
|
|
2017-11-30 16:52:28 +01:00
|
|
|
|
return appRoles[roleId];
|
2017-11-27 17:50:51 +01:00
|
|
|
|
},
|
|
|
|
|
|
2017-11-30 12:27:04 +01:00
|
|
|
|
getRoles: async () => {
|
2017-12-07 18:31:19 +01:00
|
|
|
|
const roles = strapi.plugins['users-permissions'].config.roles;
|
2017-11-30 12:27:04 +01:00
|
|
|
|
const usersCount = await strapi.query('user', 'users-permissions').countByRoles();
|
2017-11-27 16:04:57 +01:00
|
|
|
|
const formattedRoles = Object.keys(roles).reduce((acc, key) => {
|
|
|
|
|
const role = _.pick(roles[key], ['name', 'description']);
|
|
|
|
|
|
|
|
|
|
_.set(role, 'id', key);
|
2017-11-30 16:52:28 +01:00
|
|
|
|
_.set(role, 'nb_users', _.get(_.find(usersCount, { _id: parseFloat(key) }), 'total', 0));
|
2017-11-27 16:04:57 +01:00
|
|
|
|
acc.push(role);
|
|
|
|
|
|
|
|
|
|
return acc;
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
return formattedRoles;
|
|
|
|
|
},
|
|
|
|
|
|
2017-11-30 16:34:43 +01:00
|
|
|
|
getRoutes: async () => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
const apiRoutes = strapi.api ? Object.keys(strapi.api).reduce((acc, current) => {
|
2017-12-07 18:16:18 +01:00
|
|
|
|
return acc.concat(strapi.api[current].config.routes);
|
2017-12-08 10:42:45 +01:00
|
|
|
|
}, []) : [];
|
2017-12-07 18:16:18 +01:00
|
|
|
|
|
|
|
|
|
const pluginsRoutes = Object.keys(strapi.plugins).reduce((acc, current) => {
|
2017-11-30 16:34:43 +01:00
|
|
|
|
acc[current] = strapi.plugins[current].config.routes;
|
|
|
|
|
|
|
|
|
|
return acc;
|
2017-12-07 18:16:18 +01:00
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
return _.merge({ application: apiRoutes}, pluginsRoutes);
|
2017-11-30 16:34:43 +01:00
|
|
|
|
},
|
|
|
|
|
|
2017-11-17 16:36:57 +01:00
|
|
|
|
getRoleConfigPath: () => (
|
|
|
|
|
path.join(
|
|
|
|
|
strapi.config.appPath,
|
|
|
|
|
'plugins',
|
|
|
|
|
'users-permissions',
|
|
|
|
|
'config',
|
|
|
|
|
'roles.json',
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
updateData: (data, diff = 'unset') => {
|
|
|
|
|
const dataToCompare = strapi.plugins['users-permissions'].services.userspermissions.getActions();
|
|
|
|
|
|
|
|
|
|
_.forEach(data, (roleData, roleId) => {
|
|
|
|
|
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]);
|
|
|
|
|
}
|
2017-12-07 18:16:18 +01:00
|
|
|
|
} 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';
|
2018-01-11 17:13:09 +01:00
|
|
|
|
const isNewPassword = actionName === 'changePassword' && controllerName === 'auth' && pluginName === 'users-permissions' && roleId === '1';
|
2017-12-07 18:16:18 +01:00
|
|
|
|
const isInit = actionName === 'init' && controllerName === 'userspermissions';
|
2018-01-11 17:13:09 +01:00
|
|
|
|
const isMe = actionName === 'me' && controllerName === 'user' && pluginName === 'users-permissions';
|
|
|
|
|
const enabled = isCallback || isRegister || roleId === '0' || isInit || isPassword || isNewPassword || isMe;
|
2017-12-07 18:16:18 +01:00
|
|
|
|
|
|
|
|
|
_.set(data, [roleId, 'permissions', pluginName, 'controllers', controllerName, actionName], { enabled, policy: '' })
|
2017-11-17 16:36:57 +01:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
},
|
|
|
|
|
|
2017-11-20 14:35:24 +01:00
|
|
|
|
updatePermissions: async (cb) => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
const appActions = module.exports.getActions();
|
|
|
|
|
const writePermissions = module.exports.writePermissions;
|
2017-12-07 18:16:18 +01:00
|
|
|
|
const currentRoles = strapi.plugins['users-permissions'].config.roles || {
|
|
|
|
|
'0': {
|
|
|
|
|
description: '',
|
|
|
|
|
name: 'Administrator',
|
|
|
|
|
permissions: {
|
|
|
|
|
application: {
|
|
|
|
|
controllers: {},
|
2017-12-07 10:16:36 +01:00
|
|
|
|
},
|
|
|
|
|
},
|
2017-12-07 18:16:18 +01:00
|
|
|
|
},
|
|
|
|
|
'1': {
|
|
|
|
|
description: '',
|
|
|
|
|
name: 'Guest',
|
|
|
|
|
permissions: {
|
|
|
|
|
application: {
|
|
|
|
|
controllers: {},
|
2017-12-07 10:16:36 +01:00
|
|
|
|
},
|
|
|
|
|
},
|
2017-12-07 18:16:18 +01:00
|
|
|
|
},
|
|
|
|
|
};
|
2017-12-07 10:16:36 +01:00
|
|
|
|
|
2017-12-08 10:42:45 +01:00
|
|
|
|
const remove = await module.exports.updateData(_.cloneDeep(currentRoles));
|
|
|
|
|
const added = await module.exports.updateData(_.cloneDeep(remove), 'set');
|
2017-11-17 16:36:57 +01:00
|
|
|
|
|
|
|
|
|
if (!_.isEqual(currentRoles, added)) {
|
|
|
|
|
writePermissions(added);
|
2017-11-17 14:22:59 +01:00
|
|
|
|
}
|
2017-11-20 14:35:24 +01:00
|
|
|
|
|
|
|
|
|
if (cb) {
|
|
|
|
|
cb();
|
|
|
|
|
}
|
2017-11-17 16:36:57 +01:00
|
|
|
|
},
|
2017-11-17 14:22:59 +01:00
|
|
|
|
|
2017-12-01 16:06:16 +01:00
|
|
|
|
updateRole: async (roleId, body) => {
|
2017-12-07 18:16:18 +01:00
|
|
|
|
const appRoles = strapi.plugins['users-permissions'].config.roles
|
2017-11-27 17:50:51 +01:00
|
|
|
|
const updatedRole = _.pick(body, ['name', 'description', 'permissions']);
|
|
|
|
|
_.set(appRoles, [roleId], updatedRole);
|
|
|
|
|
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.writePermissions(appRoles);
|
2017-12-01 16:06:16 +01:00
|
|
|
|
|
2017-12-05 16:44:54 +01:00
|
|
|
|
const currentUsers = await strapi.query('user', 'users-permissions').find(strapi.utils.models.convertParams('user', {
|
2017-12-01 16:06:16 +01:00
|
|
|
|
role: roleId
|
2017-12-05 16:44:54 +01:00
|
|
|
|
}));
|
2017-12-07 18:40:55 +01:00
|
|
|
|
const userToAdd = _.differenceBy(body.users, currentUsers.toJSON ? currentUsers.toJSON() : currentUsers, 'id');
|
|
|
|
|
const userToRemove = _.differenceBy(currentUsers.toJSON ? currentUsers.toJSON() : currentUsers, body.users, 'id');
|
2017-12-05 16:44:54 +01:00
|
|
|
|
|
|
|
|
|
_.forEach(userToAdd, (user) => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.updateUserRole(user, roleId);
|
2017-12-05 16:44:54 +01:00
|
|
|
|
});
|
|
|
|
|
_.forEach(userToRemove, (user) => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
module.exports.updateUserRole(user, '1');
|
2017-12-01 16:06:16 +01:00
|
|
|
|
});
|
2017-11-27 17:50:51 +01:00
|
|
|
|
},
|
|
|
|
|
|
2017-12-07 10:16:36 +01:00
|
|
|
|
updateUserRole: async (user, role) => {
|
2017-12-07 18:16:15 +01:00
|
|
|
|
strapi.query('user', 'users-permissions').update({
|
2017-12-07 10:16:36 +01:00
|
|
|
|
_id: user._id || user.id,
|
|
|
|
|
role: role.toString()
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2017-11-17 16:36:57 +01:00
|
|
|
|
writePermissions: (data) => {
|
2017-12-08 10:42:45 +01:00
|
|
|
|
const roleConfigPath = module.exports.getRoleConfigPath();
|
2017-11-17 16:36:57 +01:00
|
|
|
|
|
|
|
|
|
try {
|
2017-12-07 18:16:18 +01:00
|
|
|
|
fs.writeFileSync(roleConfigPath, stringify({ roles: data }, null, 2), 'utf8');
|
2017-12-12 15:13:27 +01:00
|
|
|
|
_.set(strapi.plugins['users-permissions'], 'config.roles', data);
|
2017-11-17 16:36:57 +01:00
|
|
|
|
} catch(err) {
|
|
|
|
|
strapi.log.error(err);
|
|
|
|
|
}
|
2017-12-01 16:06:16 +01:00
|
|
|
|
},
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
|
|
|
|
syncSchema: (cb) => {
|
|
|
|
|
const Model = strapi.plugins['users-permissions'].models.user;
|
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
if (Model.orm !== 'bookshelf') {
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const tableName = Model.collectionName;
|
|
|
|
|
|
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
|
strapi.connections[Model.connection].schema.hasTable(tableName)
|
|
|
|
|
.then(exist => {
|
|
|
|
|
if (!exist) {
|
|
|
|
|
strapi.log.warn(`
|
2018-01-04 16:36:56 +01:00
|
|
|
|
⚠️ TABLE \`${tableName}\` DOESN'T EXIST
|
|
|
|
|
|
|
|
|
|
1️⃣ EXECUTE THE FOLLOWING SQL QUERY
|
|
|
|
|
|
|
|
|
|
CREATE TABLE "${tableName}" (
|
2018-01-11 15:00:34 +01:00
|
|
|
|
id integer NOT NULL,
|
|
|
|
|
username text,
|
|
|
|
|
email text,
|
|
|
|
|
role text,
|
|
|
|
|
"resetPasswordToken" text,
|
|
|
|
|
password text,
|
|
|
|
|
updated_at timestamp with time zone,
|
|
|
|
|
created_at timestamp with time zone
|
2018-01-04 16:36:56 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
2️⃣ RESTART YOUR SERVER
|
2018-01-11 15:00:34 +01:00
|
|
|
|
`);
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
strapi.stop();
|
|
|
|
|
}
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
resolve();
|
2018-01-04 16:36:56 +01:00
|
|
|
|
});
|
2018-01-11 15:00:34 +01:00
|
|
|
|
})
|
|
|
|
|
.then(() => {
|
|
|
|
|
const attributes = _.cloneDeep(Model.attributes);
|
|
|
|
|
attributes.id = {
|
|
|
|
|
type: 'integer'
|
|
|
|
|
};
|
|
|
|
|
attributes.updated_at = attributes.created_at = {
|
|
|
|
|
type: 'timestamp with time zone'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let commands = '';
|
|
|
|
|
|
|
|
|
|
const columnExist = (description, attribute) => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
strapi.connections[Model.connection].schema.hasColumn(tableName, attribute)
|
|
|
|
|
.then(exist => {
|
|
|
|
|
if (!exist) {
|
|
|
|
|
if (description.type === 'string') {
|
|
|
|
|
description.type = 'text';
|
2018-01-04 16:36:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
commands += `\r\nALTER TABLE "${tableName}" ADD "${attribute}" ${description.type};`;
|
|
|
|
|
}
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
resolve();
|
|
|
|
|
});
|
2018-01-04 16:36:56 +01:00
|
|
|
|
});
|
2018-01-11 15:00:34 +01:00
|
|
|
|
};
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
const testsColumns = Object.entries(attributes).map(([attribute, description]) => columnExist(description, attribute));
|
|
|
|
|
Promise.all(testsColumns)
|
|
|
|
|
.then(() => {
|
|
|
|
|
if (!_.isEmpty(commands)) {
|
|
|
|
|
strapi.log.warn(`
|
2018-01-04 16:36:56 +01:00
|
|
|
|
⚠️ TABLE \`${tableName}\` HAS MISSING COLUMNS
|
|
|
|
|
|
|
|
|
|
1️⃣ EXECUTE THE FOLLOWING SQL QUERIES
|
|
|
|
|
${commands}
|
|
|
|
|
|
|
|
|
|
2️⃣ RESTART YOUR SERVER
|
2018-01-11 15:00:34 +01:00
|
|
|
|
`);
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
strapi.stop();
|
|
|
|
|
}
|
2018-01-04 16:36:56 +01:00
|
|
|
|
|
2018-01-11 15:00:34 +01:00
|
|
|
|
cb();
|
2018-01-04 16:36:56 +01:00
|
|
|
|
});
|
2018-01-11 15:00:34 +01:00
|
|
|
|
});
|
2018-01-04 16:36:56 +01:00
|
|
|
|
}
|
2017-11-06 11:14:43 +01:00
|
|
|
|
};
|