mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Run prettier across app and api
This commit is contained in:
@@ -42,9 +42,7 @@ export default async function applyQuery(
|
||||
columns
|
||||
/** @todo Check if this scales between SQL vendors */
|
||||
.filter(
|
||||
(column) =>
|
||||
column.data_type.toLowerCase().includes('text') ||
|
||||
column.data_type.toLowerCase().includes('char')
|
||||
(column) => column.data_type.toLowerCase().includes('text') || column.data_type.toLowerCase().includes('char')
|
||||
)
|
||||
.forEach((column) => {
|
||||
this.orWhereRaw(`LOWER(??) LIKE ?`, [column.column_name, `%${query.search!}%`]);
|
||||
@@ -53,37 +51,19 @@ export default async function applyQuery(
|
||||
}
|
||||
}
|
||||
|
||||
export async function applyFilter(
|
||||
knex: Knex,
|
||||
rootQuery: QueryBuilder,
|
||||
rootFilter: Filter,
|
||||
collection: string
|
||||
) {
|
||||
const relations: Relation[] = [
|
||||
...(await knex.select('*').from('directus_relations')),
|
||||
...systemRelationRows,
|
||||
];
|
||||
export async function applyFilter(knex: Knex, rootQuery: QueryBuilder, rootFilter: Filter, collection: string) {
|
||||
const relations: Relation[] = [...(await knex.select('*').from('directus_relations')), ...systemRelationRows];
|
||||
|
||||
addWhereClauses(rootQuery, rootFilter, collection);
|
||||
addJoins(rootQuery, rootFilter, collection);
|
||||
|
||||
function addWhereClauses(
|
||||
dbQuery: QueryBuilder,
|
||||
filter: Filter,
|
||||
collection: string,
|
||||
logical: 'and' | 'or' = 'and'
|
||||
) {
|
||||
function addWhereClauses(dbQuery: QueryBuilder, filter: Filter, collection: string, logical: 'and' | 'or' = 'and') {
|
||||
for (const [key, value] of Object.entries(filter)) {
|
||||
if (key === '_or' || key === '_and') {
|
||||
/** @NOTE this callback function isn't called until Knex runs the query */
|
||||
dbQuery.where((subQuery) => {
|
||||
value.forEach((subFilter: Record<string, any>) => {
|
||||
addWhereClauses(
|
||||
subQuery,
|
||||
subFilter,
|
||||
collection,
|
||||
key === '_and' ? 'and' : 'or'
|
||||
);
|
||||
addWhereClauses(subQuery, subFilter, collection, key === '_and' ? 'and' : 'or');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,21 +77,11 @@ export async function applyFilter(
|
||||
const columnName = getWhereColumn(filterPath, collection);
|
||||
applyFilterToQuery(columnName, filterOperator, filterValue, logical);
|
||||
} else {
|
||||
applyFilterToQuery(
|
||||
`${collection}.${filterPath[0]}`,
|
||||
filterOperator,
|
||||
filterValue,
|
||||
logical
|
||||
);
|
||||
applyFilterToQuery(`${collection}.${filterPath[0]}`, filterOperator, filterValue, logical);
|
||||
}
|
||||
}
|
||||
|
||||
function applyFilterToQuery(
|
||||
key: string,
|
||||
operator: string,
|
||||
compareValue: any,
|
||||
logical: 'and' | 'or' = 'and'
|
||||
) {
|
||||
function applyFilterToQuery(key: string, operator: string, compareValue: any, logical: 'and' | 'or' = 'and') {
|
||||
if (operator === '_eq') {
|
||||
dbQuery[logical].where({ [key]: compareValue });
|
||||
}
|
||||
@@ -207,18 +177,14 @@ export async function applyFilter(
|
||||
function followRelation(pathParts: string[], parentCollection: string = collection) {
|
||||
const relation = relations.find((relation) => {
|
||||
return (
|
||||
(relation.many_collection === parentCollection &&
|
||||
relation.many_field === pathParts[0]) ||
|
||||
(relation.one_collection === parentCollection &&
|
||||
relation.one_field === pathParts[0])
|
||||
(relation.many_collection === parentCollection && relation.many_field === pathParts[0]) ||
|
||||
(relation.one_collection === parentCollection && relation.one_field === pathParts[0])
|
||||
);
|
||||
});
|
||||
|
||||
if (!relation) return;
|
||||
|
||||
const isM2O =
|
||||
relation.many_collection === parentCollection &&
|
||||
relation.many_field === pathParts[0];
|
||||
const isM2O = relation.many_collection === parentCollection && relation.many_field === pathParts[0];
|
||||
|
||||
pathParts.shift();
|
||||
|
||||
@@ -273,18 +239,14 @@ export async function applyFilter(
|
||||
function followRelation(pathParts: string[], parentCollection: string = collection) {
|
||||
const relation = relations.find((relation) => {
|
||||
return (
|
||||
(relation.many_collection === parentCollection &&
|
||||
relation.many_field === pathParts[0]) ||
|
||||
(relation.one_collection === parentCollection &&
|
||||
relation.one_field === pathParts[0])
|
||||
(relation.many_collection === parentCollection && relation.many_field === pathParts[0]) ||
|
||||
(relation.one_collection === parentCollection && relation.one_field === pathParts[0])
|
||||
);
|
||||
});
|
||||
|
||||
if (!relation) return;
|
||||
|
||||
const isM2O =
|
||||
relation.many_collection === parentCollection &&
|
||||
relation.many_field === pathParts[0];
|
||||
const isM2O = relation.many_collection === parentCollection && relation.many_field === pathParts[0];
|
||||
|
||||
if (isM2O) {
|
||||
dbQuery.leftJoin(
|
||||
|
||||
@@ -5,9 +5,7 @@ export function deepMap(
|
||||
): any {
|
||||
if (Array.isArray(object)) {
|
||||
return object.map(function (val, key) {
|
||||
return typeof val === 'object'
|
||||
? deepMap(val, iterator, context)
|
||||
: iterator.call(context, val, key);
|
||||
return typeof val === 'object' ? deepMap(val, iterator, context) : iterator.call(context, val, key);
|
||||
});
|
||||
} else if (typeof object === 'object') {
|
||||
const res: Record<string, any> = {};
|
||||
|
||||
@@ -45,10 +45,7 @@ export default async function getASTFromQuery(
|
||||
* we might not need al this info at all times, but it's easier to fetch it all once, than trying to fetch it for every
|
||||
* requested field. @todo look into utilizing graphql/dataloader for this purpose
|
||||
*/
|
||||
const relations = [
|
||||
...(await knex.select<Relation[]>('*').from('directus_relations')),
|
||||
...systemRelationRows,
|
||||
];
|
||||
const relations = [...(await knex.select<Relation[]>('*').from('directus_relations')), ...systemRelationRows];
|
||||
|
||||
const permissions =
|
||||
accountability && accountability.admin !== true
|
||||
@@ -76,11 +73,7 @@ export default async function getASTFromQuery(
|
||||
|
||||
return ast;
|
||||
|
||||
async function parseFields(
|
||||
parentCollection: string,
|
||||
fields: string[] | null,
|
||||
deep?: Record<string, Query>
|
||||
) {
|
||||
async function parseFields(parentCollection: string, fields: string[] | null, deep?: Record<string, Query>) {
|
||||
if (!fields) return [];
|
||||
|
||||
fields = await convertWildcards(parentCollection, fields);
|
||||
@@ -96,10 +89,7 @@ export default async function getASTFromQuery(
|
||||
field.includes('.') ||
|
||||
// We'll always treat top level o2m fields as a related item. This is an alias field, otherwise it won't return
|
||||
// anything
|
||||
!!relations.find(
|
||||
(relation) =>
|
||||
relation.one_collection === parentCollection && relation.one_field === field
|
||||
);
|
||||
!!relations.find((relation) => relation.one_collection === parentCollection && relation.one_field === field);
|
||||
|
||||
if (isRelational) {
|
||||
// field is relational
|
||||
@@ -131,9 +121,7 @@ export default async function getASTFromQuery(
|
||||
(relationalStructure[fieldKey] as anyNested)[collectionScope] = [];
|
||||
}
|
||||
|
||||
(relationalStructure[fieldKey] as anyNested)[collectionScope].push(
|
||||
childKey
|
||||
);
|
||||
(relationalStructure[fieldKey] as anyNested)[collectionScope].push(childKey);
|
||||
} else {
|
||||
(relationalStructure[fieldKey] as string[]).push(childKey);
|
||||
}
|
||||
@@ -160,14 +148,10 @@ export default async function getASTFromQuery(
|
||||
let child: NestedCollectionNode | null = null;
|
||||
|
||||
if (relationType === 'm2a') {
|
||||
const allowedCollections = relation
|
||||
.one_allowed_collections!.split(',')
|
||||
.filter((collection) => {
|
||||
if (!permissions) return true;
|
||||
return permissions.some(
|
||||
(permission) => permission.collection === collection
|
||||
);
|
||||
});
|
||||
const allowedCollections = relation.one_allowed_collections!.split(',').filter((collection) => {
|
||||
if (!permissions) return true;
|
||||
return permissions.some((permission) => permission.collection === collection);
|
||||
});
|
||||
|
||||
child = {
|
||||
type: 'm2a',
|
||||
@@ -183,20 +167,13 @@ export default async function getASTFromQuery(
|
||||
for (const relatedCollection of allowedCollections) {
|
||||
child.children[relatedCollection] = await parseFields(
|
||||
relatedCollection,
|
||||
Array.isArray(nestedFields)
|
||||
? nestedFields
|
||||
: (nestedFields as anyNested)[relatedCollection] || ['*']
|
||||
Array.isArray(nestedFields) ? nestedFields : (nestedFields as anyNested)[relatedCollection] || ['*']
|
||||
);
|
||||
child.query[relatedCollection] = {};
|
||||
child.relatedKey[relatedCollection] = schema[relatedCollection].primary;
|
||||
}
|
||||
} else if (relatedCollection) {
|
||||
if (
|
||||
permissions &&
|
||||
permissions.some(
|
||||
(permission) => permission.collection === relatedCollection
|
||||
) === false
|
||||
) {
|
||||
if (permissions && permissions.some((permission) => permission.collection === relatedCollection) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -226,9 +203,7 @@ export default async function getASTFromQuery(
|
||||
const fieldsInCollection = await getFieldsInCollection(parentCollection);
|
||||
|
||||
const allowedFields = permissions
|
||||
? permissions
|
||||
.find((permission) => parentCollection === permission.collection)
|
||||
?.fields?.split(',')
|
||||
? permissions.find((permission) => parentCollection === permission.collection)?.fields?.split(',')
|
||||
: fieldsInCollection;
|
||||
|
||||
if (!allowedFields || allowedFields.length === 0) return [];
|
||||
@@ -256,8 +231,7 @@ export default async function getASTFromQuery(
|
||||
? relations
|
||||
.filter(
|
||||
(relation) =>
|
||||
relation.many_collection === parentCollection ||
|
||||
relation.one_collection === parentCollection
|
||||
relation.many_collection === parentCollection || relation.one_collection === parentCollection
|
||||
)
|
||||
.map((relation) => {
|
||||
const isMany = relation.many_collection === parentCollection;
|
||||
@@ -265,9 +239,7 @@ export default async function getASTFromQuery(
|
||||
})
|
||||
: allowedFields.filter((fieldKey) => !!getRelation(parentCollection, fieldKey));
|
||||
|
||||
const nonRelationalFields = allowedFields.filter(
|
||||
(fieldKey) => relationalFields.includes(fieldKey) === false
|
||||
);
|
||||
const nonRelationalFields = allowedFields.filter((fieldKey) => relationalFields.includes(fieldKey) === false);
|
||||
|
||||
fields.splice(
|
||||
index,
|
||||
@@ -315,12 +287,8 @@ export default async function getASTFromQuery(
|
||||
async function getFieldsInCollection(collection: string) {
|
||||
const columns = Object.keys(schema[collection].columns);
|
||||
const fields = [
|
||||
...(await knex.select('field').from('directus_fields').where({ collection })).map(
|
||||
(field) => field.field
|
||||
),
|
||||
...systemFieldRows
|
||||
.filter((fieldMeta) => fieldMeta.collection === collection)
|
||||
.map((fieldMeta) => fieldMeta.field),
|
||||
...(await knex.select('field').from('directus_fields').where({ collection })).map((field) => field.field),
|
||||
...systemFieldRows.filter((fieldMeta) => fieldMeta.collection === collection).map((fieldMeta) => fieldMeta.field),
|
||||
];
|
||||
|
||||
const fieldsInCollection = [
|
||||
|
||||
@@ -3,8 +3,6 @@ import url from 'url';
|
||||
|
||||
export function getCacheKey(req: Request) {
|
||||
const path = url.parse(req.originalUrl).pathname;
|
||||
const key = `${req.accountability?.user || 'null'}-${path}-${JSON.stringify(
|
||||
req.sanitizedQuery
|
||||
)}`;
|
||||
const key = `${req.accountability?.user || 'null'}-${path}-${JSON.stringify(req.sanitizedQuery)}`;
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,7 @@ export function getConfigFromEnv(prefix: string, omitPrefix?: string | string[])
|
||||
let matches = false;
|
||||
|
||||
if (Array.isArray(omitPrefix)) {
|
||||
matches = omitPrefix.some((prefix) =>
|
||||
key.toLowerCase().startsWith(prefix.toLowerCase())
|
||||
);
|
||||
matches = omitPrefix.some((prefix) => key.toLowerCase().startsWith(prefix.toLowerCase()));
|
||||
} else {
|
||||
matches = key.toLowerCase().startsWith(omitPrefix.toLowerCase());
|
||||
}
|
||||
@@ -25,9 +23,7 @@ export function getConfigFromEnv(prefix: string, omitPrefix?: string | string[])
|
||||
if (key.includes('__')) {
|
||||
const path = key
|
||||
.split('__')
|
||||
.map((key, index) =>
|
||||
index === 0 ? camelcase(camelcase(key.slice(prefix.length))) : camelcase(key)
|
||||
);
|
||||
.map((key, index) => (index === 0 ? camelcase(camelcase(key.slice(prefix.length))) : camelcase(key)));
|
||||
set(config, path.join('.'), value);
|
||||
} else {
|
||||
config[camelcase(key.slice(prefix.length))] = value;
|
||||
|
||||
@@ -2,9 +2,7 @@ import getLocalType from './get-local-type';
|
||||
import { Column } from '@directus/schema/dist/types/column';
|
||||
import { SchemaOverview } from '../types';
|
||||
|
||||
export default function getDefaultValue(
|
||||
column: SchemaOverview[string]['columns'][string] | Column
|
||||
) {
|
||||
export default function getDefaultValue(column: SchemaOverview[string]['columns'][string] | Column) {
|
||||
const type = getLocalType(column);
|
||||
|
||||
let defaultValue = column.default_value || null;
|
||||
|
||||
@@ -16,13 +16,15 @@ const profileMap: Record<string, string> = {};
|
||||
* This is used in the SSO flow to extract the users
|
||||
*/
|
||||
export default function getEmailFromProfile(provider: string, profile: Record<string, any>) {
|
||||
const path =
|
||||
profileMap[provider] || env[`OAUTH_${provider.toUpperCase()}_PROFILE_EMAIL`] || 'email';
|
||||
const path = profileMap[provider] || env[`OAUTH_${provider.toUpperCase()}_PROFILE_EMAIL`] || 'email';
|
||||
|
||||
const email = get(profile, path);
|
||||
|
||||
if (!email) {
|
||||
throw new ServiceUnavailableException("Couldn't extract email address from SSO provider response", { service: 'oauth', provider });
|
||||
throw new ServiceUnavailableException("Couldn't extract email address from SSO provider response", {
|
||||
service: 'oauth',
|
||||
provider,
|
||||
});
|
||||
}
|
||||
|
||||
return email;
|
||||
|
||||
@@ -87,11 +87,7 @@ export default function getLocalType(
|
||||
const type = localTypeMap[column.data_type.toLowerCase().split('(')[0]];
|
||||
|
||||
/** Handle Postgres numeric decimals */
|
||||
if (
|
||||
column.data_type === 'numeric' &&
|
||||
column.numeric_precision !== null &&
|
||||
column.numeric_scale !== null
|
||||
) {
|
||||
if (column.data_type === 'numeric' && column.numeric_precision !== null && column.numeric_scale !== null) {
|
||||
return 'decimal';
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,7 @@ export default function parseIPTC(buffer: Buffer) {
|
||||
let lastIptcEntryPos = buffer.indexOf(IPTC_ENTRY_MARKER);
|
||||
|
||||
while (lastIptcEntryPos !== -1) {
|
||||
lastIptcEntryPos = buffer.indexOf(
|
||||
IPTC_ENTRY_MARKER,
|
||||
lastIptcEntryPos + IPTC_ENTRY_MARKER.byteLength
|
||||
);
|
||||
lastIptcEntryPos = buffer.indexOf(IPTC_ENTRY_MARKER, lastIptcEntryPos + IPTC_ENTRY_MARKER.byteLength);
|
||||
|
||||
let iptcBlockTypePos = lastIptcEntryPos + IPTC_ENTRY_MARKER.byteLength;
|
||||
let iptcBlockSizePos = iptcBlockTypePos + 1;
|
||||
|
||||
@@ -3,10 +3,7 @@ import logger from '../logger';
|
||||
import { parseFilter } from '../utils/parse-filter';
|
||||
import { flatten } from 'lodash';
|
||||
|
||||
export function sanitizeQuery(
|
||||
rawQuery: Record<string, any>,
|
||||
accountability: Accountability | null
|
||||
) {
|
||||
export function sanitizeQuery(rawQuery: Record<string, any>, accountability: Accountability | null) {
|
||||
const query: Query = {};
|
||||
|
||||
if (rawQuery.limit !== undefined) {
|
||||
|
||||
@@ -79,13 +79,8 @@ function validateFilter(filter: Query['filter']) {
|
||||
}
|
||||
|
||||
function validateFilterPrimitive(value: any, key: string) {
|
||||
if (
|
||||
(typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') ===
|
||||
false
|
||||
) {
|
||||
throw new InvalidQueryException(
|
||||
`The filter value for "${key}" has to be a string or a number`
|
||||
);
|
||||
if ((typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') === false) {
|
||||
throw new InvalidQueryException(`The filter value for "${key}" has to be a string or a number`);
|
||||
}
|
||||
|
||||
if (typeof value === 'number' && Number.isNaN(value)) {
|
||||
|
||||
Reference in New Issue
Block a user