2017-11-29 5 views
0

brakeman gem(Ruby on Railsコードで考えられるセキュリティ上の問題を識別する)を扱っています。私たちはjoin、group、selectを使うスコープを持っており、クエリの選択部分を更新する必要があります。このスコープは以下のようになります。私はここにスコープの内容を製品モデルに入れています。今rails(QueryMethods)のSQL selectクエリに日付パラメータを渡す

Product.joins('LEFT JOIN orders ON orders.product_id = products.id') 
    .group('products.id') 
    .select(
    "SUM(CASE WHEN orders.order_at BETWEEN '#{start_date}' AND '#{end_date}'" \ 
    " THEN orders.qty ELSE 0 END) as qty, products.*" 
) 

は、私はそれが私に私は、グループとなるといくつかの他の方法を試してみましたが、それはのために働いていなかった?を持っている構文エラーが発生します。この

Product.joins('LEFT JOIN orders ON orders.product_id = products.id') 
    .group('products.id') 
    .select(
    "SUM(CASE WHEN orders.order_at BETWEEN ? AND ?" \ 
    " THEN orders.qty ELSE 0 END) as qty, products.*", 
    '#{start_date}', 
    '#{end_date}' 
) 

のようにクエリを変更しようとした場合私。私はレールでPostgreSQLを使用しています4.1.8
私はこれを達成することができますか?前もって感謝します。

これはエラー

PG::SyntaxError: ERROR: syntax error at or near "?"
LINE 1: SELECT SUM(CASE WHEN orders.order_at BETWEEN ? AND ? AND ord

+0

何の十分な情報はありません。また、[ここ](https://stackoverflow.com/questions/47531438/i-want-to-use-query-in-rails-just-like/47531725#47531725)にも同様の無人質問があります。 –

答えて

0

であるあなたは?構文を使用する権利だが、selectへの通話は、その一部がintead whereへの呼び出しに出て分割必要があります。

また、日付を文字列に変換しています(たとえば、'#{start_date}')。これにより、呼び出されたメソッドが日付を値として扱い、フォーマットすることができなくなります。代わりに、生の日付(例:start_date)を渡してください。

Product 
    .joins('LEFT JOIN orders ON orders.product_id = products.id') 
    .where('orders.order_at BETWEEN ? AND ?', start_date, end_date) 
    .select("SUM(orders.qty) as qty, products.*") 
    .group('products.id') 

またdaino3の回答(.where(orders: {order_at: start_date..end_date}))に基づいてwhereコールをやり直すことができます。

推論

それはwhere(または関連)でパラメータを直接埋め込むないことが重要です呼び出します。リモートユーザーが任意の文字列のデータを入力して、すべての危険な呼び出しをデータベースで実行する可能性があるため、コードをSQL Injectionという大きなセキュリティリスクまで開きます。

だからこそ、where("various sql things #{parameter}")の代わりに​​を実行する必要があります。

このようなRailsのSQL呼び出しにパラメータを渡す件については、official Rails Guide on the Active Record Query Interfaceを参照してください。

+0

'総計、商品。*、 '2017-11-28 05:00:00.000000'、 '2017-11-29 04:00、00000000'のようにSUMを選択すると(SUMの場合はorder.order_atの間に?then?orders.qty ELSE 0 END) 59:59.999999 'FROM "products" LEFT JOIN注文はorders.product_id = products.id GROUP BY products.id' これは生成されたもので、同じエラーがあります。おもう ?日付に置き換えられるべきではありませんが、私は理由を知らないのです。 – Manishh

+0

これは普通正しいことですが、残念なことに 'select'メソッドはパラメータを受け取りません。そのため、文字列に埋め込む前に自分でサニタイズするか、クエリを構築する別の方法を見つける必要があります。 @ dainoの答えがどのように表示されるか)。 –

+0

ああ、そうです - 'select'の代わりに' where'を使ってそれを修正するべきです。 –

1

私はあなたにもWHERE句でCASE文を取り除くことができると信じて:

checkout range conditions

Product 
    .joins('LEFT JOIN orders ON orders.product_id = products.id') 
    .where(orders: {order_at: start_date..end_date}) # range condition 
    .group('products.id') 
    .select("SUM(orders.qty) as qty, products.*")