Hi,
I'm new to payload and I'm a bit unsure how to add auth based hooks to the collection. I have created the actual hook, but how do I link it with the collection? Other types of hook are added under "hooks" in the collection, but there is no "AfterLogin" type I can use. How exactly do I tie a CollectionAfterLoginHook to the document?
Thanks!
You should be able to add
afterLoginand other Auth-enabled hooks the same way you would add in the other hooks.
/**
* Hooks to modify Payload functionality
*/
hooks?: {
beforeOperation?: BeforeOperationHook[];
beforeValidate?: BeforeValidateHook[];
beforeChange?: BeforeChangeHook[];
afterChange?: AfterChangeHook[];
beforeRead?: BeforeReadHook[];
afterRead?: AfterReadHook[];
beforeDelete?: BeforeDeleteHook[];
afterDelete?: AfterDeleteHook[];
afterError?: AfterErrorHook;
beforeLogin?: BeforeLoginHook[];
afterLogin?: AfterLoginHook[];
afterLogout?: AfterLogoutHook[];
afterMe?: AfterMeHook[];
afterRefresh?: AfterRefreshHook[];
afterForgotPassword?: AfterForgotPasswordHook[];
};Could you share your collection config and hook code here? I can try to help you out
Thanks! This actually solved my issue, I was doing logic field-based but had to be collection-based everywhere.
Awesome, let me know if you run into anything else!
I'm running into a small other issue. I'm trying to create the Last Active field, and upon trying to deconstruct user I keep getting a type error:
import type { User } from 'payload/generated-types'
import type { CollectionAfterLoginHook } from 'payload/types'
// ensure there is always auser
role
// do not let non-admins change roles
export const lastLoggedIn: CollectionAfterLoginHook<User & { id: string }> = async ({ req, user, token }) => {
return [...user, { lastLoggedIn: new Date() }];
}My Last Active field under users looks like this:
{
name: 'lastActive',
label: 'Last Active',
type: 'date',
access: {
read: () => true,
update: () => true,
create: () => false,
},
saveToJWT: true,
},A couple things:
- the Login operation isn't modifying a document, so you wouldn't return an updated
userobject here. (also, if you were, return an object instead of an array. That's likely the type error)
- you can use the Local API to make an update to the document, here's a snippet of how that could work:
hooks: {
afterLogin: [
async ({ user }) => {
await payload.update({
collection: 'users',
id: user.id,
data: {
lastActive: new Date(),
},
});
}
],
},Thanks!
A followup question, is there a way to make fields required depending on a given role a user has without using hooks, or is hooks the way to go when enforcing this type of behavior?
Sure, you can create your own validation functions at the field level. Check out this example that makes a field required if the user has an
adminrole:
{
name: 'validation',
type: 'text',
label: 'validation',
validate: (value, { user }) => {
if (user.role === 'admin') {
return value ? true : 'Please provide a value'
}
return true;
},
},I pass the
validateproperty the
valueof the field, as well as the
userobject. If the user's role is
adminit checks the value, and returns true if it exists, otherwise it returns 'Please provide a value' as an error statement.
If a user's role is not
admin, it does not require a value and returns true.
The
validateproperty can either return
trueor a string to use as the error that is returned if the validation is not passed.
Thanks!
Star
Discord
online
Get dedicated engineering support directly from the Payload team.