Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can :create, Model with association conditions and validations #870

Closed
newfylox opened this issue Sep 26, 2024 · 2 comments
Closed

can :create, Model with association conditions and validations #870

newfylox opened this issue Sep 26, 2024 · 2 comments

Comments

@newfylox
Copy link

newfylox commented Sep 26, 2024

I don't know if it's a bug, a missing documentation or if it's not a cancancan concern but here is what I'm trying to achieve.

Let's say that I own markets and I'm trying to create a product with a tag

class Market < ApplicationRecord
  has_many :products
end

class Tag < ApplicationRecord
  has_many :products
end

class Product < ApplicationRecord
  belongs_to :tag
  belongs_to :product
end

Now in my ability.rb, I want to create a Product that my user owns the Tag and the Market, something like that

# market_ids = Market.query.pluck(:id) that I own and can read
# tag_ids = Tag.query.pluck(:id) that I own and can read
can [:create], Product, market_id: market_ids, tag_id: tag_ids # here is my situation

Now the problem is this one. My frontend uses server-validation. Which means that if I submit the creation of a product without choosing a market OR a tag, I'm expecting to have a validation error that tells my market OR tag is blank, that it cannot be empty. But cancancan said I'm not authorized because one of them is nil and I passed an array of ids for conditions.

If I'm including a nil value inside of each array (tags and markets), cancancan will allow the creation of a product with empty tag and market, which I don't want to allow. So I want the user to create a product ONLY with those ids (tags and markets) BUT I also want the validation the be hit (validate :presence, :tag for example) BEFORE cancancan authorize the thing.

Is it possible?

I tried to do this

can [:create], Product
can [:create], Product, market_id: market_ids, tag_id: tag_ids

but the thing is that it's a OR ability, not a AND in order. So it validates when my tag or market is empty, but then after by hijacking my frontend, I can create a product with tags and markets that my user doesn't have the rights to read.

@luke-zhou
Copy link

Not sure I understand your senario correctly, but I think if you really want to hit model validation before cancancan,what you can do is:

@product = Product.new(product_params)
if @product.valid?
	authorize! :create, @product
	@product.save!
else
	# Return validation errors
	render json: { errors: @product.errors.full_messages }, status: :unprocessable_entity
end

@newfylox newfylox closed this as completed Oct 7, 2024
@newfylox newfylox reopened this Oct 7, 2024
@newfylox
Copy link
Author

newfylox commented Oct 7, 2024

Not sure I understand your senario correctly, but I think if you really want to hit model validation before cancancan,what you can do is:

@product = Product.new(product_params)
if @product.valid?
	authorize! :create, @product
	@product.save!
else
	# Return validation errors
	render json: { errors: @product.errors.full_messages }, status: :unprocessable_entity
end

Yeah you understood correctly and yes your idea could work for us, thanks!

@newfylox newfylox closed this as completed Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants