Restrict allowable Ecto associations to matching owners

Lets say we have a Product schema and a Category schema, which both have a belongs_to User association. A Product also has a belongs_to Category association.

Users can create Products as well as Categories. When creating or updating a Product, the user can submit a category_id. I want to only allow a user to associate their products with their categories. If a user discovered the ID of another user’s category, they shouldn’t be able to forge a request to associate their product with that other user’s category.

Approaches that I can think of:

  1. In the Product context, within the create_product and update_product functions, make a Repo query to get the referenced category_id with a WHERE clause of catgeories.user_id == current_user_id. If this returns nil, add an error to the changeset.

  2. In the Product schema, make calls out to Repo (like above, but within the schema file instead of the context).

  3. Some kind of database constraint, though my research suggests that Postgres constrains can’t reference other tables.

Ideally I’d like to have this validation logic live inside the schema file, alongside the other validations.

Can anyone suggest a nice approach to this authorization/validation problem?

When I’ve needed to do similar I’ve done option 2 on your list just to keep the rules all in one place. Only run the query when the category_id changes though or you’ll be running a lot of unneeded selects.

1 Like