API: Only deliver content which was created by the requesting user

Dear all,

I am looking for a solution to only deliver the content which was created by the requesting user via the API.
I already had a look at “isOwner” to set the Owner of the content automatically (somehow I cannot do this via the API).

Let’s assume the following, I am having the following content for Articles:
Title;Description;Author
A-1;AD-1;A
A-2;AD-2;A
B-2;BD-1;B

So if user A calls the API for the Articles, only A-1 and A-2 should be delivered.
If user B does the same, only B-2.

Can this be done via an extension of the API for a certain endpoint?
Or can this be configured out of the box?

Yes you can do this with a little configuration.

There are a few steps to this.You need a relation creating on your article content type in your backend before any of this will work. This is your author field

This is how your articles will be associated with your users.

When you create your article via the API you need to set the author at the time of creation.

 async create(ctx) {
    const {id} = ctx.state.user; //ctx.state.user contains the current authenticated user

    const response = await super.create(ctx);
    const updatedResponse = await strapi.entityService
      .update('api::event.event', response.data.id, {data: {author: id}})
    return updatedResponse;
  },

You do this by overriding the create handler as above, replacing the api::event.event with your content type. eg api::article.article or whatever

That takes care of associating your article with your user when you create the article via the api.

For the data fetching side you can create a custom route.

module.exports = {
  routes: [
    {
      method: "GET",
      path: "/eventsme",
      handler: "event.me",
    }
  ]
}

so this would be hit when we make a get request to api/eventsme and it would send the request to the handler event.me for processing - which will be defined below in a minute. That’s the “me” handler in the event controller accessed via the endpoint /eventsme

'use strict';

/**
 *  event controller
 */

const {createCoreController} = require('@strapi/strapi').factories;

module.exports = createCoreController("api::event.event", ({strapi}) => ({
  async me(ctx, next) {
    const user = ctx.state.user // if we are using user account related JWT this is set.
                                // if we use backend generated tokens it isnt.
    strapi.log.debug(JSON.stringify(ctx.state));
    if (!user) {
      return ctx.badRequest(null, [{messages: [{id: "No auth header found"}]}])
    }

    const data = await strapi.entityService.findMany("api::event.event", {
      populate: ['image'],
      filters: {
        "author": {
          "id": user.id
        }
      },

    });
    if (!data) {
      return ctx.notFound();
    }

    const sanitizedEvents = await this.sanitizeOutput(data, ctx);

    return this.transformResponse(sanitizedEvents);
  },
  async create(ctx) {
    const {id} = ctx.state.user; //ctx.state.user contains the current authenticated user

    const response = await super.create(ctx);
    const updatedResponse = await strapi.entityService
      .update('api::event.event', response.data.id, {data: {author: id}})
    return updatedResponse;
  },

}));

Calling /api/eventsme that will then return only the articles (events in my case) created by the requesting author.

Hope that helps.

2 Likes

Thank you very much! This helped. The only change I did is that I overwrote the find and findOne core action, otherwise perfectly described by @smoaty