fix: upload and auth endpoints are mounted for all collections (#11231)

This PR ensures, that collections that don't have `auth: true` don't
mount authentication related endpoints like `/me`, the same for uploads.
Additionally, moves upload-related endpoints to `uploads/endpoints/*`.
This commit is contained in:
Sasha
2025-02-17 21:11:40 +02:00
committed by GitHub
parent 3229b9a4a6
commit 749962a1db
6 changed files with 101 additions and 16 deletions

View File

@@ -3,11 +3,13 @@ import type { LoginWithUsernameOptions } from '../../auth/types.js'
import type { Config, SanitizedConfig } from '../../config/types.js' import type { Config, SanitizedConfig } from '../../config/types.js'
import type { CollectionConfig, SanitizedCollectionConfig, SanitizedJoins } from './types.js' import type { CollectionConfig, SanitizedCollectionConfig, SanitizedJoins } from './types.js'
import { authCollectionEndpoints } from '../../auth/endpoints/index.js'
import { getBaseAuthFields } from '../../auth/getAuthFields.js' import { getBaseAuthFields } from '../../auth/getAuthFields.js'
import { TimestampsRequired } from '../../errors/TimestampsRequired.js' import { TimestampsRequired } from '../../errors/TimestampsRequired.js'
import { sanitizeFields } from '../../fields/config/sanitize.js' import { sanitizeFields } from '../../fields/config/sanitize.js'
import { fieldAffectsData } from '../../fields/config/types.js' import { fieldAffectsData } from '../../fields/config/types.js'
import mergeBaseFields from '../../fields/mergeBaseFields.js' import mergeBaseFields from '../../fields/mergeBaseFields.js'
import { uploadCollectionEndpoints } from '../../uploads/endpoints/index.js'
import { getBaseUploadFields } from '../../uploads/getBaseFields.js' import { getBaseUploadFields } from '../../uploads/getBaseFields.js'
import { deepMergeWithReactComponents } from '../../utilities/deepMerge.js' import { deepMergeWithReactComponents } from '../../utilities/deepMerge.js'
import { flattenAllFields } from '../../utilities/flattenAllFields.js' import { flattenAllFields } from '../../utilities/flattenAllFields.js'
@@ -58,6 +60,18 @@ export const sanitizeCollection = async (
sanitized.endpoints = [] sanitized.endpoints = []
} }
if (sanitized.auth) {
for (const endpoint of authCollectionEndpoints) {
sanitized.endpoints.push(endpoint)
}
}
if (sanitized.upload) {
for (const endpoint of uploadCollectionEndpoints) {
sanitized.endpoints.push(endpoint)
}
}
for (const endpoint of defaultCollectionEndpoints) { for (const endpoint of defaultCollectionEndpoints) {
sanitized.endpoints.push(endpoint) sanitized.endpoints.push(endpoint)
} }

View File

@@ -1,6 +1,5 @@
import type { Endpoint } from '../../config/types.js' import type { Endpoint } from '../../config/types.js'
import { authCollectionEndpoints } from '../../auth/endpoints/index.js'
import { wrapInternalEndpoints } from '../../utilities/wrapInternalEndpoints.js' import { wrapInternalEndpoints } from '../../utilities/wrapInternalEndpoints.js'
import { countHandler } from './count.js' import { countHandler } from './count.js'
import { createHandler } from './create.js' import { createHandler } from './create.js'
@@ -12,15 +11,12 @@ import { findHandler } from './find.js'
import { findByIDHandler } from './findByID.js' import { findByIDHandler } from './findByID.js'
import { findVersionByIDHandler } from './findVersionByID.js' import { findVersionByIDHandler } from './findVersionByID.js'
import { findVersionsHandler } from './findVersions.js' import { findVersionsHandler } from './findVersions.js'
import { getFileHandler } from './getFile.js'
import { getFileFromURLHandler } from './getFileFromURL.js'
import { previewHandler } from './preview.js' import { previewHandler } from './preview.js'
import { restoreVersionHandler } from './restoreVersion.js' import { restoreVersionHandler } from './restoreVersion.js'
import { updateHandler } from './update.js' import { updateHandler } from './update.js'
import { updateByIDHandler } from './updateByID.js' import { updateByIDHandler } from './updateByID.js'
export const defaultCollectionEndpoints: Endpoint[] = [ export const defaultCollectionEndpoints: Endpoint[] = [
...authCollectionEndpoints,
...wrapInternalEndpoints([ ...wrapInternalEndpoints([
{ {
handler: countHandler, handler: countHandler,
@@ -47,11 +43,6 @@ export const defaultCollectionEndpoints: Endpoint[] = [
method: 'post', method: 'post',
path: '/access/:id?', path: '/access/:id?',
}, },
{
handler: getFileFromURLHandler,
method: 'get',
path: '/paste-url/:id?',
},
{ {
handler: findVersionsHandler, handler: findVersionsHandler,
method: 'get', method: 'get',
@@ -77,11 +68,6 @@ export const defaultCollectionEndpoints: Endpoint[] = [
method: 'get', method: 'get',
path: '/versions/:id', path: '/versions/:id',
}, },
{
handler: getFileHandler,
method: 'get',
path: '/file/:filename',
},
{ {
handler: previewHandler, handler: previewHandler,
method: 'get', method: 'get',

View File

@@ -0,0 +1,18 @@
import type { Endpoint } from '../../config/types.js'
import { wrapInternalEndpoints } from '../../utilities/wrapInternalEndpoints.js'
import { getFileHandler } from './getFile.js'
import { getFileFromURLHandler } from './getFileFromURL.js'
export const uploadCollectionEndpoints: Endpoint[] = wrapInternalEndpoints([
{
handler: getFileFromURLHandler,
method: 'get',
path: '/paste-url/:id?',
},
{
handler: getFileHandler,
method: 'get',
path: '/file/:filename',
},
])

View File

@@ -17,8 +17,8 @@ import {
errorOnHookSlug, errorOnHookSlug,
methods, methods,
pointSlug, pointSlug,
relationSlug,
postsSlug, postsSlug,
relationSlug,
} from './config.js' } from './config.js'
const filename = fileURLToPath(import.meta.url) const filename = fileURLToPath(import.meta.url)
@@ -1454,7 +1454,7 @@ describe('collections-rest', () => {
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
await createPost({ await createPost({
number: i, number: i,
relationField: relatedDoc.id as string, relationField: relatedDoc.id,
title: 'paginate-test', title: 'paginate-test',
}) })
} }
@@ -1733,6 +1733,73 @@ describe('collections-rest', () => {
} }
}) })
}) })
it('should not mount auth endpoints for collection without auth', async () => {
const authEndpoints = [
{
method: 'post',
path: '/forgot-password',
},
{
method: 'post',
path: '/login',
},
{
method: 'post',
path: '/logout',
},
{
method: 'post',
path: '/refresh-token',
},
{
method: 'post',
path: '/first-register',
},
{
method: 'post',
path: '/reset-password',
},
{
method: 'post',
path: '/unlock',
},
]
for (const endpoint of authEndpoints) {
const result = await restClient[endpoint.method.toUpperCase()](
`/${endpointsSlug}${endpoint.path}`,
)
expect(result.status).toBe(404)
const json = await result.json()
expect(json.message.startsWith('Route not found')).toBeTruthy()
}
})
it('should not mount upload endpoints for collection without auth', async () => {
const uploadEndpoints = [
{
method: 'get',
path: '/paste-url/some-id',
},
{
method: 'get',
path: '/file/some-filename.png',
},
]
for (const endpoint of uploadEndpoints) {
const result = await restClient[endpoint.method.toUpperCase()](
`/${endpointsSlug}${endpoint.path}`,
)
expect(result.status).toBe(404)
expect((await result.json()).message.startsWith('Route not found')).toBeTruthy()
}
})
}) })
async function createPost(overrides?: Partial<Post>) { async function createPost(overrides?: Partial<Post>) {