Repository: directus/directus
File: api/src/permissions/modules/process-ast/utils/extract-paths-from-query.ts (TypeScript)

Code before:
 * 	['category']
 * ]
 * ```
 */
export function extractPathsFromQuery(query: Query) {
	/**
	 * All nested paths used in the current query scope.
	 * This is generated by flattening the filters and adding in the used sort/aggregate fields.
	 */
	const paths: FieldKey[][] = [];
	const readOnlyPaths: FieldKey[][] = [];

	if (query.filter) {
		flattenFilter(readOnlyPaths, query.filter);
	}

	if (query.sort) {
		for (const field of query.sort) {
			// Sort can have dot notation fields for sorting on m2o values Sort fields can start with
			// `-` to indicate descending order, which should be dropped for permissions checks

			const parts = field.split('.').map((field) => (field.startsWith('-') ? field.substring(1) : field));

			if (query.aggregate && parts.length > 0 && parts[0]! in query.aggregate) {
				// If query is an aggregate query and the first part is a requested aggregate operation ignore the whole field
				// The correct field is extracted into the field map when procession the `query.aggregate` fields.
				continue;
			}

			readOnlyPaths.push(parts);
		}
	}

	if (query.aggregate) {
		for (const fields of Object.values(query.aggregate)) {
			for (const field of fields) {
				if (field === '*') {
					// Don't add wildcard field to the paths
					continue;
				}

				// Aggregate doesn't currently support aggregating on nested fields, but it doesn't hurt
				// to standardize it in the validation layer
				paths.push(field.split('.'));
			}
		}
	}

	if (query.group) {
		for (const field of query.group) {
			// Grouping doesn't currently support grouping on nested fields, but it doesn't hurt to

Review comment (refactor):
```suggestion
				// If query is an aggregate query and the first part is a requested aggregate operation, ignore the whole field.
				// The correct field is extracted into the field map when processing the `query.aggregate` fields.
```

Code after:
 * 	['category']
 * ]
 * ```
 */
export function extractPathsFromQuery(query: Query) {
	/**
	 * All nested paths used in the current query scope.
	 * This is generated by flattening the filters and adding in the used sort/aggregate fields.
	 */
	const paths: FieldKey[][] = [];
	const readOnlyPaths: FieldKey[][] = [];

	if (query.filter) {
		flattenFilter(readOnlyPaths, query.filter);
	}

	if (query.sort) {
		for (const field of query.sort) {
			// Sort can have dot notation fields for sorting on m2o values Sort fields can start with
			// `-` to indicate descending order, which should be dropped for permissions checks

			const parts = field.split('.').map((field) => (field.startsWith('-') ? field.substring(1) : field));

			if (query.aggregate && parts.length > 0 && parts[0]! in query.aggregate) {
				// If query is an aggregate query and the first part is a requested aggregate operation, ignore the whole field.
				// The correct field is extracted into the field map when processing the `query.aggregate` fields.
				continue;
			}

			readOnlyPaths.push(parts);
		}
	}

	if (query.aggregate) {
		for (const fields of Object.values(query.aggregate)) {
			for (const field of fields) {
				if (field === '*') {
					// Don't add wildcard field to the paths
					continue;
				}

				// Aggregate doesn't currently support aggregating on nested fields, but it doesn't hurt
				// to standardize it in the validation layer
				paths.push(field.split('.'));
			}
		}
	}

	if (query.group) {
		for (const field of query.group) {
			// Grouping doesn't currently support grouping on nested fields, but it doesn't hurt to