mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
* fix graphql schema for m2o fields * add e2e tests for graphql m2o & o2m * remove unused code * fix mariadb json error * attempt to fix oracle * possibly fix graphql m2o queries
125 lines
3.5 KiB
TypeScript
125 lines
3.5 KiB
TypeScript
import { uniq } from 'lodash';
|
|
|
|
import { Permission, PermissionsAction, SchemaOverview } from '@directus/shared/types';
|
|
|
|
/**
|
|
* Reduces the schema based on the included permissions. The resulting object is the schema structure, but with only
|
|
* the allowed collections/fields/relations included based on the permissions.
|
|
* @param schema The full project schema
|
|
* @param actions Array of permissions actions (crud)
|
|
* @returns Reduced schema
|
|
*/
|
|
export function reduceSchema(
|
|
schema: SchemaOverview,
|
|
permissions: Permission[] | null,
|
|
actions: PermissionsAction[] = ['create', 'read', 'update', 'delete']
|
|
): SchemaOverview {
|
|
const reduced: SchemaOverview = {
|
|
collections: {},
|
|
relations: [],
|
|
};
|
|
|
|
const allowedFieldsInCollection =
|
|
permissions
|
|
?.filter((permission) => actions.includes(permission.action))
|
|
.reduce((acc, permission) => {
|
|
if (!acc[permission.collection]) {
|
|
acc[permission.collection] = [];
|
|
}
|
|
|
|
if (permission.fields) {
|
|
acc[permission.collection] = uniq([...acc[permission.collection], ...permission.fields]);
|
|
}
|
|
|
|
return acc;
|
|
}, {} as { [collection: string]: string[] }) ?? {};
|
|
|
|
for (const [collectionName, collection] of Object.entries(schema.collections)) {
|
|
if (
|
|
!permissions?.some(
|
|
(permission) => permission.collection === collectionName && actions.includes(permission.action)
|
|
)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
const fields: SchemaOverview['collections'][string]['fields'] = {};
|
|
|
|
for (const [fieldName, field] of Object.entries(schema.collections[collectionName].fields)) {
|
|
if (
|
|
!allowedFieldsInCollection[collectionName]?.includes('*') &&
|
|
!allowedFieldsInCollection[collectionName]?.includes(fieldName)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
const o2mRelation = schema.relations.find(
|
|
(relation) => relation.related_collection === collectionName && relation.meta?.one_field === fieldName
|
|
);
|
|
|
|
if (
|
|
o2mRelation &&
|
|
!permissions?.some(
|
|
(permission) => permission.collection === o2mRelation.collection && actions.includes(permission.action)
|
|
)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
fields[fieldName] = field;
|
|
}
|
|
|
|
reduced.collections[collectionName] = {
|
|
...collection,
|
|
fields,
|
|
};
|
|
}
|
|
|
|
reduced.relations = schema.relations.filter((relation) => {
|
|
let collectionsAllowed = true;
|
|
let fieldsAllowed = true;
|
|
|
|
if (Object.keys(allowedFieldsInCollection).includes(relation.collection) === false) {
|
|
collectionsAllowed = false;
|
|
}
|
|
|
|
if (
|
|
relation.related_collection &&
|
|
Object.keys(allowedFieldsInCollection).includes(relation.related_collection) === false
|
|
) {
|
|
collectionsAllowed = false;
|
|
}
|
|
|
|
if (
|
|
relation.meta?.one_allowed_collections &&
|
|
relation.meta.one_allowed_collections.every((collection) =>
|
|
Object.keys(allowedFieldsInCollection).includes(collection)
|
|
) === false
|
|
) {
|
|
collectionsAllowed = false;
|
|
}
|
|
|
|
if (
|
|
!allowedFieldsInCollection[relation.collection] ||
|
|
(allowedFieldsInCollection[relation.collection].includes('*') === false &&
|
|
allowedFieldsInCollection[relation.collection].includes(relation.field) === false)
|
|
) {
|
|
fieldsAllowed = false;
|
|
}
|
|
|
|
if (
|
|
relation.related_collection &&
|
|
relation.meta?.one_field &&
|
|
(!allowedFieldsInCollection[relation.related_collection] ||
|
|
(allowedFieldsInCollection[relation.related_collection].includes('*') === false &&
|
|
allowedFieldsInCollection[relation.related_collection].includes(relation.meta?.one_field) === false))
|
|
) {
|
|
fieldsAllowed = false;
|
|
}
|
|
|
|
return collectionsAllowed && fieldsAllowed;
|
|
});
|
|
|
|
return reduced;
|
|
}
|