mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Fix remaining eslint errors
h/t @paescuj
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { ItemsService } from './items';
|
||||
import { AbstractServiceOptions } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
|
||||
/**
|
||||
* @TODO only return activity of the collections you have access to
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import storage from '../storage';
|
||||
import { Range, StatResponse } from '@directus/drive';
|
||||
import { Knex } from 'knex';
|
||||
import path from 'path';
|
||||
import sharp, { ResizeOptions } from 'sharp';
|
||||
import database from '../database';
|
||||
import path from 'path';
|
||||
import { Knex } from 'knex';
|
||||
import { Accountability, AbstractServiceOptions, Transformation } from '../types';
|
||||
import { AuthorizationService } from './authorization';
|
||||
import { Range, StatResponse } from '@directus/drive';
|
||||
import { RangeNotSatisfiableException } from '../exceptions';
|
||||
import storage from '../storage';
|
||||
import { AbstractServiceOptions, Accountability, Transformation } from '../types';
|
||||
import { AuthorizationService } from './authorization';
|
||||
|
||||
export class AssetsService {
|
||||
knex: Knex;
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
import database from '../database';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import argon2 from 'argon2';
|
||||
import { nanoid } from 'nanoid';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { Knex } from 'knex';
|
||||
import { omit } from 'lodash';
|
||||
import ms from 'ms';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { authenticator } from 'otplib';
|
||||
import database from '../database';
|
||||
import emitter, { emitAsyncSafe } from '../emitter';
|
||||
import env from '../env';
|
||||
import {
|
||||
InvalidCredentialsException,
|
||||
InvalidPayloadException,
|
||||
InvalidOTPException,
|
||||
InvalidPayloadException,
|
||||
UserSuspendedException,
|
||||
} from '../exceptions';
|
||||
import { Session, Accountability, AbstractServiceOptions, Action, SchemaOverview } from '../types';
|
||||
import { Knex } from 'knex';
|
||||
import { ActivityService } from '../services/activity';
|
||||
import env from '../env';
|
||||
import { authenticator } from 'otplib';
|
||||
import emitter, { emitAsyncSafe } from '../emitter';
|
||||
import { omit } from 'lodash';
|
||||
import { createRateLimiter } from '../rate-limiter';
|
||||
import { ActivityService } from '../services/activity';
|
||||
import { AbstractServiceOptions, Accountability, Action, SchemaOverview, Session } from '../types';
|
||||
import { SettingsService } from './settings';
|
||||
import { rateLimiter } from '../middleware/rate-limiter';
|
||||
|
||||
type AuthenticateOptions = {
|
||||
email: string;
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { Knex } from 'knex';
|
||||
import { cloneDeep, flatten, merge, uniq, uniqWith } from 'lodash';
|
||||
import database from '../database';
|
||||
import { FailedValidationException, ForbiddenException } from '../exceptions';
|
||||
import {
|
||||
Accountability,
|
||||
AbstractServiceOptions,
|
||||
Accountability,
|
||||
AST,
|
||||
NestedCollectionNode,
|
||||
FieldNode,
|
||||
Query,
|
||||
Filter,
|
||||
Item,
|
||||
NestedCollectionNode,
|
||||
Permission,
|
||||
PermissionsAction,
|
||||
Item,
|
||||
PrimaryKey,
|
||||
Query,
|
||||
SchemaOverview,
|
||||
Filter,
|
||||
} from '../types';
|
||||
import { Knex } from 'knex';
|
||||
import { ForbiddenException, FailedValidationException } from '../exceptions';
|
||||
import { uniq, uniqWith, merge, flatten, cloneDeep } from 'lodash';
|
||||
import generateJoi from '../utils/generate-joi';
|
||||
import { parseFilter } from '../utils/parse-filter';
|
||||
import { ItemsService } from './items';
|
||||
import { PayloadService } from './payload';
|
||||
import { parseFilter } from '../utils/parse-filter';
|
||||
|
||||
export class AuthorizationService {
|
||||
knex: Knex;
|
||||
@@ -40,7 +40,7 @@ export class AuthorizationService {
|
||||
async processAST(ast: AST, action: PermissionsAction = 'read'): Promise<AST> {
|
||||
const collectionsRequested = getCollectionsFromAST(ast);
|
||||
|
||||
let permissionsForCollections = uniqWith(
|
||||
const permissionsForCollections = uniqWith(
|
||||
this.schema.permissions.filter((permission) => {
|
||||
return (
|
||||
permission.action === action &&
|
||||
@@ -218,7 +218,7 @@ export class AuthorizationService {
|
||||
|
||||
const payloadWithPresets = merge({}, preset, payload);
|
||||
|
||||
let requiredColumns: string[] = [];
|
||||
const requiredColumns: string[] = [];
|
||||
|
||||
for (const [name, field] of Object.entries(this.schema.collections[collection].fields)) {
|
||||
const specials = field?.special ?? [];
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
import SchemaInspector from '@directus/schema';
|
||||
import { Knex } from 'knex';
|
||||
import cache from '../cache';
|
||||
import { ALIAS_TYPES } from '../constants';
|
||||
import database, { schemaInspector } from '../database';
|
||||
import { systemCollectionRows } from '../database/system-data/collections';
|
||||
import env from '../env';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import logger from '../logger';
|
||||
import { FieldsService } from '../services/fields';
|
||||
import { ItemsService, MutationOptions } from '../services/items';
|
||||
import {
|
||||
AbstractServiceOptions,
|
||||
Accountability,
|
||||
@@ -8,15 +17,6 @@ import {
|
||||
FieldMeta,
|
||||
SchemaOverview,
|
||||
} from '../types';
|
||||
import { Knex } from 'knex';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { FieldsService } from '../services/fields';
|
||||
import { ItemsService, MutationOptions } from '../services/items';
|
||||
import cache from '../cache';
|
||||
import { systemCollectionRows } from '../database/system-data/collections';
|
||||
import SchemaInspector from '@directus/schema';
|
||||
import env from '../env';
|
||||
import logger from '../logger';
|
||||
|
||||
export class CollectionsService {
|
||||
knex: Knex;
|
||||
@@ -357,7 +357,7 @@ export class CollectionsService {
|
||||
.where({ many_collection: collectionKey, many_field: relation.many_field });
|
||||
|
||||
await fieldsService.deleteField(relation.one_collection!, relation.one_field!);
|
||||
} else if (!!relation.one_collection) {
|
||||
} else if (relation.one_collection) {
|
||||
await this.knex('directus_relations')
|
||||
.update({ one_field: null })
|
||||
.where({ one_collection: collectionKey, one_field: relation.one_field });
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import SchemaInspector from '@directus/schema';
|
||||
import { Knex } from 'knex';
|
||||
import { Column } from 'knex-schema-inspector/dist/types/column';
|
||||
import cache from '../cache';
|
||||
import { ALIAS_TYPES } from '../constants';
|
||||
import database, { schemaInspector } from '../database';
|
||||
import { Field } from '../types/field';
|
||||
import { Accountability, AbstractServiceOptions, FieldMeta, SchemaOverview } from '../types';
|
||||
import { ItemsService } from '../services/items';
|
||||
import { Knex } from 'knex';
|
||||
import getLocalType from '../utils/get-local-type';
|
||||
import { types } from '../types';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { PayloadService } from '../services/payload';
|
||||
import getDefaultValue from '../utils/get-default-value';
|
||||
import cache from '../cache';
|
||||
import emitter, { emitAsyncSafe } from '../emitter';
|
||||
import SchemaInspector from '@directus/schema';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import env from '../env';
|
||||
import { Column } from 'knex-schema-inspector/dist/types/column';
|
||||
|
||||
import { systemFieldRows } from '../database/system-data/fields/';
|
||||
import emitter, { emitAsyncSafe } from '../emitter';
|
||||
import env from '../env';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { ItemsService } from '../services/items';
|
||||
import { PayloadService } from '../services/payload';
|
||||
import { AbstractServiceOptions, Accountability, FieldMeta, SchemaOverview, types } from '../types';
|
||||
import { Field } from '../types/field';
|
||||
import getDefaultValue from '../utils/get-default-value';
|
||||
import getLocalType from '../utils/get-local-type';
|
||||
import { toArray } from '../utils/to-array';
|
||||
|
||||
type RawField = Partial<Field> & { field: string; type: typeof types[number] };
|
||||
|
||||
@@ -142,12 +140,12 @@ export class FieldsService {
|
||||
allowedFieldsInCollection[permission.collection] = permission.fields ?? [];
|
||||
});
|
||||
|
||||
if (collection && allowedFieldsInCollection.hasOwnProperty(collection) === false) {
|
||||
if (collection && collection in allowedFieldsInCollection === false) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
return result.filter((field) => {
|
||||
if (allowedFieldsInCollection.hasOwnProperty(field.collection) === false) return false;
|
||||
if (field.collection in allowedFieldsInCollection === false) return false;
|
||||
const allowedFields = allowedFieldsInCollection[field.collection];
|
||||
if (allowedFields[0] === '*') return true;
|
||||
return allowedFields.includes(field.field);
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { ItemsService, MutationOptions } from './items';
|
||||
import storage from '../storage';
|
||||
import sharp from 'sharp';
|
||||
import { parse as parseICC } from 'icc';
|
||||
import formatTitle from '@directus/format-title';
|
||||
import axios, { AxiosResponse } from 'axios';
|
||||
import parseEXIF from 'exif-reader';
|
||||
import parseIPTC from '../utils/parse-iptc';
|
||||
import { AbstractServiceOptions, File, PrimaryKey } from '../types';
|
||||
import { parse as parseICC } from 'icc';
|
||||
import { clone } from 'lodash';
|
||||
import cache from '../cache';
|
||||
import { ForbiddenException, ServiceUnavailableException } from '../exceptions';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { extension } from 'mime-types';
|
||||
import path from 'path';
|
||||
import env from '../env';
|
||||
import logger from '../logger';
|
||||
import axios, { AxiosResponse } from 'axios';
|
||||
import sharp from 'sharp';
|
||||
import url from 'url';
|
||||
import formatTitle from '@directus/format-title';
|
||||
import cache from '../cache';
|
||||
import { emitAsyncSafe } from '../emitter';
|
||||
import env from '../env';
|
||||
import { ForbiddenException, ServiceUnavailableException } from '../exceptions';
|
||||
import logger from '../logger';
|
||||
import storage from '../storage';
|
||||
import { AbstractServiceOptions, File, PrimaryKey } from '../types';
|
||||
import parseIPTC from '../utils/parse-iptc';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { ItemsService, MutationOptions } from './items';
|
||||
|
||||
export class FilesService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ItemsService } from './items';
|
||||
import { AbstractServiceOptions } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
|
||||
export class FoldersService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
@@ -1,81 +1,75 @@
|
||||
import { Knex } from 'knex';
|
||||
import database from '../database';
|
||||
import { AbstractServiceOptions, Accountability, Query, SchemaOverview, GraphQLParams, Action, Item } from '../types';
|
||||
import argon2 from 'argon2';
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLList,
|
||||
GraphQLResolveInfo,
|
||||
ObjectFieldNode,
|
||||
GraphQLID,
|
||||
FieldNode,
|
||||
InlineFragmentNode,
|
||||
SelectionNode,
|
||||
GraphQLInt,
|
||||
IntValueNode,
|
||||
StringValueNode,
|
||||
BooleanValueNode,
|
||||
ArgumentNode,
|
||||
GraphQLBoolean,
|
||||
ObjectValueNode,
|
||||
GraphQLUnionType,
|
||||
BooleanValueNode,
|
||||
execute,
|
||||
validate,
|
||||
ExecutionResult,
|
||||
FormattedExecutionResult,
|
||||
specifiedRules,
|
||||
FieldNode,
|
||||
formatError,
|
||||
GraphQLFloat,
|
||||
GraphQLError,
|
||||
GraphQLNonNull,
|
||||
FormattedExecutionResult,
|
||||
FragmentDefinitionNode,
|
||||
GraphQLSchema,
|
||||
GraphQLBoolean,
|
||||
GraphQLEnumType,
|
||||
GraphQLScalarType,
|
||||
GraphQLError,
|
||||
GraphQLFloat,
|
||||
GraphQLID,
|
||||
GraphQLInt,
|
||||
GraphQLList,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType,
|
||||
GraphQLResolveInfo,
|
||||
GraphQLScalarType,
|
||||
GraphQLSchema,
|
||||
GraphQLString,
|
||||
GraphQLUnionType,
|
||||
InlineFragmentNode,
|
||||
IntValueNode,
|
||||
ObjectFieldNode,
|
||||
ObjectValueNode,
|
||||
SelectionNode,
|
||||
specifiedRules,
|
||||
StringValueNode,
|
||||
validate,
|
||||
} from 'graphql';
|
||||
import {
|
||||
GraphQLJSON,
|
||||
InputTypeComposer,
|
||||
InputTypeComposerFieldConfigMapDefinition,
|
||||
ObjectTypeComposer,
|
||||
ObjectTypeComposerFieldConfigMapDefinition,
|
||||
SchemaComposer,
|
||||
toInputObjectType,
|
||||
} from 'graphql-compose';
|
||||
import { Knex } from 'knex';
|
||||
import { flatten, get, mapKeys, merge, set, uniq } from 'lodash';
|
||||
import ms from 'ms';
|
||||
import database from '../database';
|
||||
import env from '../env';
|
||||
import { BaseException, GraphQLValidationException, InvalidPayloadException } from '../exceptions';
|
||||
import { listExtensions } from '../extensions';
|
||||
import { AbstractServiceOptions, Accountability, Action, GraphQLParams, Item, Query, SchemaOverview } from '../types';
|
||||
import { getGraphQLType } from '../utils/get-graphql-type';
|
||||
import { RelationsService } from './relations';
|
||||
import { ItemsService } from './items';
|
||||
import { set, merge, get, mapKeys, uniq, flatten } from 'lodash';
|
||||
import { reduceSchema } from '../utils/reduce-schema';
|
||||
import { sanitizeQuery } from '../utils/sanitize-query';
|
||||
|
||||
import { ActivityService } from './activity';
|
||||
import { AuthenticationService } from './authentication';
|
||||
import { CollectionsService } from './collections';
|
||||
import { FieldsService } from './fields';
|
||||
import { FilesService } from './files';
|
||||
import { FoldersService } from './folders';
|
||||
import { ItemsService } from './items';
|
||||
import { PermissionsService } from './permissions';
|
||||
import { PresetsService } from './presets';
|
||||
import { RelationsService } from './relations';
|
||||
import { RevisionsService } from './revisions';
|
||||
import { RolesService } from './roles';
|
||||
import { SettingsService } from './settings';
|
||||
import { ServerService } from './server';
|
||||
import { SettingsService } from './settings';
|
||||
import { SpecificationService } from './specifications';
|
||||
import { UsersService } from './users';
|
||||
import { UtilsService } from './utils';
|
||||
import { WebhooksService } from './webhooks';
|
||||
|
||||
import { BaseException, InvalidPayloadException, GraphQLValidationException, ForbiddenException } from '../exceptions';
|
||||
import { toArray } from '../utils/to-array';
|
||||
|
||||
import env from '../env';
|
||||
import ms from 'ms';
|
||||
|
||||
import { reduceSchema } from '../utils/reduce-schema';
|
||||
|
||||
import {
|
||||
ObjectTypeComposer,
|
||||
ObjectTypeComposerFieldConfigMapDefinition,
|
||||
InputTypeComposerFieldConfigMapDefinition,
|
||||
SchemaComposer,
|
||||
InputTypeComposer,
|
||||
toInputObjectType,
|
||||
GraphQLJSON,
|
||||
} from 'graphql-compose';
|
||||
import { SpecificationService } from './specifications';
|
||||
|
||||
const GraphQLVoid = new GraphQLScalarType({
|
||||
name: 'Void',
|
||||
|
||||
@@ -815,7 +809,7 @@ export class GraphQLService {
|
||||
const args: Record<string, any> = this.parseArgs(info.fieldNodes[0].arguments || [], info.variableValues);
|
||||
const query = this.getQuery(args, selections, info.variableValues);
|
||||
|
||||
if (collection.endsWith('_by_id') && this.schema.collections.hasOwnProperty(collection) === false) {
|
||||
if (collection.endsWith('_by_id') && collection in this.schema.collections === false) {
|
||||
collection = collection.slice(0, -6);
|
||||
}
|
||||
|
||||
@@ -861,7 +855,7 @@ export class GraphQLService {
|
||||
const singleton =
|
||||
collection.endsWith('_items') === false &&
|
||||
collection.endsWith('_item') === false &&
|
||||
this.schema.collections.hasOwnProperty(collection);
|
||||
collection in this.schema.collections;
|
||||
|
||||
const single = collection.endsWith('_items') === false;
|
||||
|
||||
@@ -1149,7 +1143,6 @@ export class GraphQLService {
|
||||
{
|
||||
CreateCollectionTypes,
|
||||
ReadCollectionTypes,
|
||||
UpdateCollectionTypes,
|
||||
DeleteCollectionTypes,
|
||||
}: {
|
||||
CreateCollectionTypes: Record<string, ObjectTypeComposer<any, any>>;
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
import { Knex } from 'knex';
|
||||
import { clone, cloneDeep, merge, pick, without } from 'lodash';
|
||||
import cache from '../cache';
|
||||
import database from '../database';
|
||||
import runAST from '../database/run-ast';
|
||||
import getASTFromQuery from '../utils/get-ast-from-query';
|
||||
import emitter, { emitAsyncSafe } from '../emitter';
|
||||
import env from '../env';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { translateDatabaseError } from '../exceptions/database/translate';
|
||||
import logger from '../logger';
|
||||
import {
|
||||
Action,
|
||||
Accountability,
|
||||
PermissionsAction,
|
||||
Item as AnyItem,
|
||||
Query,
|
||||
PrimaryKey,
|
||||
AbstractService,
|
||||
AbstractServiceOptions,
|
||||
Accountability,
|
||||
Action,
|
||||
Item as AnyItem,
|
||||
PermissionsAction,
|
||||
PrimaryKey,
|
||||
Query,
|
||||
SchemaOverview,
|
||||
} from '../types';
|
||||
import { Knex } from 'knex';
|
||||
import cache from '../cache';
|
||||
import emitter, { emitAsyncSafe } from '../emitter';
|
||||
import getASTFromQuery from '../utils/get-ast-from-query';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import env from '../env';
|
||||
|
||||
import { PayloadService } from './payload';
|
||||
import { AuthorizationService } from './authorization';
|
||||
|
||||
import { pick, clone, cloneDeep, merge, without } from 'lodash';
|
||||
import { translateDatabaseError } from '../exceptions/database/translate';
|
||||
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
|
||||
|
||||
import logger from '../logger';
|
||||
import { PayloadService } from './payload';
|
||||
|
||||
export type QueryOptions = {
|
||||
stripNonRequested?: boolean;
|
||||
@@ -76,7 +73,7 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
.filter((field) => field.alias === true)
|
||||
.map((field) => field.field);
|
||||
|
||||
let payload: AnyItem = cloneDeep(data);
|
||||
const payload: AnyItem = cloneDeep(data);
|
||||
|
||||
// By wrapping the logic in a transaction, we make sure we automatically roll back all the
|
||||
// changes in the DB if any of the parts contained within throws an error. This also means
|
||||
@@ -457,10 +454,8 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
|
||||
for (const activityRecord of activityRecords) {
|
||||
await trx.insert(activityRecord).into('directus_activity');
|
||||
let primaryKey;
|
||||
|
||||
const result = await trx.max('id', { as: 'id' }).from('directus_activity').first();
|
||||
primaryKey = result.id;
|
||||
const primaryKey = result.id;
|
||||
|
||||
activityPrimaryKeys.push(primaryKey);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import mailer from '../mailer';
|
||||
import { AbstractServiceOptions, Accountability, SchemaOverview } from '../../types';
|
||||
import fse from 'fs-extra';
|
||||
import { Knex } from 'knex';
|
||||
import { Liquid } from 'liquidjs';
|
||||
import path from 'path';
|
||||
import database from '../../database';
|
||||
import env from '../../env';
|
||||
import logger from '../../logger';
|
||||
import fse from 'fs-extra';
|
||||
import { Liquid } from 'liquidjs';
|
||||
import path from 'path';
|
||||
import { AbstractServiceOptions, Accountability, SchemaOverview } from '../../types';
|
||||
import mailer from '../mailer';
|
||||
|
||||
const liquidEngine = new Liquid({
|
||||
root: [path.resolve(env.EXTENSIONS_PATH, 'templates'), path.resolve(__dirname, 'templates')],
|
||||
@@ -37,10 +37,11 @@ export class MailService {
|
||||
this.knex = opts?.knex || database;
|
||||
}
|
||||
|
||||
async send(options: EmailOptions) {
|
||||
async send(options: EmailOptions): Promise<void> {
|
||||
if (!mailer) return;
|
||||
|
||||
let { to, from, subject, html, text } = options;
|
||||
const { to, subject, text } = options;
|
||||
let { from, html } = options;
|
||||
|
||||
from = from || (env.EMAIL_FROM as string);
|
||||
|
||||
@@ -67,7 +68,7 @@ export class MailService {
|
||||
}
|
||||
}
|
||||
|
||||
private async renderTemplate(template: string, variables: Record<string, any>, system: boolean = false) {
|
||||
private async renderTemplate(template: string, variables: Record<string, any>, system = false) {
|
||||
const resolvedPath = system
|
||||
? path.join(__dirname, 'templates', template + '.liquid')
|
||||
: path.resolve(env.EXTENSIONS_PATH, 'templates', template + '.liquid');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import logger from '../logger';
|
||||
import nodemailer, { Transporter } from 'nodemailer';
|
||||
import env from '../env';
|
||||
import logger from '../logger';
|
||||
|
||||
let transporter: Transporter | null = null;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Query } from '../types/query';
|
||||
import database from '../database';
|
||||
import { AbstractServiceOptions, Accountability, SchemaOverview } from '../types';
|
||||
import { Knex } from 'knex';
|
||||
import { applyFilter, applySearch } from '../utils/apply-query';
|
||||
import database from '../database';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import { AbstractServiceOptions, Accountability, SchemaOverview } from '../types';
|
||||
import { Query } from '../types/query';
|
||||
import { applyFilter, applySearch } from '../utils/apply-query';
|
||||
import { parseFilter } from '../utils/parse-filter';
|
||||
|
||||
export class MetaService {
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import argon2 from 'argon2';
|
||||
import { format, formatISO, parse, parseISO } from 'date-fns';
|
||||
import Joi from 'joi';
|
||||
import { Knex } from 'knex';
|
||||
import { clone, cloneDeep, isObject, isPlainObject } from 'lodash';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import database from '../database';
|
||||
import { clone, isObject, cloneDeep } from 'lodash';
|
||||
import { Item, AbstractServiceOptions, Accountability, PrimaryKey, SchemaOverview } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
import { Knex } from 'knex';
|
||||
import { format, formatISO, parse, parseISO } from 'date-fns';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { AbstractServiceOptions, Accountability, Item, PrimaryKey, SchemaOverview } from '../types';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { systemRelationRows } from '../database/system-data/relations';
|
||||
import { InvalidPayloadException } from '../exceptions';
|
||||
import { isPlainObject } from 'lodash';
|
||||
import Joi from 'joi';
|
||||
import { ItemsService } from './items';
|
||||
|
||||
type Action = 'create' | 'read' | 'update';
|
||||
|
||||
@@ -31,7 +28,7 @@ type Alterations = {
|
||||
update: {
|
||||
[key: string]: any;
|
||||
}[];
|
||||
delete: (Number | String)[];
|
||||
delete: (number | string)[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -101,19 +98,19 @@ export class PayloadService {
|
||||
if (action === 'read') return value ? '**********' : null;
|
||||
return value;
|
||||
},
|
||||
async 'user-created'({ action, value, payload, accountability }) {
|
||||
async 'user-created'({ action, value, accountability }) {
|
||||
if (action === 'create') return accountability?.user || null;
|
||||
return value;
|
||||
},
|
||||
async 'user-updated'({ action, value, payload, accountability }) {
|
||||
async 'user-updated'({ action, value, accountability }) {
|
||||
if (action === 'update') return accountability?.user || null;
|
||||
return value;
|
||||
},
|
||||
async 'role-created'({ action, value, payload, accountability }) {
|
||||
async 'role-created'({ action, value, accountability }) {
|
||||
if (action === 'create') return accountability?.role || null;
|
||||
return value;
|
||||
},
|
||||
async 'role-updated'({ action, value, payload, accountability }) {
|
||||
async 'role-updated'({ action, value, accountability }) {
|
||||
if (action === 'update') return accountability?.role || null;
|
||||
return value;
|
||||
},
|
||||
@@ -140,18 +137,18 @@ export class PayloadService {
|
||||
action: Action,
|
||||
payload: Partial<Item> | Partial<Item>[]
|
||||
): Promise<Partial<Item> | Partial<Item>[]> {
|
||||
let processedPayload = toArray(payload);
|
||||
const processedPayload = toArray(payload);
|
||||
|
||||
if (processedPayload.length === 0) return [];
|
||||
|
||||
const fieldsInPayload = Object.keys(processedPayload[0]);
|
||||
|
||||
let specialFieldsInCollection = Object.entries(this.schema.collections[this.collection].fields).filter(
|
||||
([name, field]) => field.special && field.special.length > 0
|
||||
([_name, field]) => field.special && field.special.length > 0
|
||||
);
|
||||
|
||||
if (action === 'read') {
|
||||
specialFieldsInCollection = specialFieldsInCollection.filter(([name, field]) => {
|
||||
specialFieldsInCollection = specialFieldsInCollection.filter(([name]) => {
|
||||
return fieldsInPayload.includes(name);
|
||||
});
|
||||
}
|
||||
@@ -198,7 +195,7 @@ export class PayloadService {
|
||||
let value = clone(payload[field.field]);
|
||||
|
||||
for (const special of fieldSpecials) {
|
||||
if (this.transformers.hasOwnProperty(special)) {
|
||||
if (special in this.transformers) {
|
||||
value = await this.transformers[special]({
|
||||
action,
|
||||
value,
|
||||
@@ -221,7 +218,7 @@ export class PayloadService {
|
||||
): Promise<Partial<Record<string, any>>[]> {
|
||||
const fieldsInCollection = Object.entries(this.schema.collections[this.collection].fields);
|
||||
|
||||
const dateColumns = fieldsInCollection.filter(([name, field]) =>
|
||||
const dateColumns = fieldsInCollection.filter(([_name, field]) =>
|
||||
['dateTime', 'date', 'timestamp'].includes(field.type)
|
||||
);
|
||||
|
||||
@@ -286,11 +283,11 @@ export class PayloadService {
|
||||
|
||||
const revisions: PrimaryKey[] = [];
|
||||
|
||||
let payload = cloneDeep(data);
|
||||
const payload = cloneDeep(data);
|
||||
|
||||
// Only process related records that are actually in the payload
|
||||
const relationsToProcess = relations.filter((relation) => {
|
||||
return payload.hasOwnProperty(relation.many_field) && isPlainObject(payload[relation.many_field]);
|
||||
return relation.many_field in payload && isPlainObject(payload[relation.many_field]);
|
||||
});
|
||||
|
||||
for (const relation of relationsToProcess) {
|
||||
@@ -321,7 +318,7 @@ export class PayloadService {
|
||||
|
||||
const relatedPrimary = this.schema.collections[relatedCollection].primary;
|
||||
const relatedRecord: Partial<Item> = payload[relation.many_field];
|
||||
const hasPrimaryKey = relatedRecord.hasOwnProperty(relatedPrimary);
|
||||
const hasPrimaryKey = relatedPrimary in relatedRecord;
|
||||
|
||||
let relatedPrimaryKey: PrimaryKey = relatedRecord[relatedPrimary];
|
||||
|
||||
@@ -355,7 +352,7 @@ export class PayloadService {
|
||||
const payload = cloneDeep(data);
|
||||
|
||||
// All the revisions saved on this level
|
||||
let revisions: PrimaryKey[] = [];
|
||||
const revisions: PrimaryKey[] = [];
|
||||
|
||||
// Many to one relations that exist on the current collection
|
||||
const relations = this.schema.relations.filter((relation) => {
|
||||
@@ -364,7 +361,7 @@ export class PayloadService {
|
||||
|
||||
// Only process related records that are actually in the payload
|
||||
const relationsToProcess = relations.filter((relation) => {
|
||||
return payload.hasOwnProperty(relation.many_field) && isObject(payload[relation.many_field]);
|
||||
return relation.many_field in payload && isObject(payload[relation.many_field]);
|
||||
});
|
||||
|
||||
for (const relation of relationsToProcess) {
|
||||
@@ -379,7 +376,7 @@ export class PayloadService {
|
||||
});
|
||||
|
||||
const relatedRecord: Partial<Item> = payload[relation.many_field];
|
||||
const hasPrimaryKey = relatedRecord.hasOwnProperty(relation.one_primary);
|
||||
const hasPrimaryKey = relation.one_primary in relatedRecord;
|
||||
|
||||
if (['string', 'number'].includes(typeof relatedRecord)) continue;
|
||||
|
||||
@@ -418,12 +415,12 @@ export class PayloadService {
|
||||
return relation.one_collection === this.collection;
|
||||
});
|
||||
|
||||
let payload = cloneDeep(data);
|
||||
const payload = cloneDeep(data);
|
||||
|
||||
// Only process related records that are actually in the payload
|
||||
const relationsToProcess = relations.filter((relation) => {
|
||||
if (!relation.one_field) return false;
|
||||
return payload.hasOwnProperty(relation.one_field);
|
||||
return relation.one_field in payload;
|
||||
});
|
||||
|
||||
const nestedUpdateSchema = Joi.object({
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { AbstractServiceOptions, PermissionsAction, Query, Item, PrimaryKey } from '../types';
|
||||
import { ItemsService, MutationOptions, QueryOptions } from '../services/items';
|
||||
import { filterItems } from '../utils/filter-items';
|
||||
import logger from '../logger';
|
||||
|
||||
import { appAccessMinimalPermissions } from '../database/system-data/app-access-permissions';
|
||||
import logger from '../logger';
|
||||
import { ItemsService, QueryOptions } from '../services/items';
|
||||
import { AbstractServiceOptions, Item, PermissionsAction, PrimaryKey, Query } from '../types';
|
||||
import { filterItems } from '../utils/filter-items';
|
||||
|
||||
export class PermissionsService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
@@ -18,7 +17,9 @@ export class PermissionsService extends ItemsService {
|
||||
matchesCollection = permission.collection === collection;
|
||||
}
|
||||
|
||||
return permission.action === action;
|
||||
const matchesAction = permission.action === action;
|
||||
|
||||
return collection ? matchesCollection && matchesAction : matchesAction;
|
||||
});
|
||||
|
||||
const fieldsPerCollection: Record<string, string[]> = {};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ItemsService } from './items';
|
||||
import { AbstractServiceOptions } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
|
||||
export class PresetsService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { ItemsService, QueryOptions } from './items';
|
||||
import { AbstractServiceOptions, Query, PrimaryKey, PermissionsAction, Relation } from '../types';
|
||||
import { PermissionsService } from './permissions';
|
||||
import { toArray } from '../utils/to-array';
|
||||
|
||||
import { systemRelationRows } from '../database/system-data/relations';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
|
||||
import logger from '../logger';
|
||||
import { AbstractServiceOptions, PermissionsAction, PrimaryKey, Query, Relation } from '../types';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { ItemsService, QueryOptions } from './items';
|
||||
import { PermissionsService } from './permissions';
|
||||
|
||||
export class RelationsService extends ItemsService {
|
||||
permissionsService: PermissionsService;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { AbstractServiceOptions, PrimaryKey } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
import { AbstractServiceOptions, PrimaryKey, Revision } from '../types';
|
||||
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
|
||||
|
||||
export class RevisionsService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { ItemsService } from './items';
|
||||
import { AbstractServiceOptions, PrimaryKey } from '../types';
|
||||
import { PermissionsService } from './permissions';
|
||||
import { UsersService } from './users';
|
||||
import { PresetsService } from './presets';
|
||||
import { UnprocessableEntityException } from '../exceptions';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { AbstractServiceOptions, PrimaryKey } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
import { PermissionsService } from './permissions';
|
||||
import { PresetsService } from './presets';
|
||||
import { UsersService } from './users';
|
||||
|
||||
export class RolesService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { AbstractServiceOptions, Accountability, SchemaOverview } from '../types';
|
||||
import { Knex } from 'knex';
|
||||
import database from '../database';
|
||||
import { merge } from 'lodash';
|
||||
import macosRelease from 'macos-release';
|
||||
import { nanoid } from 'nanoid';
|
||||
import os from 'os';
|
||||
import logger from '../logger';
|
||||
import { performance } from 'perf_hooks';
|
||||
// @ts-ignore
|
||||
import { version } from '../../package.json';
|
||||
import macosRelease from 'macos-release';
|
||||
import { SettingsService } from './settings';
|
||||
import mailer from './mailer';
|
||||
import env from '../env';
|
||||
import { performance } from 'perf_hooks';
|
||||
import cache from '../cache';
|
||||
import database from '../database';
|
||||
import env from '../env';
|
||||
import logger from '../logger';
|
||||
import { rateLimiter } from '../middleware/rate-limiter';
|
||||
import storage from '../storage';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { AbstractServiceOptions, Accountability, SchemaOverview } from '../types';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { merge } from 'lodash';
|
||||
import mailer from './mailer';
|
||||
import { SettingsService } from './settings';
|
||||
|
||||
export class ServerService {
|
||||
knex: Knex;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ItemsService } from './items';
|
||||
import { AbstractServiceOptions } from '../types';
|
||||
import { ItemsService } from './items';
|
||||
|
||||
export class SettingsService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
import formatTitle from '@directus/format-title';
|
||||
import openapi from '@directus/specs';
|
||||
import { Knex } from 'knex';
|
||||
import { cloneDeep, mergeWith } from 'lodash';
|
||||
import { OpenAPIObject, OperationObject, PathItemObject, SchemaObject, TagObject } from 'openapi3-ts';
|
||||
// @ts-ignore
|
||||
import { version } from '../../package.json';
|
||||
import database from '../database';
|
||||
import env from '../env';
|
||||
import {
|
||||
AbstractServiceOptions,
|
||||
Accountability,
|
||||
@@ -8,22 +17,11 @@ import {
|
||||
SchemaOverview,
|
||||
types,
|
||||
} from '../types';
|
||||
import { getRelationType } from '../utils/get-relation-type';
|
||||
import { CollectionsService } from './collections';
|
||||
import { FieldsService } from './fields';
|
||||
import formatTitle from '@directus/format-title';
|
||||
import { cloneDeep, mergeWith } from 'lodash';
|
||||
import { RelationsService } from './relations';
|
||||
import env from '../env';
|
||||
import { OpenAPIObject, PathItemObject, OperationObject, TagObject, SchemaObject } from 'openapi3-ts';
|
||||
|
||||
// @ts-ignore
|
||||
import { version } from '../../package.json';
|
||||
import openapi from '@directus/specs';
|
||||
|
||||
import { Knex } from 'knex';
|
||||
import database from '../database';
|
||||
import { getRelationType } from '../utils/get-relation-type';
|
||||
import { GraphQLService } from './graphql';
|
||||
import { RelationsService } from './relations';
|
||||
|
||||
export class SpecificationService {
|
||||
accountability: Accountability | null;
|
||||
@@ -164,7 +162,7 @@ class OASSpecsService implements SpecificationSubService {
|
||||
if (!tags) return paths;
|
||||
|
||||
for (const tag of tags) {
|
||||
const isSystem = tag.hasOwnProperty('x-collection') === false || tag['x-collection'].startsWith('directus_');
|
||||
const isSystem = 'x-collection' in tag === false || tag['x-collection'].startsWith('directus_');
|
||||
|
||||
if (isSystem) {
|
||||
for (const [path, pathItem] of Object.entries<PathItemObject>(openapi.paths)) {
|
||||
@@ -176,7 +174,7 @@ class OASSpecsService implements SpecificationSubService {
|
||||
|
||||
const hasPermission =
|
||||
this.accountability?.admin === true ||
|
||||
tag.hasOwnProperty('x-collection') === false ||
|
||||
'x-collection' in tag === false ||
|
||||
!!permissions.find(
|
||||
(permission) =>
|
||||
permission.collection === tag['x-collection'] &&
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import { AuthenticationService } from './authentication';
|
||||
import { ItemsService, MutationOptions } from './items';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import database from '../database';
|
||||
import argon2 from 'argon2';
|
||||
import {
|
||||
InvalidPayloadException,
|
||||
ForbiddenException,
|
||||
UnprocessableEntityException,
|
||||
FailedValidationException,
|
||||
} from '../exceptions';
|
||||
import { Accountability, PrimaryKey, Item, AbstractServiceOptions, SchemaOverview, Query } from '../types';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { Knex } from 'knex';
|
||||
import env from '../env';
|
||||
import { clone } from 'lodash';
|
||||
import cache from '../cache';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import database from '../database';
|
||||
import env from '../env';
|
||||
import {
|
||||
FailedValidationException,
|
||||
ForbiddenException,
|
||||
InvalidPayloadException,
|
||||
UnprocessableEntityException,
|
||||
} from '../exceptions';
|
||||
import { RecordNotUniqueException } from '../exceptions/database/record-not-unique';
|
||||
import logger from '../logger';
|
||||
import { clone } from 'lodash';
|
||||
import { SettingsService } from './settings';
|
||||
import { AbstractServiceOptions, Accountability, Item, PrimaryKey, Query, SchemaOverview } from '../types';
|
||||
import { toArray } from '../utils/to-array';
|
||||
import { AuthenticationService } from './authentication';
|
||||
import { ItemsService, MutationOptions } from './items';
|
||||
import { MailService } from './mail';
|
||||
import { SettingsService } from './settings';
|
||||
|
||||
export class UsersService extends ItemsService {
|
||||
knex: Knex;
|
||||
@@ -132,7 +132,7 @@ export class UsersService extends ItemsService {
|
||||
await this.checkPasswordPolicy([data.password]);
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('tfa_secret')) {
|
||||
if ('tfa_secret' in data) {
|
||||
throw new InvalidPayloadException(`You can't change the "tfa_secret" value manually.`);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ export class UsersService extends ItemsService {
|
||||
await this.checkPasswordPolicy([data.password]);
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('tfa_secret')) {
|
||||
if ('tfa_secret' in data) {
|
||||
throw new InvalidPayloadException(`You can't change the "tfa_secret" value manually.`);
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export class UsersService extends ItemsService {
|
||||
await this.checkPasswordPolicy([data.password]);
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('tfa_secret')) {
|
||||
if ('tfa_secret' in data) {
|
||||
throw new InvalidPayloadException(`You can't change the "tfa_secret" value manually.`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { AbstractServiceOptions, Accountability, PrimaryKey, SchemaOverview } from '../types';
|
||||
import database from '../database';
|
||||
import { Knex } from 'knex';
|
||||
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
|
||||
import database from '../database';
|
||||
import { systemCollectionRows } from '../database/system-data/collections';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
|
||||
import { AbstractServiceOptions, Accountability, PrimaryKey, SchemaOverview } from '../types';
|
||||
|
||||
export class UtilsService {
|
||||
knex: Knex;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ItemsService, MutationOptions } from './items';
|
||||
import { Item, PrimaryKey, AbstractServiceOptions } from '../types';
|
||||
import { AbstractServiceOptions, Item, PrimaryKey } from '../types';
|
||||
import { register } from '../webhooks';
|
||||
import { ItemsService, MutationOptions } from './items';
|
||||
|
||||
export class WebhooksService extends ItemsService {
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
|
||||
Reference in New Issue
Block a user