mirror of
https://github.com/strapi/strapi.git
synced 2025-11-10 15:19:00 +00:00
Use new filters format in the upload plugin
This commit is contained in:
parent
9ce23475bc
commit
d02c7ab741
@ -6,20 +6,22 @@ module.exports = {
|
|||||||
displayName: 'Is creator',
|
displayName: 'Is creator',
|
||||||
name: 'is-creator',
|
name: 'is-creator',
|
||||||
plugin: 'admin',
|
plugin: 'admin',
|
||||||
handler: user => ({ 'createdBy.id': user.id }),
|
handler: user => ({ created_by: { id: user.id } }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Has same role as creator',
|
displayName: 'Has same role as creator',
|
||||||
name: 'has-same-role-as-creator',
|
name: 'has-same-role-as-creator',
|
||||||
plugin: 'admin',
|
plugin: 'admin',
|
||||||
handler: user => ({
|
handler: user => ({
|
||||||
'createdBy.roles': {
|
created_by: {
|
||||||
|
roles: {
|
||||||
$elemMatch: {
|
$elemMatch: {
|
||||||
id: {
|
id: {
|
||||||
$in: user.roles.map(r => r.id),
|
$in: user.roles.map(r => r.id),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -56,7 +56,7 @@ describe('Permissions Manager', () => {
|
|||||||
model: 'foo',
|
model: 'foo',
|
||||||
});
|
});
|
||||||
|
|
||||||
const expected = [{ kai: 'doe' }];
|
const expected = { $and: [{ kai: 'doe' }] };
|
||||||
|
|
||||||
expect(pm.getQuery()).toStrictEqual(expected);
|
expect(pm.getQuery()).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
@ -179,7 +179,7 @@ describe('Permissions Manager', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('queryFrom', () => {
|
describe('addPermissionsQueryTo', () => {
|
||||||
const ability = defineAbility(can =>
|
const ability = defineAbility(can =>
|
||||||
can('read', 'article', ['title'], { $and: [{ title: 'foo' }] })
|
can('read', 'article', ['title'], { $and: [{ title: 'foo' }] })
|
||||||
);
|
);
|
||||||
@ -189,25 +189,27 @@ describe('Permissions Manager', () => {
|
|||||||
model: 'article',
|
model: 'article',
|
||||||
});
|
});
|
||||||
|
|
||||||
const pmQuery = [{ title: 'foo' }];
|
const pmQuery = { $and: [{ title: 'foo' }] };
|
||||||
|
|
||||||
test('Create query from simple object', () => {
|
test('Create query from simple object', () => {
|
||||||
const query = { _limit: 100 };
|
const query = { limit: 100 };
|
||||||
const expected = { _limit: 100, _where: pmQuery };
|
const expected = { limit: 100, filters: pmQuery };
|
||||||
|
|
||||||
const res = pm.queryFrom(query);
|
const res = pm.addPermissionsQueryTo(query);
|
||||||
|
|
||||||
expect(res).toStrictEqual(expected);
|
expect(res).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Create query from complex object', () => {
|
test('Create query from complex object', () => {
|
||||||
const query = { _limit: 100, _where: [{ a: 'b' }, { c: 'd' }] };
|
const query = { limit: 100, filters: { $and: [{ a: 'b' }, { c: 'd' }] } };
|
||||||
const expected = {
|
const expected = {
|
||||||
_limit: 100,
|
limit: 100,
|
||||||
_where: [{ a: 'b' }, { c: 'd' }, ...pmQuery],
|
filters: {
|
||||||
|
$and: [query.filters, pmQuery],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = pm.queryFrom(query);
|
const res = pm.addPermissionsQueryTo(query);
|
||||||
|
|
||||||
expect(res).toStrictEqual(expected);
|
expect(res).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
@ -216,54 +218,55 @@ describe('Permissions Manager', () => {
|
|||||||
describe('buildStrapiQuery', () => {
|
describe('buildStrapiQuery', () => {
|
||||||
const tests = [
|
const tests = [
|
||||||
['No transform', { foo: 'bar' }, { foo: 'bar' }],
|
['No transform', { foo: 'bar' }, { foo: 'bar' }],
|
||||||
['Simple op', { foo: { $eq: 'bar' } }, { foo_eq: 'bar' }],
|
['Simple op', { foo: { $eq: 'bar' } }, { foo: { $eq: 'bar' } }],
|
||||||
['Nested property', { foo: { nested: 'bar' } }, { 'foo.nested': 'bar' }],
|
['Nested property', { foo: { nested: 'bar' } }, { foo: { nested: 'bar' } }],
|
||||||
[
|
[
|
||||||
'Deeply nested property',
|
'Deeply nested property',
|
||||||
{ foo: { nested: { again: 'bar' } } },
|
{ foo: { nested: { again: 'bar' } } },
|
||||||
{ 'foo.nested.again': 'bar' },
|
{ foo: { nested: { again: 'bar' } } },
|
||||||
],
|
],
|
||||||
['Op with array', { foo: { $in: ['bar', 'rab'] } }, { foo_in: ['bar', 'rab'] }],
|
['Op with array', { foo: { $in: ['bar', 'rab'] } }, { foo: { $in: ['bar', 'rab'] } }],
|
||||||
['Removable op', { foo: { $elemMatch: { a: 'b' } } }, { 'foo.a': 'b' }],
|
['Removable op', { foo: { $elemMatch: { a: 'b' } } }, { foo: { $and: [{ a: 'b' }] } }],
|
||||||
[
|
[
|
||||||
'Combination of removable and basic ops',
|
'Combination of removable and basic ops',
|
||||||
{ foo: { $elemMatch: { a: { $in: [1, 2, 3] } } } },
|
{ foo: { $elemMatch: { a: { $in: [1, 2, 3] } } } },
|
||||||
{ 'foo.a_in': [1, 2, 3] },
|
{ foo: { $and: [{ a: { $in: [1, 2, 3] } }] } },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Decoupling of nested properties with/without op',
|
'Decoupling of nested properties with/without op',
|
||||||
{ foo: { $elemMatch: { a: { $in: [1, 2, 3] }, b: 'c' } } },
|
{ foo: { $elemMatch: { a: { $in: [1, 2, 3] }, b: 'c' } } },
|
||||||
{ 'foo.a_in': [1, 2, 3], 'foo.b': 'c' },
|
{ foo: { $and: [{ a: { $in: [1, 2, 3] }, b: 'c' }] } },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'OR op and properties decoupling',
|
'OR op and properties decoupling',
|
||||||
{ $or: [{ foo: { a: 2 } }, { foo: { b: 3 } }] },
|
{ $or: [{ foo: { a: 2 } }, { foo: { b: 3 } }] },
|
||||||
{ _or: [{ 'foo.a': 2 }, { 'foo.b': 3 }] },
|
{ $or: [{ foo: { a: 2 } }, { foo: { b: 3 } }] },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'OR op with nested properties & ops',
|
'OR op with nested properties & ops',
|
||||||
{ $or: [{ foo: { a: 2 } }, { foo: { b: { $in: [1, 2, 3] } } }] },
|
{ $or: [{ foo: { a: 2 } }, { foo: { b: { $in: [1, 2, 3] } } }] },
|
||||||
{ _or: [{ 'foo.a': 2 }, { 'foo.b_in': [1, 2, 3] }] },
|
{ $or: [{ foo: { a: 2 } }, { foo: { b: { $in: [1, 2, 3] } } }] },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Nested OR op',
|
'Nested OR op',
|
||||||
{ $or: [{ $or: [{ a: 2 }, { a: 3 }] }] },
|
{ $or: [{ $or: [{ a: 2 }, { a: 3 }] }] },
|
||||||
{ _or: [{ _or: [{ a: 2 }, { a: 3 }] }] },
|
{ $or: [{ $or: [{ a: 2 }, { a: 3 }] }] },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'OR op with nested AND op',
|
'OR op with nested AND op',
|
||||||
{ $or: [{ a: 2 }, [{ a: 3 }, { $or: [{ b: 1 }, { b: 4 }] }]] },
|
{ $or: [{ a: 2 }, [{ a: 3 }, { $or: [{ b: 1 }, { b: 4 }] }]] },
|
||||||
{ _or: [{ a: 2 }, [{ a: 3 }, { _or: [{ b: 1 }, { b: 4 }] }]] },
|
{ $or: [{ a: 2 }, [{ a: 3 }, { $or: [{ b: 1 }, { b: 4 }] }]] },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'OR op with nested AND op and nested properties',
|
'OR op with nested AND op and nested properties',
|
||||||
{ _or: [{ a: 2 }, [{ a: 3 }, { b: { c: 'foo' } }]] },
|
{ $or: [{ a: 2 }, [{ a: 3 }, { b: { c: 'foo' } }]] },
|
||||||
{ _or: [{ a: 2 }, [{ a: 3 }, { 'b.c': 'foo' }]] },
|
{ $or: [{ a: 2 }, [{ a: 3 }, { b: { c: 'foo' } }]] },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Literal nested property with removable op',
|
'Literal nested property with removable op',
|
||||||
{
|
{
|
||||||
'createdBy.roles': {
|
created_by: {
|
||||||
|
roles: {
|
||||||
$elemMatch: {
|
$elemMatch: {
|
||||||
id: {
|
id: {
|
||||||
$in: [1, 2, 3],
|
$in: [1, 2, 3],
|
||||||
@ -271,8 +274,19 @@ describe('Permissions Manager', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'createdBy.roles.id_in': [1, 2, 3],
|
created_by: {
|
||||||
|
roles: {
|
||||||
|
$and: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
$in: [1, 2, 3],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { cloneDeep, isObject, set, isArray } = require('lodash/fp');
|
const { cloneDeep, isPlainObject } = require('lodash/fp');
|
||||||
const { subject: asSubject } = require('@casl/ability');
|
const { subject: asSubject } = require('@casl/ability');
|
||||||
const { permittedFieldsOf } = require('@casl/ability/extra');
|
const { permittedFieldsOf } = require('@casl/ability/extra');
|
||||||
const {
|
const {
|
||||||
@ -35,22 +35,15 @@ module.exports = ({ ability, action, model }) => ({
|
|||||||
return buildStrapiQuery(buildCaslQuery(ability, queryAction, model));
|
return buildStrapiQuery(buildCaslQuery(ability, queryAction, model));
|
||||||
},
|
},
|
||||||
|
|
||||||
// FIXME:
|
addPermissionsQueryTo(query = {}, action) {
|
||||||
queryFrom(query = {}, action) {
|
const newQuery = cloneDeep(query);
|
||||||
const permissionQuery = this.getQuery(action);
|
const permissionQuery = this.getQuery(action);
|
||||||
|
|
||||||
const newQuery = cloneDeep(query);
|
newQuery.filters = isPlainObject(query.filters)
|
||||||
const { _where } = query;
|
? { $and: [query.filters, permissionQuery] }
|
||||||
|
: permissionQuery;
|
||||||
|
|
||||||
if (isObject(_where) && !isArray(_where)) {
|
return newQuery;
|
||||||
Object.assign(newQuery, { _where: [_where] });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_where) {
|
|
||||||
Object.assign(newQuery, { _where: [] });
|
|
||||||
}
|
|
||||||
|
|
||||||
return set('_where', newQuery._where.concat(permissionQuery), newQuery);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
sanitize(data, options = {}) {
|
sanitize(data, options = {}) {
|
||||||
|
|||||||
@ -13,69 +13,34 @@ const ops = {
|
|||||||
|
|
||||||
const buildCaslQuery = (ability, action, model) => {
|
const buildCaslQuery = (ability, action, model) => {
|
||||||
const query = rulesToQuery(ability, action, model, o => o.conditions);
|
const query = rulesToQuery(ability, action, model, o => o.conditions);
|
||||||
return _.get(query, '$or[0].$and', {});
|
return _.get(query, '$or[0]', {});
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildStrapiQuery = caslQuery => {
|
const buildStrapiQuery = caslQuery => {
|
||||||
const transform = _.flow([flattenDeep, cleanupUnwantedProperties]);
|
const transform = _.flow([removeCleanable]);
|
||||||
return transform(caslQuery);
|
const res = transform(caslQuery);
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
const flattenDeep = condition => {
|
const removeCleanable = condition => {
|
||||||
if (_.isArray(condition)) {
|
if (_.isArray(condition)) {
|
||||||
return _.map(condition, flattenDeep);
|
return _.map(condition, removeCleanable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isObject(condition)) {
|
if (!_.isObject(condition)) {
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldIgnore = e => !!ops.common.includes(e);
|
|
||||||
const shouldPerformTransformation = (v, k) => _.isObject(v) && !_.isArray(v) && !shouldIgnore(k);
|
|
||||||
|
|
||||||
const result = {};
|
|
||||||
const set = (key, value) => (result[key] = value);
|
|
||||||
|
|
||||||
const getTransformParams = (prevKey, v, k) =>
|
|
||||||
shouldIgnore(k) ? [`${prevKey}_${k.replace('$', '')}`, v] : [`${prevKey}.${k}`, v];
|
|
||||||
|
|
||||||
_.each(condition, (value, key) => {
|
|
||||||
if (ops.boolean.includes(key)) {
|
|
||||||
set(key.replace('$', '_'), _.map(value, flattenDeep));
|
|
||||||
} else if (shouldPerformTransformation(value, key)) {
|
|
||||||
_.each(flattenDeep(value), (v, k) => {
|
|
||||||
set(...getTransformParams(key, v, k));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
set(key, flattenDeep(value));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const cleanupUnwantedProperties = condition => {
|
|
||||||
if (!_.isObject(condition)) {
|
|
||||||
return condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_.isArray(condition)) {
|
|
||||||
return condition.map(cleanupUnwantedProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
const shouldClean = e =>
|
|
||||||
typeof e === 'string' ? ops.cleanable.find(o => e.includes(`.${o}`)) : undefined;
|
|
||||||
|
|
||||||
return _.reduce(
|
return _.reduce(
|
||||||
condition,
|
condition,
|
||||||
(acc, value, key) => {
|
(newCondition, value, key) => {
|
||||||
const keyToClean = shouldClean(key);
|
if (ops.cleanable.includes(key)) {
|
||||||
const newKey = keyToClean ? key.split(`.${keyToClean}`).join('') : key;
|
newCondition.$and = [removeCleanable(value)];
|
||||||
|
} else {
|
||||||
|
newCondition[key] = removeCleanable(value);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return newCondition;
|
||||||
...acc,
|
|
||||||
[newKey]: _.isArray(value) ? value.map(cleanupUnwantedProperties) : value,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -43,7 +43,8 @@ const createPermissionChecker = strapi => ({ userAbility, model }) => {
|
|||||||
const sanitizeCreateInput = data => sanitizeInput(ACTIONS.create, data);
|
const sanitizeCreateInput = data => sanitizeInput(ACTIONS.create, data);
|
||||||
const sanitizeUpdateInput = entity => data => sanitizeInput(ACTIONS.update, data, entity);
|
const sanitizeUpdateInput = entity => data => sanitizeInput(ACTIONS.update, data, entity);
|
||||||
|
|
||||||
const buildPermissionQuery = (query, action) => permissionsManager.queryFrom(query, action);
|
const buildPermissionQuery = (query, action) =>
|
||||||
|
permissionsManager.addPermissionsQueryTo(query, action);
|
||||||
|
|
||||||
const buildReadQuery = query => buildPermissionQuery(query, ACTIONS.read);
|
const buildReadQuery = query => buildPermissionQuery(query, ACTIONS.read);
|
||||||
const buildDeleteQuery = query => buildPermissionQuery(query, ACTIONS.delete);
|
const buildDeleteQuery = query => buildPermissionQuery(query, ACTIONS.delete);
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { contentTypes: contentTypesUtils } = require('@strapi/utils');
|
const { contentTypes: contentTypesUtils, sanitizeEntity } = require('@strapi/utils');
|
||||||
const validateSettings = require('../validation/settings');
|
const { getService } = require('../utils');
|
||||||
const validateUploadBody = require('../validation/upload');
|
const validateSettings = require('./validation/settings');
|
||||||
const { getService } = require('../../utils');
|
const validateUploadBody = require('./validation/upload');
|
||||||
|
|
||||||
const { CREATED_BY_ATTRIBUTE } = contentTypesUtils.constants;
|
const { CREATED_BY_ATTRIBUTE } = contentTypesUtils.constants;
|
||||||
|
|
||||||
@ -35,7 +35,8 @@ module.exports = {
|
|||||||
return ctx.forbidden();
|
return ctx.forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = pm.queryFrom(ctx.query);
|
const query = pm.addPermissionsQueryTo(ctx.query);
|
||||||
|
|
||||||
const files = await getService('upload').fetchAll(query);
|
const files = await getService('upload').fetchAll(query);
|
||||||
|
|
||||||
ctx.body = pm.sanitize(files, { withPrivate: false });
|
ctx.body = pm.sanitize(files, { withPrivate: false });
|
||||||
@ -68,7 +69,7 @@ module.exports = {
|
|||||||
return ctx.forbidden();
|
return ctx.forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = pm.queryFrom(ctx.query);
|
const query = pm.addPermissionsQueryTo(ctx.query);
|
||||||
const count = await getService('upload').count(query);
|
const count = await getService('upload').count(query);
|
||||||
|
|
||||||
ctx.body = { count };
|
ctx.body = { count };
|
||||||
@ -185,6 +186,37 @@ module.exports = {
|
|||||||
|
|
||||||
ctx.body = pm.sanitize(uploadedFiles, { action: ACTIONS.read, withPrivate: false });
|
ctx.body = pm.sanitize(uploadedFiles, { action: ACTIONS.read, withPrivate: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async upload(ctx) {
|
||||||
|
const {
|
||||||
|
query: { id },
|
||||||
|
request: { files: { files } = {} },
|
||||||
|
} = ctx;
|
||||||
|
|
||||||
|
if (id && (_.isEmpty(files) || files.size === 0)) {
|
||||||
|
return this.updateFileInfo(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isEmpty(files) || files.size === 0) {
|
||||||
|
throw strapi.errors.badRequest(null, {
|
||||||
|
errors: [{ id: 'Upload.status.empty', message: 'Files are empty' }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await (id ? this.replaceFile : this.uploadFiles)(ctx);
|
||||||
|
},
|
||||||
|
|
||||||
|
async search(ctx) {
|
||||||
|
const { id } = ctx.params;
|
||||||
|
const model = strapi.getModel('plugin::upload.file');
|
||||||
|
const entries = await strapi.query('plugin::upload.file').findMany({
|
||||||
|
where: {
|
||||||
|
$or: [{ hash: { $contains: id } }, { name: { $contains: id } }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.body = sanitizeEntity(entries, { model });
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const findEntityAndCheckPermissions = async (ability, action, model, id) => {
|
const findEntityAndCheckPermissions = async (ability, action, model, id) => {
|
||||||
@ -1,9 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
const { sanitizeEntity } = require('@strapi/utils');
|
const { sanitizeEntity } = require('@strapi/utils');
|
||||||
const validateSettings = require('../validation/settings');
|
const { getService } = require('../utils');
|
||||||
const validateUploadBody = require('../validation/upload');
|
const validateSettings = require('./validation/settings');
|
||||||
const { getService } = require('../../utils');
|
const validateUploadBody = require('./validation/upload');
|
||||||
|
|
||||||
const sanitize = (data, options = {}) => {
|
const sanitize = (data, options = {}) => {
|
||||||
return sanitizeEntity(data, {
|
return sanitizeEntity(data, {
|
||||||
@ -118,4 +119,35 @@ module.exports = {
|
|||||||
|
|
||||||
ctx.body = sanitize(uploadedFiles);
|
ctx.body = sanitize(uploadedFiles);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async upload(ctx) {
|
||||||
|
const {
|
||||||
|
query: { id },
|
||||||
|
request: { files: { files } = {} },
|
||||||
|
} = ctx;
|
||||||
|
|
||||||
|
if (id && (_.isEmpty(files) || files.size === 0)) {
|
||||||
|
return this.updateFileInfo(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isEmpty(files) || files.size === 0) {
|
||||||
|
throw strapi.errors.badRequest(null, {
|
||||||
|
errors: [{ id: 'Upload.status.empty', message: 'Files are empty' }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await (id ? this.replaceFile : this.uploadFiles)(ctx);
|
||||||
|
},
|
||||||
|
|
||||||
|
async search(ctx) {
|
||||||
|
const { id } = ctx.params;
|
||||||
|
const model = strapi.getModel('plugin::upload.file');
|
||||||
|
const entries = await strapi.query('plugin::upload.file').findMany({
|
||||||
|
where: {
|
||||||
|
$or: [{ hash: { $contains: id } }, { name: { $contains: id } }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.body = sanitizeEntity(entries, { model });
|
||||||
|
},
|
||||||
};
|
};
|
||||||
@ -1,7 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const upload = require('./upload');
|
const adminApi = require('./admin-api');
|
||||||
|
const contentApi = require('./content-api');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
upload,
|
'admin-api': adminApi,
|
||||||
|
'content-api': contentApi,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload.js controller
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
const _ = require('lodash');
|
|
||||||
const { sanitizeEntity } = require('@strapi/utils');
|
|
||||||
const apiUploadController = require('./upload/api');
|
|
||||||
const adminUploadController = require('./upload/admin');
|
|
||||||
|
|
||||||
const resolveController = ctx => {
|
|
||||||
const {
|
|
||||||
state: { isAuthenticatedAdmin },
|
|
||||||
} = ctx;
|
|
||||||
|
|
||||||
return isAuthenticatedAdmin ? adminUploadController : apiUploadController;
|
|
||||||
};
|
|
||||||
|
|
||||||
const resolveControllerMethod = method => ctx => {
|
|
||||||
const controller = resolveController(ctx);
|
|
||||||
const callbackFn = controller[method];
|
|
||||||
|
|
||||||
if (!_.isFunction(callbackFn)) {
|
|
||||||
return ctx.notFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return callbackFn(ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
find: resolveControllerMethod('find'),
|
|
||||||
findOne: resolveControllerMethod('findOne'),
|
|
||||||
count: resolveControllerMethod('count'),
|
|
||||||
destroy: resolveControllerMethod('destroy'),
|
|
||||||
updateSettings: resolveControllerMethod('updateSettings'),
|
|
||||||
getSettings: resolveControllerMethod('getSettings'),
|
|
||||||
|
|
||||||
async upload(ctx) {
|
|
||||||
const {
|
|
||||||
query: { id },
|
|
||||||
request: { files: { files } = {} },
|
|
||||||
} = ctx;
|
|
||||||
|
|
||||||
const controller = resolveController(ctx);
|
|
||||||
|
|
||||||
if (id && (_.isEmpty(files) || files.size === 0)) {
|
|
||||||
return controller.updateFileInfo(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_.isEmpty(files) || files.size === 0) {
|
|
||||||
throw strapi.errors.badRequest(null, {
|
|
||||||
errors: [{ id: 'Upload.status.empty', message: 'Files are empty' }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await (id ? controller.replaceFile : controller.uploadFiles)(ctx);
|
|
||||||
},
|
|
||||||
|
|
||||||
async search(ctx) {
|
|
||||||
const { id } = ctx.params;
|
|
||||||
const model = strapi.getModel('plugin::upload.file');
|
|
||||||
const entries = await strapi.query('plugin::upload.file').findMany({
|
|
||||||
where: {
|
|
||||||
$or: [{ hash: { $contains: id } }, { name: { $contains: id } }],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
ctx.body = sanitizeEntity(entries, { model });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -6,7 +6,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
handler: 'upload.getSettings',
|
handler: 'admin-api.getSettings',
|
||||||
config: {
|
config: {
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
@ -22,7 +22,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
handler: 'upload.updateSettings',
|
handler: 'admin-api.updateSettings',
|
||||||
config: {
|
config: {
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
@ -38,7 +38,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: '/',
|
path: '/',
|
||||||
handler: 'upload.upload',
|
handler: 'admin-api.upload',
|
||||||
config: {
|
config: {
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
},
|
},
|
||||||
@ -46,7 +46,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/files/count',
|
path: '/files/count',
|
||||||
handler: 'upload.count',
|
handler: 'admin-api.count',
|
||||||
config: {
|
config: {
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
@ -62,7 +62,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/files',
|
path: '/files',
|
||||||
handler: 'upload.find',
|
handler: 'admin-api.find',
|
||||||
config: {
|
config: {
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
@ -78,7 +78,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/files/:id',
|
path: '/files/:id',
|
||||||
handler: 'upload.findOne',
|
handler: 'admin-api.findOne',
|
||||||
config: {
|
config: {
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
@ -94,7 +94,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/search/:id',
|
path: '/search/:id',
|
||||||
handler: 'upload.search',
|
handler: 'admin-api.search',
|
||||||
config: {
|
config: {
|
||||||
policies: ['admin::isAuthenticatedAdmin'],
|
policies: ['admin::isAuthenticatedAdmin'],
|
||||||
},
|
},
|
||||||
@ -102,7 +102,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
path: '/files/:id',
|
path: '/files/:id',
|
||||||
handler: 'upload.destroy',
|
handler: 'admin-api.destroy',
|
||||||
config: {
|
config: {
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
|
|||||||
@ -6,27 +6,27 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: '/',
|
path: '/',
|
||||||
handler: 'upload.upload',
|
handler: 'content-api.upload',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/files/count',
|
path: '/files/count',
|
||||||
handler: 'upload.count',
|
handler: 'content-api.count',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/files',
|
path: '/files',
|
||||||
handler: 'upload.find',
|
handler: 'content-api.find',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: '/files/:id',
|
path: '/files/:id',
|
||||||
handler: 'upload.findOne',
|
handler: 'content-api.findOne',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
path: '/files/:id',
|
path: '/files/:id',
|
||||||
handler: 'upload.destroy',
|
handler: 'content-api.destroy',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -44,10 +44,11 @@ const sendMediaMetrics = data => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const combineFilters = params => {
|
const combineFilters = params => {
|
||||||
// FIXME: until we support boolean operators for querying we need to make mime_ncontains use AND instead of OR
|
|
||||||
if (_.has(params, 'mime_ncontains') && Array.isArray(params.mime_ncontains)) {
|
if (_.has(params, 'mime_ncontains') && Array.isArray(params.mime_ncontains)) {
|
||||||
params._where = params.mime_ncontains.map(val => ({ mime_ncontains: val }));
|
const mimeFilters = { $or: params.mime_ncontains.map(val => ({ mime_ncontains: val })) };
|
||||||
delete params.mime_ncontains;
|
delete params.mime_ncontains;
|
||||||
|
|
||||||
|
params.filters = params.filters ? { $and: [params.filters, mimeFilters] } : mimeFilters;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -201,7 +202,7 @@ module.exports = ({ strapi }) => ({
|
|||||||
caption: _.isNil(caption) ? dbFile.caption : caption,
|
caption: _.isNil(caption) ? dbFile.caption : caption,
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.update({ id }, newInfos, { user });
|
return this.update(id, newInfos, { user });
|
||||||
},
|
},
|
||||||
|
|
||||||
async replace(id, { data, file }, { user } = {}) {
|
async replace(id, { data, file }, { user } = {}) {
|
||||||
@ -274,20 +275,20 @@ module.exports = ({ strapi }) => ({
|
|||||||
height,
|
height,
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.update({ id }, fileData, { user });
|
return this.update(id, fileData, { user });
|
||||||
},
|
},
|
||||||
|
|
||||||
async update(params, values, { user } = {}) {
|
async update(id, values, { user } = {}) {
|
||||||
const fileValues = { ...values };
|
const fileValues = { ...values };
|
||||||
if (user) {
|
if (user) {
|
||||||
fileValues[UPDATED_BY_ATTRIBUTE] = user.id;
|
fileValues[UPDATED_BY_ATTRIBUTE] = user.id;
|
||||||
}
|
}
|
||||||
sendMediaMetrics(fileValues);
|
sendMediaMetrics(fileValues);
|
||||||
|
|
||||||
//
|
// const res = await strapi
|
||||||
const res = await strapi
|
// .query('plugin::upload.file')
|
||||||
.query('plugin::upload.file')
|
// .update({ where: params, data: fileValues });
|
||||||
.update({ where: params, data: fileValues });
|
const res = await strapi.entityService.update('plugin::upload.file', id, { data: fileValues });
|
||||||
|
|
||||||
this.emitEvent(MEDIA_UPDATE, res);
|
this.emitEvent(MEDIA_UPDATE, res);
|
||||||
|
|
||||||
@ -309,18 +310,18 @@ module.exports = ({ strapi }) => ({
|
|||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
findOne(params, populate) {
|
findOne(filters, populate) {
|
||||||
return strapi.query('plugin::upload.file').findOne({ where: params, populate });
|
return strapi.entityService.findOne('plugin::upload.file', { params: { filters, populate } });
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchAll(params) {
|
fetchAll(query) {
|
||||||
combineFilters(params);
|
combineFilters(query);
|
||||||
return strapi.query('plugin::upload.file').findMany({ ...params });
|
return strapi.entityService.find('plugin::upload.file', { params: query });
|
||||||
},
|
},
|
||||||
|
|
||||||
count(params) {
|
count(query) {
|
||||||
combineFilters(params);
|
combineFilters(query);
|
||||||
return strapi.query('plugin::upload.file').count({ ...params });
|
return strapi.entityService.count('plugin::upload.file', { params: query });
|
||||||
},
|
},
|
||||||
|
|
||||||
async remove(file) {
|
async remove(file) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user