diff --git a/app/src/controllers/object.js b/app/src/controllers/object.js index dddd851a..3b83c83e 100644 --- a/app/src/controllers/object.js +++ b/app/src/controllers/object.js @@ -929,14 +929,20 @@ const controller = { public: isTruthy(req.query.public), active: isTruthy(req.query.active), deleteMarker: isTruthy(req.query.deleteMarker), - latest: isTruthy(req.query.latest) + latest: isTruthy(req.query.latest), + page: req.query.page, + limit: req.query.limit, + sort: req.query.sort, + order: req.query.order, + permissions: isTruthy(req.query.permissions) }; // if scoping to current user permissions on objects if (config.has('server.privacyMask')) { params.userId = await userService.getCurrentUserId(getCurrentIdentity(req.currentUser, SYSTEM_USER)); } const response = await objectService.searchObjects(params); - res.status(200).json(response); + res.setHeader('X-Total-Rows', response.total); + res.status(200).json(response.data); } catch (error) { next(error); } diff --git a/app/src/db/models/tables/objectModel.js b/app/src/db/models/tables/objectModel.js index e391d203..81df5254 100644 --- a/app/src/db/models/tables/objectModel.js +++ b/app/src/db/models/tables/objectModel.js @@ -176,6 +176,12 @@ class ObjectModel extends Timestamps(Model) { }); }); } + }, + pagination(query, page, limit){ + if( page && limit) query.page(page - 1, limit); + }, + sortOrder(query, column, order='asc'){ + if(column) query.orderBy(column, order); } }; } diff --git a/app/src/services/object.js b/app/src/services/object.js index 736bb20b..19410970 100644 --- a/app/src/services/object.js +++ b/app/src/services/object.js @@ -117,11 +117,13 @@ const service = { */ searchObjects: async (params, etrx = undefined) => { let trx; + let response = []; try { trx = etrx ? etrx : await ObjectModel.startTransaction(); - const response = await ObjectModel.query(trx) - .allowGraph('version') + response.data = await ObjectModel.query(trx) + .allowGraph('objectPermission') + .withGraphFetched('objectPermission') .modify('filterIds', params.id) .modify('filterBucketIds', params.bucketId) .modify('filterName', params.name) @@ -136,16 +138,34 @@ const service = { tag: params.tag }) .modify('hasPermission', params.userId, 'READ') - // format result + .modify('pagination', params.page, params.limit) + .modify('sortOrder', params.sort, params.order) .then(result => { - // just return object table records - const res = result.map(row => { - // eslint-disable-next-line no-unused-vars - const { objectPermission, bucketPermission, version, ...object } = row; - return object; - }); - // remove duplicates - return [...new Map(res.map(item => [item.id, item])).values()]; + if (Object.hasOwn(result, 'results')) { + response.total = result.total; + const res = result.results.map(row => { + const { objectPermission, ...object } = row; + if (params.permissions) { + object.objectPermissions = []; + objectPermission.map(o => { + object.objectPermissions.push(o.permCode); + }); + } + return object; + }); + // remove duplicates + return [...new Map(res.map(item => [item.id, item])).values()]; + } else { + response.total = result.length; + //just return object table records + const res = result.map(row => { + // eslint-disable-next-line no-unused-vars + const { objectPermission, bucketPermission, version, ...object } = row; + return object; + }); + // remove duplicates + return [...new Map(res.map(item => [item.id, item])).values()]; + } }); if (!etrx) await trx.commit(); diff --git a/app/src/validators/common.js b/app/src/validators/common.js index d4c2c174..d0fcb341 100644 --- a/app/src/validators/common.js +++ b/app/src/validators/common.js @@ -81,7 +81,12 @@ const scheme = { guid: oneOrMany(type.uuidv4), string: oneOrMany(Joi.string().max(255)), - + pagination: { + page: Joi.number().min(1), + limit: Joi.number(), + sort: Joi.string(), + order: Joi.string().valid('asc', 'desc'), + }, permCode: oneOrMany(Joi.string().valid(...Object.values(Permissions))) }; diff --git a/app/src/validators/object.js b/app/src/validators/object.js index bfd66caa..48a1a4a0 100644 --- a/app/src/validators/object.js +++ b/app/src/validators/object.js @@ -137,7 +137,9 @@ const schema = { public: type.truthy, active: type.truthy, deleteMarker: type.truthy, - latest: type.truthy + latest: type.truthy, + permissions: type.truthy, + ...scheme.pagination, }) }, diff --git a/app/tests/unit/services/object.spec.js b/app/tests/unit/services/object.spec.js index efdedeb3..b3b1f9de 100644 --- a/app/tests/unit/services/object.spec.js +++ b/app/tests/unit/services/object.spec.js @@ -134,6 +134,8 @@ describe('searchObjects', () => { tag: params.tag }); expect(ObjectModel.modify).toHaveBeenNthCalledWith(11, 'hasPermission', params.userId, 'READ'); + expect(ObjectModel.modify).toHaveBeenNthCalledWith(12, 'pagination', params.page, params.limit); + expect(ObjectModel.modify).toHaveBeenNthCalledWith(13, 'sortOrder', params.sort, params.order); expect(ObjectModel.then).toHaveBeenCalledTimes(1); expect(objectModelTrx.commit).toHaveBeenCalledTimes(1); }); diff --git a/app/tests/unit/validators/object.spec.js b/app/tests/unit/validators/object.spec.js index 61d62c3e..3e156cc9 100644 --- a/app/tests/unit/validators/object.spec.js +++ b/app/tests/unit/validators/object.spec.js @@ -512,6 +512,47 @@ describe('searchObjects', () => { expect(active).toEqual(type.truthy.describe()); }); }); + + describe('page', () => { + const page = query.keys.page; + + it('is a number', () => { + expect(page.type).toEqual('number'); + }); + }); + + describe('limit', () => { + const limit = query.keys.limit; + + it('is a number', () => { + expect(limit.type).toEqual('number'); + }); + }); + + describe('sort', () => { + const sort = query.keys.sort; + + it('is a string', () => { + expect(sort.type).toEqual('string'); + }); + }); + + describe('order', () => { + const order = query.keys.order; + + it('is a string', () => { + expect(order.type).toEqual('string'); + }); + }); + + describe('permissions', () => { + const permissions = query.keys.permissions; + + it('is the expected schema', () => { + expect(permissions).toEqual(type.truthy.describe()); + }); + }); + }); });