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

Support Rails's attribute in Cancancan's permitted_attributes #838

Closed
kalsan opened this issue Nov 30, 2023 · 1 comment
Closed

Support Rails's attribute in Cancancan's permitted_attributes #838

kalsan opened this issue Nov 30, 2023 · 1 comment

Comments

@kalsan
Copy link
Contributor

kalsan commented Nov 30, 2023

TLDR: Cancancan does not "see" non-database backed attributes, so they are missing in permitted_attributes.

Steps to reproduce

Rails 7.1.2 application with a basic user model with the database fields email and password_digest, with the important parts from the model being:

class User < ApplicationRecord

has_secure_password

With the god-ability:

class Ability
  include CanCan::Ability

  attr_reader :user

  def initialize(user)
    return if user.blank?

    can :manage, :all
  end
end

Now run: Ability.new(User.first).permitted_attributes(:edit, User.first)

Expected behavior

[:email, :password_digest, :password, :password_confirmation]

Actual behavior

[:email, :password_digest]

-> Cancancan misses out on the password attributes. The same problem can be reproduced by using Rail's attribute method, i.e.

class MyModel < ApplicationRecord
  attribute :foo # Cancancan will miss this
end

System configuration

Rails version: 7.1.2

Ruby version: 3.2.2

CanCanCan version 3.4.0

I guess this also interferes with other Gems such as active_type or any custom accessor logic using virtual fields using attribute.

I hope the examples above are useful to you. Let me know if I can help you enlighten this further.

Best,
Kalsan

@kalsan
Copy link
Contributor Author

kalsan commented Dec 1, 2023

I have created pull request #839 to address this. This pull request fixes the core issue where cancancan misses attribute :foo in general.

Rail's method has_secure_password is still missed, because for some reason, Rails does not declare an explicit attribute for password and password_confirmation. I don't think there is a simple way to detect those (and hardcoding a search for those two methods is likely a terrible idea), so I'd suggest mentionning in the documentation that for this particular case, cancancan can be brought to "see" the extra attributes by typing:

class User < ApplicationRecord
  has_secure_password
  attribute :password # perhaps, add additional arguments such as the type (string)
  attribute :password_confirmation # as above
end

Looking forward to hear what you think :-)

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

1 participant