From 44b48637881697d6a3082bbe197e12f0fea30f6b Mon Sep 17 00:00:00 2001 From: Rijk van Zanten Date: Tue, 2 May 2023 16:02:43 -0400 Subject: [PATCH] Require curly brackets in if statements when they're multi-line (#18387) * Enable Curly rule * Fix curly misuse --- .eslintrc.js | 1 + api/src/controllers/utils.ts | 6 +++-- api/src/services/collections.ts | 3 ++- api/src/services/graphql/index.ts | 9 +++++--- api/src/utils/apply-query.ts | 3 ++- api/src/utils/transformations.ts | 6 +++-- .../components/v-field-list/v-field-list.vue | 4 +++- app/src/composables/use-relation-multiple.ts | 23 +++++++++++++------ app/src/interfaces/files/files.vue | 7 ++++-- app/src/interfaces/list-m2a/list-m2a.vue | 12 +++++++--- app/src/interfaces/list-m2m/list-m2m.vue | 4 +++- .../list-o2m-tree-view/list-o2m-tree-view.vue | 4 +++- app/src/layouts/tabular/tabular.vue | 4 +++- app/src/modules/activity/routes/item.vue | 4 +++- app/src/modules/insights/routes/dashboard.vue | 15 ++++++++---- .../flows/components/operation-detail.vue | 3 ++- .../routes/flows/components/operation.vue | 4 +++- .../modules/settings/routes/flows/flow.vue | 7 ++++-- .../permissions-overview-toggle.vue | 4 +++- app/src/stores/fields.ts | 4 +++- app/src/utils/get-js-type.ts | 3 ++- .../views/private/components/drawer-item.vue | 5 +++- .../components/flow-sidebar-detail.vue | 5 +++- .../components/refresh-sidebar-detail.vue | 3 ++- tests/blackbox/setup/setup-utils.js | 5 +++- tests/blackbox/setup/setup.ts | 3 ++- 26 files changed, 109 insertions(+), 42 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index ecf0ec24b2..39eb38bd48 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,6 +38,7 @@ const defaultRules = { ], 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], 'no-nested-ternary': 'error', + curly: ['error', 'multi-line'], }; module.exports = { diff --git a/api/src/controllers/utils.ts b/api/src/controllers/utils.ts index 70cae488ee..e8ece84f04 100644 --- a/api/src/controllers/utils.ts +++ b/api/src/controllers/utils.ts @@ -25,8 +25,9 @@ router.get( asyncHandler(async (req, res) => { const { nanoid } = await import('nanoid'); - if (req.query && req.query['length'] && Number(req.query['length']) > 500) + if (req.query && req.query['length'] && Number(req.query['length']) > 500) { throw new InvalidQueryException(`"length" can't be more than 500 characters`); + } const string = nanoid(req.query?.['length'] ? Number(req.query['length']) : 32); @@ -105,8 +106,9 @@ router.post( '/import/:collection', collectionExists, asyncHandler(async (req, res, next) => { - if (req.is('multipart/form-data') === false) + if (req.is('multipart/form-data') === false) { throw new UnsupportedMediaTypeException(`Unsupported Content-Type header`); + } const service = new ImportService({ accountability: req.accountability, diff --git a/api/src/services/collections.ts b/api/src/services/collections.ts index b29f9f25bc..a82dd005e7 100644 --- a/api/src/services/collections.ts +++ b/api/src/services/collections.ts @@ -88,7 +88,7 @@ export class CollectionsService { // Directus heavily relies on the primary key of a collection, so we have to make sure that // every collection that is created has a primary key. If no primary key field is created // while making the collection, we default to an auto incremented id named `id` - if (!payload.fields) + if (!payload.fields) { payload.fields = [ { field: 'id', @@ -104,6 +104,7 @@ export class CollectionsService { }, }, ]; + } // Ensure that every field meta has the field/collection fields filled correctly payload.fields = payload.fields.map((field) => { diff --git a/api/src/services/graphql/index.ts b/api/src/services/graphql/index.ts index 4f9a3bed7a..9a38ef4e02 100644 --- a/api/src/services/graphql/index.ts +++ b/api/src/services/graphql/index.ts @@ -157,8 +157,11 @@ export class GraphQLService { const formattedResult: FormattedExecutionResult = {}; if (result['data']) formattedResult.data = result['data']; - if (result['errors']) + + if (result['errors']) { formattedResult.errors = result['errors'].map((error) => processError(this.accountability, error)); + } + if (result['extensions']) formattedResult.extensions = result['extensions']; return formattedResult; @@ -422,9 +425,9 @@ export class GraphQLService { } if (collection.primary === field.field) { - if (!field.defaultValue && !field.special.includes('uuid') && action === 'create') + if (!field.defaultValue && !field.special.includes('uuid') && action === 'create') { type = new GraphQLNonNull(GraphQLID); - else if (['create', 'update'].includes(action)) type = GraphQLID; + } else if (['create', 'update'].includes(action)) type = GraphQLID; else type = new GraphQLNonNull(GraphQLID); } diff --git a/api/src/utils/apply-query.ts b/api/src/utils/apply-query.ts index fad5834349..7a3c6d6a88 100644 --- a/api/src/utils/apply-query.ts +++ b/api/src/utils/apply-query.ts @@ -357,8 +357,9 @@ export function applyFilter( if (key === '_or' || key === '_and') { // If the _or array contains an empty object (full permissions), we should short-circuit and ignore all other // permission checks, as {} already matches full permissions. - if (key === '_or' && value.some((subFilter: Record) => Object.keys(subFilter).length === 0)) + if (key === '_or' && value.some((subFilter: Record) => Object.keys(subFilter).length === 0)) { continue; + } value.forEach((subFilter: Record) => { addJoins(dbQuery, subFilter, collection); diff --git a/api/src/utils/transformations.ts b/api/src/utils/transformations.ts index e342702006..4ba317aa91 100644 --- a/api/src/utils/transformations.ts +++ b/api/src/utils/transformations.ts @@ -3,7 +3,7 @@ import type { File, Transformation, TransformationParams } from '../types/index. export function resolvePreset(input: TransformationParams, file: File): Transformation[] { const transforms = input.transforms ? [...input.transforms] : []; - if (input.format || input.quality) + if (input.format || input.quality) { transforms.push([ 'toFormat', input.format || (file.type!.split('/')[1] as any), @@ -11,8 +11,9 @@ export function resolvePreset(input: TransformationParams, file: File): Transfor quality: input.quality ? Number(input.quality) : undefined, }, ]); + } - if (input.width || input.height) + if (input.width || input.height) { transforms.push([ 'resize', { @@ -22,6 +23,7 @@ export function resolvePreset(input: TransformationParams, file: File): Transfor withoutEnlargement: input.withoutEnlargement ? Boolean(input.withoutEnlargement) : undefined, }, ]); + } return transforms; } diff --git a/app/src/components/v-field-list/v-field-list.vue b/app/src/components/v-field-list/v-field-list.vue index 62375903e3..0b7913b3e4 100644 --- a/app/src/components/v-field-list/v-field-list.vue +++ b/app/src/components/v-field-list/v-field-list.vue @@ -111,8 +111,10 @@ function filter(field: Field, parent?: FieldNode): boolean { if ( !includeRelations.value && (field.collection !== collection.value || (field.type === 'alias' && !field.meta?.special?.includes('group'))) - ) + ) { return false; + } + if (!search.value || isNil(parent) === false) return true; const children = isNil(field.schema?.foreign_key_table) diff --git a/app/src/composables/use-relation-multiple.ts b/app/src/composables/use-relation-multiple.ts index 7ad01ac22c..f4b394c1aa 100644 --- a/app/src/composables/use-relation-multiple.ts +++ b/app/src/composables/use-relation-multiple.ts @@ -44,12 +44,14 @@ export function useRelationMultiple( const _value = computed({ get() { - if (!value.value || Array.isArray(value.value)) + if (!value.value || Array.isArray(value.value)) { return { create: [], update: [], delete: [], }; + } + return value.value as ChangesItem; }, set(newValue) { @@ -380,8 +382,9 @@ export function useRelationMultiple( newPreviewQuery.filter === oldPreviewQuery?.filter && newPreviewQuery.search === oldPreviewQuery?.search && newItemId === oldItemId - ) + ) { return; + } updateItemCount(); }, @@ -457,8 +460,12 @@ export function useRelationMultiple( watch( selectedOnPage, (newVal, oldVal) => { - if (newVal.length !== oldVal?.length || !isEqual(newVal.map(getRelatedIDs), (oldVal ?? []).map(getRelatedIDs))) + if ( + newVal.length !== oldVal?.length || + !isEqual(newVal.map(getRelatedIDs), (oldVal ?? []).map(getRelatedIDs)) + ) { loadSelectedDisplay(); + } }, { immediate: true } ); @@ -657,8 +664,9 @@ export function useRelationMultiple( topLevelKeys.includes(relation.value.junctionField.field) && topLevelKeys.includes(relation.value.junctionPrimaryKeyField.field) && deepLevelKeys.length === 1 - ) + ) { return true; + } return ( topLevelKeys.length === 3 && @@ -685,25 +693,26 @@ export function useRelationMultiple( function getItemEdits(item: DisplayItem) { if ('$type' in item && item.$index !== undefined) { - if (item.$type === 'created') + if (item.$type === 'created') { return { ..._value.value.create[item.$index], $type: 'created', $index: item.$index, }; - else if (item.$type === 'updated') + } else if (item.$type === 'updated') { return { ..._value.value.update[item.$index], $type: 'updated', $index: item.$index, }; - else if (item.$type === 'deleted' && item.$edits !== undefined) + } else if (item.$type === 'deleted' && item.$edits !== undefined) { return { ..._value.value.update[item.$edits], $type: 'deleted', $index: item.$index, $edits: item.$edits, }; + } } return {}; diff --git a/app/src/interfaces/files/files.vue b/app/src/interfaces/files/files.vue index bde428931b..9c6899bf49 100644 --- a/app/src/interfaces/files/files.vue +++ b/app/src/interfaces/files/files.vue @@ -181,8 +181,10 @@ const templateWithDefaults = computed(() => { if (!relationInfo.value) return null; if (props.template) return props.template; - if (relationInfo.value.junctionCollection.meta?.display_template) + + if (relationInfo.value.junctionCollection.meta?.display_template) { return relationInfo.value.junctionCollection.meta?.display_template; + } let relatedDisplayTemplate = relationInfo.value.relatedCollection.meta?.display_template; @@ -390,12 +392,13 @@ const customFilter = computed(() => { }, }; - if (selectedPrimaryKeys.value.length > 0) + if (selectedPrimaryKeys.value.length > 0) { filter._and.push({ [relationInfo.value.relatedPrimaryKeyField.field]: { _nin: selectedPrimaryKeys.value, }, }); + } if (props.primaryKey !== '+') filter._and.push(selectFilter); diff --git a/app/src/interfaces/list-m2a/list-m2a.vue b/app/src/interfaces/list-m2a/list-m2a.vue index 2b0b6a5af9..4f9132fd7c 100644 --- a/app/src/interfaces/list-m2a/list-m2a.vue +++ b/app/src/interfaces/list-m2a/list-m2a.vue @@ -380,10 +380,15 @@ function getCollectionName(item: DisplayItem) { if (!info) return false; const collection = allowedCollections.value.find((coll) => coll.collection === item[info.collectionField.field]); - if (te(`collection_names_singular.${collection?.collection}`)) + + if (te(`collection_names_singular.${collection?.collection}`)) { return t(`collection_names_singular.${collection?.collection}`); - if (te(`collection_names_plural.${collection?.collection}`)) + } + + if (te(`collection_names_plural.${collection?.collection}`)) { return t(`collection_names_plural.${collection?.collection}`); + } + return collection?.name; } @@ -425,12 +430,13 @@ const customFilter = computed(() => { return acc; }, [] as (string | number)[]); - if (selectedPrimaryKeys.length > 0) + if (selectedPrimaryKeys.length > 0) { filter._and.push({ [info.relationPrimaryKeyFields[selectingFrom.value].field]: { _nin: selectedPrimaryKeys, }, }); + } if (props.primaryKey !== '+') filter._and.push(selectFilter); diff --git a/app/src/interfaces/list-m2m/list-m2m.vue b/app/src/interfaces/list-m2m/list-m2m.vue index 3abdf364c5..a708e78c66 100644 --- a/app/src/interfaces/list-m2m/list-m2m.vue +++ b/app/src/interfaces/list-m2m/list-m2m.vue @@ -278,8 +278,10 @@ const templateWithDefaults = computed(() => { if (!relationInfo.value) return null; if (props.template) return props.template; - if (relationInfo.value.junctionCollection.meta?.display_template) + + if (relationInfo.value.junctionCollection.meta?.display_template) { return relationInfo.value.junctionCollection.meta.display_template; + } let relatedDisplayTemplate = relationInfo.value.relatedCollection.meta?.display_template; diff --git a/app/src/interfaces/list-o2m-tree-view/list-o2m-tree-view.vue b/app/src/interfaces/list-o2m-tree-view/list-o2m-tree-view.vue index a5cb26c99d..cdc2c04447 100644 --- a/app/src/interfaces/list-o2m-tree-view/list-o2m-tree-view.vue +++ b/app/src/interfaces/list-o2m-tree-view/list-o2m-tree-view.vue @@ -65,12 +65,14 @@ const { collection, field, primaryKey } = toRefs(props); const _value = computed({ get() { - if (Array.isArray(props.value)) + if (Array.isArray(props.value)) { return { create: [], update: [], delete: [], }; + } + return props.value as ChangesItem; }, set: (val) => { diff --git a/app/src/layouts/tabular/tabular.vue b/app/src/layouts/tabular/tabular.vue index 31dc512def..97d63831ba 100644 --- a/app/src/layouts/tabular/tabular.vue +++ b/app/src/layouts/tabular/tabular.vue @@ -275,8 +275,10 @@ const showManualSort = computed(() => { if (!permission) return false; - if (Array.isArray(permission.fields) && permission.fields.length > 0) + if (Array.isArray(permission.fields) && permission.fields.length > 0) { return permission.fields.includes(props.sortField) || permission.fields.includes('*'); + } + return true; }); diff --git a/app/src/modules/activity/routes/item.vue b/app/src/modules/activity/routes/item.vue index 4e6a2caa9b..58d1c14e69 100644 --- a/app/src/modules/activity/routes/item.vue +++ b/app/src/modules/activity/routes/item.vue @@ -123,8 +123,10 @@ export default defineComponent({ item.value = response.data.data; if (item.value) { - if (te(`field_options.directus_activity.${item.value.action}`)) + if (te(`field_options.directus_activity.${item.value.action}`)) { item.value.action_translated = t(`field_options.directus_activity.${item.value.action}`); + } + item.value.timestamp = new Date(item.value.timestamp).toLocaleString(i18n.global.locale.value); } } catch (err: any) { diff --git a/app/src/modules/insights/routes/dashboard.vue b/app/src/modules/insights/routes/dashboard.vue index de091af96d..620b57ec70 100644 --- a/app/src/modules/insights/routes/dashboard.vue +++ b/app/src/modules/insights/routes/dashboard.vue @@ -275,14 +275,21 @@ const tiles = computed(() => { [otherPanel.coordinates[3], otherPanel.coordinates[0]], ]; - if (topLeftIntersects === false) + if (topLeftIntersects === false) { topLeftIntersects = borders.some(([p1, p2]) => pointOnLine(panel.coordinates[0], p1, p2)); - if (topRightIntersects === false) + } + + if (topRightIntersects === false) { topRightIntersects = borders.some(([p1, p2]) => pointOnLine(panel.coordinates[1], p1, p2)); - if (bottomRightIntersects === false) + } + + if (bottomRightIntersects === false) { bottomRightIntersects = borders.some(([p1, p2]) => pointOnLine(panel.coordinates[2], p1, p2)); - if (bottomLeftIntersects === false) + } + + if (bottomLeftIntersects === false) { bottomLeftIntersects = borders.some(([p1, p2]) => pointOnLine(panel.coordinates[3], p1, p2)); + } } const panelType = unref(panelsInfo).find((panelType) => panelType.id === panel.type); diff --git a/app/src/modules/settings/routes/flows/components/operation-detail.vue b/app/src/modules/settings/routes/flows/components/operation-detail.vue index 1a8ee7761a..b338facc92 100644 --- a/app/src/modules/settings/routes/flows/components/operation-detail.vue +++ b/app/src/modules/settings/routes/flows/components/operation-detail.vue @@ -142,10 +142,11 @@ watch( slugify(oldName ?? '', { separator: '_', }) - ) + ) { operationKey.value = slugify(newName ?? '', { separator: '_', }); + } }, { immediate: true } ); diff --git a/app/src/modules/settings/routes/flows/components/operation.vue b/app/src/modules/settings/routes/flows/components/operation.vue index d6a7d84136..8828154207 100644 --- a/app/src/modules/settings/routes/flows/components/operation.vue +++ b/app/src/modules/settings/routes/flows/components/operation.vue @@ -265,8 +265,10 @@ function pointerup() { !moving.value && ((down === 'reject' && (!props.panel.reject || panelsToBeDeleted.value.includes(props.panel.reject))) || (down === 'resolve' && (!props.panel.resolve || panelsToBeDeleted.value.includes(props.panel.resolve)))) - ) + ) { emit('create', props.panel.id, down); + } + moving.value = false; down = undefined; if (rafId) window.cancelAnimationFrame(rafId); diff --git a/app/src/modules/settings/routes/flows/flow.vue b/app/src/modules/settings/routes/flows/flow.vue index 55476ff216..868b8f71b7 100644 --- a/app/src/modules/settings/routes/flows/flow.vue +++ b/app/src/modules/settings/routes/flows/flow.vue @@ -363,18 +363,21 @@ const currentOperation = computed(() => { const parentPanels = computed(() => { const parents = panels.value.reduce>((acc, panel) => { - if (panel.resolve) + if (panel.resolve) { acc[panel.resolve] = { id: panel.id, type: 'resolve', loner: true, }; - if (panel.reject) + } + + if (panel.reject) { acc[panel.reject] = { id: panel.id, type: 'reject', loner: true, }; + } return acc; }, {}); diff --git a/app/src/modules/settings/routes/roles/item/components/permissions-overview-toggle.vue b/app/src/modules/settings/routes/roles/item/components/permissions-overview-toggle.vue index 256b954099..8b300d81ef 100644 --- a/app/src/modules/settings/routes/roles/item/components/permissions-overview-toggle.vue +++ b/app/src/modules/settings/routes/roles/item/components/permissions-overview-toggle.vue @@ -110,12 +110,14 @@ export default defineComponent({ const permissionLevel = computed<'all' | 'none' | 'custom'>(() => { if (permission.value === undefined) return 'none'; + if ( permission.value.fields?.includes('*') && Object.keys(permission.value.permissions || {}).length === 0 && Object.keys(permission.value.validation || {}).length === 0 - ) + ) { return 'all'; + } return 'custom'; }); diff --git a/app/src/stores/fields.ts b/app/src/stores/fields.ts index f417038c8a..b01a4ac3b7 100644 --- a/app/src/stores/fields.ts +++ b/app/src/stores/fields.ts @@ -133,8 +133,10 @@ export const useFieldsStore = defineStore({ if (field.meta?.note) field.meta.note = translateLiteral(field.meta.note); if (field.meta?.options) field.meta.options = translate(field.meta.options); if (field.meta?.display_options) field.meta.display_options = translate(field.meta.display_options); - if (field.meta?.validation_message) + + if (field.meta?.validation_message) { field.meta.validation_message = translateLiteral(field.meta.validation_message); + } return field; }); diff --git a/app/src/utils/get-js-type.ts b/app/src/utils/get-js-type.ts index 69dafbcacc..82a7a6b508 100644 --- a/app/src/utils/get-js-type.ts +++ b/app/src/utils/get-js-type.ts @@ -4,8 +4,9 @@ export function getJSType(field: Field): string { if ( Array.isArray(field.meta?.special) && field.meta!.special.some((special) => ['m2o', 'o2m', 'm2m', 'm2a', 'files', 'translations'].includes(special)) - ) + ) { return 'object'; + } switch (field.type) { case 'bigInteger': diff --git a/app/src/views/private/components/drawer-item.vue b/app/src/views/private/components/drawer-item.vue index e63ce4a4d6..23986521e1 100644 --- a/app/src/views/private/components/drawer-item.vue +++ b/app/src/views/private/components/drawer-item.vue @@ -368,11 +368,14 @@ function useRelation() { if (!relationForField) return null; if (relationForField.related_collection) return relationForField.related_collection; - if (relationForField.meta?.one_collection_field) + + if (relationForField.meta?.one_collection_field) { return ( props.edits[relationForField.meta.one_collection_field] || initialValues.value?.[relationForField.meta.one_collection_field] ); + } + return null; }); diff --git a/app/src/views/private/components/flow-sidebar-detail.vue b/app/src/views/private/components/flow-sidebar-detail.vue index c875990be6..31e3fe6f9d 100644 --- a/app/src/views/private/components/flow-sidebar-detail.vue +++ b/app/src/views/private/components/flow-sidebar-detail.vue @@ -153,8 +153,11 @@ const resetConfirm = () => { const getFlowTooltip = (manualFlow: FlowRaw) => { if (location.value === 'item') return t('run_flow_on_current'); - if (manualFlow.options?.requireSelection === false && selection.value.length === 0) + + if (manualFlow.options?.requireSelection === false && selection.value.length === 0) { return t('run_flow_on_current_collection'); + } + return t('run_flow_on_selected', selection.value.length); }; diff --git a/app/src/views/private/components/refresh-sidebar-detail.vue b/app/src/views/private/components/refresh-sidebar-detail.vue index 1fb7760420..fd0e045056 100644 --- a/app/src/views/private/components/refresh-sidebar-detail.vue +++ b/app/src/views/private/components/refresh-sidebar-detail.vue @@ -55,11 +55,12 @@ export default defineComponent({ const intervals = [null, 10, 30, 60, 300]; return intervals.map((seconds) => { - if (seconds === null) + if (seconds === null) { return { text: t('no_refresh'), value: null, }; + } return seconds >= 60 && seconds % 60 === 0 ? { diff --git a/tests/blackbox/setup/setup-utils.js b/tests/blackbox/setup/setup-utils.js index 625be228d5..a8f5508fba 100644 --- a/tests/blackbox/setup/setup-utils.js +++ b/tests/blackbox/setup/setup-utils.js @@ -3,8 +3,11 @@ const argon2 = require('argon2'); exports.hash = function (stringToHash) { const buffer = 'string'; const argon2HashConfigOptions = { test: 'test', associatedData: buffer }; // Disallow the HASH_RAW option, see https://github.com/directus/directus/discussions/7670#discussioncomment-1255805 + // test, if specified, must be passed as a Buffer to argon2.hash, see https://github.com/ranisalt/node-argon2/wiki/Options#test - if ('test' in argon2HashConfigOptions) + if ('test' in argon2HashConfigOptions) { argon2HashConfigOptions.associatedData = Buffer.from(argon2HashConfigOptions.associatedData); + } + return argon2.hash(stringToHash, argon2HashConfigOptions); }; diff --git a/tests/blackbox/setup/setup.ts b/tests/blackbox/setup/setup.ts index 11f38ca108..f90292c85e 100644 --- a/tests/blackbox/setup/setup.ts +++ b/tests/blackbox/setup/setup.ts @@ -96,8 +96,9 @@ export default async (): Promise => { writeFileSync(__dirname + `/../server-log-${vendor}-no-cache.txt`, serverNoCacheOutput); } - if (code !== null) + if (code !== null) { throw new Error(`Directus-${vendor}-no-cache server failed: \n ${serverNoCacheOutput}`); + } }); // Give the server some time to start