ValidationError Understanding Help

default discord avatar
shisue
last month
7

Hi,



I am running into the following error:



[16:56:43] ERROR (payload): ValidationError: The following field is invalid: organization at beforeChange (C:\Users\Igor\Desktop\IMF Solutions\blueprint-payload-cms\node_modules\payload\src\fields\hooks\beforeChange\index.ts:52:11) at processTicksAndRejections (node:internal/process/task_queues:96:5) at updateByID (C:\Users\Igor\Desktop\IMF Solutions\blueprint-payload-cms\node_modules\payload\src\collections\operations\updateByID.ts:211:16)

The error only happens when I am trying to log into the dashboard. After I am logged in, the usage functions normally.



Organizations is a relationship field in Users, as follows:



{ name: 'organization', label: 'Organization', type: 'relationship', relationTo: 'organizations', hasMany: false, access: { read: () => true, update: () => false, create: () => false, }, },

I get the error 'organization is not a valid field' when I try to login, however after refreshing the page, I am loged in and things work normally. Any idea of what this could be?

  • default discord avatar
    notchr
    last month

    Good afternoon @shisue - happy to help - do you mind sharing your User collection?

  • default discord avatar
    shisue
    last month

    Good afternoon! I managed to pinpoint the issue, but I am not sure how to fix it. The problem is, I want to have two roles (manager and member) be assigned only through hooks, but not manually. I currently have a validate that checks if the assigned role is one of the two, and it rejects if so. The problem is, the validate is also rejecting requests from a hook, not only form a user.



    if (val.includes('organizationManager')


    val.includes('organizationMember')) {
    console.log('here');
    console.log(data);
    return 'The Organization Manager and Organization Member roles are not assignable manually. Please assign user as manager or member of an organization.';
    }

    Am I able to, in the roles "select" type, exclude these two roles but still add them on a hook?

    This is what the roles field looks like:

    `{
    name: 'roles',
    label: 'Roles',
    type: 'select',
    hasMany: true,
    defaultValue: ['user'],
    options: [
    {
    label: 'User',
    value: 'user',
    },
    {
    label: 'Admin',
    value: 'admin',
    },
    {
    label: 'Organization Manager',
    value: 'organizationManager',
    },
    {
    label: 'Organization Member',
    value: 'organizationMember',
    },
    {
    label: 'Funder',
    value: 'funder',
    },
    {
    label: 'Facilitator',
    value: 'facilitator',
    }
    ],
    access: {
    read: () => true,
    update: isAdminFieldLevel,
    create: isAdminFieldLevel,
    },
    saveToJWT: true,
    hooks: {
    beforeChange: [protectRoles, enforceFacilitator],
    },
    validate (val, { data }) {
    // If the user has a role that requires an organization, but they don't have one, throw an error.
    if (!val) {
    return 'You are not logged in';
    }

    if (val.includes('organizationManager')

    val.includes('organizationMember')) {


    console.log('here');


    console.log(data);


    return 'The Organization Manager and Organization Member roles are not assignable manually. Please assign user as manager or member of an organization.';


    }


    ...


    },

    And this is what the hook that alters the role looks like:

    export const manageManagerRole: FieldHook = async ({ data, previousDoc }) => {


    // If no updates in the manager field, return


    if (!data || !previousDoc) {


    return;


    }



    // if no updated managers, return


    if (


    data?.managers?.length === previousDoc?.managers?.length &&


    data.managers.every((manager, index) => manager === previousDoc.managers[index])


    ) {


    return;


    }



    const newManagers = data?.managers.filter(manager => !previousDoc?.managers.includes(manager));


    const removedManagers = previousDoc?.managers.filter(manager => !data?.managers.includes(manager));



    // Add the organization manager role to the new managers


    for (const manager of newManagers) {


    const user = await payload.findByID({


    collection: 'users',


    id: manager,


    depth: 0,


    });



    if (user?.roles.includes('organizationManager')) {


    continue;


    }



    const newRoles = user?.roles.concat('organizationManager');



    await payload.update({


    collection: 'users',


    id: manager,


    data: {


    roles: newRoles,


    },


    });


    }



    // Remove the organization manager role from the removed managers


    for (const manager of removedManagers) {


    const user = await payload.findByID({


    collection: 'users',


    id: manager,


    depth: 0,


    });



    if (!user?.roles.includes('organizationManager')) {


    continue;


    }



    // Generate new roles list without organizationManager


    const newRoles = user?.roles.filter(role => role !== 'organizationManager');



    await payload.update({


    collection: 'users',


    id: manager,


    data: {


    roles: newRoles,


    },


    });


    }


    }`



    Just pinging to ask if there is a solution. The code works fine as is currnetly, but typescript keeps complaining;



    Since I don't have the roles organizationManager in the options of roles

    image.png
  • default discord avatar
    notchr
    last month

    @shisue What is the type of user.roles?



    it should just be string[] right?

  • default discord avatar
    shisue
    last month

    Its a select



    Because even though I Want to have some assigned automatically like manager, others are manually assigned through a dropdown or simple update calls

  • default discord avatar
    notchr
    last month

    @shisue Just as a side though, is it possible to use

    https://payloadcms.com/docs/fields/relationship


    With hasmany



    That way you could create a collection type for the roles



    not sure if that's a solution or not

  • discord user avatar
    jarrod_not_jared
    Payload Team
    last month

    I would keep all options in the select field. Then I would either render a custom component if the issue you want to avoid is the visual part where they can "select" an incorrect role.



    I would pair that with a beforeChange hook that looks at their current role and the role they are attempting to set and then allow the change to go through if you deem it ok, else just keep the set of roles that they currently have.



    @notchr it creates an enum, so its not string[], the only valid opitons are the ones set on the select field



    @shisue Here is a video on how to create a custom select field!

    https://www.youtube.com/watch?v=Efn9OxSjA6Y
  • default discord avatar
    shisue
    last month

    Thanks!



    Just a quick follow-up, but would you be able to help me with setting up jest?

Open the post
Continue the discussion in Discord
Like what we're doing?
Star us on GitHub!

Star

Connect with the Payload Community on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.