Add logged in user ID to foreign key field automatically in KeystoneJS

52 Views Asked by At

I'm creating an application in KeystoneJS with the documentation provided for that framework. So, in my application, there are 2 tables, one is user and the other one is post. So, I would like to know, when I'm creating a post by logging into the admin area, there is a field with the foreign key column and that field is empty to fill the foreign key values coming from the user table. So, I want the system to add foreign key value to author automatically when I'm creating a new post with the id of logged in user in KeystoneJS.

So, I looked for everywhere to find a solution for this and I failed to find a proper solution for this.

If anyone have any idea about this, please reply this question and it would be appreciate a lot.

Thank you

1

There are 1 best solutions below

1
On

Have you looked at the moderated blog example?

It has lists similar to your project: Posts and Users, that can be Contributors or Moderators. The contributor/moderator distinction doesn't matter much in your case, the part you'll be interested in are the hooks on the Post list, specifically the resolveInput.create hook, which looks like this:

hooks: {
  resolveInput: {
    create: ({ context, resolvedData }) => {
      resolvedData.createdAt = new Date();
      if (context.session?.contributor) {
        return {
          ...resolvedData,
          createdBy: {
            connect: {
              id: context.session?.contributor?.id,
            },
          },
        };
      }
      return resolvedData;
    },
  },
  // Other hooks...
},

As per the docs:

The resolveInput function is used to modify or augment the data values passed in to a create or update operation.

So this is our chance to change values before they're saved, including populating or enforcing values like your Post.author field.

resolveInput gets the context object, which includes a reference to the session object. The contents of this object is determine by your session store functions but usually contains info about the current user. In this example, if the user signed in is a contributor, we get their contributor Id from context.session?.contributor?.id and save it to the createdBy field. The createdAt field is also set to the current date and time.

Note that, because this hook is configured at the list level, data for the whole item should be returned (basically, the resolvedData object with any additional changes the hook wants to make). Another way to do this would be to add resolvedData functions at the field level but then we'd need two separate functions - one for createdAt and another for createdBy – each of which would return a single value. See the hooks guide for more on this distinction.

Also, its important not to conflate hooks with access control – ie. whether a contributor should be allowed to create a post in the first place. In this example access control is configured separately, up in the list access config, as it should be.

One final note – at the time of writing the hook API docs cover the resolveInput hook (at the list and field levels), but don't break it down into the different operations (ie. resolveInput.create and resolveInput.update). This is just a recent syntactic improvement, it doesn't change anything fundamental about how hooks are to be used. If using just the documented API, the code above could be written as:

hooks: {
  resolveInput: ({ operation, context, resolvedData }) => {
    // Only run for create operations (so ignore updates)
    if (operation !== 'create') return resolvedData;
    resolvedData.createdAt = new Date();
    if (context.session?.contributor) {
      return {
        ...resolvedData,
        createdBy: {
          connect: {
            id: context.session?.contributor?.id,
          },
        },
      };
    }
    return resolvedData;
  },
  // Other hooks...
},