mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Treat sanitizedquery as frozen
This commit is contained in:
@@ -6,7 +6,7 @@ let cache: Keyv | null = null;
|
||||
|
||||
if (env.CACHE_ENABLED === true) {
|
||||
validateEnv(['CACHE_NAMESPACE', 'CACHE_TTL', 'CACHE_STORE']);
|
||||
cache = new Keyv({ namespace: process.env.CACHE_NAMESPACE });
|
||||
cache = new Keyv({ namespace: env.CACHE_NAMESPACE, ttl: env.CACHE_TTL });
|
||||
}
|
||||
|
||||
export default cache;
|
||||
|
||||
@@ -30,10 +30,10 @@ STORAGE_LOCAL_ROOT="./uploads"
|
||||
|
||||
{{ security }}
|
||||
|
||||
ACCESS_TOKEN_TTL="15m",
|
||||
REFRESH_TOKEN_TTL="7d",
|
||||
REFRESH_TOKEN_COOKIE_SECURE=false,
|
||||
REFRESH_TOKEN_COOKIE_SAME_SITE="lax",
|
||||
ACCESS_TOKEN_TTL="15m"
|
||||
REFRESH_TOKEN_TTL="7d"
|
||||
REFRESH_TOKEN_COOKIE_SECURE=false
|
||||
REFRESH_TOKEN_COOKIE_SAME_SITE="lax"
|
||||
|
||||
####################################################################################################
|
||||
## SSO (OAuth) Providers
|
||||
|
||||
@@ -2,6 +2,7 @@ import express from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import PermissionsService from '../services/permissions';
|
||||
import MetaService from '../services/meta';
|
||||
import { clone } from 'lodash';
|
||||
import { InvalidCredentialsException } from '../exceptions';
|
||||
|
||||
const router = express.Router();
|
||||
@@ -40,7 +41,7 @@ router.get(
|
||||
}
|
||||
|
||||
const service = new PermissionsService();
|
||||
const query = req.sanitizedQuery || {};
|
||||
const query = clone(req.sanitizedQuery || {});
|
||||
|
||||
query.filter = {
|
||||
...(query.filter || {}),
|
||||
@@ -59,6 +60,7 @@ router.get(
|
||||
router.get(
|
||||
'/:pk',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
if (req.path.endsWith('me')) return next();
|
||||
const service = new PermissionsService({ accountability: req.accountability });
|
||||
const record = await service.readByKey(Number(req.params.pk), req.sanitizedQuery);
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ router.get(
|
||||
router.get(
|
||||
'/:pk',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
if (req.path.endsWith('me')) return next();
|
||||
const service = new UsersService({ accountability: req.accountability });
|
||||
const items = await service.readByKey(req.params.pk, req.sanitizedQuery);
|
||||
res.locals.payload = { data: items || null };
|
||||
|
||||
@@ -13,8 +13,6 @@ const checkCacheMiddleware: RequestHandler = asyncHandler(async (req, res, next)
|
||||
const key = getCacheKey(req);
|
||||
const cachedData = await cache.get(key);
|
||||
|
||||
console.log(key);
|
||||
|
||||
if (cachedData) {
|
||||
return res.json(cachedData);
|
||||
} else {
|
||||
|
||||
@@ -5,10 +5,9 @@ import { getCacheKey } from "../utils/get-cache-key";
|
||||
import cache from '../cache';
|
||||
|
||||
export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
if (env.CACHE_ENABLED === true && cache) {
|
||||
if (req.method.toLowerCase() === 'get' && env.CACHE_ENABLED === true && cache) {
|
||||
const key = getCacheKey(req);
|
||||
await cache.set(key, res.locals.payload);
|
||||
console.log(key);
|
||||
}
|
||||
|
||||
return res.json(res.locals.payload);
|
||||
|
||||
@@ -57,6 +57,7 @@ const sanitizeQuery: RequestHandler = (req, res, next) => {
|
||||
}
|
||||
|
||||
req.sanitizedQuery = query;
|
||||
Object.freeze(req.sanitizedQuery);
|
||||
return next();
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import SchemaInspector from 'knex-schema-inspector';
|
||||
import FieldsService from '../services/fields';
|
||||
import { omit } from 'lodash';
|
||||
import ItemsService from '../services/items';
|
||||
import cache from '../cache';
|
||||
|
||||
export default class CollectionsService {
|
||||
knex: Knex;
|
||||
@@ -85,6 +86,10 @@ export default class CollectionsService {
|
||||
}
|
||||
});
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return Array.isArray(data) ? createdCollections : createdCollections[0];
|
||||
}
|
||||
|
||||
@@ -233,6 +238,10 @@ export default class CollectionsService {
|
||||
|
||||
await collectionItemsService.update(collectionUpdates);
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return key!;
|
||||
}
|
||||
|
||||
@@ -296,6 +305,10 @@ export default class CollectionsService {
|
||||
await this.knex.schema.dropTable(collectionKey);
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@ import ItemsService from '../services/items';
|
||||
import { ColumnBuilder } from 'knex';
|
||||
import getLocalType from '../utils/get-local-type';
|
||||
import { types } from '../types';
|
||||
import { FieldNotFoundException, ForbiddenException } from '../exceptions';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import Knex, { CreateTableBuilder } from 'knex';
|
||||
import PayloadService from '../services/payload';
|
||||
import getDefaultValue from '../utils/get-default-value';
|
||||
import cache from '../cache';
|
||||
|
||||
type RawField = Partial<Field> & { field: string; type: typeof types[number] };
|
||||
|
||||
@@ -205,6 +206,10 @@ export default class FieldsService {
|
||||
field: field.field,
|
||||
});
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** @todo research how to make this happen in SQLite / Redshift */
|
||||
@@ -272,6 +277,10 @@ export default class FieldsService {
|
||||
}
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return field.field;
|
||||
}
|
||||
|
||||
@@ -309,6 +318,10 @@ export default class FieldsService {
|
||||
.where({ one_collection: collection, one_field: field });
|
||||
}
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public addColumnToTable(table: CreateTableBuilder, field: Field) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import parseIPTC from '../utils/parse-iptc';
|
||||
import path from 'path';
|
||||
import { AbstractServiceOptions, File, PrimaryKey } from '../types';
|
||||
import { clone } from 'lodash';
|
||||
import cache from '../cache';
|
||||
|
||||
export default class FilesService extends ItemsService {
|
||||
constructor(options?: AbstractServiceOptions) {
|
||||
@@ -77,6 +78,10 @@ export default class FilesService extends ItemsService {
|
||||
const sudoService = new ItemsService('directus_files');
|
||||
await sudoService.update(payload, primaryKey);
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return primaryKey;
|
||||
}
|
||||
|
||||
@@ -97,6 +102,10 @@ export default class FilesService extends ItemsService {
|
||||
|
||||
await super.delete(keys);
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
AbstractServiceOptions,
|
||||
} from '../types';
|
||||
import Knex from 'knex';
|
||||
import cache from '../cache';
|
||||
|
||||
import PayloadService from './payload';
|
||||
import AuthorizationService from './authorization';
|
||||
@@ -145,6 +146,10 @@ export default class ItemsService implements AbstractService {
|
||||
await trx.insert(revisionRecords).into('directus_revisions');
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return primaryKeys;
|
||||
});
|
||||
|
||||
@@ -172,6 +177,7 @@ export default class ItemsService implements AbstractService {
|
||||
query: Query = {},
|
||||
action: PermissionsAction = 'read'
|
||||
): Promise<Item | Item[]> {
|
||||
query = clone(query);
|
||||
const schemaInspector = SchemaInspector(this.knex);
|
||||
const primaryKeyField = await schemaInspector.primary(this.collection);
|
||||
const keys = Array.isArray(key) ? key : [key];
|
||||
@@ -301,6 +307,10 @@ export default class ItemsService implements AbstractService {
|
||||
}
|
||||
});
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -359,10 +369,15 @@ export default class ItemsService implements AbstractService {
|
||||
}
|
||||
});
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
async readSingleton(query: Query) {
|
||||
query = clone(query);
|
||||
const schemaInspector = SchemaInspector(this.knex);
|
||||
query.limit = 1;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { InvalidPayloadException, ForbiddenException } from '../exceptions';
|
||||
import { Accountability, PrimaryKey, Item, AbstractServiceOptions } from '../types';
|
||||
import Knex from 'knex';
|
||||
import env from '../env';
|
||||
import cache from '../cache';
|
||||
|
||||
export default class UsersService extends ItemsService {
|
||||
knex: Knex;
|
||||
@@ -42,6 +43,10 @@ export default class UsersService extends ItemsService {
|
||||
}
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
|
||||
return this.service.update(data, key as any);
|
||||
}
|
||||
|
||||
@@ -78,6 +83,10 @@ export default class UsersService extends ItemsService {
|
||||
await this.knex('directus_users')
|
||||
.update({ password: passwordHashed, status: 'active' })
|
||||
.where({ id: user.id });
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
async requestPasswordReset(email: string) {
|
||||
@@ -114,6 +123,10 @@ export default class UsersService extends ItemsService {
|
||||
await this.knex('directus_users')
|
||||
.update({ password: passwordHashed, status: 'active' })
|
||||
.where({ id: user.id });
|
||||
|
||||
if (cache) {
|
||||
await cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
async enableTFA(pk: string) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
Accountability,
|
||||
} from '../types';
|
||||
import database from '../database';
|
||||
import { clone } from 'lodash';
|
||||
|
||||
export default async function getASTFromQuery(
|
||||
collection: string,
|
||||
@@ -19,6 +20,7 @@ export default async function getASTFromQuery(
|
||||
accountability?: Accountability | null,
|
||||
action?: PermissionsAction
|
||||
): Promise<AST> {
|
||||
query = clone(query);
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Request } from "express";
|
||||
import url from 'url';
|
||||
|
||||
export function getCacheKey(req: Request) {
|
||||
const key = `${req.accountability?.user || 'null'}-${req.originalUrl}-${JSON.stringify(req.sanitizedQuery)}`;
|
||||
const path = url.parse(req.originalUrl).pathname;
|
||||
const key = `${req.accountability?.user || 'null'}-${path}-${JSON.stringify(req.sanitizedQuery)}`;
|
||||
return key;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user