directus

Форк
0
/
reduce-schema.ts 
128 строк · 3.6 Кб
1
import type { Permission, PermissionsAction, SchemaOverview } from '@directus/types';
2
import { uniq } from 'lodash-es';
3

4
/**
5
 * Reduces the schema based on the included permissions. The resulting object is the schema structure, but with only
6
 * the allowed collections/fields/relations included based on the permissions.
7
 * @param schema The full project schema
8
 * @param actions Array of permissions actions (crud)
9
 * @returns Reduced schema
10
 */
11
export function reduceSchema(
12
	schema: SchemaOverview,
13
	permissions: Permission[] | null,
14
	actions: PermissionsAction[] = ['create', 'read', 'update', 'delete'],
15
): SchemaOverview {
16
	const reduced: SchemaOverview = {
17
		collections: {},
18
		relations: [],
19
	};
20

21
	const allowedFieldsInCollection =
22
		permissions
23
			?.filter((permission) => actions.includes(permission.action))
24
			.reduce(
25
				(acc, permission) => {
26
					if (!acc[permission.collection]) {
27
						acc[permission.collection] = [];
28
					}
29

30
					if (permission.fields) {
31
						acc[permission.collection] = uniq([...acc[permission.collection]!, ...permission.fields]);
32
					}
33

34
					return acc;
35
				},
36
				{} as { [collection: string]: string[] },
37
			) ?? {};
38

39
	for (const [collectionName, collection] of Object.entries(schema.collections)) {
40
		if (
41
			!permissions?.some(
42
				(permission) => permission.collection === collectionName && actions.includes(permission.action),
43
			)
44
		) {
45
			continue;
46
		}
47

48
		const fields: SchemaOverview['collections'][string]['fields'] = {};
49

50
		for (const [fieldName, field] of Object.entries(schema.collections[collectionName]!.fields)) {
51
			if (
52
				!allowedFieldsInCollection[collectionName]?.includes('*') &&
53
				!allowedFieldsInCollection[collectionName]?.includes(fieldName)
54
			) {
55
				continue;
56
			}
57

58
			const o2mRelation = schema.relations.find(
59
				(relation) => relation.related_collection === collectionName && relation.meta?.one_field === fieldName,
60
			);
61

62
			if (
63
				o2mRelation &&
64
				!permissions?.some(
65
					(permission) => permission.collection === o2mRelation.collection && actions.includes(permission.action),
66
				)
67
			) {
68
				continue;
69
			}
70

71
			fields[fieldName] = field;
72
		}
73

74
		reduced.collections[collectionName] = {
75
			...collection,
76
			fields,
77
		};
78
	}
79

80
	reduced.relations = schema.relations.filter((relation) => {
81
		let collectionsAllowed = true;
82
		let fieldsAllowed = true;
83

84
		if (Object.keys(allowedFieldsInCollection).includes(relation.collection) === false) {
85
			collectionsAllowed = false;
86
		}
87

88
		if (
89
			relation.related_collection &&
90
			(Object.keys(allowedFieldsInCollection).includes(relation.related_collection) === false ||
91
				// Ignore legacy permissions with an empty fields array
92
				allowedFieldsInCollection[relation.related_collection]?.length === 0)
93
		) {
94
			collectionsAllowed = false;
95
		}
96

97
		if (
98
			relation.meta?.one_allowed_collections &&
99
			relation.meta.one_allowed_collections.every((collection) =>
100
				Object.keys(allowedFieldsInCollection).includes(collection),
101
			) === false
102
		) {
103
			collectionsAllowed = false;
104
		}
105

106
		if (
107
			!allowedFieldsInCollection[relation.collection] ||
108
			(allowedFieldsInCollection[relation.collection]?.includes('*') === false &&
109
				allowedFieldsInCollection[relation.collection]?.includes(relation.field) === false)
110
		) {
111
			fieldsAllowed = false;
112
		}
113

114
		if (
115
			relation.related_collection &&
116
			relation.meta?.one_field &&
117
			(!allowedFieldsInCollection[relation.related_collection] ||
118
				(allowedFieldsInCollection[relation.related_collection]?.includes('*') === false &&
119
					allowedFieldsInCollection[relation.related_collection]?.includes(relation.meta?.one_field) === false))
120
		) {
121
			fieldsAllowed = false;
122
		}
123

124
		return collectionsAllowed && fieldsAllowed;
125
	});
126

127
	return reduced;
128
}
129

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

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

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

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