From 909d1847786cab4cb0316481bda8fb96df2f0813 Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Fri, 12 Mar 2021 14:53:41 -0500 Subject: [PATCH] Respect permissions in item count Fixes #4422 --- api/src/services/meta.ts | 43 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/api/src/services/meta.ts b/api/src/services/meta.ts index ff51ae45b4..f14c1f9785 100644 --- a/api/src/services/meta.ts +++ b/api/src/services/meta.ts @@ -3,6 +3,8 @@ import database from '../database'; import { AbstractServiceOptions, Accountability, SchemaOverview } from '../types'; import { Knex } from 'knex'; import { applyFilter, applySearch } from '../utils/apply-query'; +import { ForbiddenException } from '../exceptions'; +import { parseFilter } from '../utils/parse-filter'; export class MetaService { knex: Knex; @@ -34,15 +36,48 @@ export class MetaService { } async totalCount(collection: string) { - const records = await this.knex(collection).count('*', { as: 'count' }); - return Number(records[0].count); + const dbQuery = this.knex(collection).count('*', { as: 'count' }).first(); + + if (this.accountability?.admin !== true) { + const permissionsRecord = this.schema.permissions.find((permission) => { + return permission.action === 'read' && permission.collection === collection; + }); + + if (!permissionsRecord) throw new ForbiddenException(); + + const permissions = parseFilter(permissionsRecord.permissions, this.accountability); + + applyFilter(this.schema, dbQuery, permissions, collection); + } + + const result = await dbQuery; + + return Number(result?.count ?? 0); } async filterCount(collection: string, query: Query) { const dbQuery = this.knex(collection).count('*', { as: 'count' }); - if (query.filter) { - applyFilter(this.schema, dbQuery, query.filter, collection); + let filter = query.filter || {}; + + if (this.accountability?.admin !== true) { + const permissionsRecord = this.schema.permissions.find((permission) => { + return permission.action === 'read' && permission.collection === collection; + }); + + if (!permissionsRecord) throw new ForbiddenException(); + + const permissions = parseFilter(permissionsRecord.permissions, this.accountability); + + if (Object.keys(filter).length > 0) { + filter = { _and: [permissions, filter] }; + } else { + filter = permissions; + } + } + + if (Object.keys(filter).length > 0) { + applyFilter(this.schema, dbQuery, filter, collection); } if (query.search) {