UNPKG

@directus/api

Version:

Directus is a real-time API and App dashboard for managing SQL database content

80 lines (79 loc) 3.88 kB
import { getRelation } from '@directus/utils'; import { cloneDeep } from 'lodash-es'; import { fetchAllowedFields } from '../../../permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js'; import { parseFilterKey } from '../../../utils/parse-filter-key.js'; export async function convertWildcards(options, context) { const fields = cloneDeep(options.fields); const fieldsInCollection = Object.entries(context.schema.collections[options.collection].fields).map(([name]) => name); let allowedFields = fieldsInCollection; if (options.accountability && options.accountability.admin === false) { allowedFields = await fetchAllowedFields({ collection: options.collection, action: 'read', accountability: options.accountability, }, context); } if (!allowedFields || allowedFields.length === 0) return []; // In case of full read permissions if (allowedFields[0] === '*') allowedFields = fieldsInCollection; for (let index = 0; index < fields.length; index++) { const fieldKey = fields[index]; if (fieldKey.includes('*') === false) continue; if (fieldKey === '*') { const aliases = Object.keys(options.alias ?? {}); // Set to all fields in collection if (allowedFields.includes('*')) { fields.splice(index, 1, ...fieldsInCollection, ...aliases); } else { // Set to all allowed fields const allowedAliases = aliases.filter((fieldKey) => { const { fieldName } = parseFilterKey(options.alias[fieldKey]); return allowedFields.includes(fieldName); }); fields.splice(index, 1, ...allowedFields, ...allowedAliases); } } // Swap *.* case for *,<relational-field>.*,<another-relational>.* if (fieldKey.includes('.') && fieldKey.split('.')[0] === '*') { const parts = fieldKey.split('.'); let relationalFields = []; if (allowedFields.includes('*')) { relationalFields = context.schema.relations.reduce((acc, relation) => { if (relation.collection === options.collection && !acc.includes(relation.field)) { acc.push(relation.field); } if (relation.related_collection === options.collection && !acc.includes(relation.meta.one_field)) { acc.push(relation.meta.one_field); } return acc; }, []); } else { relationalFields = allowedFields.filter((fieldKey) => getRelation(context.schema.relations, options.collection, fieldKey) !== undefined); } if (options.backlink === false) { relationalFields = relationalFields.filter((relationField) => getRelation(context.schema.relations, options.collection, relationField) !== context.parentRelation); } const nonRelationalFields = allowedFields.filter((fieldKey) => relationalFields.includes(fieldKey) === false); const aliasFields = Object.keys(options.alias ?? {}).map((fieldKey) => { const name = options.alias[fieldKey]; if (relationalFields.includes(name)) { return `${fieldKey}.${parts.slice(1).join('.')}`; } return fieldKey; }); fields.splice(index, 1, ...[ ...relationalFields.map((relationalField) => { return `${relationalField}.${parts.slice(1).join('.')}`; }), ...nonRelationalFields, ...aliasFields, ]); } } return fields; }