Conditions For Collection over-ridden by search params

10 views
Skip to first unread message

Dennis Bulgatz

unread,
Feb 28, 2022, 4:41:00 PM2/28/22
to ActiveScaffold : Ruby on Rails Gem
Hello,

I am using the "conditions for collection" method in the controller to add sql for security trimming.  This works fine for a straight list, but when a user runs a search, it appears that the search form, which has some of the same params used for security trimming, will override the security settings in the conditions for collection method.

A few specific questions:
1.  How can I log the sql statement used to get results for a search?  Is there some method in the controller that is run last that I could put a Logger.Info statement to get an FinderMethods.to_sql ?
2.  Is there any way to set a priority on the "conditions for collections" to override search params?
3.  Does it matter if the "conditions for collection" is a sql string, vs an array or hash?

I could use logic to better generate a search form that is essentially security trimmed, but will be tough, and would like to better understand how the "where" clauses in the conditions for collection are merged with the search where clauses.

Thanks!

Dennis

Sergio Cambra

unread,
Mar 1, 2022, 10:11:25 AM3/1/22
to ActiveScaffold : Ruby on Rails Gem, 'Dennis Bulgatz' via ActiveScaffold : Ruby on Rails Gem

El lunes, 28 de febrero de 2022 22:41:00 (CET) 'Dennis Bulgatz' via ActiveScaffold : Ruby on Rails Gem escribió:

> Hello,

>

> I am using the "conditions for collection" method in the controller to add

> sql for security trimming.  This works fine for a straight list, but when a

> user runs a search, it appears that the search form, which has some of the

> same params used for security trimming, will override the security settings

> in the conditions for collection method.


The method building the query is find_page, it gets options for query calling finder_options, which return a hash, and then build the query passing those options to append_to_query method. The hash returned by finder_options has :conditions key with the value returned by all_conditions, this method collect conditions returned by several methods, including conditions_for_collection and active_scaffold_conditions (the conditions from search params):


    def all_conditions(include_id_condition = true)

      [

        (id_condition if include_id_condition),       # for list with id (e.g. /users/:id/index)

        active_scaffold_conditions,                   # from the search modules

        conditions_for_collection,                    # from the dev

        conditions_from_params,                       # from the parameters (e.g. /users/list?first_name=Fred)

        conditions_from_constraints,                  # from any constraints (embedded scaffolds)

        active_scaffold_embedded_conditions           # embedding conditions (weaker constraints)

      ].reject(&:blank?)

    end



>

> A few specific questions:

> 1.  How can I *log* the sql statement used to get results for a search?  Is

> there some method in the controller that is run last that I could put a

> Logger.Info statement to get an FinderMethods.to_sql ?


You can override find_page, call super to get the page and use it to call .to_sql on items:


def find_page(*)

  super.tap do |page|

    logger.info page.items.to_sql

  end

end


Or override do_list, call super and log @records.to_sql, @records is @page.items:


def do_list

  super

  logger.info @records.to_sql

end


> 2.  Is there any way to set a priority on the "conditions for collections"

> to override search params?


It shouldn't be needed, FieldSearch and Search modules have do_search action, which builds conditions for search params, and add them to active_scaffold_conditions which keeps an array in the variable @active_scaffold_conditions:


    def active_scaffold_conditions

      @active_scaffold_conditions ||= []

    end


And all_conditions method collects result both from active_scaffold_conditions and conditions_for_collection, so both conditions should be present in the query. I have tested now and I can see both conditions in the SQL query.


You can debug the value returned by all_conditions method, or finder_options method:


def all_conditions(*)

  super.tap do |conditions|

    logger.info conditions.inspect

  end

end

 

def finder_options(*)

  super.tap do |options|

    logger.info options.inspect

  end

end


> 3.  Does it matter if the "conditions for collection" is a sql string, vs

> an array or hash?


Append_to_query will call apply_conditions, which loops over array, it will call where with each item if item is hash, string, or array where first element is string, so every value is valid, any of these would work:


{column1: value1, column2: value2}

['column1 = ? and column2 = ?', value1, value2]

'column1 = 0'


I think an array combining hashes, sql strings, or array with sql string and values would work too, if first item is not string.


    def apply_conditions(relation, *conditions)

      conditions.reject(&:blank?).inject(relation) do |rel, condition|

        if condition.is_a?(Array) && !condition.first.is_a?(String) # multiple conditions

          apply_conditions(rel, *condition)

        else

          rel.where(condition)

        end

      end

    end

Reply all
Reply to author
Forward
0 new messages