Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Ensuring the first user's role can't be changed

default discord avatar
ratiu52 years ago
14

I need some new ideas. I'm currently getting this error:


 ⨯ APIError: The collection with slug users can't be found. Find Operation.
    at isFirstUser (./src/lib/payload/is-first-user.ts:11:74)
    at hasAdminAccessButNotFirstUser (./src/lib/payload/access.ts:23:123)
    at async Promise.all (index 1)
    at async Promise.all (index 0)

The code with the error:


import { User } from '@/payload-types'
import payload from 'payload'

export default async function isFirstUser(id: User['id'] | undefined) {
  if (!id) {
    return false
  }
  const result = await payload.find({
    collection: 'users',
    depth: 1,
    page: 1,
    limit: 1,
    pagination: false,
    sort: '+id',
  })
  if (result.docs[0].id === id) {
    return true
  }
  return false
}

Again, my goal is to ensure the first user's role can't be changed.


This isn't working because at the first time an account is created, the slugs/database must not be setup yet. Is what I'm asking possible in Payload? I'd hope so.

  • default discord avatar
    paulpopus2 years ago

    The first time an account is created, the database is setup, but the table is empty



    That's what should be happening at least

  • default discord avatar
    ratiu52 years ago

    Makes sense. Do you suggest going about this a different way? My goal is to prevent the first user's role being changed.

  • default discord avatar
    paulpopus2 years ago

    beforeChange hook, if operation is create and if no other users in the collection exist, i'd assert the role returning the data with a hardcoded value for roles



    alternatively, defaultValue on the role



    and then access.update being false for those conditions



    the latter sounds more pragmatic

  • default discord avatar
    ratiu52 years ago

    Ah hadn't considered those, thanks. I'll mess with those and see if I can get something working



    One more question, is there a built in way to access the toast api in payload? Say I want to show a toast whenever the user tries to change the first user's role, mostly for UX

  • default discord avatar
    paulpopus2 years ago

    so you wont need to do that



    if you set the access.update



    the form fields will be disabled

  • default discord avatar
    ratiu52 years ago

    ah



    So I got


    access: {
      create: hasAdminAccess,
      update: isAdminNotFirstUser, // the only place i'm using this fn
    },

    with the the following function:


    export const isAdminNotFirstUser: FieldAccess<{ id: string }, unknown, User> = async ({
      req: { user },
    }) => {
      const firstUser = await isFirstUser(user?.id)
      if (user?.role === 'admin') {
        if (firstUser) {
          return false
        }
        return true
      }
      return false
    }

    and I'm still getting the error previously. Is this a bug?



    Changing it back to

    hasAdminAccess

    from

    isAdminNotFirstUser

    causes the og error to disappear, but it still happens with that function

    isAdminNotFirstUser

    . Anyone have any ideas?



    I also tried it with what

    @858693520012476436

    mentioned with the

    beforeChange

    hook, I still get that error when using the

    isFirstUser

    function:


    else if (data.operation === 'update') {
        if (data.originalDoc) {
          if (await isFirstUser(data.originalDoc.id)) {
            return 'admin'
          }
        }
      }


    Oh, and there already exists one user, the admin. So I don't see why this error is occuring.

  • default discord avatar
    paulpopus2 years ago

    what does your isFirstUser function look like?



    pass it the

    req

    and then reuse the same

    req.payload
  • default discord avatar
    ratiu52 years ago
    export default async function isFirstUser(id: User['id'] | undefined) {
      if (!id) {
        return false
      }
      const result = await payload.find({
        collection: 'users',
        depth: 1,
        page: 1,
        limit: 1,
        pagination: false,
        sort: '+id',
      })
      if (result.docs[0].id === id) {
        return true
      }
      return false
    }


    Currently not passing in the

    req

    . I'll try it with the request.



    Update: Using the

    req

    prevents the error from occurring:


      const result = await req.payload.find({
        collection: 'users',
        depth: 1,
        page: 1,
        limit: 1,
        pagination: false,
        sort: '+id',
      })

    However, I can't seem to sort the results correctly. I've tried

    +id

    and

    -id

    , both times my first user appears last in the array of users (I'm accessing

    result.docs[0]

    ).



    I also changed the limit to 10, giving me all the current users (2) and even then the first user appars at the bottom.

  • default discord avatar
    paulpopus2 years ago

    not sure, maybe id is not a sortable field



    do you have createdAt?

  • default discord avatar
    ratiu52 years ago

    Tried

    +createdAt

    and

    -createdAt

    , still results in the first user pulled up last in the array of users.



    I would do a hacky solution and grab all the users and just select the last one, but I don't really like that solution

  • default discord avatar
    paulpopus2 years ago

    that's odd, maybe your createdAt isn't being set if timestamps aren't enabeld on the users, i'd check in the database to see if it exists



    but aside from that another solution here might be for you to have a flag on the first user



    a checkbox like

    isFirst

    or

    isRoot

    and then you query for it using

    where
  • default discord avatar
    ratiu52 years ago

    It appears in the result doc

  • default discord avatar
    paulpopus2 years ago

    so you always get only 1 user

  • default discord avatar
    ratiu52 years ago

    Ah that could work



    I'm going to mark this as resolved as the checkbox trick should work.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.