directus

Форк
0
100 строк · 2.9 Кб
1
import type { Accountability, Query, SchemaOverview } from '@directus/types';
2
import type { Knex } from 'knex';
3
import getDatabase from '../database/index.js';
4
import { ForbiddenError } from '@directus/errors';
5
import type { AbstractServiceOptions } from '../types/index.js';
6
import { applyFilter, applySearch } from '../utils/apply-query.js';
7

8
export class MetaService {
9
	knex: Knex;
10
	accountability: Accountability | null;
11
	schema: SchemaOverview;
12

13
	constructor(options: AbstractServiceOptions) {
14
		this.knex = options.knex || getDatabase();
15
		this.accountability = options.accountability || null;
16
		this.schema = options.schema;
17
	}
18

19
	async getMetaForQuery(collection: string, query: any): Promise<Record<string, any> | undefined> {
20
		if (!query || !query.meta) return;
21

22
		const results = await Promise.all(
23
			query.meta.map((metaVal: string) => {
24
				if (metaVal === 'total_count') return this.totalCount(collection);
25
				if (metaVal === 'filter_count') return this.filterCount(collection, query);
26
				return undefined;
27
			}),
28
		);
29

30
		return results.reduce((metaObject: Record<string, any>, value, index) => {
31
			return {
32
				...metaObject,
33
				[query.meta![index]]: value,
34
			};
35
		}, {});
36
	}
37

38
	async totalCount(collection: string): Promise<number> {
39
		const dbQuery = this.knex(collection).count('*', { as: 'count' }).first();
40

41
		if (this.accountability?.admin !== true) {
42
			const permissionsRecord = this.accountability?.permissions?.find((permission) => {
43
				return permission.action === 'read' && permission.collection === collection;
44
			});
45

46
			if (!permissionsRecord) throw new ForbiddenError();
47

48
			const permissions = permissionsRecord.permissions ?? {};
49

50
			applyFilter(this.knex, this.schema, dbQuery, permissions, collection, {});
51
		}
52

53
		const result = await dbQuery;
54

55
		return Number(result?.count ?? 0);
56
	}
57

58
	async filterCount(collection: string, query: Query): Promise<number> {
59
		const dbQuery = this.knex(collection);
60

61
		let filter = query.filter || {};
62
		let hasJoins = false;
63

64
		if (this.accountability?.admin !== true) {
65
			const permissionsRecord = this.accountability?.permissions?.find((permission) => {
66
				return permission.action === 'read' && permission.collection === collection;
67
			});
68

69
			if (!permissionsRecord) throw new ForbiddenError();
70

71
			const permissions = permissionsRecord.permissions ?? {};
72

73
			if (Object.keys(filter).length > 0) {
74
				filter = { _and: [permissions, filter] };
75
			} else {
76
				filter = permissions;
77
			}
78
		}
79

80
		if (Object.keys(filter).length > 0) {
81
			({ hasJoins } = applyFilter(this.knex, this.schema, dbQuery, filter, collection, {}));
82
		}
83

84
		if (query.search) {
85
			applySearch(this.knex, this.schema, dbQuery, query.search, collection);
86
		}
87

88
		if (hasJoins) {
89
			const primaryKeyName = this.schema.collections[collection]!.primary;
90

91
			dbQuery.countDistinct({ count: [`${collection}.${primaryKeyName}`] });
92
		} else {
93
			dbQuery.count('*', { as: 'count' });
94
		}
95

96
		const records = await dbQuery;
97

98
		return Number(records[0]!['count']);
99
	}
100
}
101

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.