feat: exports additional login helper utils (#12309)
Exports a few utilities that are used internally to the login operation, but could be helpful for others building plugins. Specifically: - `isUserLocked` - a check to ensure that a given user is not locked due to too many invalid attempts - `checkLoginPermissions` - checks to see that the user is not locked as well as that it is properly verified, if applicable - `jwtSign` - Payload's internal JWT signing approach - `getFieldsToSign` - reduce down a document's fields for JWT creation based on collection config settings - `incrementLoginAttempts` / `resetLoginAttempts` - utilities to handle both failed and successful login attempts - `UnverifiedEmail` - an error that could be thrown if attempting to log in to an account without prior successful email verification
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
const isLocked = (date: number): boolean => {
|
||||
if (!date) {
|
||||
return false
|
||||
}
|
||||
return date > Date.now()
|
||||
}
|
||||
export default isLocked
|
||||
6
packages/payload/src/auth/isUserLocked.ts
Normal file
6
packages/payload/src/auth/isUserLocked.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const isUserLocked = (date: number): boolean => {
|
||||
if (!date) {
|
||||
return false
|
||||
}
|
||||
return date > Date.now()
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import type {
|
||||
AuthOperationsFromCollectionSlug,
|
||||
Collection,
|
||||
DataFromCollectionSlug,
|
||||
SanitizedCollectionConfig,
|
||||
} from '../../collections/config/types.js'
|
||||
import type { CollectionSlug } from '../../index.js'
|
||||
import type { PayloadRequest, Where } from '../../types/index.js'
|
||||
@@ -21,7 +22,7 @@ import { killTransaction } from '../../utilities/killTransaction.js'
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields.js'
|
||||
import { getFieldsToSign } from '../getFieldsToSign.js'
|
||||
import { getLoginOptions } from '../getLoginOptions.js'
|
||||
import isLocked from '../isLocked.js'
|
||||
import { isUserLocked } from '../isUserLocked.js'
|
||||
import { jwtSign } from '../jwt.js'
|
||||
import { authenticateLocalStrategy } from '../strategies/local/authenticate.js'
|
||||
import { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts.js'
|
||||
@@ -42,6 +43,32 @@ export type Arguments<TSlug extends CollectionSlug> = {
|
||||
showHiddenFields?: boolean
|
||||
}
|
||||
|
||||
type CheckLoginPermissionArgs = {
|
||||
collection: SanitizedCollectionConfig
|
||||
loggingInWithUsername?: boolean
|
||||
req: PayloadRequest
|
||||
user: any
|
||||
}
|
||||
|
||||
export const checkLoginPermission = ({
|
||||
collection,
|
||||
loggingInWithUsername,
|
||||
req,
|
||||
user,
|
||||
}: CheckLoginPermissionArgs) => {
|
||||
if (!user) {
|
||||
throw new AuthenticationError(req.t, Boolean(loggingInWithUsername))
|
||||
}
|
||||
|
||||
if (collection.auth.verify && user._verified === false) {
|
||||
throw new UnverifiedEmail({ t: req.t })
|
||||
}
|
||||
|
||||
if (isUserLocked(new Date(user.lockUntil).getTime())) {
|
||||
throw new LockedAuth(req.t)
|
||||
}
|
||||
}
|
||||
|
||||
export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
incomingArgs: Arguments<TSlug>,
|
||||
): Promise<{ user: DataFromCollectionSlug<TSlug> } & Result> => {
|
||||
@@ -184,21 +211,16 @@ export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
where: whereConstraint,
|
||||
})
|
||||
|
||||
if (!user) {
|
||||
throw new AuthenticationError(req.t, Boolean(canLoginWithUsername && sanitizedUsername))
|
||||
}
|
||||
|
||||
if (args.collection.config.auth.verify && user._verified === false) {
|
||||
throw new UnverifiedEmail({ t: req.t })
|
||||
}
|
||||
checkLoginPermission({
|
||||
collection: collectionConfig,
|
||||
loggingInWithUsername: Boolean(canLoginWithUsername && sanitizedUsername),
|
||||
req,
|
||||
user,
|
||||
})
|
||||
|
||||
user.collection = collectionConfig.slug
|
||||
user._strategy = 'local-jwt'
|
||||
|
||||
if (isLocked(new Date(user.lockUntil).getTime())) {
|
||||
throw new LockedAuth(req.t)
|
||||
}
|
||||
|
||||
const authResult = await authenticateLocalStrategy({ doc: user, password })
|
||||
|
||||
user = sanitizeInternalFields(user)
|
||||
|
||||
@@ -89,6 +89,10 @@ import { traverseFields } from './utilities/traverseFields.js'
|
||||
|
||||
export { default as executeAccess } from './auth/executeAccess.js'
|
||||
export { executeAuthStrategies } from './auth/executeAuthStrategies.js'
|
||||
export { extractAccessFromPermission } from './auth/extractAccessFromPermission.js'
|
||||
export { getAccessResults } from './auth/getAccessResults.js'
|
||||
export { getFieldsToSign } from './auth/getFieldsToSign.js'
|
||||
export { getLoginOptions } from './auth/getLoginOptions.js'
|
||||
|
||||
export interface GeneratedTypes {
|
||||
authUntyped: {
|
||||
@@ -977,13 +981,12 @@ interface RequestContext {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface DatabaseAdapter extends BaseDatabaseAdapter {}
|
||||
export type { Payload, RequestContext }
|
||||
export { extractAccessFromPermission } from './auth/extractAccessFromPermission.js'
|
||||
export { getAccessResults } from './auth/getAccessResults.js'
|
||||
export { getFieldsToSign } from './auth/getFieldsToSign.js'
|
||||
export * from './auth/index.js'
|
||||
export { jwtSign } from './auth/jwt.js'
|
||||
export { accessOperation } from './auth/operations/access.js'
|
||||
export { forgotPasswordOperation } from './auth/operations/forgotPassword.js'
|
||||
export { initOperation } from './auth/operations/init.js'
|
||||
export { checkLoginPermission } from './auth/operations/login.js'
|
||||
export { loginOperation } from './auth/operations/login.js'
|
||||
export { logoutOperation } from './auth/operations/logout.js'
|
||||
export type { MeOperationResult } from './auth/operations/me.js'
|
||||
@@ -994,6 +997,8 @@ export { resetPasswordOperation } from './auth/operations/resetPassword.js'
|
||||
export { unlockOperation } from './auth/operations/unlock.js'
|
||||
export { verifyEmailOperation } from './auth/operations/verifyEmail.js'
|
||||
export { JWTAuthentication } from './auth/strategies/jwt.js'
|
||||
export { incrementLoginAttempts } from './auth/strategies/local/incrementLoginAttempts.js'
|
||||
export { resetLoginAttempts } from './auth/strategies/local/resetLoginAttempts.js'
|
||||
export type {
|
||||
AuthStrategyFunction,
|
||||
AuthStrategyFunctionArgs,
|
||||
@@ -1201,6 +1206,7 @@ export {
|
||||
MissingFile,
|
||||
NotFound,
|
||||
QueryError,
|
||||
UnverifiedEmail,
|
||||
ValidationError,
|
||||
ValidationErrorName,
|
||||
} from './errors/index.js'
|
||||
|
||||
Reference in New Issue
Block a user