Server can start

This commit is contained in:
Alexandre Bodin 2021-06-22 17:13:11 +02:00
parent a992a73b2e
commit 64c1e1f21a
33 changed files with 313 additions and 212 deletions

View File

@ -38,6 +38,7 @@ const syncAuthSettings = async () => {
};
module.exports = async () => {
registerAdminConditions();
registerPermissionActions();
@ -45,9 +46,12 @@ module.exports = async () => {
const userService = getService('user');
const roleService = getService('role');
await userService.migrateUsers();
// await userService.migrateUsers();
await roleService.createRolesIfNoneExist();
return;
await roleService.resetSuperAdminPermissions();
await roleService.displayWarningIfNoSuperAdmin();

View File

@ -86,7 +86,7 @@ module.exports = {
return ctx.notFound('role.notFound');
}
const permissions = await permissionService.find({ role: role.id, _limit: -1 });
const permissions = await permissionService.find({ where: { role: { id: role.id } } });
const sanitizedPermissions = permissions.map(permissionService.sanitizePermission);
ctx.body = {

View File

@ -80,7 +80,7 @@ module.exports = {
if (_.has(input, 'email')) {
const uniqueEmailCheck = await strapi.admin.services.user.exists({
id_ne: id,
id: { $ne: id },
email: input.email,
});

View File

@ -17,7 +17,9 @@ module.exports = strapi => ({
if (isValid) {
// request is made by an admin
const admin = await strapi.query('user', 'admin').findOne({ id: payload.id }, ['roles']);
const admin = await strapi
.query('strapi::user')
.findOne({ where: { id: payload.id }, populate: ['roles'] });
if (!admin || !(admin.isActive === true)) {
return ctx.forbidden('Invalid credentials');

View File

@ -48,8 +48,10 @@ module.exports = {
},
role: {
configurable: false,
model: 'role',
plugin: 'admin',
type: 'relation',
relation: 'manyToOne',
inversedBy: 'permissions',
target: 'strapi::role',
},
},
};

View File

@ -42,15 +42,17 @@ module.exports = {
},
users: {
configurable: false,
collection: 'user',
via: 'roles',
plugin: 'admin',
type: 'relation',
relation: 'manyToMany',
mappedBy: 'roles',
target: 'strapi::user',
},
permissions: {
configurable: false,
plugin: 'admin',
collection: 'permission',
via: 'role',
type: 'relation',
relation: 'oneToMany',
mappedBy: 'role',
target: 'strapi::permission',
},
},
};

View File

@ -71,13 +71,14 @@ module.exports = {
private: true,
},
roles: {
collection: 'role',
collectionName: 'strapi_users_roles',
via: 'users',
dominant: true,
plugin: 'admin',
configurable: false,
private: true,
type: 'relation',
relation: 'manyToMany',
inversedBy: 'users',
target: 'strapi::role',
// FIXME: Allow setting this
collectionName: 'strapi_users_roles',
},
blocked: {
type: 'boolean',

View File

@ -29,7 +29,7 @@ describe('Permission Service', () => {
},
});
await permissionService.find({ role: 1 });
await permissionService.find({ where: { role: { id: 1 } } });
expect(find).toHaveBeenCalledWith({ role: 1 }, []);
});

View File

@ -26,7 +26,7 @@ const validatePassword = (password, hash) => bcrypt.compare(password, hash);
* @param {string} options.password
*/
const checkCredentials = async ({ email, password }) => {
const user = await strapi.query('user', 'admin').findOne({ email });
const user = await strapi.query('strapi::user').findOne({ where: { email } });
if (!user || !user.password) {
return [null, false, { message: 'Invalid credentials' }];
@ -51,7 +51,7 @@ const checkCredentials = async ({ email, password }) => {
* @param {string} param.email user email for which to reset the password
*/
const forgotPassword = async ({ email } = {}) => {
const user = await strapi.query('user', 'admin').findOne({ email, isActive: true });
const user = await strapi.query('strapi::user').findOne({ where: { email, isActive: true } });
if (!user) {
return;
@ -91,8 +91,8 @@ const forgotPassword = async ({ email } = {}) => {
*/
const resetPassword = async ({ resetPasswordToken, password } = {}) => {
const matchingUser = await strapi
.query('user', 'admin')
.findOne({ resetPasswordToken, isActive: true });
.query('strapi::user')
.findOne({ where: { resetPasswordToken, isActive: true } });
if (!matchingUser) {
throw strapi.errors.badRequest();

View File

@ -26,9 +26,11 @@ const permissionDomain = require('../../domain/permission/index');
* @returns {Promise<array>}
*/
const deleteByRolesIds = async rolesIds => {
const deletedPermissions = await strapi
.query('permission', 'admin')
.delete({ role_in: rolesIds });
const deletedPermissions = await strapi.query('strapi::permission').delete({
where: {
role: { id: rolesIds },
},
});
return permissionDomain.toPermission(deletedPermissions);
};
@ -39,7 +41,9 @@ const deleteByRolesIds = async rolesIds => {
* @returns {Promise<array>}
*/
const deleteByIds = async ids => {
const deletedPermissions = await strapi.query('permission', 'admin').delete({ id_in: ids });
const deletedPermissions = await strapi
.query('strapi::permission')
.delete({ where: { id: ids } });
return permissionDomain.toPermission(deletedPermissions);
};
@ -50,7 +54,9 @@ const deleteByIds = async ids => {
* @returns {Promise<*[]|*>}
*/
const createMany = async permissions => {
const createdPermissions = await strapi.query('permission', 'admin').createMany(permissions);
const createdPermissions = await strapi
.query('strapi::permission')
.createMany({ data: permissions });
return permissionDomain.toPermission(createdPermissions);
};
@ -62,7 +68,9 @@ const createMany = async permissions => {
* @param attributes
*/
const update = async (params, attributes) => {
const updatedPermissions = await strapi.query('permission', 'admin').update(params, attributes);
const updatedPermissions = await strapi
.query('strapi::permission')
.update({ where: params, data: attributes });
return permissionDomain.toPermission(updatedPermissions);
};
@ -73,7 +81,7 @@ const update = async (params, attributes) => {
* @returns {Promise<Permission[]>}
*/
const find = async (params = {}) => {
const rawPermissions = await strapi.query('permission', 'admin').find(params, []);
const rawPermissions = await strapi.query('strapi::permission').findMany(params);
return permissionDomain.toPermission(rawPermissions);
};
@ -88,7 +96,7 @@ const findUserPermissions = async ({ roles }) => {
return [];
}
return find({ role_in: roles.map(prop('id')), _limit: -1 });
return find({ role: { id: roles.map(prop('id')) } });
};
const filterPermissionsToRemove = async permissions => {
@ -135,6 +143,7 @@ const cleanPermissionsInDatabase = async () => {
for (let page = 1; page * pageSize < total; page++) {
// 1. Find invalid permissions and collect their ID to delete them later
// FIXME: to impl / reimpl
const { pagination, results } = await strapi
.query('permission', 'admin')
.findPage({ page, pageSize }, []);
@ -183,7 +192,11 @@ const ensureBoundPermissionsInDatabase = async () => {
}
const contentTypes = Object.values(strapi.contentTypes);
const editorRole = await strapi.query('role', 'admin').findOne({ code: EDITOR_CODE }, []);
const editorRole = await strapi.query('strapi::role').findOne({
where: {
code: EDITOR_CODE,
},
});
if (isNil(editorRole)) {
return;

View File

@ -85,7 +85,7 @@ const create = async attributes => {
code: attributes.code || autoGeneratedCode,
};
return strapi.query('role', 'admin').create(rolesWithCode);
return strapi.query('strapi::role').create({ data: rolesWithCode });
};
/**
@ -95,7 +95,7 @@ const create = async attributes => {
* @returns {Promise<role>}
*/
const findOne = (params = {}, populate = []) => {
return strapi.query('role', 'admin').findOne(params, populate);
return strapi.query('strapi::role').findOne({ where: params, populate });
};
/**
@ -105,7 +105,7 @@ const findOne = (params = {}, populate = []) => {
* @returns {Promise<role>}
*/
const findOneWithUsersCount = async (params = {}, populate = []) => {
const role = await strapi.query('role', 'admin').findOne(params, populate);
const role = await strapi.query('strapi::role').findOne({ where: params, populate });
if (role) {
role.usersCount = await getUsersCount(role.id);
@ -121,7 +121,7 @@ const findOneWithUsersCount = async (params = {}, populate = []) => {
* @returns {Promise<array>}
*/
const find = (params = {}, populate = []) => {
return strapi.query('role', 'admin').find(params, populate);
return strapi.query('strapi::role').findMany({ where: params, populate });
};
/**
@ -129,7 +129,7 @@ const find = (params = {}, populate = []) => {
* @returns {Promise<array>}
*/
const findAllWithUsersCount = async (populate = []) => {
const roles = await strapi.query('role', 'admin').find({ _limit: -1 }, populate);
const roles = await strapi.query('strapi::role').findMany({ populate });
for (let role of roles) {
role.usersCount = await getUsersCount(role.id);
}
@ -149,7 +149,7 @@ const update = async (params, attributes) => {
if (_.has(params, 'id') && _.has(sanitizedAttributes, 'name')) {
const alreadyExists = await exists({
name: sanitizedAttributes.name,
id_ne: params.id,
id: { $ne: params.id },
});
if (alreadyExists) {
throw strapi.errors.badRequest('ValidationError', {
@ -160,7 +160,7 @@ const update = async (params, attributes) => {
}
}
return strapi.query('role', 'admin').update(params, sanitizedAttributes);
return strapi.query('strapi::role').update({ where: params, data: sanitizedAttributes });
};
/**
@ -168,8 +168,8 @@ const update = async (params, attributes) => {
* @param params query params to find the role
* @returns {Promise<boolean>}
*/
const exists = async params => {
const foundCount = await strapi.query('role', 'admin').count(params);
const exists = async (params = {}) => {
const foundCount = await strapi.query('strapi::role').count({ where: params });
return foundCount > 0;
};
@ -180,7 +180,7 @@ const exists = async params => {
* @returns {Promise<number>}
*/
const count = async (params = {}) => {
return strapi.query('role', 'admin').count(params);
return strapi.query('strapi::role').count(params);
};
/**
@ -213,7 +213,7 @@ const deleteByIds = async (ids = []) => {
await getService('permission').deleteByRolesIds(ids);
let deletedRoles = await strapi.query('role', 'admin').delete({ id_in: ids });
let deletedRoles = await strapi.query('strapi::role').delete({ where: { id: ids } });
if (!Array.isArray(deletedRoles)) {
deletedRoles = [deletedRoles];
@ -227,7 +227,7 @@ const deleteByIds = async (ids = []) => {
* @param roleId
*/
const getUsersCount = async roleId => {
return strapi.query('user', 'admin').count({ roles: [roleId] });
return strapi.query('strapi::user').count({ where: { roles: { id: roleId } } });
};
/** Returns admin role
@ -348,8 +348,8 @@ const assignPermissions = async (roleId, permissions = []) => {
.map(permissionDomain.create);
const existingPermissions = await getService('permission').find({
role: roleId,
_limit: -1,
where: { role: { id: roleId } },
populate: ['role'],
});
const permissionsToAdd = differenceWith(
@ -368,6 +368,7 @@ const assignPermissions = async (roleId, permissions = []) => {
await getService('permission').deleteByIds(permissionsToDelete.map(prop('id')));
}
if (permissionsToAdd.length > 0) {
const createdPermissions = await addPermissions(roleId, permissionsToAdd);
permissionsToReturn.push(...createdPermissions.map(p => ({ ...p, role: p.role.id })));

View File

@ -35,7 +35,8 @@ const create = async attributes => {
}
const user = createUser(userInfo);
const createdUser = await strapi.query('user', 'admin').create(user);
const createdUser = await strapi.query('strapi::user').create({ data: user });
await strapi.admin.services.metrics.sendDidInviteUser();
@ -78,16 +79,19 @@ const updateById = async (id, attributes) => {
if (_.has(attributes, 'password')) {
const hashedPassword = await strapi.admin.services.auth.hashPassword(attributes.password);
return strapi.query('user', 'admin').update(
{ id },
{
return strapi.query('strapi::user').update({
where: { id },
data: {
...attributes,
password: hashedPassword,
}
);
},
});
}
return strapi.query('user', 'admin').update({ id }, attributes);
return strapi.query('strapi::user').update({
where: { id },
data: attributes,
});
};
/**
@ -130,7 +134,7 @@ const isLastSuperAdminUser = async userId => {
* @returns {Promise<boolean>}
*/
const exists = async (attributes = {}) => {
return (await strapi.query('user', 'admin').count(attributes)) > 0;
return (await strapi.query('strapi::user').count({ where: attributes })) > 0;
};
/**
@ -139,7 +143,7 @@ const exists = async (attributes = {}) => {
* @returns {Promise<registrationInfo>} - Returns user email, firstname and lastname
*/
const findRegistrationInfo = async registrationToken => {
const user = await strapi.query('user', 'admin').findOne({ registrationToken });
const user = await strapi.query('strapi::user').findOne({ where: { registrationToken } });
if (!user) {
return undefined;
@ -155,7 +159,7 @@ const findRegistrationInfo = async registrationToken => {
* @param {Object} params.userInfo user info
*/
const register = async ({ registrationToken, userInfo }) => {
const matchingUser = await strapi.query('user', 'admin').findOne({ registrationToken });
const matchingUser = await strapi.query('strapi::user').findOne({ where: { registrationToken } });
if (!matchingUser) {
throw strapi.errors.badRequest('Invalid registration info');
@ -173,24 +177,26 @@ const register = async ({ registrationToken, userInfo }) => {
/**
* Find one user
*/
const findOne = async (params, populate) => {
return strapi.query('user', 'admin').findOne(params, populate);
const findOne = async (where = {}, populate) => {
return strapi.query('strapi::user').findOne({ where, populate });
};
/** Find many users (paginated)
* @param query
* @returns {Promise<user>}
*/
// FIXME: to impl
const findPage = async query => {
return strapi.query('user', 'admin').findPage(query);
return strapi.query('strapi::user').findPage(query);
};
/** Search for many users (paginated)
* @param query
* @returns {Promise<user>}
*/
// FIXME: to impl
const searchPage = async query => {
return strapi.query('user', 'admin').searchPage(query);
return strapi.query('strapi::user').searchPage(query);
};
/** Delete a user
@ -199,7 +205,11 @@ const searchPage = async query => {
*/
const deleteById = async id => {
// Check at least one super admin remains
const userToDelete = await strapi.query('user', 'admin').findOne({ id }, ['roles']);
const userToDelete = await strapi.query('strapi::user').findOne({
where: { id },
populate: ['roles'],
});
if (userToDelete) {
if (userToDelete.roles.some(r => r.code === SUPER_ADMIN_CODE)) {
const superAdminRole = await strapi.admin.services.role.getSuperAdminWithUsersCount();
@ -214,7 +224,7 @@ const deleteById = async id => {
return null;
}
return strapi.query('user', 'admin').delete({ id });
return strapi.query('strapi::user').delete({ where: { id } });
};
/** Delete a user
@ -224,9 +234,13 @@ const deleteById = async id => {
const deleteByIds = async ids => {
// Check at least one super admin remains
const superAdminRole = await strapi.admin.services.role.getSuperAdminWithUsersCount();
const nbOfSuperAdminToDelete = await strapi
.query('user', 'admin')
.count({ id_in: ids, roles: [superAdminRole.id] });
const nbOfSuperAdminToDelete = await strapi.query('strapi::user').count({
where: {
id: ids,
roles: { id: superAdminRole.id },
},
});
if (superAdminRole.usersCount === nbOfSuperAdminToDelete) {
throw strapi.errors.badRequest(
'ValidationError',
@ -234,30 +248,35 @@ const deleteByIds = async ids => {
);
}
return strapi.query('user', 'admin').delete({ id_in: ids });
return strapi.query('strapi::user').delete({
where: { id: ids },
});
};
/** Count the users that don't have any associated roles
* @returns {Promise<number>}
*/
// FIXME: test / cleanup
const countUsersWithoutRole = async () => {
const userModel = strapi.query('user', 'admin').model;
let count;
return strapi.query('strapi::user').count({ where: { roles: { id: { $null: true } } } });
if (userModel.orm === 'bookshelf') {
count = await strapi.query('user', 'admin').count({ roles_null: true });
} else if (userModel.orm === 'mongoose') {
count = await strapi.query('user', 'admin').model.countDocuments({
$or: [{ roles: { $exists: false } }, { roles: { $size: 0 } }],
});
} else {
const allRoles = await strapi.query('role', 'admin').find({ _limit: -1 });
count = await strapi.query('user', 'admin').count({
roles_nin: allRoles.map(r => r.id),
});
}
// const userModel = strapi.query('strapi::user').model;
// let count;
return count;
// if (userModel.orm === 'bookshelf') {
// count = await strapi.query('strapi::user').count({ roles_null: true });
// } else if (userModel.orm === 'mongoose') {
// count = await strapi.query('strapi::user').model.countDocuments({
// $or: [{ roles: { $exists: false } }, { roles: { $size: 0 } }],
// });
// } else {
// const allRoles = await strapi.query('role', 'admin').find({ _limit: -1 });
// count = await strapi.query('strapi::user').count({
// roles_nin: allRoles.map(r => r.id),
// });
// }
// return count;
};
/**
@ -265,34 +284,38 @@ const countUsersWithoutRole = async () => {
* @param params params used for the query
* @returns {Promise<number>}
*/
const count = async (params = {}) => {
return strapi.query('user', 'admin').count(params);
const count = async (where = {}) => {
return strapi.query('strapi::user').count({ where });
};
/** Assign some roles to several users
* @returns {undefined}
*/
// FIXME: to impl
const assignARoleToAll = async roleId => {
const userModel = strapi.query('user', 'admin').model;
await strapi.query('strapi::user').updateMany({
where: { roles: { id: { $null: true } } },
data: { roles: [roleId] },
});
if (userModel.orm === 'bookshelf') {
const assocTable = userModel.associations.find(a => a.alias === 'roles').tableCollectionName;
const userTable = userModel.collectionName;
const knex = strapi.connections[userModel.connection];
const usersIds = await knex
.select(`${userTable}.id`)
.from(userTable)
.leftJoin(assocTable, `${userTable}.id`, `${assocTable}.user_id`)
.where(`${assocTable}.role_id`, null)
.pluck(`${userTable}.id`);
if (usersIds.length > 0) {
const newRelations = usersIds.map(userId => ({ user_id: userId, role_id: roleId }));
await knex.insert(newRelations).into(assocTable);
}
} else if (userModel.orm === 'mongoose') {
await strapi.query('user', 'admin').model.updateMany({}, { roles: [roleId] });
}
// const userModel = strapi.query('strapi::user').model;
// if (userModel.orm === 'bookshelf') {
// const assocTable = userModel.associations.find(a => a.alias === 'roles').tableCollectionName;
// const userTable = userModel.collectionName;
// const knex = strapi.connections[userModel.connection];
// const usersIds = await knex
// .select(`${userTable}.id`)
// .from(userTable)
// .leftJoin(assocTable, `${userTable}.id`, `${assocTable}.user_id`)
// .where(`${assocTable}.role_id`, null)
// .pluck(`${userTable}.id`);
// if (usersIds.length > 0) {
// const newRelations = usersIds.map(userId => ({ user_id: userId, role_id: roleId }));
// await knex.insert(newRelations).into(assocTable);
// }
// } else if (userModel.orm === 'mongoose') {
// await strapi.query('strapi::user').model.updateMany({}, { roles: [roleId] });
// }
};
/** Display a warning if some users don't have at least one role
@ -306,26 +329,27 @@ const displayWarningIfUsersDontHaveRole = async () => {
}
};
const migrateUsers = async () => {
const someRolesExist = await strapi.admin.services.role.exists();
if (someRolesExist) {
return;
}
// FIXME: to delete
// const migrateUsers = async () => {
// const someRolesExist = await strapi.admin.services.role.exists();
// if (someRolesExist) {
// return;
// }
const userModel = strapi.query('user', 'admin').model;
// const userModel = strapi.query('strapi::user').model;
if (userModel.orm === 'bookshelf') {
await userModel
.query(qb => qb.where('blocked', false).orWhere('blocked', null))
.save({ isActive: true }, { method: 'update', patch: true, require: false });
await userModel
.query(qb => qb.where('blocked', true))
.save({ isActive: false }, { method: 'update', patch: true, require: false });
} else if (userModel.orm === 'mongoose') {
await userModel.updateMany({ blocked: { $in: [false, null] } }, { isActive: true });
await userModel.updateMany({ blocked: true }, { isActive: false });
}
};
// if (userModel.orm === 'bookshelf') {
// await userModel
// .query(qb => qb.where('blocked', false).orWhere('blocked', null))
// .save({ isActive: true }, { method: 'update', patch: true, require: false });
// await userModel
// .query(qb => qb.where('blocked', true))
// .save({ isActive: false }, { method: 'update', patch: true, require: false });
// } else if (userModel.orm === 'mongoose') {
// await userModel.updateMany({ blocked: { $in: [false, null] } }, { isActive: true });
// await userModel.updateMany({ blocked: true }, { isActive: false });
// }
// };
module.exports = {
create,
@ -343,6 +367,6 @@ module.exports = {
count,
assignARoleToAll,
displayWarningIfUsersDontHaveRole,
migrateUsers,
// migrateUsers,
resetPasswordByEmail,
};

View File

@ -64,17 +64,22 @@ const formatAttributes = model => {
}, {});
};
// FIXME: not needed
const formatAttribute = (key, attribute, { model }) => {
if (has('type', attribute)) return attribute;
return attribute;
if (isMediaAttribute(attribute)) {
return toMedia(attribute);
}
const relation = (model.associations || []).find(assoc => assoc.alias === key);
return toRelation(attribute, relation);
// if (has('type', attribute)) return attribute;
// if (isMediaAttribute(attribute)) {
// return toMedia(attribute);
// }
// const relation = (model.associations || []).find(assoc => assoc.alias === key);
// return toRelation(attribute, relation);
};
// FIXME: not needed
const toMedia = attribute => {
return {
type: 'media',
@ -85,6 +90,7 @@ const toMedia = attribute => {
};
};
// FIXME: not needed
const toRelation = (attribute, relation) => {
return {
...attribute,

View File

@ -28,7 +28,7 @@ const findCreatorRoles = entity => {
if (has(createdByPath, entity)) {
const creatorId = prop(createdByPath, entity);
return strapi.query('role', 'admin').find({ 'users.id': creatorId }, []);
return strapi.query('strapi::role').findMany({ where: { users: { id: creatorId } } });
}
return [];

View File

@ -46,37 +46,21 @@ const setModelConfiguration = async (key, value) => {
};
const deleteKey = key => {
return strapi.query('core_store').delete({ key: `plugin_content_manager_configuration_${key}` });
return strapi
.query('strapi::core-store')
.delete({ where: { key: `plugin_content_manager_configuration_${key}` } });
};
function findByKeyQuery({ model }, key) {
if (model.orm === 'mongoose') {
return model
.find({
key: { $regex: `${key}.*` },
})
.then(results => results.map(({ value }) => JSON.parse(value)));
}
return model
.query(qb => {
qb.where('key', 'like', `${key}%`);
})
.fetchAll()
.then(config => config && config.toJSON())
.then(results => results.map(({ value }) => JSON.parse(value)));
}
const findByKey = key => strapi.query('core_store').custom(findByKeyQuery)(key);
const moveKey = (oldKey, newKey) => {
return strapi.query('core_store').update(
{
key: `plugin_content_manager_configuration_${oldKey}`,
const findByKey = async key => {
const results = await strapi.query('strapi::core-store').findMany({
where: {
key: {
$startsWith: key,
},
},
{
key: `plugin_content_manager_configuration_${newKey}`,
}
);
});
return results.map(({ value }) => JSON.parse(value));
};
const getAllConfigurations = () => findByKey('plugin_content_manager_configuration');
@ -88,6 +72,5 @@ module.exports = {
setModelConfiguration,
deleteKey,
moveKey,
keys,
};

View File

@ -1,8 +1,19 @@
'use strict';
const _ = require('lodash/fp');
const types = require('./types');
const { createQueryBuilder } = require('./query');
const { createRepository } = require('./entity-repository');
const pickScalarAtttibutes = (metadata, data) => {
const { attributes } = metadata;
const scalarKeys = Object.keys(attributes).filter(key => types.isScalar(attributes[key].type));
const picker = _.pick(scalarKeys);
return Array.isArray(data) ? data.map(data => picker(data)) : picker(data);
};
const createEntityManager = db => {
const repoMap = {};
@ -29,7 +40,7 @@ const createEntityManager = db => {
},
// TODO: define api
async count(uid, params) {
async count(uid, params = {}) {
const qb = this.createQueryBuilder(uid).where(params.where);
const res = await qb
@ -58,8 +69,10 @@ const createEntityManager = db => {
// apply programatic defaults if any -> I think this should be handled outside of this layer as we might have some applicative rules in the entity service
// remove relation entries
const dataToInsert = pickScalarAtttibutes(db.metadata.get(uid), data);
const [id] = await this.createQueryBuilder(uid)
.insert(data)
.insert(dataToInsert)
.execute();
// create relation associations or move this to the entity service & call attach on the repo instead
@ -70,10 +83,15 @@ const createEntityManager = db => {
async createMany(uid, params) {
const { data } = params;
// pick scalar fields only
const dataToInsert = pickScalarAtttibutes(db.metadata.get(uid), data);
const ids = await this.createQueryBuilder(uid)
.insert(data)
.insert(dataToInsert)
.execute();
// TODO: create relation links
return ids.map(id => ({ id }));
},
@ -82,9 +100,11 @@ const createEntityManager = db => {
async update(uid, params) {
const { where, data } = params;
const dataToUpdate = pickScalarAtttibutes(db.metadata.get(uid), data);
/*const r =*/ await this.createQueryBuilder(uid)
.where(where)
.update(data)
.update(dataToUpdate)
.execute();
return {};
@ -93,9 +113,11 @@ const createEntityManager = db => {
async updateMany(uid, params) {
const { where, data } = params;
const dataToUpdate = pickScalarAtttibutes(db.metadata.get(uid), data);
return this.createQueryBuilder(uid)
.where(where)
.update(data)
.update(dataToUpdate)
.execute();
},

View File

@ -32,6 +32,10 @@ class Database {
}
query(uid) {
if (!this.metadata.has(uid)) {
throw new Error(`Model ${uid} not found`);
}
return this.entityManager.getRepository(uid);
}

View File

@ -158,10 +158,6 @@ const createMetadata = (models = []) => {
// init pass
for (const model of models) {
if (!model.tableName) {
console.log(model);
}
metadata.add({
singularName: model.singularName,
uid: model.uid,

View File

@ -208,7 +208,12 @@ const processWhere = (where, ctx, depth = 0) => {
// move to if else to check for scalar / relation / components & throw for other types
if (attribute.type === 'relation') {
// TODO: support shortcut like { role: X } => {role: { id: X }}
// TODO: pass down some filters (e.g published at)
// attribute
const subAlias = createJoin(ctx, { alias, uid, attributeName: key, attribute });
const nestedWhere = processNested(value, {
@ -399,6 +404,22 @@ const processPopulate = (populate, ctx) => {
// TODO: transform to full object populate
}
if (Array.isArray(populate)) {
return populate.reduce((acc, attributeName) => {
if (typeof attributeName !== 'string') {
throw new Error(`Expected a string receveid ${typeof attributeName}.`);
}
const attribute = meta.attributes[attributeName];
if (!attribute) {
throw new Error(`Cannot populate unknown field ${attributeName}`);
}
return { ...acc, [attributeName]: true };
}, {});
}
if (!_.isPlainObject(populate)) {
// TODO: link to the doc
throw new Error('Populate must be an object');

View File

@ -63,7 +63,7 @@ const createQueryBuilder = (uid, db) => {
},
// TODO: convert where into aliases where & nested joins
where(where) {
where(where = {}) {
const processedWhere = helpers.processWhere(where, { qb: this, uid, db });
state.where.push(processedWhere);
@ -190,7 +190,7 @@ const createQueryBuilder = (uid, db) => {
break;
}
case 'count': {
qb.count(state.count);
qb.count({ count: state.count });
break;
}
case 'insert': {

View File

@ -351,7 +351,7 @@ class Strapi {
// Init core store
const contentTypes = [
// todo: move corestore and webhook to real models instead of content types
// todo: move corestore and webhook to real models instead of content types to avoid adding extra attributes
coreStoreModel,
webhookModel,
...Object.values(strapi.models),

View File

@ -14,7 +14,7 @@ module.exports = async function({ file: filePath, pretty }) {
const app = await strapi().load();
const count = await app.query('core_store').count();
const count = await app.query('strapi::core-store').count();
const exportData = [];
@ -22,8 +22,8 @@ module.exports = async function({ file: filePath, pretty }) {
for (let page = 0; page < pageCount; page++) {
const results = await app
.query('core_store')
.find({ _limit: CHUNK_SIZE, _start: page * CHUNK_SIZE, _sort: 'key' });
.query('strapi::core-store')
.findMany({ limit: CHUNK_SIZE, offset: page * CHUNK_SIZE, orderBy: 'key' });
results
.filter(result => result.key.startsWith('plugin_'))

View File

@ -90,13 +90,16 @@ const createReplaceImporter = db => {
},
async import(conf) {
const matching = await db.query('core_store').count({ key: conf.key });
const matching = await db.query('strapi::core-store').count({ where: { key: conf.key } });
if (matching > 0) {
stats.replaced += 1;
await db.query('core_store').update({ key: conf.key }, conf);
await db.query('strapi::core-store').update({
where: { key: conf.key },
data: conf,
});
} else {
stats.created += 1;
await db.query('core_store').create(conf);
await db.query('strapi::core-store').create({ data: conf });
}
},
};
@ -118,13 +121,19 @@ const createMergeImporter = db => {
},
async import(conf) {
const existingConf = await db.query('core_store').find({ key: conf.key });
const existingConf = await db
.query('strapi::core-store')
.findOne({ where: { key: conf.key } });
if (existingConf) {
stats.merged += 1;
await db.query('core_store').update({ key: conf.key }, _.merge(existingConf, conf));
await db.query('strapi::core-store').update({
where: { key: conf.key },
data: _.merge(existingConf, conf),
});
} else {
stats.created += 1;
await db.query('core_store').create(conf);
await db.query('strapi::core-store').create({ data: conf });
}
},
};
@ -146,7 +155,7 @@ const createKeepImporter = db => {
},
async import(conf) {
const matching = await db.query('core_store').count({ key: conf.key });
const matching = await db.query('strapi::core-store').count({ where: { key: conf.key } });
if (matching > 0) {
stats.untouched += 1;
// if configuration already exists do not overwrite it
@ -154,7 +163,7 @@ const createKeepImporter = db => {
}
stats.created += 1;
await db.query('core_store').create(conf);
await db.query('strapi::core-store').create({ data: conf });
},
};
};

View File

@ -1,7 +1,7 @@
'use strict';
const coreStoreModel = {
uid: 'core-store',
uid: 'strapi::core-store',
collectionName: 'strapi_core_store_settings',
attributes: {
key: {
@ -39,7 +39,7 @@ const createCoreStore = ({ environment: defaultEnv, db }) => {
tag,
};
const data = await db.query('core-store').findOne(where);
const data = await db.query('strapi::core-store').findOne({ where });
if (!data) {
return null;
@ -78,7 +78,7 @@ const createCoreStore = ({ environment: defaultEnv, db }) => {
tag,
};
const data = await db.query('core-store').findOne(where);
const data = await db.query('strapi::core-store').findOne({ where });
if (data) {
Object.assign(data, {
@ -86,7 +86,7 @@ const createCoreStore = ({ environment: defaultEnv, db }) => {
type: (typeof value).toString(),
});
await db.query('core-store').update({ id: data.id }, data);
await db.query('strapi::core-store').update({ where: { id: data.id }, data });
} else {
const data = Object.assign({}, where, {
value: JSON.stringify(value) || value.toString(),
@ -94,7 +94,7 @@ const createCoreStore = ({ environment: defaultEnv, db }) => {
tag,
});
await db.query('core-store').create(data);
await db.query('strapi::core-store').create({ data });
}
}
@ -113,7 +113,7 @@ const createCoreStore = ({ environment: defaultEnv, db }) => {
tag,
};
await db.query('core-store').delete(where);
await db.query('strapi::core-store').delete({ where });
}
return {

View File

@ -1,7 +1,7 @@
'use strict';
// Dependencies.
const { isEmpty } = require('lodash');
const { isEmpty, isNil } = require('lodash');
const openBrowser = require('./openBrowser');
module.exports = {
@ -14,9 +14,10 @@ module.exports = {
return true;
}
const numberOfAdministrators = await strapi.query('user', 'admin').find({ _limit: 1 });
// test if there is at least one admin
const anyAdministrator = await strapi.query('strapi::user').findOne({ select: ['id'] });
return numberOfAdministrators.length > 0;
return !isNil(anyAdministrator);
} catch (err) {
strapi.stopWithError(err);
}

View File

@ -24,7 +24,7 @@ module.exports = async () => {
});
}
await pruneObsoleteRelations();
// await pruneObsoleteRelations();
await registerPermissionActions();
};
@ -69,30 +69,30 @@ const baseProvider = {
},
};
const pruneObsoleteRelations = async () => {
const { upload: plugin } = strapi.plugins;
const modelIsNotDefined = !plugin || !plugin.models || !plugin.models.file;
// const pruneObsoleteRelations = async () => {
// const { upload: plugin } = strapi.plugins;
// const modelIsNotDefined = !plugin || !plugin.models || !plugin.models.file;
if (modelIsNotDefined) {
return Promise.resolve();
}
// if (modelIsNotDefined) {
// return Promise.resolve();
// }
await strapi.query('file', 'upload').custom(pruneObsoleteRelationsQuery)();
};
// await strapi.query('file', 'upload').custom(pruneObsoleteRelationsQuery)();
// };
const pruneObsoleteRelationsQuery = ({ model }) => {
if (model.orm !== 'mongoose') {
return Promise.resolve();
}
// const pruneObsoleteRelationsQuery = ({ model }) => {
// if (model.orm !== 'mongoose') {
// return Promise.resolve();
// }
const models = Array.from(strapi.db.models.values());
const modelsId = models.map(model => model.globalId);
// const models = Array.from(strapi.db.models.values());
// const modelsId = models.map(model => model.globalId);
return model.updateMany(
{ related: { $elemMatch: { kind: { $nin: modelsId } } } },
{ $pull: { related: { kind: { $nin: modelsId } } } }
);
};
// return model.updateMany(
// { related: { $elemMatch: { kind: { $nin: modelsId } } } },
// { $pull: { related: { kind: { $nin: modelsId } } } }
// );
// };
const registerPermissionActions = async () => {
const actions = [

View File

@ -5,6 +5,7 @@ const path = require('path');
const _ = require('lodash');
module.exports = async () => {
return;
// Check if the plugin users-permissions is installed because the documentation needs it
if (Object.keys(strapi.plugins).indexOf('users-permissions') === -1) {
throw new Error(
@ -27,6 +28,7 @@ module.exports = async () => {
const services = strapi.plugins['documentation'].services.documentation;
// Generate plugins' documentation
const pluginsWithDocumentationNeeded = services.getPluginsWithDocumentationNeeded();
pluginsWithDocumentationNeeded.forEach(plugin => {
const isDocExisting = services.checkIfPluginDocumentationFolderExists(plugin);

View File

@ -3,6 +3,7 @@
const { getService } = require('../../utils');
module.exports = async () => {
return;
const { sendDidInitializeEvent } = getService('metrics');
const { decorator } = getService('entity-service-decorator');
const { initDefaultLocale } = getService('locales');

View File

@ -27,7 +27,7 @@ const getSortedLocales = async ({ transacting } = {}) => {
let defaultLocale;
try {
const storeRes = await strapi
.query('core_store')
.query('strapi::core-store')
.findOne({ key: 'plugin_i18n_default_locale' }, null, { transacting });
defaultLocale = JSON.parse(storeRes.value);
} catch (e) {

View File

@ -65,7 +65,7 @@ const setIsDefault = async locales => {
};
const initDefaultLocale = async () => {
const existingLocalesNb = await strapi.query('locale', 'i18n').count();
const existingLocalesNb = await strapi.query('plugins::i18n.locale').count();
if (existingLocalesNb === 0) {
await create(DEFAULT_LOCALE);
await setDefaultLocale({ code: DEFAULT_LOCALE.code });

View File

@ -13,6 +13,7 @@ const uuid = require('uuid/v4');
const usersPermissionsActions = require('../users-permissions-actions');
module.exports = async () => {
return;
const pluginStore = strapi.store({
environment: '',
type: 'plugin',

View File

@ -28,8 +28,13 @@ const findEntityAndCheckPermissions = async (ability, action, model, id) => {
const pm = strapi.admin.services.permission.createPermissionsManager({ ability, action, model });
const roles = _.has(entity, `${CREATED_BY_ATTRIBUTE}.id`)
? await strapi.query('role', 'admin').find({ 'users.id': entity[CREATED_BY_ATTRIBUTE].id }, [])
? await strapi.query('strapi::role').findMany({
where: {
users: { id: entity[CREATED_BY_ATTRIBUTE].id },
},
})
: [];
const entityWithRoles = _.set(_.cloneDeep(entity), `${CREATED_BY_ATTRIBUTE}.roles`, roles);
if (pm.ability.cannot(pm.action, pm.toSubject(entityWithRoles))) {

View File

@ -1,6 +1,6 @@
'use strict';
const { transports } = require('winston');
const { transports, format } = require('winston');
const { LEVEL, LEVEL_LABEL, LEVELS } = require('./constants');
const { prettyPrint } = require('./formats');
@ -8,6 +8,7 @@ const createDefaultConfiguration = () => {
return {
level: LEVEL,
levels: LEVELS,
format: format.errors({ stack: true }),
transports: [new transports.Console({ level: LEVEL_LABEL, format: prettyPrint() })],
};
};