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

fix: search association field by type and id #3230

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/components/avo/base_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class Avo::BaseComponent < ViewComponent::Base
extend Literal::Properties
include Turbo::FramesHelper
include Avo::Concerns::FindAssociationField

def has_with_trial(ability)
Avo.license.has_with_trial(ability)
Expand All @@ -12,8 +13,7 @@ def has_with_trial(ability)

# Use the @parent_resource to fetch the field using the @reflection name.
def field
reflection_name = params[:related_name]&.to_sym || @reflection.name
@parent_resource.get_field(reflection_name)
find_association_field(resource: @parent_resource, association: params[:related_name]&.to_sym || @reflection.name)
rescue
nil
end
Expand Down
12 changes: 8 additions & 4 deletions app/controllers/avo/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ApplicationController < ::ActionController::Base
include Avo::ApplicationHelper
include Avo::UrlHelpers
include Avo::Concerns::Breadcrumbs
include Avo::Concerns::FindAssociationField

protect_from_forgery with: :exception
around_action :set_avo_locale
Expand Down Expand Up @@ -83,13 +84,16 @@ def resource
Avo.resource_manager.get_resource_by_controller_name @resource_name
end

def association_from_params
params[:for_attribute] || params[:related_name]
end

def related_resource
# Find the field from the parent resource
field = @resource.get_field params[:related_name]
reflection = @record.class.reflect_on_association(association_from_params)

return field.use_resource if field&.use_resource.present?
field = find_association_field(resource: @resource, association: association_from_params, type: reflection.macro)

reflection = @record.class.reflect_on_association(field&.for_attribute || params[:related_name])
return field.use_resource if field&.use_resource.present?

reflected_model = reflection.klass

Expand Down
10 changes: 3 additions & 7 deletions app/controllers/avo/associations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
before_action :set_related_resource_name
before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy]
before_action :set_related_authorization
before_action :set_reflection
before_action :set_reflection_field
before_action :set_related_record, only: [:show]
before_action :set_reflection
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy]
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy]
before_action :set_attachment_record, only: [:create, :destroy]
Expand All @@ -25,8 +25,8 @@
@parent_record = @parent_resource.find_record(params[:id], params: params)
@parent_resource.hydrate(record: @parent_record)
association_name = BaseResource.valid_association_name(@parent_record, association_from_params)
@query = @related_authorization.apply_policy @parent_record.send(association_name)

Check failure

Code scanning / CodeQL

Code injection Critical

This code execution depends on a
user-provided value
.
This code execution depends on a
user-provided value
.
@association_field = @parent_resource.get_field params[:related_name]
@association_field = find_association_field(resource: @parent_resource, association: params[:related_name])

if @association_field.present? && @association_field.scope.present?
@query = Avo::ExecutionContext.new(target: @association_field.scope, query: @query, parent: @parent_record).handle
Expand Down Expand Up @@ -126,7 +126,7 @@
end

def set_reflection_field
@field = @resource.get_field(@related_resource_name.to_sym)
@field = find_association_field(resource: @resource, association: @related_resource_name.to_sym, type: @reflection.macro)
@field.hydrate(resource: @resource, record: @record, view: Avo::ViewInquirer.new(:new))
rescue
end
Expand Down Expand Up @@ -171,10 +171,6 @@
end
end

def association_from_params
@field&.for_attribute || params[:related_name]
end

def source_foreign_key
@reflection.source_reflection.foreign_key
end
Expand Down
17 changes: 17 additions & 0 deletions lib/avo/concerns/find_association_field.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Avo
module Concerns
module FindAssociationField
def find_association_field(resource:, association: nil, type: nil)
if params[:turbo_frame]&.starts_with?("has_") || type.present?
type ||= params[:turbo_frame][/.*(?=_field)/]
Dismissed Show dismissed Hide dismissed

resource.get_field_definitions.find do |field|
(field.id == association.to_sym) && (field.type == type.to_s)
end
else
resource.get_field association
end
end
end
end
end
4 changes: 4 additions & 0 deletions spec/dummy/app/avo/resources/store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def fields
field :location, as: :has_one
end

field :patrons, as: :tags do # , hide_on: [:show, :forms] do
record.patrons.map(&:name)
end

field :patrons,
as: :has_many,
through: :patronships,
Expand Down
Loading