Fixed detection of UnscopedFind if optional: true is defined in the model and is not self-reference association#1764
Conversation
|
@presidentbeef |
|
I'm not sure I understand the intent here. If the relationship is optional, wouldn't you have legitimate cases where the application can't look up a model via the relationship..? In other words, is this change just as likely to increase false positives as it is to decrease false negatives? |
|
The first example I gave was a little confusing, so I will give an example that is similar to the problem we encountered. class User < ApplicationRecord
end
class Organization < ApplicationRecord
has_many :members, dependent: :destroy
has_many :users, dependent: :destroy
end
class Member < ApplicationRecord
belongs_to :user
belongs_to :organization
has_many :articles, dependent: :destroy
end
class Article < ApplicationRecord
belongs_to :author, class_name: "User", foreign_key: "author_id", optional: true
belongs_to :organization
end
# Bad
artciles = Article.find(params[:id])
# Good
organization = Organization.first
articles = organization.articles.find(params[:id])I expected brakeman to detect that the Article was not being retrieved via an Organization instance, but it did not because the Article model already defines optional: true for the User. |
| def self_referential_association? exp, name | ||
| return false unless exp.is_a? Array | ||
|
|
||
| exp.each do |e| |
There was a problem hiding this comment.
I think what we actually want is to check if there is any belongs_to relationship that is not optional?
Is the self-referential piece actually that important?
| exp.each do |e| | ||
| if hash? e and true? hash_access(e, :optional) | ||
| return true | ||
| hash_iterate e do |key, value| |
There was a problem hiding this comment.
Is class_name going to show up more than once as a key? Couldn't this also use hash_access(:class_name) instead of iterating?
|
@NerdyBoyCool I’m interested in this PR and can address the remaining items. Would it be alright if I took it over? |
|
@willnet |
ref #1139
ref #1153
The change in #1153 avoids checking UnscopedFind for model classes with optional: true settings, but I think UnscopedFind warning should be issued for the following cases.
The current code only checks if optional: true is defined in the model class, so the check for the Group model is skipped.
This PR solves this problem by also checking self-reference associations.
We have also added implementation and testing for the issues mentioned in #1139 so that they are not affected.