TS Config Modernization Program Part 3 of many (#17904)

* noImplicitOverride: true

* noImplicitReturns: true

* noPropertyAccessFromIndexSignature: true
This commit is contained in:
Rijk van Zanten
2023-03-23 16:47:55 -04:00
committed by GitHub
parent 8b0c5f1250
commit 80f4807a09
129 changed files with 1097 additions and 1017 deletions

View File

@@ -96,7 +96,7 @@ test('Sets accountability to payload contents if valid token is passed', async (
share,
share_scope: shareScope,
},
env.SECRET,
env['SECRET'],
{ issuer: 'directus' }
);
@@ -145,7 +145,7 @@ test('Sets accountability to payload contents if valid token is passed', async (
share,
share_scope: shareScope,
},
env.SECRET,
env['SECRET'],
{ issuer: 'directus' }
);

View File

@@ -52,7 +52,7 @@ export const handler = async (req: Request, res: Response, next: NextFunction) =
if (req.token) {
if (isDirectusJWT(req.token)) {
const payload = verifyAccessJWT(req.token, env.SECRET);
const payload = verifyAccessJWT(req.token, env['SECRET']);
req.accountability.role = payload.role;
req.accountability.admin = payload.admin_access === true || payload.admin_access == 1;

View File

@@ -11,11 +11,11 @@ const checkCacheMiddleware: RequestHandler = asyncHandler(async (req, res, next)
const { cache } = getCache();
if (req.method.toLowerCase() !== 'get' && req.originalUrl?.startsWith('/graphql') === false) return next();
if (env.CACHE_ENABLED !== true) return next();
if (env['CACHE_ENABLED'] !== true) return next();
if (!cache) return next();
if (shouldSkipCache(req)) {
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
if (env['CACHE_STATUS_HEADER']) res.setHeader(`${env['CACHE_STATUS_HEADER']}`, 'MISS');
return next();
}
@@ -27,7 +27,7 @@ const checkCacheMiddleware: RequestHandler = asyncHandler(async (req, res, next)
cachedData = await getCacheValue(cache, key);
} catch (err: any) {
logger.warn(err, `[cache] Couldn't read key ${key}. ${err.message}`);
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
if (env['CACHE_STATUS_HEADER']) res.setHeader(`${env['CACHE_STATUS_HEADER']}`, 'MISS');
return next();
}
@@ -38,7 +38,7 @@ const checkCacheMiddleware: RequestHandler = asyncHandler(async (req, res, next)
cacheExpiryDate = (await getCacheValue(cache, `${key}__expires_at`))?.exp;
} catch (err: any) {
logger.warn(err, `[cache] Couldn't read key ${`${key}__expires_at`}. ${err.message}`);
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
if (env['CACHE_STATUS_HEADER']) res.setHeader(`${env['CACHE_STATUS_HEADER']}`, 'MISS');
return next();
}
@@ -46,11 +46,11 @@ const checkCacheMiddleware: RequestHandler = asyncHandler(async (req, res, next)
res.setHeader('Cache-Control', getCacheControlHeader(req, cacheTTL, true, true));
res.setHeader('Vary', 'Origin, Cache-Control');
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'HIT');
if (env['CACHE_STATUS_HEADER']) res.setHeader(`${env['CACHE_STATUS_HEADER']}`, 'HIT');
return res.json(cachedData);
} else {
if (env.CACHE_STATUS_HEADER) res.setHeader(`${env.CACHE_STATUS_HEADER}`, 'MISS');
if (env['CACHE_STATUS_HEADER']) res.setHeader(`${env['CACHE_STATUS_HEADER']}`, 'MISS');
return next();
}
});

View File

@@ -8,13 +8,13 @@ import { ForbiddenException } from '../exceptions';
import asyncHandler from '../utils/async-handler';
const collectionExists: RequestHandler = asyncHandler(async (req, res, next) => {
if (!req.params.collection) return next();
if (!req.params['collection']) return next();
if (req.params.collection in req.schema.collections === false) {
if (req.params['collection'] in req.schema.collections === false) {
throw new ForbiddenException();
}
req.collection = req.params.collection;
req.collection = req.params['collection'];
if (req.collection.startsWith('directus_')) {
const systemRow = systemCollectionRows.find((collection) => {

View File

@@ -4,14 +4,14 @@ import env from '../env';
let corsMiddleware: RequestHandler = (req, res, next) => next();
if (env.CORS_ENABLED === true) {
if (env['CORS_ENABLED'] === true) {
corsMiddleware = cors({
origin: env.CORS_ORIGIN || true,
methods: env.CORS_METHODS || 'GET,POST,PATCH,DELETE',
allowedHeaders: env.CORS_ALLOWED_HEADERS,
exposedHeaders: env.CORS_EXPOSED_HEADERS,
credentials: env.CORS_CREDENTIALS || undefined,
maxAge: env.CORS_MAX_AGE || undefined,
origin: env['CORS_ORIGIN'] || true,
methods: env['CORS_METHODS'] || 'GET,POST,PATCH,DELETE',
allowedHeaders: env['CORS_ALLOWED_HEADERS'],
exposedHeaders: env['CORS_EXPOSED_HEADERS'],
credentials: env['CORS_CREDENTIALS'] || undefined,
maxAge: env['CORS_MAX_AGE'] || undefined,
});
}

View File

@@ -33,7 +33,7 @@ const errorHandler: ErrorRequestHandler = (err, req, res, _next) => {
}
for (const err of errors) {
if (env.NODE_ENV === 'development') {
if (env['NODE_ENV'] === 'development') {
err.extensions = {
...(err.extensions || {}),
stack: err.stack,
@@ -54,7 +54,7 @@ const errorHandler: ErrorRequestHandler = (err, req, res, _next) => {
});
if (err instanceof MethodNotAllowedException) {
res.header('Allow', err.extensions.allow.join(', '));
res.header('Allow', err.extensions['allow'].join(', '));
}
} else {
logger.error(err);

View File

@@ -12,8 +12,8 @@ import type { RequestHandler } from 'express';
const extractToken: RequestHandler = (req, res, next) => {
let token: string | null = null;
if (req.query && req.query.access_token) {
token = req.query.access_token as string;
if (req.query && req.query['access_token']) {
token = req.query['access_token'] as string;
}
if (req.headers && req.headers.authorization) {

View File

@@ -16,11 +16,11 @@ export const parseGraphQL: RequestHandler = asyncHandler(async (req, res, next)
let document: DocumentNode;
if (req.method === 'GET') {
query = (req.query.query as string | undefined) || null;
query = (req.query['query'] as string | undefined) || null;
if (req.query.variables) {
if (req.query['variables']) {
try {
variables = parseJSON(req.query.variables as string);
variables = parseJSON(req.query['variables'] as string);
} catch {
throw new InvalidQueryException(`Variables are invalid JSON.`);
}
@@ -28,7 +28,7 @@ export const parseGraphQL: RequestHandler = asyncHandler(async (req, res, next)
variables = {};
}
operationName = (req.query.operationName as string | undefined) || null;
operationName = (req.query['operationName'] as string | undefined) || null;
} else {
query = req.body.query || null;
variables = req.body.variables || null;
@@ -58,10 +58,16 @@ export const parseGraphQL: RequestHandler = asyncHandler(async (req, res, next)
// Prevent caching responses when mutations are made
if (operationAST?.operation === 'mutation') {
res.locals.cache = false;
res.locals['cache'] = false;
}
res.locals.graphqlParams = { document, query, variables, operationName, contextValue: { req, res } } as GraphQLParams;
res.locals['graphqlParams'] = {
document,
query,
variables,
operationName,
contextValue: { req, res },
} as GraphQLParams;
return next();
});

View File

@@ -13,7 +13,7 @@ const RATE_LIMITER_GLOBAL_KEY = 'global-rate-limit';
let checkRateLimit: RequestHandler = (_req, _res, next) => next();
export let rateLimiterGlobal: RateLimiterRedis | RateLimiterMemcache | RateLimiterMemory;
if (env.RATE_LIMITER_GLOBAL_ENABLED === true) {
if (env['RATE_LIMITER_GLOBAL_ENABLED'] === true) {
validateEnv(['RATE_LIMITER_GLOBAL_STORE', 'RATE_LIMITER_GLOBAL_DURATION', 'RATE_LIMITER_GLOBAL_POINTS']);
validateConfiguration();
@@ -27,7 +27,7 @@ if (env.RATE_LIMITER_GLOBAL_ENABLED === true) {
res.set('Retry-After', String(Math.round(rateLimiterRes.msBeforeNext / 1000)));
throw new HitRateLimitException(`Too many requests, retry after ${ms(rateLimiterRes.msBeforeNext)}.`, {
limit: +env.RATE_LIMITER_GLOBAL_POINTS,
limit: +env['RATE_LIMITER_GLOBAL_POINTS'],
reset: new Date(Date.now() + rateLimiterRes.msBeforeNext),
});
}
@@ -39,13 +39,13 @@ if (env.RATE_LIMITER_GLOBAL_ENABLED === true) {
export default checkRateLimit;
function validateConfiguration() {
if (env.RATE_LIMITER_ENABLED !== true) {
if (env['RATE_LIMITER_ENABLED'] !== true) {
logger.error(`The IP based rate limiter needs to be enabled when using the global rate limiter.`);
process.exit(1);
}
const globalPointsPerSec =
Number(env.RATE_LIMITER_GLOBAL_POINTS) / Math.max(Number(env.RATE_LIMITER_GLOBAL_DURATION), 1);
const regularPointsPerSec = Number(env.RATE_LIMITER_POINTS) / Math.max(Number(env.RATE_LIMITER_DURATION), 1);
Number(env['RATE_LIMITER_GLOBAL_POINTS']) / Math.max(Number(env['RATE_LIMITER_GLOBAL_DURATION']), 1);
const regularPointsPerSec = Number(env['RATE_LIMITER_POINTS']) / Math.max(Number(env['RATE_LIMITER_DURATION']), 1);
if (globalPointsPerSec <= regularPointsPerSec) {
logger.error(`The global rate limiter needs to allow more requests per second than the IP based rate limiter.`);
process.exit(1);

View File

@@ -11,7 +11,7 @@ import { validateEnv } from '../utils/validate-env';
let checkRateLimit: RequestHandler = (_req, _res, next) => next();
export let rateLimiter: RateLimiterRedis | RateLimiterMemcache | RateLimiterMemory;
if (env.RATE_LIMITER_ENABLED === true) {
if (env['RATE_LIMITER_ENABLED'] === true) {
validateEnv(['RATE_LIMITER_STORE', 'RATE_LIMITER_DURATION', 'RATE_LIMITER_POINTS']);
rateLimiter = createRateLimiter('RATE_LIMITER');
@@ -24,7 +24,7 @@ if (env.RATE_LIMITER_ENABLED === true) {
res.set('Retry-After', String(Math.round(rateLimiterRes.msBeforeNext / 1000)));
throw new HitRateLimitException(`Too many requests, retry after ${ms(rateLimiterRes.msBeforeNext)}.`, {
limit: +env.RATE_LIMITER_POINTS,
limit: +env['RATE_LIMITER_POINTS'],
reset: new Date(Date.now() + rateLimiterRes.msBeforeNext),
});
}

View File

@@ -16,30 +16,30 @@ export const respond: RequestHandler = asyncHandler(async (req, res) => {
let exceedsMaxSize = false;
if (env.CACHE_VALUE_MAX_SIZE !== false) {
const valueSize = res.locals.payload ? stringByteSize(JSON.stringify(res.locals.payload)) : 0;
const maxSize = parseBytesConfiguration(env.CACHE_VALUE_MAX_SIZE);
if (env['CACHE_VALUE_MAX_SIZE'] !== false) {
const valueSize = res.locals['payload'] ? stringByteSize(JSON.stringify(res.locals['payload'])) : 0;
const maxSize = parseBytesConfiguration(env['CACHE_VALUE_MAX_SIZE']);
exceedsMaxSize = valueSize > maxSize;
}
if (
(req.method.toLowerCase() === 'get' || req.originalUrl?.startsWith('/graphql')) &&
env.CACHE_ENABLED === true &&
env['CACHE_ENABLED'] === true &&
cache &&
!req.sanitizedQuery.export &&
res.locals.cache !== false &&
res.locals['cache'] !== false &&
exceedsMaxSize === false
) {
const key = getCacheKey(req);
try {
await setCacheValue(cache, key, res.locals.payload, getMilliseconds(env.CACHE_TTL));
await setCacheValue(cache, `${key}__expires_at`, { exp: Date.now() + getMilliseconds(env.CACHE_TTL, 0) });
await setCacheValue(cache, key, res.locals['payload'], getMilliseconds(env['CACHE_TTL']));
await setCacheValue(cache, `${key}__expires_at`, { exp: Date.now() + getMilliseconds(env['CACHE_TTL'], 0) });
} catch (err: any) {
logger.warn(err, `[cache] Couldn't set key ${key}. ${err}`);
}
res.setHeader('Cache-Control', getCacheControlHeader(req, getMilliseconds(env.CACHE_TTL), true, true));
res.setHeader('Cache-Control', getCacheControlHeader(req, getMilliseconds(env['CACHE_TTL']), true, true));
res.setHeader('Vary', 'Origin, Cache-Control');
} else {
// Don't cache anything by default
@@ -63,32 +63,32 @@ export const respond: RequestHandler = asyncHandler(async (req, res) => {
if (req.sanitizedQuery.export === 'json') {
res.attachment(`${filename}.json`);
res.set('Content-Type', 'application/json');
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'json'));
return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'json'));
}
if (req.sanitizedQuery.export === 'xml') {
res.attachment(`${filename}.xml`);
res.set('Content-Type', 'text/xml');
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'xml'));
return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'xml'));
}
if (req.sanitizedQuery.export === 'csv') {
res.attachment(`${filename}.csv`);
res.set('Content-Type', 'text/csv');
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'csv'));
return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'csv'));
}
if (req.sanitizedQuery.export === 'yaml') {
res.attachment(`${filename}.yaml`);
res.set('Content-Type', 'text/yaml');
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'yaml'));
return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'yaml'));
}
}
if (Buffer.isBuffer(res.locals.payload)) {
return res.end(res.locals.payload);
} else if (res.locals.payload) {
return res.json(res.locals.payload);
if (Buffer.isBuffer(res.locals['payload'])) {
return res.end(res.locals['payload']);
} else if (res.locals['payload']) {
return res.json(res.locals['payload']);
} else {
return res.status(204).end();
}

View File

@@ -13,7 +13,7 @@ const sanitizeQueryMiddleware: RequestHandler = (req, _res, next) => {
req.sanitizedQuery = sanitizeQuery(
{
fields: req.query.fields || '*',
fields: req.query['fields'] || '*',
...req.query,
},
req.accountability || null