directus

Форк
0
/
merge-permissions.ts 
105 строк · 3.2 Кб
1
import type { LogicalFilterAND, LogicalFilterOR, Permission } from '@directus/types';
2
import { flatten, intersection, isEqual, merge, omit } from 'lodash-es';
3

4
export function mergePermissions(strategy: 'and' | 'or', ...permissions: Permission[][]): Permission[] {
5
	const allPermissions = flatten(permissions);
6

7
	const mergedPermissions = allPermissions
8
		.reduce((acc, val) => {
9
			const key = `${val.collection}__${val.action}__${val.role || '$PUBLIC'}`;
10
			const current = acc.get(key);
11
			acc.set(key, current ? mergePermission(strategy, current, val) : val);
12
			return acc;
13
		}, new Map())
14
		.values();
15

16
	return Array.from(mergedPermissions);
17
}
18

19
export function mergePermission(
20
	strategy: 'and' | 'or',
21
	currentPerm: Permission,
22
	newPerm: Permission,
23
): Omit<Permission, 'id' | 'system'> {
24
	const logicalKey = `_${strategy}` as keyof LogicalFilterOR | keyof LogicalFilterAND;
25

26
	let permissions = currentPerm.permissions;
27
	let validation = currentPerm.validation;
28
	let fields = currentPerm.fields;
29
	let presets = currentPerm.presets;
30

31
	if (newPerm.permissions) {
32
		if (currentPerm.permissions && Object.keys(currentPerm.permissions)[0] === logicalKey) {
33
			permissions = {
34
				[logicalKey]: [
35
					...(currentPerm.permissions as LogicalFilterOR & LogicalFilterAND)[logicalKey],
36
					newPerm.permissions,
37
				],
38
			} as LogicalFilterAND | LogicalFilterOR;
39
		} else if (currentPerm.permissions) {
40
			// Empty {} supersedes other permissions in _OR merge
41
			if (strategy === 'or' && (isEqual(currentPerm.permissions, {}) || isEqual(newPerm.permissions, {}))) {
42
				permissions = {};
43
			} else {
44
				permissions = {
45
					[logicalKey]: [currentPerm.permissions, newPerm.permissions],
46
				} as LogicalFilterAND | LogicalFilterOR;
47
			}
48
		} else {
49
			permissions = {
50
				[logicalKey]: [newPerm.permissions],
51
			} as LogicalFilterAND | LogicalFilterOR;
52
		}
53
	}
54

55
	if (newPerm.validation) {
56
		if (currentPerm.validation && Object.keys(currentPerm.validation)[0] === logicalKey) {
57
			validation = {
58
				[logicalKey]: [
59
					...(currentPerm.validation as LogicalFilterOR & LogicalFilterAND)[logicalKey],
60
					newPerm.validation,
61
				],
62
			} as LogicalFilterAND | LogicalFilterOR;
63
		} else if (currentPerm.validation) {
64
			// Empty {} supersedes other validations in _OR merge
65
			if (strategy === 'or' && (isEqual(currentPerm.validation, {}) || isEqual(newPerm.validation, {}))) {
66
				validation = {};
67
			} else {
68
				validation = {
69
					[logicalKey]: [currentPerm.validation, newPerm.validation],
70
				} as LogicalFilterAND | LogicalFilterOR;
71
			}
72
		} else {
73
			validation = {
74
				[logicalKey]: [newPerm.validation],
75
			} as LogicalFilterAND | LogicalFilterOR;
76
		}
77
	}
78

79
	if (newPerm.fields) {
80
		if (Array.isArray(currentPerm.fields) && strategy === 'or') {
81
			fields = [...new Set([...currentPerm.fields, ...newPerm.fields])];
82
		} else if (Array.isArray(currentPerm.fields) && strategy === 'and') {
83
			fields = intersection(currentPerm.fields, newPerm.fields);
84
		} else {
85
			fields = newPerm.fields;
86
		}
87

88
		if (fields.includes('*')) fields = ['*'];
89
	}
90

91
	if (newPerm.presets) {
92
		presets = merge({}, presets, newPerm.presets);
93
	}
94

95
	return omit(
96
		{
97
			...currentPerm,
98
			permissions,
99
			validation,
100
			fields,
101
			presets,
102
		},
103
		['id', 'system'],
104
	);
105
}
106

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

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

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

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