storage-upload/api/media/security.mjs
Jonatan Nilsson afde7fb89a
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
cors: Add proper full cors support to all the media routes
2023-11-15 13:21:22 +00:00

118 lines
2.9 KiB
JavaScript

import { HttpError } from 'flaska'
import decode from '../jwt/decode.mjs'
import config from '../config.mjs'
export function verifyToken(ctx) {
let token = ctx.query.get('token')
if (!token) {
throw new HttpError(422, 'Token is missing in query')
}
let org = config.get('sites')
let sites = {}
for (let key in org) {
if (org.hasOwnProperty(key)) {
sites[key] = org[key].keys
}
}
try {
let decoded = decode(token, sites, [])
return decoded.iss
} catch (err) {
ctx.log.error(err, 'Error decoding token: ' + token)
throw new HttpError(422, 'Token was invalid')
}
}
export function hasCors(site) {
let sites = config.get('sites')
return sites[site]?.cors === true
}
export function verifyCorsEnabled(ctx) {
let site
try {
site = verifyToken(ctx)
} catch (err) {
throw new HttpError(404)
}
if (!hasCors(site)) {
throw new HttpError(404)
}
}
export function throwIfNotPublic(site) {
let sites = config.get('sites')
if (!sites[site] || sites[site].public !== true) {
throw new HttpError(404, `Requested site ${site} did not exist`)
}
}
const validObjectOperations = [
'resize',
'extend',
'flatten',
]
const validNumberOperations = [
'blur',
'trim',
]
export function verifyBody(ctx) {
let keys = Object.keys(ctx.req.body)
for (let key of keys) {
if (key === 'filename' || key === 'path') {
throw new HttpError(422, 'Body item with name filename or path is not allowed')
}
let item = ctx.req.body[key]
if (item == null) continue
if (typeof(item) !== 'object'
|| Array.isArray(item)) {
throw new HttpError(422, `Body item ${key} was not valid`)
}
if (typeof(item.format) !== 'string'
|| !item.format
|| validObjectOperations.includes(item.format)
|| item.format === 'out') {
throw new HttpError(422, `Body item ${key} missing valid format`)
}
if (typeof(item[item.format]) !== 'object'
|| !item[item.format]
|| Array.isArray(item[item.format])) {
throw new HttpError(422, `Body item ${key} options for format ${item.format} was not valid`)
}
if (item.out != null) {
if (typeof(item.out) !== 'string'
|| (item.out !== '' && item.out !== 'file' && item.out !== 'base64')
) {
throw new HttpError(422, `Body item ${key} key out was invalid`)
}
}
for (let operation of validObjectOperations) {
if (item[operation] != null) {
if (typeof(item[operation]) !== 'object'
|| Array.isArray(item[operation])) {
throw new HttpError(422, `Body item ${key} key ${operation} was invalid`)
}
}
}
for (let operation of validNumberOperations) {
if (item[operation] != null) {
if (typeof(item[operation]) !== 'number') {
throw new HttpError(422, `Body item ${key} key ${operation} was invalid`)
}
}
}
}
}