@directus/api
Version:
Directus is a real-time API and App dashboard for managing SQL database content
64 lines (63 loc) • 2.69 kB
JavaScript
import { isArray } from 'lodash-es';
import getDatabase from '../database/index.js';
import applyQuery from '../database/run-ast/lib/apply-query/index.js';
import { fetchPermissions } from '../permissions/lib/fetch-permissions.js';
import { fetchPolicies } from '../permissions/lib/fetch-policies.js';
import { getCases } from '../permissions/modules/process-ast/lib/get-cases.js';
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
export class MetaService {
knex;
accountability;
schema;
constructor(options) {
this.knex = options.knex || getDatabase();
this.accountability = options.accountability || null;
this.schema = options.schema;
}
async getMetaForQuery(collection, query) {
if (!query || !query.meta)
return;
const results = await Promise.all(query.meta.map((metaVal) => {
if (metaVal === 'total_count')
return this.totalCount(collection);
if (metaVal === 'filter_count')
return this.filterCount(collection, query);
return undefined;
}));
return results.reduce((metaObject, value, index) => {
return {
...metaObject,
[query.meta[index]]: value,
};
}, {});
}
async totalCount(collection) {
return this.filterCount(collection, {});
}
async filterCount(collection, query) {
let permissions = [];
if (this.accountability && this.accountability.admin !== true) {
const context = { knex: this.knex, schema: this.schema };
await validateAccess({
accountability: this.accountability,
action: 'read',
collection,
}, context);
const policies = await fetchPolicies(this.accountability, context);
permissions = await fetchPermissions({ action: 'read', accountability: this.accountability, policies }, context);
}
const { cases } = getCases(collection, permissions, []);
const { query: dbQuery, hasJoins } = applyQuery(this.knex, collection, this.knex(collection), {
filter: query.filter ?? null,
search: query.search ?? null,
}, this.schema, cases, permissions);
if (hasJoins) {
dbQuery.countDistinct({ count: [`${collection}.${this.schema.collections[collection].primary}`] });
}
else {
dbQuery.count('*', { as: 'count' });
}
const records = await dbQuery;
return Number((isArray(records) ? records[0]?.['count'] : records?.['count']) ?? 0);
}
}