Strapi Permissions - Admin vs Site Users - How to assign ownership of items?

System Information
  • Strapi Version: 3.2.4
  • Operating System: macOS
  • Database: mysql 5.7
  • Node Version: v12.18.4
  • NPM Version: 7.0.10
  • Yarn Version: 1.22.10 (not using)

Hi, I’m really struggling with Strapi collection / item ownership and how to set the permissions of things via controllers. I posted a thread last week and nobody commented on it… it’s a very difficult to google problem so I’m back here explaining the problem hoping someone understands it and can help.

Problem: I can’t set record ownership from controllers / services.

I want to 1: Have an API only user log in via the API, and then when they create a record, I want to take their JWT / token / user-id from the request and use that to set ownership of the record they created.

I want to 2: Have the API only request user only things they have created

While researching this today I found an article that breaks down the difference between admin users and end-users / website users.

The problem(s) I have right now is:

  1. I can only assign ownership of records to admin users… admins can create records and their ownership shows up correct in Admin and API responses
  2. I can’t assign ownership from within the controllers / services, even if I specify valid ID values. The ORM strips out the created_by values / does nothing with it. (see previous forum post)
  3. Strapi has no documentation on how to deal with the seperation of admin users and regular users

This is a well intentioned feature of Strapi that is a complete nightmare for me right now. There is a smug proudness to this article that is completely infuriating. It’s fine to make things more modular, but it’s insane to take away valid features / workflows in favor of forcing your own weird concept of users on others. At the very least provide documentation on how to turn the feature off or how to unify the two sets of users.

I’m stuck in this horrible logic loop where only admin users can own things, but only web users can log in so how do I make ownership / assignment to items created by API users work?!

PLEASE HELP… I’m failing to understand something here and it’s causing me to stress instead of working smart and efficiently.

2 Likes

Thanks for exploring this. I only just realised this myself, and upon searching, your posts came up. Would love to hear from the Strapi team how to resolve this as well.

To add the salient points from the other post, the unsatisfying short-term solution to this problem for me is to add my own createdBy field to my model using a relation on user-permissions (users), and then update my controller functions to use that field for filtering.

  async create(ctx) {

    let newCampaign = ctx.request.body;

    newCampaign.createdBy = ctx.state.user.id; //not using strapi built-in

    newCampaign.created_by = ctx.state.user.id // strapi will ignore this, strip it out and throw it away

    let entity = await strapi.services.campaign.create(newCampaign);
    return sanitizeEntity(entity, { model: strapi.models.campaign });
  },

Here is how you would take advantage of that in the find:

  async find (ctx){

  let entities;
  
  if(ctx.query.createdBy) delete ctx.query.createdBy;
  ctx.query.createdBy = ctx.state.user.id.toString();

  if (ctx.query._q) entities = await strapi.services.campaign.search(ctx.query);
  else  entities = await strapi.services.campaign.find(ctx.query);

  const campaigns = entities.map((entity) => {
    //TODO: Find better way to provide this data
    entity.participantCount = entity.participants.length;
    return sanitizeEntity(entity, { model: strapi.models.campaign });
  });
    
  return campaigns;      

  },

Because the user / API session isn’t available in the lifecycle model functions… you are forced to then override the default & create your own model.create() function(s)… which in my opinion defeats the entire purpose of using Strapi to take advantage of its auto-generated CRUD etc.

I really wish I could use the awesome strapi permissions system related to admins on the end-users… in fact I was explicitly planning on doing this for my current project and now I’m seriously stuck not sure what to do.

While I write this post I’m considering writing my own middleware / authentication that looks at the strapi-administrator table instead of users. If that works I’ll update here.

I really can’t stress enough the negative impact of this “feature” (separate admin & users). I like Strapi a lot and I want the project to succeed. I wish someone on the project leadership would consider that this feature is not a positive, and in fact is a huge negative for many organizations considering Strapi. I think it will negatively impact adoption of the platform when someone get 2 months into building something and realizes a seemingly available feature has been made functionally useless.

To provide some context, we are building an MVP API system, and we have a functional demo we have been doing for investors. We are at a point where we would like to set up a few different accounts we can demo with for different market segments. The “easy” feature request of "only let API users see stuff they have created" has led me down this seemingly bottomless rabbit hole.

The problem is API users can create stuff, but you can’t assign ownership to them. The reasons for this are unclear. One of the solutions to this would be letting Admin users authenticate via the API… since the built in mechanisms for ownership DO function for admin panel users. This would let more granular access control for API users be accomplished via the built in Admin panel permissions.

I know Strapi is capable of all this, it’s just a matter of figuring out how. I’m sorry for the frustrated tone in my post, I hope the information within is constructive and can help other orgs who want to build SaaS products w/Strapi.

Strapi’s Admin package and users-permissions plugin are two different things. Created_by is a feature used only by the Admin package for Permissions. If you overwrite it with the user from user-permissions, you can lose access to your own Admin data. Because user from user-permissions doesn’t exist in Admin users and they are not related to each other. Please do not mix them. That’s a bad practice.

To obtain creator, author features with the user-permissions plugin, take a look at the documentation, there you have an example of how to achieve this feature in a few seconds (if you type fast):

Before building serious SaaS products, I would recommend reading the whole documentation and examples provided by Strapi to be sure that you understand how all the things work. Otherwise, you will not take full advantage from the strapi. When I started my first project with strapi, I didn’t read even 5% of the docs, and I was so frustrated that things don’t work as I expected. Then I paused my project for a week to study the whole documentation and read some extra tutorials and blogs. After that, I finished my project in less than a week.

1 Like

OSS gets a bad rap not just because of experts being short with beginners, but also beginners being lazy and not reading up on the material. Learning is messy, I’m messy. What can I say but thanks for politely saying I need to read more docs. :slight_smile:

I agree with your sentiment, I think part of why I was so frustrated it it seemed like the tool could do what I wanted but I wasn’t figuring it out.

Created_by is a feature used only by the Admin package for Permissions.

This is helpful to understand. Would it be possible to create a plugin that added this functionality to models so I could keep my app more DRY? Ideally I would like to avoid duplicating this same logic in multiple controllers. I’m trying to understand the Strapi way to accomplish what I want.

The built in admin level created_by field is so attractive for my use case in part because it already works as expected… just with the wrong pool of users. The fact that it’s also integrated with datetimes for created / updated is also nice.

A way to assign creating/editing attribution / for model records created by API users is what I’m after. I think the strapi model is that admins are creating content on blogs… in our use case we are building a SaaS product and every “user” (user-permissions) is an API client consuming our API, making requests to add records and have us “do stuff” for them like an API does. As the API scales its important that not only the primary records the users are creating are attributed, but also the secondaries because the Strapi CRUD that gets generated is not going to be aware of this ownership.

As an example because I have to manually add all this ownership stuff, if I’m building some sort of School app you can consider a data model with Teachers, Classes and Students. Because I have to manually code up the constraints around only showing each Teacher the Classes they have access too, some nefarious person might be able to use the built in Strapi routes to get lists of students.

I know its been a while but this post helped me to add owner/createdBy functionality.

1 Like

This is a dead link. Is there an alternative location?