Question

I'll try to explain this as thoroughly as possible. I'm trying to figure out what the best way of passing existing data that should not be tampered with as a hidden value through a form -- or if there is a better way to send data on rails to a new "create" method.

Basically what I'm trying to achieve is, first a transaction created and stores group_id, owner_id, user_id, message and status. Then when the user "accepts" the request, a new transaction is created with basically all the same information (group_id, owner_id, and user_id), except the status and message can be changed.

So here's how the flow goes: A user first creates a request as such:

Request.create("gid" => 1, "user_id" => 2, "owner_id" => 4, "message" => "Bla Bla", "status" => 'pending')

Then the owner of that request views that request, and is able to accept or reject the transaction. Bare in mind, all the requests are in the same page, so there will be many accepts, and rejects on the same page, but each is iterated through the @request = Requests.where(:owner_id => 4).

The problem with hidden input is that you can tamper with it easily to change columns you aren't supposed to. What I'm trying to figure out is, if there is a way to pass the values into the accept method, with both new (message) and old (group_id, user_id, owner_id) to create a new row with?

The new transaction will basically be as such:

Request.accept("gid" => ori_trans, "user_id" => ori_trans, "owner_id" => ori_trans, "message" => "New Message", "appointment" => ori_trans, "status" => 'accepted')

def accept
    @request = Request.new(request_params)
    @request.status = 'accepted'
    @request.expert_id = current_user.id
    respond_to do |format|
      if @request.save
        format.html { redirect_to @request, notice: 'Request was successfully created.' }
        format.json { render action: 'show', status: :created, location: @request }
      else
        format.html { render action: 'new' }
        format.json { render json: @request.errors, status: :unprocessable_entity }
      end
    end        
end

def request_params
    params.require(:request).permit(:gid, :user_id, :message)
end

Problem with whitelisting GID and user_id is that users can temper with forms to allow for this field to be changed. Ideally, I'd only want to permit :message to come through from the params.

Hope this explains what I'm trying to do - let me know if you have any suggestions.

Was it helpful?

Solution

I think the following code should do what you want:

def accept
  original_request = Request.find(params[:request][:id])
  if original_request.owner_id != current_user.id
    #do something here, logout maybe?
    return
  end
  @request = original_request.dup
  @request.message = params[:request][:message]
  @request.status = 'accepted'

  respond_to do |format|
    if @request.save
      format.html { redirect_to @request, notice: 'Request was successfully created.' }
      format.json { render action: 'show', status: :created, location: @request }
    else
      format.html { render action: 'new' }
      format.json { render json: @request.errors, status: :unprocessable_entity }
    end
  end  
end

With this code, even if someone tampers with the request id parameter, if they try and accept a request they don't own, then it will fail.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top