0

Here is my situation :

Items :

has_many :games

Users :

has_many :games

Games :

belongs_to :user
belongs_to :item

On my Item page i have a link to create a new game. How to get the item ID in a secure way ? Because in my database I need to store for 1 game the user_id and the item_id. For now, I'm doing this which store only the user_id automatically :

 def create
    @game = current_user.games.build(game_params)
    if @game.save
      redirect_to root_url
    else
      render 'pages/home'
    end
  end

  private

    def game_params
      params.require(:game).permit(:time, :score)
    end

I suppose that adding a game_params :item_id is not the right way and is not secure ?!


Here is the scenario wanted :

A user came to an item page, click on a button to create a game, when I record the game I want to be able to store the user_id (it's OK for this part) and the item_id without any more user interaction. I don't want him to choose "manually" I want to "force it" (thanks to the item page where he comes from)

In a perfect world I would like to :

  • retrieve every games from one user with something like current_user.games

  • retrieve every games from one item with something like item_id.games

ZazOufUmI
  • 3,212
  • 6
  • 37
  • 67
  • 1
    "Security" is handled server-side. You need to pass in the ID of the related record, and then check whether the current user is authorized to perform the given action on it. – user229044 Sep 16 '14 at 20:44
  • How do you pass the item_id ? Through URL ? And if so, the user can change the URL. Thanks – ZazOufUmI Sep 16 '14 at 20:46
  • What is an `Item` in this case? You would not pass it through the URL it should be passed through the `POST` request. Then validated appropriately in case someone alters their request. Without more information it is hard to help other than to `permit` `item_id` – engineersmnky Sep 16 '14 at 20:49
  • `Item` is just a basic item with an ID, a name, description, etc... Do you have an example of an item ID passed through a POST request ? Today I create a game thanks to a button on the item list. This button redirect the user to the game/new page. Thanks – ZazOufUmI Sep 16 '14 at 20:52
  • `create` is a `POST` route unless you modified it otherwise. You just need to add a field for the user to select an "Item" to this form but without seeing things like your view, model, etc. I cannot really help. Why does a `Game` need an `Item`? – engineersmnky Sep 16 '14 at 20:55
  • Yes, use the URL. You probably want a nested resource. It doesn't matter if the use can change the URL because, as I said, it's your job to authorize the user and ensure they have access to whatever record they're trying to use. – user229044 Sep 16 '14 at 21:01
  • @engineersmnky & meagar I update my post to add a scenario, hopes this will help you to understand my request. – ZazOufUmI Sep 16 '14 at 21:05

2 Answers2

0

in your item page use:

new_form_path(item_id: @item.id)

instead of:

new_form_path

in your game form:

= form_for @game do |f|
  = f.hidden_field :item_id, value: params[:item_id]

in your game controller:

params.require(:game).permit(:time, :score, :item_id)

There are many ways to do what you want, this is one of them.

sites
  • 21,417
  • 17
  • 87
  • 146
  • Thank you @juanpastas for your answer. With this method, is the user be able to modify the item_id via web browser or all those operations are made in server side ? – ZazOufUmI Sep 17 '14 at 06:14
  • that's another part, you need to validate which users are allowed to create which games, this logic would make sense in game model. but you have not specified any condition, for example: user is only able to create games for items that... – sites Sep 17 '14 at 15:55
  • note although client can modify item id from browser, you actually want that since user clicks create game in an item page, meaning: user will do set item id preliminarily. – sites Sep 17 '14 at 15:58
0

I think this is what you are looking for

<%= button_to "New Game", {controller: 'games', action: 'create'}, params:{item_id: item.id} %>

this will generate html like

<form method="post" action="/games/create" class="button_to">
    <div>
        <input type="hidden" name="item_id" value="YOUR ITEM ID" />
        <input type="submit" value="New Game" /> 
    </div>
</form>

When you click the button it will pass item_id as a post request to the controller. Since I have no idea what your actual view looks like I am not sure where you are getting things like :time and :score

engineersmnky
  • 25,495
  • 2
  • 36
  • 52