chore: improve cookie helper functions (#5866)
This commit is contained in:
23
.vscode/launch.json
vendored
23
.vscode/launch.json
vendored
@@ -41,6 +41,13 @@
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "node --no-deprecation test/dev.js auth",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Auth",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev plugin-cloud-storage",
|
||||
"cwd": "${workspaceFolder}",
|
||||
@@ -69,36 +76,26 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev versions",
|
||||
"command": "node --no-deprecation test/dev.js versions",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Versions",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev localization",
|
||||
"command": "node --no-deprecation test/dev.js localization",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Localization",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev uploads",
|
||||
"command": "node --no-deprecation test/dev.js uploads",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Uploads",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "PAYLOAD_BUNDLER=vite pnpm run dev fields",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Fields (Vite)",
|
||||
"request": "launch",
|
||||
"type": "node-terminal",
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pnpm run test:int live-preview",
|
||||
"cwd": "${workspaceFolder}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Payload } from '../index.js'
|
||||
import type { SanitizedCollectionConfig } from './../collections/config/types.js'
|
||||
|
||||
type CookieOptions = {
|
||||
domain?: string
|
||||
expires?: Date
|
||||
@@ -7,53 +8,108 @@ type CookieOptions = {
|
||||
maxAge?: number
|
||||
name: string
|
||||
path?: string
|
||||
returnCookieAsObject: boolean
|
||||
sameSite?: 'Lax' | 'None' | 'Strict'
|
||||
secure?: boolean
|
||||
value?: string
|
||||
}
|
||||
|
||||
export const generateCookies = (cookies: CookieOptions[]): string => {
|
||||
return cookies.map((options) => generateCookie(options)).join('; ')
|
||||
type CookieObject = {
|
||||
domain?: string
|
||||
expires?: string
|
||||
httpOnly?: boolean
|
||||
maxAge?: number
|
||||
name: string
|
||||
path?: string
|
||||
sameSite?: 'Lax' | 'None' | 'Strict'
|
||||
secure?: boolean
|
||||
value: string
|
||||
}
|
||||
|
||||
export const generateCookie = (args: CookieOptions): string => {
|
||||
const { name, domain, expires, httpOnly, maxAge, path, sameSite, secure: secureArg, value } = args
|
||||
export const generateCookie = <ReturnCookieAsObject = boolean>(
|
||||
args: CookieOptions,
|
||||
): ReturnCookieAsObject extends true ? CookieObject : string => {
|
||||
const {
|
||||
name,
|
||||
domain,
|
||||
expires,
|
||||
httpOnly,
|
||||
maxAge,
|
||||
path,
|
||||
returnCookieAsObject,
|
||||
sameSite,
|
||||
secure: secureArg,
|
||||
value,
|
||||
} = args
|
||||
|
||||
let cookieString = `${name}=${value || ''}`
|
||||
const cookieObject: CookieObject = {
|
||||
name,
|
||||
value,
|
||||
}
|
||||
|
||||
const secure = secureArg || sameSite === 'None'
|
||||
|
||||
if (expires) {
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.expires = expires.toUTCString()
|
||||
} else {
|
||||
cookieString += `; Expires=${expires.toUTCString()}`
|
||||
}
|
||||
}
|
||||
|
||||
if (maxAge) {
|
||||
cookieString += `; Max-Age=${maxAge}`
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.maxAge = maxAge
|
||||
} else {
|
||||
cookieString += `; Max-Age=${maxAge.toString()}`
|
||||
}
|
||||
}
|
||||
|
||||
if (domain) {
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.domain = domain
|
||||
} else {
|
||||
cookieString += `; Domain=${domain}`
|
||||
}
|
||||
}
|
||||
|
||||
if (path) {
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.path = path
|
||||
} else {
|
||||
cookieString += `; Path=${path}`
|
||||
}
|
||||
}
|
||||
|
||||
if (secure) {
|
||||
cookieString += '; Secure'
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.secure = secure
|
||||
} else {
|
||||
cookieString += `; Secure=${secure}`
|
||||
}
|
||||
}
|
||||
|
||||
if (httpOnly) {
|
||||
cookieString += '; HttpOnly'
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.httpOnly = httpOnly
|
||||
} else {
|
||||
cookieString += `; HttpOnly=${httpOnly}`
|
||||
}
|
||||
}
|
||||
|
||||
if (sameSite) {
|
||||
if (returnCookieAsObject) {
|
||||
cookieObject.sameSite = sameSite
|
||||
} else {
|
||||
cookieString += `; SameSite=${sameSite}`
|
||||
}
|
||||
}
|
||||
|
||||
return cookieString
|
||||
return (returnCookieAsObject ? cookieObject : cookieString) as ReturnCookieAsObject extends true
|
||||
? CookieObject
|
||||
: string
|
||||
}
|
||||
|
||||
type GetCookieExpirationArgs = {
|
||||
/*
|
||||
The number of seconds until the cookie expires
|
||||
@@ -72,14 +128,17 @@ type GeneratePayloadCookieArgs = {
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
/* An instance of payload */
|
||||
payload: Payload
|
||||
/* The returnAs value */
|
||||
returnCookieAsObject?: boolean
|
||||
/* The token to be stored in the cookie */
|
||||
token: string
|
||||
}
|
||||
export const generatePayloadCookie = ({
|
||||
export const generatePayloadCookie = <T extends GeneratePayloadCookieArgs>({
|
||||
collectionConfig,
|
||||
payload,
|
||||
returnCookieAsObject = false,
|
||||
token,
|
||||
}: GeneratePayloadCookieArgs): string => {
|
||||
}: T): T['returnCookieAsObject'] extends true ? CookieObject : string => {
|
||||
const sameSite =
|
||||
typeof collectionConfig.auth.cookies.sameSite === 'string'
|
||||
? collectionConfig.auth.cookies.sameSite
|
||||
@@ -87,22 +146,24 @@ export const generatePayloadCookie = ({
|
||||
? 'Strict'
|
||||
: undefined
|
||||
|
||||
return generateCookie({
|
||||
return generateCookie<T['returnCookieAsObject']>({
|
||||
name: `${payload.config.cookiePrefix}-token`,
|
||||
domain: collectionConfig.auth.cookies.domain ?? undefined,
|
||||
expires: getCookieExpiration({ seconds: collectionConfig.auth.tokenExpiration }),
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
returnCookieAsObject,
|
||||
sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
value: token,
|
||||
})
|
||||
}
|
||||
|
||||
export const generateExpiredPayloadCookie = ({
|
||||
export const generateExpiredPayloadCookie = <T extends Omit<GeneratePayloadCookieArgs, 'token'>>({
|
||||
collectionConfig,
|
||||
payload,
|
||||
}: Omit<GeneratePayloadCookieArgs, 'token'>): string => {
|
||||
returnCookieAsObject = false,
|
||||
}: T): T['returnCookieAsObject'] extends true ? CookieObject : string => {
|
||||
const sameSite =
|
||||
typeof collectionConfig.auth.cookies.sameSite === 'string'
|
||||
? collectionConfig.auth.cookies.sameSite
|
||||
@@ -112,12 +173,13 @@ export const generateExpiredPayloadCookie = ({
|
||||
|
||||
const expires = new Date(Date.now() - 1000)
|
||||
|
||||
return generateCookie({
|
||||
return generateCookie<T['returnCookieAsObject']>({
|
||||
name: `${payload.config.cookiePrefix}-token`,
|
||||
domain: collectionConfig.auth.cookies.domain ?? undefined,
|
||||
expires,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
returnCookieAsObject,
|
||||
sameSite,
|
||||
secure: collectionConfig.auth.cookies.secure,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user