chore: moves file handler into catch all GET rest handler
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { GET_STATIC_FILE } from '@payloadcms/next/routes/index.js'
|
||||
|
||||
export const GET = GET_STATIC_FILE(config)
|
||||
@@ -6,5 +6,3 @@ export {
|
||||
PATCH as REST_PATCH,
|
||||
POST as REST_POST,
|
||||
} from './rest/index.js'
|
||||
|
||||
export { GET as GET_STATIC_FILE } from './rest/[collection]/file/[filename]/route.js'
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
import type { Collection, PayloadRequest, SanitizedConfig, Where } from 'payload/types'
|
||||
|
||||
import fsPromises from 'fs/promises'
|
||||
import httpStatus from 'http-status'
|
||||
import path from 'path'
|
||||
import { executeAccess } from 'payload/auth'
|
||||
import { APIError, Forbidden } from 'payload/errors'
|
||||
|
||||
import { streamFile } from '../../../../../next-stream-file/index.js'
|
||||
import { createPayloadRequest } from '../../../../../utilities/createPayloadRequest.js'
|
||||
import { RouteError } from '../../../RouteError.js'
|
||||
import { endpointsAreDisabled } from '../../../checkEndpoints.js'
|
||||
|
||||
async function checkFileAccess({
|
||||
collection,
|
||||
filename,
|
||||
req,
|
||||
}: {
|
||||
collection: Collection
|
||||
filename: string
|
||||
req: PayloadRequest
|
||||
}) {
|
||||
const { config } = collection
|
||||
const disableEndpoints = endpointsAreDisabled({ endpoints: config.endpoints, request: req })
|
||||
if (disableEndpoints) return disableEndpoints
|
||||
|
||||
const accessResult = await executeAccess({ isReadingStaticFile: true, req }, config.access.read)
|
||||
|
||||
if (typeof accessResult === 'object') {
|
||||
const queryToBuild: Where = {
|
||||
and: [
|
||||
{
|
||||
or: [
|
||||
{
|
||||
filename: {
|
||||
equals: filename,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
accessResult,
|
||||
],
|
||||
}
|
||||
|
||||
if (config.upload.imageSizes) {
|
||||
config.upload.imageSizes.forEach(({ name }) => {
|
||||
queryToBuild.and[0].or.push({
|
||||
[`sizes.${name}.filename`]: {
|
||||
equals: filename,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const doc = await req.payload.db.findOne({
|
||||
collection: config.slug,
|
||||
req,
|
||||
where: queryToBuild,
|
||||
})
|
||||
|
||||
if (!doc) {
|
||||
throw new Forbidden(req.t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const GET =
|
||||
(config: Promise<SanitizedConfig>) =>
|
||||
async (request: Request, { params }: { params: { collection: string; filename: string } }) => {
|
||||
const { collection: collectionSlug, filename } = params
|
||||
let req: PayloadRequest
|
||||
let collection: Collection
|
||||
|
||||
try {
|
||||
req = await createPayloadRequest({
|
||||
config,
|
||||
params: { collection: collectionSlug },
|
||||
request,
|
||||
})
|
||||
|
||||
collection = req.payload.collections?.[collectionSlug]
|
||||
|
||||
if (!collection) {
|
||||
throw new APIError(`Media collection not found: ${collectionSlug}`, httpStatus.BAD_REQUEST)
|
||||
}
|
||||
|
||||
if (!collection.config.upload) {
|
||||
throw new APIError(
|
||||
`This collection is not an upload collection: ${collectionSlug}`,
|
||||
httpStatus.BAD_REQUEST,
|
||||
)
|
||||
}
|
||||
|
||||
if (collection.config.upload.disableLocalStorage && !collection.config.upload.handlers) {
|
||||
throw new APIError(
|
||||
`This collection has local storage disabled: ${collectionSlug}`,
|
||||
httpStatus.BAD_REQUEST,
|
||||
)
|
||||
}
|
||||
|
||||
await checkFileAccess({
|
||||
collection,
|
||||
filename,
|
||||
req,
|
||||
})
|
||||
|
||||
let response: Response = null
|
||||
if (collection.config.upload.handlers?.length) {
|
||||
for (const handler of collection.config.upload.handlers) {
|
||||
response = await handler(req, { params })
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
const fileDir = collection.config.upload?.staticDir || collection.config.slug
|
||||
const filePath = path.resolve(`${fileDir}/${filename}`)
|
||||
|
||||
const stats = await fsPromises.stat(filePath)
|
||||
const data = streamFile(filePath)
|
||||
|
||||
return new Response(data, {
|
||||
headers: new Headers({
|
||||
'content-length': stats.size + '',
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
} catch (error) {
|
||||
return RouteError({
|
||||
collection,
|
||||
err: error,
|
||||
req,
|
||||
})
|
||||
}
|
||||
}
|
||||
59
packages/next/src/routes/rest/files/checkFileAccess.ts
Normal file
59
packages/next/src/routes/rest/files/checkFileAccess.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import type { Collection, PayloadRequest, Where } from 'payload/types'
|
||||
|
||||
import { executeAccess } from 'payload/auth'
|
||||
import { Forbidden } from 'payload/errors'
|
||||
|
||||
import { endpointsAreDisabled } from '../checkEndpoints.js'
|
||||
|
||||
export async function checkFileAccess({
|
||||
collection,
|
||||
filename,
|
||||
req,
|
||||
}: {
|
||||
collection: Collection
|
||||
filename: string
|
||||
req: PayloadRequest
|
||||
}) {
|
||||
const { config } = collection
|
||||
const disableEndpoints = endpointsAreDisabled({ endpoints: config.endpoints, request: req })
|
||||
if (disableEndpoints) return disableEndpoints
|
||||
|
||||
const accessResult = await executeAccess({ isReadingStaticFile: true, req }, config.access.read)
|
||||
|
||||
if (typeof accessResult === 'object') {
|
||||
const queryToBuild: Where = {
|
||||
and: [
|
||||
{
|
||||
or: [
|
||||
{
|
||||
filename: {
|
||||
equals: filename,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
accessResult,
|
||||
],
|
||||
}
|
||||
|
||||
if (config.upload.imageSizes) {
|
||||
config.upload.imageSizes.forEach(({ name }) => {
|
||||
queryToBuild.and[0].or.push({
|
||||
[`sizes.${name}.filename`]: {
|
||||
equals: filename,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const doc = await req.payload.db.findOne({
|
||||
collection: config.slug,
|
||||
req,
|
||||
where: queryToBuild,
|
||||
})
|
||||
|
||||
if (!doc) {
|
||||
throw new Forbidden(req.t)
|
||||
}
|
||||
}
|
||||
}
|
||||
73
packages/next/src/routes/rest/files/getFile.ts
Normal file
73
packages/next/src/routes/rest/files/getFile.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { Collection, PayloadRequest } from 'payload/types'
|
||||
|
||||
import fsPromises from 'fs/promises'
|
||||
import httpStatus from 'http-status'
|
||||
import path from 'path'
|
||||
import { APIError } from 'payload/errors'
|
||||
|
||||
import { streamFile } from '../../../next-stream-file/index.js'
|
||||
import { RouteError } from '../RouteError.js'
|
||||
import { checkFileAccess } from './checkFileAccess.js'
|
||||
|
||||
// /:collectionSlug/file/:filename
|
||||
type Args = {
|
||||
collection: Collection
|
||||
filename: string
|
||||
req: PayloadRequest
|
||||
}
|
||||
export const getFile = async ({ collection, filename, req }: Args): Promise<Response> => {
|
||||
try {
|
||||
if (!collection.config.upload) {
|
||||
throw new APIError(
|
||||
`This collection is not an upload collection: ${collection.config.slug}`,
|
||||
httpStatus.BAD_REQUEST,
|
||||
)
|
||||
}
|
||||
|
||||
if (collection.config.upload.disableLocalStorage && !collection.config.upload.handlers) {
|
||||
throw new APIError(
|
||||
`This collection has local storage disabled: ${collection.config.slug}`,
|
||||
httpStatus.BAD_REQUEST,
|
||||
)
|
||||
}
|
||||
|
||||
await checkFileAccess({
|
||||
collection,
|
||||
filename,
|
||||
req,
|
||||
})
|
||||
|
||||
let response: Response = null
|
||||
if (collection.config.upload.handlers?.length) {
|
||||
for (const handler of collection.config.upload.handlers) {
|
||||
response = await handler(req, {
|
||||
params: {
|
||||
collection: collection.config.slug,
|
||||
filename,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
const fileDir = collection.config.upload?.staticDir || collection.config.slug
|
||||
const filePath = path.resolve(`${fileDir}/${filename}`)
|
||||
|
||||
const stats = await fsPromises.stat(filePath)
|
||||
const data = streamFile(filePath)
|
||||
|
||||
return new Response(data, {
|
||||
headers: new Headers({
|
||||
'content-length': stats.size + '',
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
} catch (error) {
|
||||
return RouteError({
|
||||
collection,
|
||||
err: error,
|
||||
req,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import { findVersions } from './collections/findVersions.js'
|
||||
import { restoreVersion } from './collections/restoreVersion.js'
|
||||
import { update } from './collections/update.js'
|
||||
import { updateByID } from './collections/updateByID.js'
|
||||
import { getFile } from './files/getFile.js'
|
||||
import { docAccess as docAccessGlobal } from './globals/docAccess.js'
|
||||
import { findOne } from './globals/findOne.js'
|
||||
import { findVersionByID as findVersionByIdGlobal } from './globals/findVersionByID.js'
|
||||
@@ -55,6 +56,7 @@ const endpoints = {
|
||||
'doc-versions-by-id': findVersionByID,
|
||||
find,
|
||||
findByID,
|
||||
getFile,
|
||||
init,
|
||||
me,
|
||||
versions: findVersions,
|
||||
@@ -205,7 +207,10 @@ export const GET =
|
||||
}
|
||||
break
|
||||
case 3:
|
||||
if (`doc-${slug2}-by-id` in endpoints.collection.GET) {
|
||||
if (slug2 === 'file') {
|
||||
// /:collection/file/:filename
|
||||
res = await endpoints.collection.GET.getFile({ collection, filename: slug3, req })
|
||||
} else if (`doc-${slug2}-by-id` in endpoints.collection.GET) {
|
||||
// /:collection/access/:id
|
||||
// /:collection/versions/:id
|
||||
|
||||
|
||||
Reference in New Issue
Block a user