feat(3.0): next route handlers (#4590)
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import { me } from '@payloadcms/next/routes/me'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const GET = me({ config })
|
||||
export { GET, POST, DELETE, PATCH } from '@payloadcms/next/dist/routes/index'
|
||||
@@ -1,6 +0,0 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { init } from '@payloadcms/next/routes/init'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const GET = init({ config })
|
||||
@@ -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 { login } from '@payloadcms/next/routes/login'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const POST = login({ config })
|
||||
15
packages/next/.swcrc
Normal file
15
packages/next/.swcrc
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/swcrc",
|
||||
"sourceMaps": "inline",
|
||||
"jsc": {
|
||||
"target": "esnext",
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"tsx": true,
|
||||
"dts": true
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "commonjs"
|
||||
}
|
||||
}
|
||||
@@ -30,18 +30,24 @@
|
||||
"import": "./src/routes/*.ts",
|
||||
"require": "./src/routes/*.ts",
|
||||
"types": "./src/routes/*.ts"
|
||||
}
|
||||
},
|
||||
"./dist/routes/*": "./dist/routes/*.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@payloadcms/ui": "workspace:*",
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"@payloadcms/ui": "workspace:*",
|
||||
"payload": "workspace:*",
|
||||
"sass": "^1.69.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonwebtoken": "9.0.1",
|
||||
"path-to-regexp": "^6.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"payload": "^2.0.0",
|
||||
"http-status": "1.6.2",
|
||||
"i18next": "22.5.1",
|
||||
"next": "^14.0.0",
|
||||
"i18next": "22.5.1"
|
||||
"payload": "^2.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"exports": {
|
||||
@@ -60,6 +66,11 @@
|
||||
"require": "./dist/pages/*.js",
|
||||
"types": "./dist/pages/*.d.ts"
|
||||
},
|
||||
"./app/*": {
|
||||
"import": "./dist/app/*.js",
|
||||
"require": "./dist/app/*.js",
|
||||
"types": "./dist/app/*.d.ts"
|
||||
},
|
||||
"./routes/*": {
|
||||
"import": "./dist/routes/*.js",
|
||||
"require": "./dist/routes/*.js",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import { me } from '@payloadcms/next/routes/me'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const GET = me({ config })
|
||||
export { GET, POST, DELETE, PATCH } from '@payloadcms/next/dist/routes/index'
|
||||
@@ -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 { init } from '@payloadcms/next/routes/init'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const GET = init({ config })
|
||||
@@ -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 { login } from '@payloadcms/next/routes/login'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const POST = login({ config })
|
||||
@@ -1,9 +0,0 @@
|
||||
import { PayloadRequest, SanitizedConfig } from 'payload/types'
|
||||
|
||||
type Args = {
|
||||
config: SanitizedConfig
|
||||
req: PayloadRequest
|
||||
}
|
||||
export const authenticate = async ({ config, req }: Args): Promise<PayloadRequest> => {
|
||||
return req
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export { init } from '../routes/init'
|
||||
export { login } from '../routes/login'
|
||||
14
packages/next/src/routes/auth/access.ts
Normal file
14
packages/next/src/routes/auth/access.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import httpStatus from 'http-status'
|
||||
import { accessOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const access = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const results = await accessOperation({
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(results, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
25
packages/next/src/routes/auth/forgotPassword.ts
Normal file
25
packages/next/src/routes/auth/forgotPassword.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { forgotPasswordOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const forgotPassword = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
await forgotPasswordOperation({
|
||||
collection: req.collection,
|
||||
data: {
|
||||
email: req.data.email as string,
|
||||
},
|
||||
disableEmail: Boolean(req.data?.disableEmail),
|
||||
expiration: typeof req.data.expiration === 'number' ? req.data.expiration : undefined,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Success',
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
11
packages/next/src/routes/auth/init.ts
Normal file
11
packages/next/src/routes/auth/init.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
import { init as initOperation } from 'payload/operations'
|
||||
|
||||
export const init = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const initialized = await initOperation({
|
||||
collection: req.collection.config.slug,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json({ initialized })
|
||||
}
|
||||
42
packages/next/src/routes/auth/login.ts
Normal file
42
packages/next/src/routes/auth/login.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import httpStatus from 'http-status'
|
||||
import { loginOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { generatePayloadCookie } from '../../utilities/cookies'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const login = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await loginOperation({
|
||||
collection: req.collection,
|
||||
data: {
|
||||
email: typeof req.data?.email === 'string' ? req.data.email : '',
|
||||
password: typeof req.data?.password === 'string' ? req.data.password : '',
|
||||
},
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
req,
|
||||
})
|
||||
|
||||
const cookie = generatePayloadCookie({
|
||||
token: result.token,
|
||||
payload: req.payload,
|
||||
collectionConfig: req.collection.config,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
exp: result.exp,
|
||||
message: 'Auth Passed',
|
||||
token: result.token,
|
||||
user: result.user,
|
||||
},
|
||||
{
|
||||
headers: new Headers({
|
||||
'Set-Cookie': cookie,
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
40
packages/next/src/routes/auth/logout.ts
Normal file
40
packages/next/src/routes/auth/logout.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import httpStatus from 'http-status'
|
||||
import { logoutOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import { generateExpiredPayloadCookie } from '../../utilities/cookies'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const logout = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const result = logoutOperation({
|
||||
collection: req.collection,
|
||||
req,
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Logout failed.',
|
||||
},
|
||||
{
|
||||
status: httpStatus.BAD_REQUEST,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const expiredCookie = generateExpiredPayloadCookie({
|
||||
collectionConfig: req.collection.config,
|
||||
payload: req.payload,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Logout successful.',
|
||||
},
|
||||
{
|
||||
headers: new Headers({
|
||||
'Set-Cookie': expiredCookie,
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
25
packages/next/src/routes/auth/me.ts
Normal file
25
packages/next/src/routes/auth/me.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import httpStatus from 'http-status'
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
import { meOperation } from 'payload/operations'
|
||||
import { extractJWT } from '../../utilities/jwt'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const me = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const currentToken = extractJWT(req)
|
||||
|
||||
const result = await meOperation({
|
||||
collection: req.collection,
|
||||
req,
|
||||
currentToken,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
...result,
|
||||
message: 'Successfully retrieved me user.',
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
48
packages/next/src/routes/auth/refresh.ts
Normal file
48
packages/next/src/routes/auth/refresh.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { extractJWT } from '../../utilities/jwt'
|
||||
import { refreshOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import httpStatus from 'http-status'
|
||||
import { generatePayloadCookie } from '../../utilities/cookies'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const refresh = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const token = typeof req.data?.token === 'string' ? req.data.token : extractJWT(req)
|
||||
|
||||
if (!token) {
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Token not provided.',
|
||||
},
|
||||
{
|
||||
status: httpStatus.UNAUTHORIZED,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const result = await refreshOperation({
|
||||
token,
|
||||
req,
|
||||
collection: req.collection,
|
||||
})
|
||||
|
||||
const cookie = generatePayloadCookie({
|
||||
token: result.refreshedToken,
|
||||
payload: req.payload,
|
||||
collectionConfig: req.collection.config,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
exp: result.exp,
|
||||
message: 'Token refresh successful',
|
||||
token: result.refreshedToken,
|
||||
user: result.user,
|
||||
},
|
||||
{
|
||||
headers: new Headers({
|
||||
'Set-Cookie': cookie,
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
37
packages/next/src/routes/auth/registerFirstUser.ts
Normal file
37
packages/next/src/routes/auth/registerFirstUser.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import httpStatus from 'http-status'
|
||||
import { registerFirstUserOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import { generatePayloadCookie } from '../../utilities/cookies'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const registerFirstUser = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const result = await registerFirstUserOperation({
|
||||
collection: req.collection,
|
||||
data: {
|
||||
email: typeof req.data?.email === 'string' ? req.data.email : '',
|
||||
password: typeof req.data?.password === 'string' ? req.data.password : '',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
const cookie = generatePayloadCookie({
|
||||
token: result.token,
|
||||
payload: req.payload,
|
||||
collectionConfig: req.collection.config,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
exp: result.exp,
|
||||
message: 'Successfully registered first user.',
|
||||
token: result.token,
|
||||
user: result.user,
|
||||
},
|
||||
{
|
||||
headers: new Headers({
|
||||
'Set-Cookie': cookie,
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
41
packages/next/src/routes/auth/resetPassword.ts
Normal file
41
packages/next/src/routes/auth/resetPassword.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { resetPasswordOperation } from 'payload/operations'
|
||||
import { generatePayloadCookie } from '../../utilities/cookies'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const resetPassword = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await resetPasswordOperation({
|
||||
collection: req.collection,
|
||||
data: {
|
||||
password: typeof req.data?.password === 'string' ? req.data.password : '',
|
||||
token: typeof req.data?.token === 'string' ? req.data.token : '',
|
||||
},
|
||||
depth: depth ? Number(depth) : undefined,
|
||||
req,
|
||||
})
|
||||
|
||||
const cookie = generatePayloadCookie({
|
||||
token: result.token,
|
||||
payload: req.payload,
|
||||
collectionConfig: req.collection.config,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Password reset successfully.',
|
||||
token: result.token,
|
||||
user: result.user,
|
||||
},
|
||||
{
|
||||
headers: new Headers({
|
||||
'Set-Cookie': cookie,
|
||||
}),
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
22
packages/next/src/routes/auth/unlock.ts
Normal file
22
packages/next/src/routes/auth/unlock.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { unlockOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const unlock = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
await unlockOperation({
|
||||
collection: req.collection,
|
||||
data: { email: req.data.email as string },
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Success',
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
27
packages/next/src/routes/auth/verifyEmail.ts
Normal file
27
packages/next/src/routes/auth/verifyEmail.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { verifyEmailOperation } from 'payload/operations'
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
|
||||
export const verifyEmail = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
await verifyEmailOperation({
|
||||
collection: req.collection,
|
||||
req,
|
||||
token: id,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Email verified successfully.',
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
33
packages/next/src/routes/collections/create.ts
Normal file
33
packages/next/src/routes/collections/create.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { createOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const create = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const autosave = searchParams.get('autosave') === 'true'
|
||||
const draft = searchParams.get('draft') === 'true'
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const doc = await createOperation({
|
||||
autosave,
|
||||
collection: req.collection,
|
||||
data: req.data,
|
||||
depth: isNumber(depth) ? depth : undefined,
|
||||
draft,
|
||||
req,
|
||||
})
|
||||
|
||||
// ...formatSuccessResponse(
|
||||
// req.t('general:successfullyCreated', {
|
||||
// label: getTranslation(req.collection.config.labels.singular, req.i18n),
|
||||
// }),
|
||||
// 'message',
|
||||
// )
|
||||
return Response.json(doc, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
62
packages/next/src/routes/collections/delete.ts
Normal file
62
packages/next/src/routes/collections/delete.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, Where } from 'payload/types'
|
||||
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { deleteOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const deleteDoc = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
const where = searchParams.get('where')
|
||||
|
||||
const result = await deleteOperation({
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? depth : undefined,
|
||||
req,
|
||||
where: where ? (JSON.parse(where) as Where) : {},
|
||||
})
|
||||
|
||||
if (result.errors.length === 0) {
|
||||
// const message = req.t('general:deletedCountSuccessfully', {
|
||||
// count: result.docs.length,
|
||||
// label: getTranslation(
|
||||
// req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'],
|
||||
// req.i18n,
|
||||
// ),
|
||||
// })
|
||||
|
||||
// res.status(httpStatus.OK).json({
|
||||
// ...formatSuccessResponse(message, 'message'),
|
||||
// ...result,
|
||||
// })
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
|
||||
// const total = result.docs.length + result.errors.length
|
||||
// const message = req.t('error:unableToDeleteCount', {
|
||||
// count: result.errors.length,
|
||||
// label: getTranslation(
|
||||
// req.collection.config.labels[total > 1 ? 'plural' : 'singular'],
|
||||
// req.i18n,
|
||||
// ),
|
||||
// total,
|
||||
// })
|
||||
|
||||
// res.status(httpStatus.BAD_REQUEST).json({
|
||||
// message,
|
||||
// ...result,
|
||||
// })
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
...result,
|
||||
},
|
||||
{
|
||||
status: httpStatus.BAD_REQUEST,
|
||||
},
|
||||
)
|
||||
}
|
||||
45
packages/next/src/routes/collections/deleteByID.ts
Normal file
45
packages/next/src/routes/collections/deleteByID.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { deleteByIDOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const deleteByID = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
const doc = await deleteByIDOperation({
|
||||
id,
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? depth : undefined,
|
||||
req,
|
||||
})
|
||||
|
||||
if (!doc) {
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Not Found',
|
||||
},
|
||||
{
|
||||
status: httpStatus.NOT_FOUND,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
...doc,
|
||||
// ...formatSuccessResponse(req.t('general:successfullyDeleted'), 'message'),
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
23
packages/next/src/routes/collections/docAccess.ts
Normal file
23
packages/next/src/routes/collections/docAccess.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
|
||||
import { docAccessOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const docAccess = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const result = await docAccessOperation({
|
||||
id,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
31
packages/next/src/routes/collections/find.ts
Normal file
31
packages/next/src/routes/collections/find.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { findOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const find = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
|
||||
const depth = searchParams.get('depth')
|
||||
const limit = searchParams.get('limit')
|
||||
const page = searchParams.get('page')
|
||||
const where = searchParams.get('where')
|
||||
|
||||
const result = await findOperation({
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft: searchParams.get('draft') === 'true',
|
||||
limit: isNumber(limit) ? Number(limit) : undefined,
|
||||
page: isNumber(page) ? Number(page) : undefined,
|
||||
req,
|
||||
sort: searchParams.get('sort'),
|
||||
where: where ? JSON.parse(where) : undefined,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
29
packages/next/src/routes/collections/findByID.ts
Normal file
29
packages/next/src/routes/collections/findByID.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import { findByIDOperation } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const findByID = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await findByIDOperation({
|
||||
id,
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft: searchParams.get('draft') === 'true',
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
28
packages/next/src/routes/collections/findVersionByID.ts
Normal file
28
packages/next/src/routes/collections/findVersionByID.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import { findVersionByIDOperation } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const findVersionByID = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await findVersionByIDOperation({
|
||||
id,
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
35
packages/next/src/routes/collections/findVersions.ts
Normal file
35
packages/next/src/routes/collections/findVersions.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { PayloadRequest, Where } from 'payload/types'
|
||||
import { findVersionsOperation } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const findVersions = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const page = searchParams.get('page')
|
||||
const depth = searchParams.get('depth')
|
||||
const limit = searchParams.get('limit')
|
||||
const where = searchParams.get('where')
|
||||
const sort = searchParams.get('sort')
|
||||
|
||||
const result = await findVersionsOperation({
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
limit: isNumber(limit) ? Number(limit) : undefined,
|
||||
page: isNumber(page) ? Number(page) : undefined,
|
||||
req,
|
||||
sort: sort,
|
||||
where: where ? (JSON.parse(where) as Where) : undefined,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
34
packages/next/src/routes/collections/restoreVersion.ts
Normal file
34
packages/next/src/routes/collections/restoreVersion.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import { PayloadRequest } from 'payload/types'
|
||||
import { restoreVersionOperation } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const restoreVersion = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await restoreVersionOperation({
|
||||
id,
|
||||
collection: req.collection,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
...result,
|
||||
// ...formatSuccessResponse(req.t('version:restoredSuccessfully'), 'message'),
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
63
packages/next/src/routes/collections/update.ts
Normal file
63
packages/next/src/routes/collections/update.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, Where } from 'payload/types'
|
||||
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { updateOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const update = async ({ req }: { req: PayloadRequest }): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
const where = searchParams.get('where')
|
||||
|
||||
const result = await updateOperation({
|
||||
collection: req.collection,
|
||||
data: req.data,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft: searchParams.get('draft') === 'true',
|
||||
req,
|
||||
where: where ? (JSON.parse(where) as Where) : undefined,
|
||||
})
|
||||
|
||||
if (result.errors.length === 0) {
|
||||
// const message = req.t('general:updatedCountSuccessfully', {
|
||||
// count: result.docs.length,
|
||||
// label: getTranslation(
|
||||
// req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'],
|
||||
// req.i18n,
|
||||
// ),
|
||||
// })
|
||||
|
||||
// res.status(httpStatus.OK).json({
|
||||
// ...formatSuccessResponse(message, 'message'),
|
||||
// ...result,
|
||||
// })
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
|
||||
// const total = result.docs.length + result.errors.length
|
||||
// const message = req.t('error:unableToUpdateCount', {
|
||||
// count: result.errors.length,
|
||||
// label: getTranslation(
|
||||
// req.collection.config.labels[total > 1 ? 'plural' : 'singular'],
|
||||
// req.i18n,
|
||||
// ),
|
||||
// total,
|
||||
// })
|
||||
|
||||
// res.status(httpStatus.BAD_REQUEST).json({
|
||||
// ...formatSuccessResponse(message, 'message'),
|
||||
// ...result,
|
||||
// })
|
||||
return Response.json(
|
||||
{
|
||||
...result,
|
||||
},
|
||||
{
|
||||
status: httpStatus.BAD_REQUEST,
|
||||
},
|
||||
)
|
||||
}
|
||||
45
packages/next/src/routes/collections/updateByID.ts
Normal file
45
packages/next/src/routes/collections/updateByID.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
|
||||
import { isNumber } from 'payload/utilities'
|
||||
import { updateByIDOperation } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const updateByID = async ({
|
||||
req,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
const autosave = searchParams.get('autosave') === 'true'
|
||||
const draft = searchParams.get('draft') === 'true'
|
||||
|
||||
const doc = await updateByIDOperation({
|
||||
id,
|
||||
autosave,
|
||||
collection: req.collection,
|
||||
data: req.data,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft,
|
||||
req,
|
||||
})
|
||||
|
||||
let message = req.t('general:updatedSuccessfully')
|
||||
|
||||
if (draft) message = req.t('version:draftSavedSuccessfully')
|
||||
if (autosave) message = req.t('version:autosavedSuccessfully')
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
// ...formatSuccessResponse(message, 'message'),
|
||||
doc,
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
}
|
||||
23
packages/next/src/routes/globals/docAccess.ts
Normal file
23
packages/next/src/routes/globals/docAccess.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
||||
|
||||
import { docAccessOperationGlobal } from 'payload/operations'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const docAccess = async ({
|
||||
req,
|
||||
globalConfig,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
globalConfig: SanitizedGlobalConfig
|
||||
}): Promise<Response> => {
|
||||
const result = await docAccessOperationGlobal({
|
||||
globalConfig,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
30
packages/next/src/routes/globals/findOne.ts
Normal file
30
packages/next/src/routes/globals/findOne.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
||||
|
||||
import { findOneOperation } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const findOne = async ({
|
||||
req,
|
||||
globalConfig,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
globalConfig: SanitizedGlobalConfig
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await findOneOperation({
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft: searchParams.get('draft') === 'true',
|
||||
globalConfig,
|
||||
req,
|
||||
slug: globalConfig.slug,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
31
packages/next/src/routes/globals/findVersionByID.ts
Normal file
31
packages/next/src/routes/globals/findVersionByID.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
||||
|
||||
import { findVersionByIDOperationGlobal } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const findVersionByID = async ({
|
||||
req,
|
||||
globalConfig,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
globalConfig: SanitizedGlobalConfig
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await findVersionByIDOperationGlobal({
|
||||
id,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
globalConfig,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
35
packages/next/src/routes/globals/findVersions.ts
Normal file
35
packages/next/src/routes/globals/findVersions.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, SanitizedGlobalConfig, Where } from 'payload/types'
|
||||
|
||||
import { findVersionsOperationGlobal } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const findVersions = async ({
|
||||
req,
|
||||
globalConfig,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
globalConfig: SanitizedGlobalConfig
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const page = searchParams.get('page')
|
||||
const limit = searchParams.get('limit')
|
||||
const depth = searchParams.get('depth')
|
||||
const where = searchParams.get('where')
|
||||
|
||||
const result = await findVersionsOperationGlobal({
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
globalConfig,
|
||||
limit: isNumber(limit) ? Number(limit) : undefined,
|
||||
page: isNumber(page) ? Number(page) : undefined,
|
||||
req,
|
||||
sort: searchParams.get('sort'),
|
||||
where: where ? (JSON.parse(where) as Where) : undefined,
|
||||
})
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
32
packages/next/src/routes/globals/restoreVersion.ts
Normal file
32
packages/next/src/routes/globals/restoreVersion.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
||||
|
||||
import { restoreVersionOperationGlobal } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const restoreVersion = async ({
|
||||
req,
|
||||
globalConfig,
|
||||
id,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
globalConfig: SanitizedGlobalConfig
|
||||
id: string
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const doc = await restoreVersionOperationGlobal({
|
||||
id,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
globalConfig,
|
||||
req,
|
||||
})
|
||||
|
||||
// ...formatSuccessResponse(req.t('version:restoredSuccessfully'), 'message'),
|
||||
return Response.json(doc, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
39
packages/next/src/routes/globals/update.ts
Normal file
39
packages/next/src/routes/globals/update.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
||||
|
||||
import { updateOperationGlobal } from 'payload/operations'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
// TODO(JARROD): pattern to catch errors and return correct Response
|
||||
export const update = async ({
|
||||
req,
|
||||
globalConfig,
|
||||
}: {
|
||||
req: PayloadRequest
|
||||
globalConfig: SanitizedGlobalConfig
|
||||
}): Promise<Response> => {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const depth = searchParams.get('depth')
|
||||
const draft = searchParams.get('draft') === 'true'
|
||||
const autosave = searchParams.get('autosave') === 'true'
|
||||
|
||||
const result = await updateOperationGlobal({
|
||||
autosave,
|
||||
data: req.data,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft,
|
||||
globalConfig,
|
||||
req,
|
||||
slug: globalConfig.slug,
|
||||
})
|
||||
|
||||
let message = req.t('general:updatedSuccessfully')
|
||||
|
||||
if (draft) message = req.t('version:draftSavedSuccessfully')
|
||||
if (autosave) message = req.t('version:autosavedSuccessfully')
|
||||
|
||||
return Response.json(result, {
|
||||
status: httpStatus.OK,
|
||||
})
|
||||
}
|
||||
258
packages/next/src/routes/index.ts
Normal file
258
packages/next/src/routes/index.ts
Normal file
@@ -0,0 +1,258 @@
|
||||
import config from 'payload-config'
|
||||
import { createPayloadRequest } from '../utilities/createPayloadRequest'
|
||||
|
||||
import { me } from './auth/me'
|
||||
import { init } from './auth/init'
|
||||
import { login } from './auth/login'
|
||||
import { unlock } from './auth/unlock'
|
||||
import { access } from './auth/access'
|
||||
import { logout } from './auth/logout'
|
||||
import { refresh } from './auth/refresh'
|
||||
|
||||
import { find } from './collections/find'
|
||||
import { create } from './collections/create'
|
||||
import { update } from './collections/update'
|
||||
import { deleteDoc } from './collections/delete'
|
||||
import { verifyEmail } from './auth/verifyEmail'
|
||||
import { findByID } from './collections/findByID'
|
||||
import { docAccess } from './collections/docAccess'
|
||||
import { resetPassword } from './auth/resetPassword'
|
||||
import { updateByID } from './collections/updateByID'
|
||||
import { deleteByID } from './collections/deleteByID'
|
||||
import { forgotPassword } from './auth/forgotPassword'
|
||||
import { findVersions } from './collections/findVersions'
|
||||
import { registerFirstUser } from './auth/registerFirstUser'
|
||||
import { restoreVersion } from './collections/restoreVersion'
|
||||
import { findVersionByID } from './collections/findVersionByID'
|
||||
|
||||
import { findOne } from './globals/findOne'
|
||||
import { update as updateGlobal } from './globals/update'
|
||||
import { docAccess as docAccessGlobal } from './globals/docAccess'
|
||||
import { findVersions as findVersionsGlobal } from './globals/findVersions'
|
||||
import { restoreVersion as restoreVersionGlobal } from './globals/restoreVersion'
|
||||
import { findVersionByID as findVersionByIdGlobal } from './globals/findVersionByID'
|
||||
|
||||
const endpoints = {
|
||||
root: {
|
||||
GET: {
|
||||
access,
|
||||
},
|
||||
},
|
||||
collection: {
|
||||
GET: {
|
||||
init,
|
||||
me,
|
||||
versions: findVersions,
|
||||
find,
|
||||
findByID,
|
||||
'doc-access-by-id': docAccess,
|
||||
'doc-versions-by-id': findVersionByID,
|
||||
},
|
||||
POST: {
|
||||
create,
|
||||
login,
|
||||
logout,
|
||||
unlock,
|
||||
access: docAccess,
|
||||
'first-register': registerFirstUser,
|
||||
'forgot-password': forgotPassword,
|
||||
'reset-password': resetPassword,
|
||||
'refresh-token': refresh,
|
||||
'doc-access-by-id': docAccess,
|
||||
'doc-versions-by-id': restoreVersion,
|
||||
'doc-verify-by-id': verifyEmail,
|
||||
},
|
||||
PATCH: {
|
||||
update,
|
||||
updateByID,
|
||||
},
|
||||
DELETE: {
|
||||
delete: deleteDoc,
|
||||
deleteByID,
|
||||
},
|
||||
},
|
||||
global: {
|
||||
GET: {
|
||||
findOne,
|
||||
'doc-access': docAccessGlobal,
|
||||
'doc-versions': findVersionsGlobal,
|
||||
'doc-versions-by-id': findVersionByIdGlobal,
|
||||
},
|
||||
POST: {
|
||||
update: updateGlobal,
|
||||
'doc-access': docAccessGlobal,
|
||||
'doc-versions-by-id': restoreVersionGlobal,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const GET = async (
|
||||
request: Request,
|
||||
{ params: { slug } }: { params: { slug: string[] } },
|
||||
) => {
|
||||
const [slug1, slug2, slug3, slug4] = slug
|
||||
|
||||
const req = await createPayloadRequest({
|
||||
request,
|
||||
config,
|
||||
params: {
|
||||
collection: slug1,
|
||||
},
|
||||
})
|
||||
|
||||
if (slug.length === 1 && slug1 === 'access') {
|
||||
return endpoints.root.GET.access({ req })
|
||||
}
|
||||
|
||||
if (req?.collection) {
|
||||
switch (slug.length) {
|
||||
case 1:
|
||||
// /:collection
|
||||
return endpoints.collection.GET.find({ req })
|
||||
case 2:
|
||||
if (slug2 in endpoints.collection.GET) {
|
||||
// /:collection/init
|
||||
// /:collection/me
|
||||
// /:collection/versions
|
||||
return endpoints.collection.GET?.[slug2]({ req })
|
||||
} else if (req.collection.config.endpoints && req.collection.config.endpoints.length > 0) {
|
||||
// /:collection/:id
|
||||
}
|
||||
return endpoints.collection.GET.findByID({ req, id: slug2 })
|
||||
case 3:
|
||||
// /:collection/access/:id
|
||||
// /:collection/versions/:id
|
||||
const key = `doc-${slug2}-by-id`
|
||||
if (key in endpoints.collection.GET) {
|
||||
return endpoints.collection.GET[key]({ req, id: slug3 })
|
||||
}
|
||||
break
|
||||
default:
|
||||
return new Response('Route Not Found', { status: 404 })
|
||||
}
|
||||
} else if (slug1 === 'globals') {
|
||||
const globalConfig = req.payload.config.globals.find((global) => global.slug === slug2)
|
||||
|
||||
switch (slug.length) {
|
||||
case 2:
|
||||
// /globals/:slug
|
||||
return endpoints.global.GET.findOne({ req, globalConfig })
|
||||
case 3:
|
||||
// /globals/:slug/access
|
||||
// /globals/:slug/versions
|
||||
return endpoints.global.GET?.[`doc-${slug3}`]({ req, globalConfig })
|
||||
case 4:
|
||||
// /globals/:slug/versions/:id
|
||||
return endpoints.global.GET?.[`doc-${slug3}-by-id`]({ req, id: slug4, globalConfig })
|
||||
default:
|
||||
return new Response('Route Not Found', { status: 404 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
request: Request,
|
||||
{ params: { slug } }: { params: { slug: string[] } },
|
||||
) => {
|
||||
const [slug1, slug2, slug3, slug4] = slug
|
||||
|
||||
const req = await createPayloadRequest({ request, config, params: { collection: slug1 } })
|
||||
|
||||
if (req?.collection) {
|
||||
switch (slug.length) {
|
||||
case 1:
|
||||
// /:collection
|
||||
return endpoints.collection.POST.create({ req })
|
||||
case 2:
|
||||
if (slug2 in endpoints.collection.POST) {
|
||||
// /:collection/login
|
||||
// /:collection/logout
|
||||
// /:collection/unlock
|
||||
// /:collection/access
|
||||
// /:collection/first-register
|
||||
// /:collection/forgot-password
|
||||
// /:collection/reset-password
|
||||
// /:collection/refresh-token
|
||||
return endpoints.collection.POST[slug2]({ req })
|
||||
}
|
||||
case 3:
|
||||
// /:collection/access/:id
|
||||
// /:collection/versions/:id
|
||||
// /:collection/verify/:token ("doc-verify-by-id" uses id as token internally)
|
||||
return endpoints.collection.POST?.[`doc-${slug2}-by-id`]({ req, id: slug3 })
|
||||
default:
|
||||
return new Response('Route Not Found', { status: 404 })
|
||||
}
|
||||
} else if (slug1 === 'globals') {
|
||||
const globalConfig = req.payload.config.globals.find((global) => global.slug === slug2)
|
||||
switch (slug.length) {
|
||||
case 2:
|
||||
// /globals/:slug
|
||||
return endpoints.global.POST.update({ req, globalConfig })
|
||||
case 3:
|
||||
// /globals/:slug/access
|
||||
return endpoints.global.POST?.[`doc-${slug3}`]({ req, globalConfig })
|
||||
case 4:
|
||||
// /globals/:slug/versions/:id
|
||||
return endpoints.global.POST?.[`doc-${slug3}-by-id`]({ req, id: slug4, globalConfig })
|
||||
default:
|
||||
return new Response('Route Not Found', { status: 404 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
request: Request,
|
||||
{ params: { slug } }: { params: { slug: string[] } },
|
||||
) => {
|
||||
const [slug1, slug2] = slug
|
||||
|
||||
const req = await createPayloadRequest({
|
||||
request,
|
||||
config,
|
||||
params: {
|
||||
collection: slug1,
|
||||
},
|
||||
})
|
||||
|
||||
if (req?.collection) {
|
||||
switch (slug.length) {
|
||||
case 1:
|
||||
// /:collection
|
||||
return endpoints.collection.DELETE.delete({ req })
|
||||
case 2:
|
||||
// /:collection/:id
|
||||
return endpoints.collection.DELETE.deleteByID({ req, id: slug2 })
|
||||
default:
|
||||
return new Response('Route Not Found', { status: 404 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const PATCH = async (
|
||||
request: Request,
|
||||
{ params: { slug } }: { params: { slug: string[] } },
|
||||
) => {
|
||||
const [slug1, slug2] = slug
|
||||
|
||||
const req = await createPayloadRequest({
|
||||
request,
|
||||
config,
|
||||
params: {
|
||||
collection: slug1,
|
||||
},
|
||||
})
|
||||
|
||||
if (req?.collection) {
|
||||
switch (slug.length) {
|
||||
case 1:
|
||||
// /:collection
|
||||
return endpoints.collection.PATCH.update({ req })
|
||||
case 2:
|
||||
// /:collection/:id
|
||||
return endpoints.collection.PATCH.updateByID({ req, id: slug2 })
|
||||
default:
|
||||
return new Response('Route Not Found', { status: 404 })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
import { init as initOperation } from 'payload/operations'
|
||||
import { createPayloadRequest } from '../createPayloadRequest'
|
||||
|
||||
export const init = ({ config }: { config: Promise<SanitizedConfig> }) =>
|
||||
async function (request: Request, { params }: { params: { collection: string } }) {
|
||||
const req = await createPayloadRequest({ request, config, params })
|
||||
|
||||
const initialized = await initOperation({
|
||||
collection: params.collection,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json({ initialized })
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { login as loginOperation } from 'payload/operations'
|
||||
import { createPayloadRequest } from '../createPayloadRequest'
|
||||
import { SanitizedConfig } from 'payload/types'
|
||||
import { isNumber } from 'payload/utilities'
|
||||
|
||||
export const login = ({ config }: { config: Promise<SanitizedConfig> }) =>
|
||||
async function (request: Request, { params }: { params: { collection: string } }) {
|
||||
const req = await createPayloadRequest({ request, config })
|
||||
const collection = req.payload.collections[params.collection]
|
||||
|
||||
const { searchParams } = new URL(request.url)
|
||||
const depth = searchParams.get('depth')
|
||||
let responseOptions = {
|
||||
headers: new Headers(),
|
||||
}
|
||||
const result = await loginOperation({
|
||||
collection,
|
||||
data: {
|
||||
email: typeof req.data?.email === 'string' ? req.data.email : '',
|
||||
password: typeof req.data?.password === 'string' ? req.data.password : '',
|
||||
},
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
req,
|
||||
responseOptions,
|
||||
})
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
exp: result.exp,
|
||||
message: 'Auth Passed',
|
||||
token: result.token,
|
||||
user: result.user,
|
||||
},
|
||||
responseOptions,
|
||||
)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
import { me as meOperation } from 'payload/operations'
|
||||
import { createPayloadRequest } from '../createPayloadRequest'
|
||||
|
||||
export const me = ({ config }: { config: Promise<SanitizedConfig> }) =>
|
||||
async function (request: Request, { params }: { params: { collection: string } }) {
|
||||
const req = await createPayloadRequest({ request, config })
|
||||
const collection = req.payload.collections[params.collection]
|
||||
const meRes = await meOperation({
|
||||
collection,
|
||||
req,
|
||||
})
|
||||
|
||||
return Response.json(meRes)
|
||||
}
|
||||
146
packages/next/src/utilities/cookies.ts
Normal file
146
packages/next/src/utilities/cookies.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import type { PayloadT, SanitizedCollectionConfig } from 'payload/types'
|
||||
|
||||
type CookieOptions = {
|
||||
domain?: string
|
||||
expires?: Date
|
||||
httpOnly?: boolean
|
||||
maxAge?: number
|
||||
name: string
|
||||
path?: string
|
||||
sameSite?: 'Lax' | 'None' | 'Strict'
|
||||
secure?: boolean
|
||||
value?: string
|
||||
}
|
||||
|
||||
export const generateCookies = (cookies: CookieOptions[]): string => {
|
||||
return cookies.map((options) => generateCookie(options)).join('; ')
|
||||
}
|
||||
|
||||
export const generateCookie = (args: CookieOptions): string => {
|
||||
const { name, domain, expires, httpOnly, maxAge, path, sameSite, secure: secureArg, value } = args
|
||||
|
||||
let cookieString = `${name}=${value || ''}`
|
||||
|
||||
const secure = secureArg || sameSite === 'None'
|
||||
|
||||
if (expires) {
|
||||
cookieString += `; Expires=${expires.toUTCString()}`
|
||||
}
|
||||
|
||||
if (maxAge) {
|
||||
cookieString += `; Max-Age=${maxAge}`
|
||||
}
|
||||
|
||||
if (domain) {
|
||||
cookieString += `; Domain=${domain}`
|
||||
}
|
||||
|
||||
if (path) {
|
||||
cookieString += `; Path=${path}`
|
||||
}
|
||||
|
||||
if (secure) {
|
||||
cookieString += '; Secure'
|
||||
}
|
||||
|
||||
if (httpOnly) {
|
||||
cookieString += '; HttpOnly'
|
||||
}
|
||||
|
||||
if (sameSite) {
|
||||
cookieString += `; SameSite=${sameSite}`
|
||||
}
|
||||
|
||||
return cookieString
|
||||
}
|
||||
|
||||
type GetCookieExpirationArgs = {
|
||||
/*
|
||||
The number of seconds until the cookie expires
|
||||
@default 7200 seconds (2 hours)
|
||||
*/
|
||||
seconds: number
|
||||
}
|
||||
const getCookieExpiration = ({ seconds = 7200 }: GetCookieExpirationArgs) => {
|
||||
const currentTime = new Date()
|
||||
currentTime.setSeconds(currentTime.getSeconds() + seconds)
|
||||
return currentTime
|
||||
}
|
||||
|
||||
type GeneratePayloadCookieArgs = {
|
||||
/* The auth collection config */
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
/* An instance of payload */
|
||||
payload: PayloadT
|
||||
/* The token to be stored in the cookie */
|
||||
token: string
|
||||
}
|
||||
export const generatePayloadCookie = ({
|
||||
collectionConfig,
|
||||
payload,
|
||||
token,
|
||||
}: GeneratePayloadCookieArgs): string => {
|
||||
const sameSite =
|
||||
typeof collectionConfig.auth.cookies.sameSite === 'string'
|
||||
? collectionConfig.auth.cookies.sameSite
|
||||
: collectionConfig.auth.cookies.sameSite
|
||||
? 'Strict'
|
||||
: undefined
|
||||
|
||||
return generateCookie({
|
||||
name: `${payload.config.cookiePrefix}-token`,
|
||||
domain: collectionConfig.auth.cookies.domain ?? undefined,
|
||||
expires: getCookieExpiration({ seconds: collectionConfig.auth.tokenExpiration }),
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
value: token,
|
||||
})
|
||||
}
|
||||
|
||||
export const generateExpiredPayloadCookie = ({
|
||||
collectionConfig,
|
||||
payload,
|
||||
}: Omit<GeneratePayloadCookieArgs, 'token'>): string => {
|
||||
const sameSite =
|
||||
typeof collectionConfig.auth.cookies.sameSite === 'string'
|
||||
? collectionConfig.auth.cookies.sameSite
|
||||
: collectionConfig.auth.cookies.sameSite
|
||||
? 'Strict'
|
||||
: undefined
|
||||
|
||||
const expires = new Date(Date.now() - 1000)
|
||||
|
||||
return generateCookie({
|
||||
name: `${payload.config.cookiePrefix}-token`,
|
||||
domain: collectionConfig.auth.cookies.domain ?? undefined,
|
||||
expires,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
})
|
||||
}
|
||||
|
||||
export const parseCookies = (headers: Request['headers']): Map<string, string> => {
|
||||
const cookieMap = new Map<string, string>()
|
||||
const cookie = headers.get('Cookie')
|
||||
|
||||
if (cookie) {
|
||||
cookie.split(';').forEach((cookie) => {
|
||||
const parts = cookie.split('=')
|
||||
const key = parts.shift().trim()
|
||||
const encodedValue = parts.join('=')
|
||||
|
||||
try {
|
||||
const decodedValue = decodeURI(encodedValue)
|
||||
cookieMap.set(key, decodedValue)
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return cookieMap
|
||||
}
|
||||
34
packages/next/src/utilities/jwt.ts
Normal file
34
packages/next/src/utilities/jwt.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { AuthStrategyFunctionArgs } from 'payload/auth'
|
||||
import { parseCookies } from './cookies'
|
||||
|
||||
export const extractJWT = (
|
||||
args: Pick<AuthStrategyFunctionArgs, 'headers' | 'payload'>,
|
||||
): null | string => {
|
||||
const { headers, payload } = args
|
||||
|
||||
const jwtFromHeader = headers.get('Authorization')
|
||||
const origin = headers.get('Origin')
|
||||
|
||||
if (jwtFromHeader?.startsWith('JWT ')) {
|
||||
return jwtFromHeader.replace('JWT ', '')
|
||||
}
|
||||
// allow RFC6750 OAuth 2.0 compliant Bearer tokens
|
||||
// in addition to the payload default JWT format
|
||||
if (jwtFromHeader?.startsWith('Bearer ')) {
|
||||
return jwtFromHeader.replace('Bearer ', '')
|
||||
}
|
||||
|
||||
const cookies = parseCookies(headers)
|
||||
const tokenCookieName = `${payload.config.cookiePrefix}-token`
|
||||
const cookieToken = cookies?.get(tokenCookieName)
|
||||
|
||||
if (!cookieToken) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (!origin || payload.config.csrf.length === 0 || payload.config.csrf.indexOf(origin) > -1) {
|
||||
return cookieToken
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import type { PayloadRequest } from '../exports/types'
|
||||
import { Forbidden } from '../errors'
|
||||
|
||||
type OperationArgs = {
|
||||
data?: Record<string, unknown>
|
||||
data?: any
|
||||
disableErrors?: boolean
|
||||
id?: number | string
|
||||
req: PayloadRequest
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AuthStrategyFunctionArgs } from '.'
|
||||
|
||||
import { parseCookies } from '../utilities/cookies'
|
||||
import { parseCookies } from '../utilities/parseCookies'
|
||||
|
||||
export const extractJWT = (
|
||||
args: Pick<AuthStrategyFunctionArgs, 'headers' | 'payload'>,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { User } from '..'
|
||||
import type { CollectionConfig } from '../../collections/config/types'
|
||||
import type { Field, TabAsField } from '../../fields/config/types'
|
||||
import type { User } from '.'
|
||||
import type { CollectionConfig } from '../collections/config/types'
|
||||
import type { Field, TabAsField } from '../fields/config/types'
|
||||
|
||||
import { fieldAffectsData, tabHasName } from '../../fields/config/types'
|
||||
import { fieldAffectsData, tabHasName } from '../fields/config/types'
|
||||
|
||||
type TraverseFieldsArgs = {
|
||||
data: Record<string, unknown>
|
||||
@@ -2,7 +2,7 @@ import type { PayloadT } from '../../..'
|
||||
|
||||
import formatName from '../../../graphql/utilities/formatName'
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import access from '../../operations/access'
|
||||
import { accessOperation } from '../../operations/access'
|
||||
|
||||
const formatConfigNames = (results, configs) => {
|
||||
const formattedResults = { ...results }
|
||||
@@ -22,7 +22,7 @@ function accessResolver(payload: PayloadT) {
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const accessResults = await access(options)
|
||||
const accessResults = await accessOperation(options)
|
||||
|
||||
return {
|
||||
...accessResults,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import init from '../../operations/init'
|
||||
import { init } from '../../operations/init'
|
||||
|
||||
function initResolver(collection: string) {
|
||||
async function resolver(_, args, context) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import login from '../../operations/login'
|
||||
import { loginOperation } from '../../operations/login'
|
||||
|
||||
function loginResolver(collection: Collection) {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -16,7 +16,7 @@ function loginResolver(collection: Collection) {
|
||||
res: context.res,
|
||||
}
|
||||
|
||||
const result = login(options)
|
||||
const result = loginOperation(options)
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import logout from '../../operations/logout'
|
||||
import { logoutOperation } from '../../operations/logout'
|
||||
|
||||
function logoutResolver(collection: Collection): any {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -11,7 +11,7 @@ function logoutResolver(collection: Collection): any {
|
||||
res: context.res,
|
||||
}
|
||||
|
||||
const result = await logout(options)
|
||||
const result = await logoutOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import me from '../../operations/me'
|
||||
import { meOperation } from '../../operations/me'
|
||||
|
||||
function meResolver(collection: Collection): any {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -10,7 +10,7 @@ function meResolver(collection: Collection): any {
|
||||
depth: 0,
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
return me(options)
|
||||
return meOperation(options)
|
||||
}
|
||||
|
||||
return resolver
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import { extractJWT } from '../../getExtractJWT'
|
||||
import refresh from '../../operations/refresh'
|
||||
import { refreshOperation } from '../../operations/refresh'
|
||||
|
||||
function refreshResolver(collection: Collection) {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -22,7 +22,7 @@ function refreshResolver(collection: Collection) {
|
||||
token,
|
||||
}
|
||||
|
||||
const result = await refresh(options)
|
||||
const result = await refreshOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import resetPassword from '../../operations/resetPassword'
|
||||
import { resetPasswordOperation } from '../../operations/resetPassword'
|
||||
|
||||
function resetPasswordResolver(collection: Collection) {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -18,7 +18,7 @@ function resetPasswordResolver(collection: Collection) {
|
||||
res: context.res,
|
||||
}
|
||||
|
||||
const result = await resetPassword(options)
|
||||
const result = await resetPasswordOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import unlock from '../../operations/unlock'
|
||||
import { unlockOperation } from '../../operations/unlock'
|
||||
|
||||
function unlockResolver(collection: Collection) {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -11,7 +11,7 @@ function unlockResolver(collection: Collection) {
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await unlock(options)
|
||||
const result = await unlockOperation(options)
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Collection } from '../../../collections/config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import verifyEmail from '../../operations/verifyEmail'
|
||||
import { verifyEmailOperation } from '../../operations/verifyEmail'
|
||||
|
||||
function verifyEmailResolver(collection: Collection) {
|
||||
async function resolver(_, args, context) {
|
||||
@@ -17,7 +17,7 @@ function verifyEmailResolver(collection: Collection) {
|
||||
token: args.token,
|
||||
}
|
||||
|
||||
const success = await verifyEmail(options)
|
||||
const success = await verifyEmailOperation(options)
|
||||
return success
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
import type { Permissions } from '../types'
|
||||
|
||||
import access from '../operations/access'
|
||||
|
||||
export default async function accessRequestHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<Response<Permissions> | void> {
|
||||
try {
|
||||
const accessResults = await access({
|
||||
req,
|
||||
})
|
||||
|
||||
return res.status(httpStatus.OK).json(accessResults)
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import forgotPassword from '../operations/forgotPassword'
|
||||
|
||||
export default async function forgotPasswordHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
await forgotPassword({
|
||||
collection: req.collection,
|
||||
// TODO(JARROD): remove reliance on express body parsing
|
||||
data: { email: req.body.email },
|
||||
disableEmail: req.body.disableEmail,
|
||||
expiration: req.body.expiration,
|
||||
req,
|
||||
})
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
message: 'Success',
|
||||
})
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import type { SanitizedConfig } from '../../exports/config'
|
||||
|
||||
import { getPayload } from '../..'
|
||||
import init from '../operations/init'
|
||||
|
||||
export const initHandler = ({ config }: { config: Promise<SanitizedConfig> }) =>
|
||||
async function (request: Request, { params }: { params: { collection: string } }) {
|
||||
const payload = await getPayload({ config })
|
||||
request.payload = payload
|
||||
|
||||
const initialized = await init({
|
||||
collection: params.collection,
|
||||
req: request,
|
||||
})
|
||||
|
||||
return Response.json({ initialized })
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
import { URL } from 'url'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
import type { Result } from '../operations/login'
|
||||
|
||||
import { isNumber } from '../../utilities/isNumber'
|
||||
import login from '../operations/login'
|
||||
|
||||
export default async function loginHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<Response<Result & { message: string }> | void> {
|
||||
try {
|
||||
const searchParams = new URL(req.url).searchParams
|
||||
const depth = searchParams.get('depth')
|
||||
|
||||
const result = await login({
|
||||
collection: req.collection,
|
||||
// TODO(JARROD): remove reliance on express body parsing
|
||||
data: req.body,
|
||||
depth: isNumber(depth) ? depth : undefined,
|
||||
req,
|
||||
res,
|
||||
})
|
||||
|
||||
res.status(httpStatus.OK).json({
|
||||
exp: result.exp,
|
||||
message: 'Auth Passed',
|
||||
token: result.token,
|
||||
user: result.user,
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import logout from '../operations/logout'
|
||||
|
||||
export default async function logoutHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<Response<{ message: string }> | void> {
|
||||
try {
|
||||
const message = await logout({
|
||||
collection: req.collection,
|
||||
req,
|
||||
res,
|
||||
})
|
||||
|
||||
return res.status(httpStatus.OK).json({ message })
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import me from '../operations/me'
|
||||
|
||||
export default async function meHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const response = await me({
|
||||
collection: req.collection,
|
||||
req,
|
||||
})
|
||||
return res.status(200).json(response)
|
||||
} catch (err) {
|
||||
return next(err)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import { extractJWT } from '../getExtractJWT'
|
||||
import refresh from '../operations/refresh'
|
||||
|
||||
export default async function refreshHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
let token
|
||||
|
||||
token = extractJWT(req)
|
||||
|
||||
if (req.body) {
|
||||
token = req.body.data
|
||||
}
|
||||
|
||||
const result = await refresh({
|
||||
collection: req.collection,
|
||||
req,
|
||||
res,
|
||||
token,
|
||||
})
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Token refresh successful',
|
||||
...result,
|
||||
})
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import registerFirstUser from '../operations/registerFirstUser'
|
||||
|
||||
export default async function registerFirstUserHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const firstUser = await registerFirstUser({
|
||||
collection: req.collection,
|
||||
// TODO(JARROD): remove reliance on express body parsing
|
||||
data: req.body,
|
||||
req,
|
||||
res,
|
||||
})
|
||||
|
||||
return res.status(201).json(firstUser)
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import resetPassword from '../operations/resetPassword'
|
||||
|
||||
async function resetPasswordHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const result = await resetPassword({
|
||||
collection: req.collection,
|
||||
// TODO(JARROD): remove reliance on express body parsing
|
||||
data: req.body,
|
||||
req,
|
||||
res,
|
||||
})
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
message: 'Password reset successfully.',
|
||||
token: result.token,
|
||||
user: result.user,
|
||||
})
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
|
||||
export default resetPasswordHandler
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import unlock from '../operations/unlock'
|
||||
|
||||
export default async function unlockHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
await unlock({
|
||||
collection: req.collection,
|
||||
// TODO(JARROD): remove reliance on express body parsing
|
||||
data: { email: req.body.email },
|
||||
req,
|
||||
})
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
message: 'Success',
|
||||
})
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// TODO(JARROD): remove reliance on express
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
import verifyEmail from '../operations/verifyEmail'
|
||||
|
||||
async function verifyEmailHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
await verifyEmail({
|
||||
collection: req.collection,
|
||||
req,
|
||||
token: req.params.token,
|
||||
})
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
message: 'Email verified successfully.',
|
||||
})
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
|
||||
export default verifyEmailHandler
|
||||
@@ -1,13 +0,0 @@
|
||||
import passport from 'passport'
|
||||
import AnonymousStrategy from 'passport-anonymous'
|
||||
|
||||
import type { Payload } from '../payload'
|
||||
|
||||
import jwtStrategy from './strategies/jwt'
|
||||
|
||||
function initAuth(ctx: Payload): void {
|
||||
passport.use(new AnonymousStrategy.Strategy())
|
||||
passport.use('jwt', jwtStrategy(ctx))
|
||||
}
|
||||
|
||||
export default initAuth
|
||||
@@ -11,7 +11,7 @@ type Arguments = {
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
async function accessOperation(args: Arguments): Promise<Permissions> {
|
||||
export const accessOperation = async (args: Arguments): Promise<Permissions> => {
|
||||
const {
|
||||
req,
|
||||
req: { payload, user },
|
||||
@@ -40,5 +40,3 @@ async function accessOperation(args: Arguments): Promise<Permissions> {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export default accessOperation
|
||||
|
||||
@@ -23,7 +23,7 @@ export type Arguments = {
|
||||
|
||||
export type Result = string
|
||||
|
||||
async function forgotPassword(incomingArgs: Arguments): Promise<null | string> {
|
||||
export const forgotPasswordOperation = async (incomingArgs: Arguments): Promise<null | string> => {
|
||||
if (!Object.prototype.hasOwnProperty.call(incomingArgs.data, 'email')) {
|
||||
throw new APIError('Missing email.', 400)
|
||||
}
|
||||
@@ -66,8 +66,7 @@ async function forgotPassword(incomingArgs: Arguments): Promise<null | string> {
|
||||
// Forget password
|
||||
// /////////////////////////////////////
|
||||
|
||||
let token: Buffer | string = crypto.randomBytes(20)
|
||||
token = token.toString('hex')
|
||||
let token: string = crypto.randomBytes(20).toString('hex')
|
||||
|
||||
type UserDoc = {
|
||||
id: number | string
|
||||
@@ -165,5 +164,3 @@ async function forgotPassword(incomingArgs: Arguments): Promise<null | string> {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export default forgotPassword
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { PayloadRequest } from '../../types'
|
||||
|
||||
async function init(args: { collection: string; req: PayloadRequest }): Promise<boolean> {
|
||||
export const initOperation = async (args: {
|
||||
collection: string
|
||||
req: PayloadRequest
|
||||
}): Promise<boolean> => {
|
||||
const { collection: slug, req } = args
|
||||
|
||||
const doc = await req.payload.db.findOne({
|
||||
@@ -10,5 +13,3 @@ async function init(args: { collection: string; req: PayloadRequest }): Promise<
|
||||
|
||||
return !!doc
|
||||
}
|
||||
|
||||
export default init
|
||||
|
||||
@@ -6,7 +6,7 @@ import { getDataLoader } from '../../../collections/dataloader'
|
||||
import { APIError } from '../../../errors'
|
||||
import { i18nInit } from '../../../translations/init'
|
||||
import { setRequestContext } from '../../../utilities/setRequestContext'
|
||||
import forgotPassword from '../forgotPassword'
|
||||
import { forgotPasswordOperation } from '../forgotPassword'
|
||||
|
||||
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||
collection: T
|
||||
@@ -50,7 +50,7 @@ async function localForgotPassword<T extends keyof GeneratedTypes['collections']
|
||||
if (!req.t) req.t = req.i18n.t
|
||||
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req)
|
||||
|
||||
return forgotPassword({
|
||||
return forgotPasswordOperation({
|
||||
collection,
|
||||
data,
|
||||
disableEmail,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { Response } from 'express'
|
||||
|
||||
import type { PayloadT, RequestContext } from '../../..'
|
||||
import type { GeneratedTypes } from '../../../index'
|
||||
import type { PayloadRequest } from '../../../types'
|
||||
@@ -9,7 +7,7 @@ import { getDataLoader } from '../../../collections/dataloader'
|
||||
import { APIError } from '../../../errors'
|
||||
import { i18nInit } from '../../../translations/init'
|
||||
import { setRequestContext } from '../../../utilities/setRequestContext'
|
||||
import login from '../login'
|
||||
import { loginOperation } from '../login'
|
||||
|
||||
export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
|
||||
collection: TSlug
|
||||
@@ -23,7 +21,6 @@ export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
|
||||
locale?: string
|
||||
overrideAccess?: boolean
|
||||
req?: PayloadRequest
|
||||
res?: Response
|
||||
showHiddenFields?: boolean
|
||||
}
|
||||
|
||||
@@ -40,7 +37,6 @@ async function localLogin<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
locale,
|
||||
overrideAccess = true,
|
||||
req = {} as PayloadRequest,
|
||||
res,
|
||||
showHiddenFields,
|
||||
} = options
|
||||
setRequestContext(req, context)
|
||||
@@ -68,14 +64,13 @@ async function localLogin<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
depth,
|
||||
overrideAccess,
|
||||
req,
|
||||
res,
|
||||
showHiddenFields,
|
||||
}
|
||||
|
||||
if (locale) args.req.locale = locale
|
||||
if (fallbackLocale) args.req.fallbackLocale = fallbackLocale
|
||||
|
||||
return login<TSlug>(args)
|
||||
return loginOperation<TSlug>(args)
|
||||
}
|
||||
|
||||
export default localLogin
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getDataLoader } from '../../../collections/dataloader'
|
||||
import { APIError } from '../../../errors'
|
||||
import { i18nInit } from '../../../translations/init'
|
||||
import { setRequestContext } from '../../../utilities/setRequestContext'
|
||||
import resetPassword from '../resetPassword'
|
||||
import { resetPasswordOperation } from '../resetPassword'
|
||||
|
||||
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||
collection: T
|
||||
@@ -51,7 +51,7 @@ async function localResetPassword<T extends keyof GeneratedTypes['collections']>
|
||||
if (!req.t) req.t = req.i18n.t
|
||||
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req)
|
||||
|
||||
return resetPassword({
|
||||
return resetPasswordOperation({
|
||||
collection,
|
||||
data,
|
||||
overrideAccess,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { getDataLoader } from '../../../collections/dataloader'
|
||||
import { APIError } from '../../../errors'
|
||||
import { i18nInit } from '../../../translations/init'
|
||||
import { setRequestContext } from '../../../utilities/setRequestContext'
|
||||
import unlock from '../unlock'
|
||||
import { unlockOperation } from '../unlock'
|
||||
|
||||
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||
collection: T
|
||||
@@ -46,7 +46,7 @@ async function localUnlock<T extends keyof GeneratedTypes['collections']>(
|
||||
if (!req.t) req.t = req.i18n.t
|
||||
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req)
|
||||
|
||||
return unlock({
|
||||
return unlockOperation({
|
||||
collection,
|
||||
data,
|
||||
overrideAccess,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { PayloadRequest } from '../../../types'
|
||||
import { APIError } from '../../../errors'
|
||||
import { i18nInit } from '../../../translations/init'
|
||||
import { setRequestContext } from '../../../utilities/setRequestContext'
|
||||
import verifyEmail from '../verifyEmail'
|
||||
import { verifyEmailOperation } from '../verifyEmail'
|
||||
|
||||
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||
collection: T
|
||||
@@ -33,7 +33,7 @@ async function localVerifyEmail<T extends keyof GeneratedTypes['collections']>(
|
||||
req.payloadAPI = req.payloadAPI || 'local'
|
||||
req.i18n = i18nInit(payload.config.i18n)
|
||||
|
||||
return verifyEmail({
|
||||
return verifyEmailOperation({
|
||||
collection,
|
||||
req,
|
||||
token,
|
||||
|
||||
@@ -9,16 +9,14 @@ import { buildAfterOperation } from '../../collections/operations/utils'
|
||||
import { AuthenticationError, LockedAuth } from '../../errors'
|
||||
import { afterRead } from '../../fields/hooks/afterRead'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction'
|
||||
import { generateCookie } from '../../utilities/cookies'
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration'
|
||||
import { initTransaction } from '../../utilities/initTransaction'
|
||||
import { killTransaction } from '../../utilities/killTransaction'
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields'
|
||||
import { getFieldsToSign } from '../getFieldsToSign'
|
||||
import isLocked from '../isLocked'
|
||||
import { authenticateLocalStrategy } from '../strategies/local/authenticate'
|
||||
import { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts'
|
||||
import { getFieldsToSign } from './getFieldsToSign'
|
||||
import unlock from './unlock'
|
||||
import { unlockOperation } from './unlock'
|
||||
|
||||
export type Result = {
|
||||
exp?: number
|
||||
@@ -35,15 +33,12 @@ export type Arguments = {
|
||||
depth?: number
|
||||
overrideAccess?: boolean
|
||||
req: PayloadRequest
|
||||
responseOptions?: ResponseInit & {
|
||||
headers: Headers
|
||||
}
|
||||
showHiddenFields?: boolean
|
||||
}
|
||||
|
||||
async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
export const loginOperation = async <TSlug extends keyof GeneratedTypes['collections']>(
|
||||
incomingArgs: Arguments,
|
||||
): Promise<Result & { user: GeneratedTypes['collections'][TSlug] }> {
|
||||
): Promise<Result & { user: GeneratedTypes['collections'][TSlug] }> => {
|
||||
let args = incomingArgs
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -70,7 +65,7 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
req,
|
||||
req: {
|
||||
payload,
|
||||
payload: { config, secret },
|
||||
payload: { secret },
|
||||
},
|
||||
showHiddenFields,
|
||||
} = args
|
||||
@@ -120,7 +115,7 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
}
|
||||
|
||||
if (maxLoginAttemptsEnabled) {
|
||||
await unlock({
|
||||
await unlockOperation({
|
||||
collection: {
|
||||
config: collectionConfig,
|
||||
},
|
||||
@@ -152,28 +147,6 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
expiresIn: collectionConfig.auth.tokenExpiration,
|
||||
})
|
||||
|
||||
if (args.responseOptions) {
|
||||
const sameSite =
|
||||
typeof collectionConfig.auth.cookies.sameSite === 'string'
|
||||
? collectionConfig.auth.cookies.sameSite
|
||||
: collectionConfig.auth.cookies.sameSite
|
||||
? 'Strict'
|
||||
: undefined
|
||||
|
||||
const cookie = generateCookie({
|
||||
name: `${config.cookiePrefix}-token`,
|
||||
domain: collectionConfig.auth.cookies.domain ?? undefined,
|
||||
expires: getCookieExpiration(collectionConfig.auth.tokenExpiration),
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
value: token,
|
||||
})
|
||||
|
||||
args.responseOptions.headers.set('Set-Cookie', cookie)
|
||||
}
|
||||
|
||||
req.user = user
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -273,5 +246,3 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export default login
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// TODO(JARROD): remove express Response
|
||||
import type { Response } from 'express'
|
||||
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { Collection } from '../../collections/config/types'
|
||||
@@ -11,37 +8,20 @@ import { APIError } from '../../errors'
|
||||
export type Arguments = {
|
||||
collection: Collection
|
||||
req: PayloadRequest
|
||||
res: Response
|
||||
}
|
||||
|
||||
async function logout(incomingArgs: Arguments): Promise<string> {
|
||||
export const logoutOperation = async (incomingArgs: Arguments): Promise<boolean> => {
|
||||
let args = incomingArgs
|
||||
const {
|
||||
collection,
|
||||
collection: { config: collectionConfig },
|
||||
req: { collection, user },
|
||||
req,
|
||||
req: {
|
||||
payload: { config },
|
||||
user,
|
||||
},
|
||||
res,
|
||||
} = incomingArgs
|
||||
|
||||
if (!user) throw new APIError('No User', httpStatus.BAD_REQUEST)
|
||||
if (user.collection !== collectionConfig.slug)
|
||||
throw new APIError('Incorrect collection', httpStatus.FORBIDDEN)
|
||||
|
||||
const cookieOptions = {
|
||||
domain: undefined,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: collectionConfig.auth.cookies.sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
}
|
||||
|
||||
if (collectionConfig.auth.cookies.domain)
|
||||
cookieOptions.domain = collectionConfig.auth.cookies.domain
|
||||
|
||||
await collection.config.hooks.afterLogout.reduce(async (priorHook, hook) => {
|
||||
await priorHook
|
||||
|
||||
@@ -50,13 +30,8 @@ async function logout(incomingArgs: Arguments): Promise<string> {
|
||||
collection: args.collection?.config,
|
||||
context: req.context,
|
||||
req,
|
||||
res,
|
||||
})) || args
|
||||
}, Promise.resolve())
|
||||
|
||||
res.clearCookie(`${config.cookiePrefix}-token`, cookieOptions)
|
||||
|
||||
return req.t('authentication:loggedOutSuccessfully')
|
||||
return true
|
||||
}
|
||||
|
||||
export default logout
|
||||
|
||||
@@ -5,8 +5,6 @@ import type { Collection } from '../../collections/config/types'
|
||||
import type { PayloadRequest } from '../../types'
|
||||
import type { User } from '../types'
|
||||
|
||||
import { extractJWT } from '../getExtractJWT'
|
||||
|
||||
export type Result = {
|
||||
collection?: string
|
||||
exp?: number
|
||||
@@ -16,11 +14,16 @@ export type Result = {
|
||||
|
||||
export type Arguments = {
|
||||
collection: Collection
|
||||
currentToken?: string
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
async function me({ collection, req }: Arguments): Promise<Result> {
|
||||
let response: Result = {
|
||||
export const meOperation = async ({
|
||||
collection,
|
||||
currentToken,
|
||||
req,
|
||||
}: Arguments): Promise<Result> => {
|
||||
let result: Result = {
|
||||
user: null,
|
||||
}
|
||||
|
||||
@@ -45,17 +48,15 @@ async function me({ collection, req }: Arguments): Promise<Result> {
|
||||
|
||||
delete user.collection
|
||||
|
||||
response = {
|
||||
result = {
|
||||
collection: req.user.collection,
|
||||
user,
|
||||
}
|
||||
|
||||
const token = extractJWT(req)
|
||||
|
||||
if (token) {
|
||||
const decoded = jwt.decode(token) as jwt.JwtPayload
|
||||
if (decoded) response.exp = decoded.exp
|
||||
if (!collection.config.auth.removeTokenFromResponses) response.token = token
|
||||
if (currentToken) {
|
||||
const decoded = jwt.decode(currentToken) as jwt.JwtPayload
|
||||
if (decoded) result.exp = decoded.exp
|
||||
if (!collection.config.auth.removeTokenFromResponses) result.token = currentToken
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,16 +67,14 @@ async function me({ collection, req }: Arguments): Promise<Result> {
|
||||
await collection.config.hooks.afterMe.reduce(async (priorHook, hook) => {
|
||||
await priorHook
|
||||
|
||||
response =
|
||||
result =
|
||||
(await hook({
|
||||
collection: collection?.config,
|
||||
context: req.context,
|
||||
req,
|
||||
response,
|
||||
})) || response
|
||||
response: result,
|
||||
})) || result
|
||||
}, Promise.resolve())
|
||||
|
||||
return response
|
||||
return result
|
||||
}
|
||||
|
||||
export default me
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// TODO(JARROD): remove express Response
|
||||
import type { Response } from 'express'
|
||||
|
||||
import jwt from 'jsonwebtoken'
|
||||
import url from 'url'
|
||||
|
||||
@@ -10,8 +7,7 @@ import type { Document } from '../../types'
|
||||
|
||||
import { buildAfterOperation } from '../../collections/operations/utils'
|
||||
import { Forbidden } from '../../errors'
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration'
|
||||
import { getFieldsToSign } from './getFieldsToSign'
|
||||
import { getFieldsToSign } from '../getFieldsToSign'
|
||||
|
||||
export type Result = {
|
||||
exp: number
|
||||
@@ -22,11 +18,10 @@ export type Result = {
|
||||
export type Arguments = {
|
||||
collection: Collection
|
||||
req: PayloadRequest
|
||||
res?: Response
|
||||
token: string
|
||||
}
|
||||
|
||||
async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
export const refreshOperation = async (incomingArgs: Arguments): Promise<Result> => {
|
||||
let args = incomingArgs
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -83,22 +78,6 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
|
||||
const exp = (jwt.decode(refreshedToken) as Record<string, unknown>).exp as number
|
||||
|
||||
if (args.res) {
|
||||
const cookieOptions = {
|
||||
domain: undefined,
|
||||
expires: getCookieExpiration(collectionConfig.auth.tokenExpiration),
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: collectionConfig.auth.cookies.sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
}
|
||||
|
||||
if (collectionConfig.auth.cookies.domain)
|
||||
cookieOptions.domain = collectionConfig.auth.cookies.domain
|
||||
|
||||
args.res.cookie(`${config.cookiePrefix}-token`, refreshedToken, cookieOptions)
|
||||
}
|
||||
|
||||
let result: Result = {
|
||||
exp,
|
||||
refreshedToken,
|
||||
@@ -118,7 +97,6 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
context: args.req.context,
|
||||
exp,
|
||||
req: args.req,
|
||||
res: args.res,
|
||||
token: refreshedToken,
|
||||
})) || result
|
||||
}, Promise.resolve())
|
||||
@@ -144,5 +122,3 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export default refresh
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// TODO(JARROD): remove express Response
|
||||
import type { Response } from 'express'
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { GeneratedTypes } from '../../'
|
||||
@@ -18,18 +16,17 @@ export type Arguments<T extends { [field: number | string | symbol]: unknown }>
|
||||
password: string
|
||||
}
|
||||
req: PayloadRequest
|
||||
// TODO(JARROD): remove express Response
|
||||
res: Response
|
||||
}
|
||||
|
||||
export type Result<T> = {
|
||||
message: string
|
||||
user: T
|
||||
exp?: number
|
||||
token?: string
|
||||
user?: T
|
||||
}
|
||||
|
||||
async function registerFirstUser<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
export const registerFirstUserOperation = async <TSlug extends keyof GeneratedTypes['collections']>(
|
||||
args: Arguments<GeneratedTypes['collections'][TSlug]>,
|
||||
): Promise<Result<GeneratedTypes['collections'][TSlug]>> {
|
||||
): Promise<Result<GeneratedTypes['collections'][TSlug]>> => {
|
||||
const {
|
||||
collection: {
|
||||
config,
|
||||
@@ -80,27 +77,21 @@ async function registerFirstUser<TSlug extends keyof GeneratedTypes['collections
|
||||
// Log in new user
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { token } = await payload.login({
|
||||
const { exp, token } = await payload.login({
|
||||
...args,
|
||||
collection: slug,
|
||||
req,
|
||||
})
|
||||
|
||||
const resultToReturn = {
|
||||
...result,
|
||||
token,
|
||||
}
|
||||
|
||||
if (shouldCommit) await commitTransaction(req)
|
||||
|
||||
return {
|
||||
message: 'Registered and logged in successfully. Welcome!',
|
||||
user: resultToReturn,
|
||||
exp,
|
||||
token,
|
||||
user: result,
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
await killTransaction(req)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export default registerFirstUser
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// TODO(JARROD): remove express Response
|
||||
import type { Response } from 'express'
|
||||
|
||||
import jwt from 'jsonwebtoken'
|
||||
|
||||
import type { Collection } from '../../collections/config/types'
|
||||
@@ -8,12 +5,11 @@ import type { PayloadRequest } from '../../types'
|
||||
|
||||
import { APIError } from '../../errors'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction'
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration'
|
||||
import { initTransaction } from '../../utilities/initTransaction'
|
||||
import { killTransaction } from '../../utilities/killTransaction'
|
||||
import { getFieldsToSign } from '../getFieldsToSign'
|
||||
import { authenticateLocalStrategy } from '../strategies/local/authenticate'
|
||||
import { generatePasswordSaltHash } from '../strategies/local/generatePasswordSaltHash'
|
||||
import { getFieldsToSign } from './getFieldsToSign'
|
||||
|
||||
export type Result = {
|
||||
token?: string
|
||||
@@ -29,11 +25,9 @@ export type Arguments = {
|
||||
depth?: number
|
||||
overrideAccess?: boolean
|
||||
req: PayloadRequest
|
||||
// TODO(JARROD): remove express Response
|
||||
res?: Response
|
||||
}
|
||||
|
||||
async function resetPassword(args: Arguments): Promise<Result> {
|
||||
export const resetPasswordOperation = async (args: Arguments): Promise<Result> => {
|
||||
if (
|
||||
!Object.prototype.hasOwnProperty.call(args.data, 'token') ||
|
||||
!Object.prototype.hasOwnProperty.call(args.data, 'password')
|
||||
@@ -47,7 +41,7 @@ async function resetPassword(args: Arguments): Promise<Result> {
|
||||
depth,
|
||||
overrideAccess,
|
||||
req: {
|
||||
payload: { config, secret },
|
||||
payload: { secret },
|
||||
payload,
|
||||
},
|
||||
req,
|
||||
@@ -102,22 +96,6 @@ async function resetPassword(args: Arguments): Promise<Result> {
|
||||
expiresIn: collectionConfig.auth.tokenExpiration,
|
||||
})
|
||||
|
||||
if (args.res) {
|
||||
const cookieOptions = {
|
||||
domain: undefined,
|
||||
expires: getCookieExpiration(collectionConfig.auth.tokenExpiration),
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: collectionConfig.auth.cookies.sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
}
|
||||
|
||||
if (collectionConfig.auth.cookies.domain)
|
||||
cookieOptions.domain = collectionConfig.auth.cookies.domain
|
||||
|
||||
args.res.cookie(`${config.cookiePrefix}-token`, token, cookieOptions)
|
||||
}
|
||||
|
||||
const fullUser = await payload.findByID({
|
||||
id: user.id,
|
||||
collection: collectionConfig.slug,
|
||||
@@ -137,4 +115,4 @@ async function resetPassword(args: Arguments): Promise<Result> {
|
||||
}
|
||||
}
|
||||
|
||||
export default resetPassword
|
||||
export default resetPasswordOperation
|
||||
|
||||
@@ -17,7 +17,7 @@ export type Args = {
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
async function unlock(args: Args): Promise<boolean> {
|
||||
export const unlockOperation = async (args: Args): Promise<boolean> => {
|
||||
if (!Object.prototype.hasOwnProperty.call(args.data, 'email')) {
|
||||
throw new APIError('Missing email.')
|
||||
}
|
||||
@@ -25,7 +25,7 @@ async function unlock(args: Args): Promise<boolean> {
|
||||
const {
|
||||
collection: { config: collectionConfig },
|
||||
overrideAccess,
|
||||
req: { locale, payload },
|
||||
req: { locale },
|
||||
req,
|
||||
} = args
|
||||
|
||||
@@ -82,4 +82,4 @@ async function unlock(args: Args): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
export default unlock
|
||||
export default unlockOperation
|
||||
|
||||
@@ -14,7 +14,7 @@ export type Args = {
|
||||
token: string
|
||||
}
|
||||
|
||||
async function verifyEmail(args: Args): Promise<boolean> {
|
||||
export const verifyEmailOperation = async (args: Args): Promise<boolean> => {
|
||||
const { collection, req, token } = args
|
||||
if (!Object.prototype.hasOwnProperty.call(args, 'token')) {
|
||||
throw new APIError('Missing required data.', httpStatus.BAD_REQUEST)
|
||||
@@ -55,4 +55,4 @@ async function verifyEmail(args: Args): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
export default verifyEmail
|
||||
export default verifyEmailOperation
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
|
||||
import type { Collection } from './config/types'
|
||||
|
||||
const bindCollectionMiddleware =
|
||||
(collection: Collection) =>
|
||||
(req: Request & { collection: Collection }, res: Response, next: NextFunction): void => {
|
||||
req.collection = collection
|
||||
next()
|
||||
}
|
||||
|
||||
export default bindCollectionMiddleware
|
||||
@@ -1,177 +0,0 @@
|
||||
import type { Endpoint } from '../config/types'
|
||||
import type { SanitizedCollectionConfig } from './config/types'
|
||||
|
||||
import forgotPasswordHandler from '../auth/handlers/forgotPassword'
|
||||
import initHandler from '../auth/handlers/init'
|
||||
import loginHandler from '../auth/handlers/login'
|
||||
import logoutHandler from '../auth/handlers/logout'
|
||||
import meHandler from '../auth/handlers/me'
|
||||
import refreshHandler from '../auth/handlers/refresh'
|
||||
import registerFirstUserHandler from '../auth/handlers/registerFirstUser'
|
||||
import resetPassword from '../auth/handlers/resetPassword'
|
||||
import unlock from '../auth/handlers/unlock'
|
||||
import verifyEmail from '../auth/handlers/verifyEmail'
|
||||
import create from './requestHandlers/create'
|
||||
import deleteHandler from './requestHandlers/delete'
|
||||
import deleteByID from './requestHandlers/deleteByID'
|
||||
import docAccessRequestHandler from './requestHandlers/docAccess'
|
||||
import find from './requestHandlers/find'
|
||||
import findByID from './requestHandlers/findByID'
|
||||
import findVersionByID from './requestHandlers/findVersionByID'
|
||||
import findVersions from './requestHandlers/findVersions'
|
||||
import restoreVersion from './requestHandlers/restoreVersion'
|
||||
import update from './requestHandlers/update'
|
||||
import updateByID, { deprecatedUpdate } from './requestHandlers/updateByID'
|
||||
|
||||
const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
|
||||
if (!collection.endpoints) return []
|
||||
const endpoints = [...collection.endpoints]
|
||||
|
||||
if (collection.auth) {
|
||||
if (!collection.auth.disableLocalStrategy) {
|
||||
if (collection.auth.verify) {
|
||||
endpoints.push({
|
||||
handler: verifyEmail,
|
||||
method: 'post',
|
||||
path: '/verify/:token',
|
||||
})
|
||||
}
|
||||
|
||||
if (collection.auth.maxLoginAttempts > 0) {
|
||||
endpoints.push({
|
||||
handler: unlock,
|
||||
method: 'post',
|
||||
path: '/unlock',
|
||||
})
|
||||
}
|
||||
|
||||
endpoints.push(
|
||||
{
|
||||
handler: loginHandler,
|
||||
method: 'post',
|
||||
path: '/login',
|
||||
},
|
||||
{
|
||||
handler: registerFirstUserHandler,
|
||||
method: 'post',
|
||||
path: '/first-register',
|
||||
},
|
||||
{
|
||||
handler: forgotPasswordHandler,
|
||||
method: 'post',
|
||||
path: '/forgot-password',
|
||||
},
|
||||
{
|
||||
handler: resetPassword,
|
||||
method: 'post',
|
||||
path: '/reset-password',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
endpoints.push(
|
||||
{
|
||||
handler: initHandler,
|
||||
method: 'get',
|
||||
path: '/init',
|
||||
},
|
||||
{
|
||||
handler: meHandler,
|
||||
method: 'get',
|
||||
path: '/me',
|
||||
},
|
||||
{
|
||||
handler: logoutHandler,
|
||||
method: 'post',
|
||||
path: '/logout',
|
||||
},
|
||||
{
|
||||
handler: refreshHandler,
|
||||
method: 'post',
|
||||
path: '/refresh-token',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if (collection.versions) {
|
||||
endpoints.push(
|
||||
{
|
||||
handler: findVersions,
|
||||
method: 'get',
|
||||
path: '/versions',
|
||||
},
|
||||
{
|
||||
handler: findVersionByID,
|
||||
method: 'get',
|
||||
path: '/versions/:id',
|
||||
},
|
||||
{
|
||||
handler: restoreVersion,
|
||||
method: 'post',
|
||||
path: '/versions/:id',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
endpoints.push(
|
||||
{
|
||||
handler: find,
|
||||
method: 'get',
|
||||
path: '/',
|
||||
},
|
||||
{
|
||||
handler: create,
|
||||
method: 'post',
|
||||
path: '/',
|
||||
},
|
||||
{
|
||||
handler: docAccessRequestHandler,
|
||||
method: 'get',
|
||||
path: '/access/:id',
|
||||
},
|
||||
{
|
||||
handler: docAccessRequestHandler,
|
||||
method: 'post',
|
||||
path: '/access/:id',
|
||||
},
|
||||
{
|
||||
handler: docAccessRequestHandler,
|
||||
method: 'post',
|
||||
path: '/access',
|
||||
},
|
||||
{
|
||||
handler: deprecatedUpdate,
|
||||
method: 'put',
|
||||
path: '/:id',
|
||||
},
|
||||
{
|
||||
handler: update,
|
||||
method: 'patch',
|
||||
path: '/',
|
||||
},
|
||||
{
|
||||
handler: updateByID,
|
||||
method: 'patch',
|
||||
path: '/:id',
|
||||
},
|
||||
{
|
||||
handler: findByID,
|
||||
method: 'get',
|
||||
path: '/:id',
|
||||
},
|
||||
{
|
||||
handler: deleteByID,
|
||||
method: 'delete',
|
||||
path: '/:id',
|
||||
},
|
||||
{
|
||||
handler: deleteHandler,
|
||||
method: 'delete',
|
||||
path: '/',
|
||||
},
|
||||
)
|
||||
|
||||
return endpoints
|
||||
}
|
||||
|
||||
export default buildEndpoints
|
||||
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { Response } from 'express'
|
||||
import type { GraphQLInputObjectType, GraphQLNonNull, GraphQLObjectType } from 'graphql'
|
||||
import type { DeepRequired } from 'ts-essentials'
|
||||
|
||||
@@ -169,7 +167,6 @@ export type AfterLogoutHook<T extends TypeWithID = any> = (args: {
|
||||
collection: SanitizedCollectionConfig
|
||||
context: RequestContext
|
||||
req: PayloadRequest
|
||||
res: Response
|
||||
}) => any
|
||||
|
||||
export type AfterMeHook<T extends TypeWithID = any> = (args: {
|
||||
@@ -186,7 +183,6 @@ export type AfterRefreshHook<T extends TypeWithID = any> = (args: {
|
||||
context: RequestContext
|
||||
exp: number
|
||||
req: PayloadRequest
|
||||
res: Response
|
||||
token: string
|
||||
}) => any
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
GraphQLString,
|
||||
} from 'graphql'
|
||||
|
||||
import type { PayloadT } from '../..'
|
||||
import type { Field } from '../../fields/config/types'
|
||||
import type { ObjectTypeConfig } from '../../graphql/schema/buildObjectType'
|
||||
import type { Payload } from '../../payload'
|
||||
import type { Collection, SanitizedCollectionConfig } from '../config/types'
|
||||
|
||||
import forgotPassword from '../../auth/graphql/resolvers/forgotPassword'
|
||||
@@ -42,7 +42,7 @@ import findVersionsResolver from './resolvers/findVersions'
|
||||
import restoreVersionResolver from './resolvers/restoreVersion'
|
||||
import updateResolver from './resolvers/update'
|
||||
|
||||
function initCollectionsGraphQL(payload: Payload): void {
|
||||
function initCollectionsGraphQL(payload: PayloadT): void {
|
||||
Object.keys(payload.collections).forEach((slug) => {
|
||||
const collection: Collection = payload.collections[slug]
|
||||
const {
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { PayloadRequest } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import create from '../../operations/create'
|
||||
import { createOperation } from '../../operations/create'
|
||||
|
||||
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (
|
||||
_: unknown,
|
||||
@@ -21,7 +21,6 @@ export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (
|
||||
},
|
||||
context: {
|
||||
req: PayloadRequest
|
||||
res: Response
|
||||
},
|
||||
) => Promise<GeneratedTypes['collections'][TSlug]>
|
||||
|
||||
@@ -41,7 +40,7 @@ export default function createResolver<TSlug extends keyof GeneratedTypes['colle
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await create(options)
|
||||
const result = await createOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { PayloadRequest } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import deleteByID from '../../operations/deleteByID'
|
||||
import { deleteByIDOperation } from '../../operations/deleteByID'
|
||||
|
||||
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (
|
||||
_: unknown,
|
||||
@@ -34,7 +34,7 @@ export default function getDeleteResolver<TSlug extends keyof GeneratedTypes['co
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await deleteByID(options)
|
||||
const result = await deleteByIDOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { CollectionPermission, GlobalPermission } from '../../../auth'
|
||||
import type { PayloadRequest } from '../../../types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import { docAccess } from '../../operations/docAccess'
|
||||
import { docAccessOperation } from '../../operations/docAccess'
|
||||
|
||||
export type Resolver = (
|
||||
_: unknown,
|
||||
@@ -17,7 +17,7 @@ export type Resolver = (
|
||||
|
||||
export function docAccessResolver(): Resolver {
|
||||
async function resolver(_, args, context) {
|
||||
return docAccess({
|
||||
return docAccessOperation({
|
||||
id: args.id,
|
||||
req: isolateTransactionID(context.req),
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { Where } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import find from '../../operations/find'
|
||||
import { findOperation } from '../../operations/find'
|
||||
|
||||
export type Resolver = (
|
||||
_: unknown,
|
||||
@@ -42,7 +42,7 @@ export default function findResolver(collection: Collection): Resolver {
|
||||
where: args.where,
|
||||
}
|
||||
|
||||
const results = await find(options)
|
||||
const results = await findOperation(options)
|
||||
return results
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { PayloadRequest } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import findByID from '../../operations/findByID'
|
||||
import { findByIDOperation } from '../../operations/findByID'
|
||||
|
||||
export type Resolver<T> = (
|
||||
_: unknown,
|
||||
@@ -35,7 +35,7 @@ export default function findByIDResolver<T extends keyof GeneratedTypes['collect
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await findByID(options)
|
||||
const result = await findByIDOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { TypeWithVersion } from '../../../versions/types'
|
||||
import type { Collection, TypeWithID } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import findVersionByID from '../../operations/findVersionByID'
|
||||
import { findVersionByIDOperation } from '../../operations/findVersionByID'
|
||||
|
||||
export type Resolver<T extends TypeWithID = any> = (
|
||||
_: unknown,
|
||||
@@ -35,7 +35,7 @@ export default function findVersionByIDResolver(collection: Collection): Resolve
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await findVersionByID(options)
|
||||
const result = await findVersionByIDOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { Where } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import findVersions from '../../operations/findVersions'
|
||||
import { findVersionsOperation } from '../../operations/findVersions'
|
||||
|
||||
export type Resolver = (
|
||||
_: unknown,
|
||||
@@ -41,7 +41,7 @@ export default function findVersionsResolver(collection: Collection): Resolver {
|
||||
where: args.where,
|
||||
}
|
||||
|
||||
const result = await findVersions(options)
|
||||
const result = await findVersionsOperation(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { PayloadRequest } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import restoreVersion from '../../operations/restoreVersion'
|
||||
import { restoreVersionOperation } from '../../operations/restoreVersion'
|
||||
|
||||
export type Resolver = (
|
||||
_: unknown,
|
||||
@@ -27,7 +27,7 @@ export default function restoreVersionResolver(collection: Collection): Resolver
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await restoreVersion(options)
|
||||
const result = await restoreVersionOperation(options)
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { PayloadRequest } from '../../../types'
|
||||
import type { Collection } from '../../config/types'
|
||||
|
||||
import isolateTransactionID from '../../../utilities/isolateTransactionID'
|
||||
import updateByID from '../../operations/updateByID'
|
||||
import { updateByIDOperation } from '../../operations/updateByID'
|
||||
|
||||
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (
|
||||
_: unknown,
|
||||
@@ -40,7 +40,7 @@ export default function updateResolver<TSlug extends keyof GeneratedTypes['colle
|
||||
req: isolateTransactionID(context.req),
|
||||
}
|
||||
|
||||
const result = await updateByID<TSlug>(options)
|
||||
const result = await updateByIDOperation<TSlug>(options)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import express from 'express'
|
||||
import passport from 'passport'
|
||||
|
||||
import type { Payload } from '../payload'
|
||||
import type { SanitizedCollectionConfig } from './config/types'
|
||||
|
||||
import apiKeyStrategy from '../auth/strategies/apiKey'
|
||||
import mountEndpoints from '../express/mountEndpoints'
|
||||
import bindCollectionMiddleware from './bindCollection'
|
||||
import buildEndpoints from './buildEndpoints'
|
||||
|
||||
export default function initCollectionsHTTP(ctx: Payload): void {
|
||||
ctx.config.collections = ctx.config.collections.map((collection: SanitizedCollectionConfig) => {
|
||||
const formattedCollection = collection
|
||||
|
||||
const router = express.Router()
|
||||
const { slug } = collection
|
||||
|
||||
router.all('*', bindCollectionMiddleware(ctx.collections[formattedCollection.slug]))
|
||||
|
||||
if (collection.auth) {
|
||||
const { config } = ctx.collections[formattedCollection.slug]
|
||||
|
||||
if (collection.auth.useAPIKey) {
|
||||
passport.use(`${config.slug}-api-key`, apiKeyStrategy(ctx, config))
|
||||
}
|
||||
|
||||
if (Array.isArray(collection.auth.strategies)) {
|
||||
collection.auth.strategies.forEach(({ name, strategy }, index) => {
|
||||
const passportStrategy = typeof strategy === 'object' ? strategy : strategy(ctx)
|
||||
passport.use(`${config.slug}-${name ?? index}`, passportStrategy)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const endpoints = buildEndpoints(collection)
|
||||
mountEndpoints(ctx.express, router, endpoints)
|
||||
|
||||
ctx.router.use(`/${slug}`, router)
|
||||
|
||||
return formattedCollection
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user