Safe Erb plugin Implementation Issue - ruby-on-rails

I am trying to implement the Safe Erb Plugin in my rails 2.0.2 app. I am
using this version for project specific purposes along with Ruby 1.8.7.
I have referred to the following tutorials:
http://www.railslodge.com/plugins/430-safe-erb
http://agilewebdevelopment.com/plugins/safe_erb
I could make only some sense of the above Url's as I am a newbie to
Rails and Rails related plugins. I honestly also found the above
tutorials to be very generic.
I really also couldn't relate this plugin's use to a great extent in terms of real world sense from the above tutorials. Could you please enlighten me on its usage on a day to day real world....?
I have implemented a books appl which has an author, title and
publishing date. I am currently facing issues implementing the taint
feature of this plugin
In the second tutorial, they say we need to call the tainted? method
from the Objects class. I have done this in my create method of my
books_controller.rb. The code for the create method looks like this:
def create
#book = Book.new(params[:book])
#book.publishing_date = params[:publishing_date]
respond_to do |format|
if #book.save
flash[:notice] = 'Book was successfully created.'
format.html { redirect_to(#book) }
format.xml { render :xml => #book, :status => :created,
:location => #book }
else
format.html { render :action => "new" }
format.xml { render :xml => #book.errors, :status =>
:unprocessable_entity }
end
if #book.tainted?
flash[:notice] = 'Books are tainted'
format.html { redirect_to(#book) }
format.xml { render :xml => #book, :status => :created,
:location => #book }
else
flash[:notice] = 'Books aren\'t tainted'
format.html { render :action => "new" }
format.xml { render :xml => #book.errors, :status =>
:unprocessable_entity }
end
end
Upon creating a new book record I get a notice saying that "Books aren't tainted". I have
copied this plugin into my vendor/plugins directory.
As per the second tutorial url they say "The string becomes tainted when
it is read from IO, such as the data read from the DB or HTTP request."
But its not happening in my case when I try to create a new book record.
Do I need to explicitly taint the string input I am taking(its currently
in varchar as per DB types - I guess that shouldn't be an issue). If yes
could you please tell me how to do it.
OR
if its not the above case.. Am I missing something?
Any insights on this would be really appreciated.
Thank you..

To begin with, if you can move on to rails 3 and ruby 1.9.2, please do so. It will almost certainly be worth the effort. Rails 2.0.2 was released in 2007 and is at least 3 years old. Rails 3 provides better protection than this plugin, right out of the box.
Having said that, safe-erb appears to be providing some xss protection. Going through the version of the plugin at https://github.com/abedra/safe-erb, you won't need to do anything special anywhere in your app to get it to work. Just install the plugin in vendor/plugins and you are good to go. Your controller should look just like it would without the plugin. You can do away with the if tainted block.
The way this plugin works is by hooking into various parts of the rails processing queue and doing some taint management to make your views automatically throw an error whenever there is unescaped user text. To use it, you don't need to do anything in your models and controllers. In your views, make sure that data is passed through h before being displayed.

Related

My rendering in Rails (possibly) causes a 422 error

I have received reports from users to my website that they get Error 422 when visiting a "result" page using POST. I cannot re-create this error at all so I am wondering if there is anything in my code below that would cause this error in formatting? I expect there could be errors here since I have upgraded a Rails 3.x project to a Rails 4.2.
I would either like to know if there is anything obvious in the code that would create 422 errors or if there is anyway to troubleshoot 422-errors.
Basically, in #show there is a POST method to result. It is creating a result text and lands on a url like /this-post-name/result?r=abc123 . I am rendering #show in /result because it is basically loading the same page again but with a "result box". Having to use /result is a choice I made as a newbie programmer and is not absolutely necessary, I think.
I am quite sure the error lies within the "respond_to" but can't figure that out, or troubleshoot it (i.e. re-create it).
Also, I am not sure if this is important, but I get tons of AuthencityToken errors on this page.
Edit: I managed to recreate this issue by accessing it through my iPhone and post a form, then I disabled cookies and send the form again. That would not be something people would do often but I guess having cookies disabled may cause this?
def show
#avaliable_posts = Post.where(:available => true)
end
def result
if request.get? && params[:r].blank? # Just visiting /result withoutout POST or ?r url
redirect_to category_path(#category)
else
set_round(session[:round_by_number])
# Either the visitor just posted the result or is revisiting through URL
if !params[:r].blank? # Visitor arrived from URL
#result = Result.find_by_scrambled_identifier(params[:r])
params_to_use = #result.params_used
#params_to_use = #result.params_used
else
params_to_use = params
#params_to_use = params_to_use
end
post_instance = #post.get_post_instance(params_to_use)
if post_instance.valid?
#post_result_array = post_instance.calculate_me(params_to_use)
#post_result_text_array = #post_result_array[0]
respond_to do |format|
format.html { render :action => "show" }
format.json { render :json => #post }
end
else # post not valid
#errors = post_instance.errors
respond_to do |format|
format.html { render :action => "show" }
format.xml { render :xml => #validator.errors, :status => :unprocessable_entity }
format.json { render :json => #post }
end
end
end
end
A 422 means Unprocessable Entity. Within your sample code is only one place with this http status code:
format.xml { render :xml => #validator.errors, :status => :unprocessable_entity }
Obviously this happens when format is XML and #validator contains an error.
Edit:
With the new information about the exception within the logs and the second linked stackoverflow question it seems to be releated to a known Rails issue
It seems like this issue is related to another issue that I have written another question for. I have an InvalidAuthencityToken issue with my website and the exceptions created through that cause a 422 (and not a 500) error as far as I understand from http://api.rubyonrails.org/v2.3/classes/ActionController/RequestForgeryProtection/ClassMethods.html
I am not 100% sure that this is the same issue but it seems quite likely and therefore I will close this question.

RESTful API Ruby on Rails

I'm playing with Ruby on Rails for the first time, and have an app up and running. Here's the quick database definition:
Teams
- id: int
- name: char[20]
Answers
- id: int
- answer_value: text
I want to be able to type: "http://localhost:3000/teams/1/answers/purple" in a browser
if team 1 answers purple.
I thought that adding the following to my routes.rb file would allow me to do that, but it hasn't.
resources :teams do
resources :answers
post 'answer_value', :on => :member
end
I can see the first answer by team 1 by going to "http://localhost:3000/teams/1/answers/1" , but I don't know how to actually set values via the URI.
If I understand you correctly, in you answers controller's show action, instead of doing Answer.find(params[:id]), do Answer.find_by_answer_value(params[:id])
If you want to create an answer, please post to
/teams/1/answers
with parameter :answer => { :answer_value => 'purple' }
Don't append answer_value to the url, looks like it's record id.
You need to either over ride the to_param method in the model, which can do what you are looking for although there are some caveats - including needing to use what #Chirantan suggested with Answer.find_by_answer_value(params[:id]) for all your finders. You can find more info in this Railscast on the subject or search for to_param in the Rails API and select the entry under ActiveRecord::Integration.
Alternatively you can go with a gem like FriendlyId which provides some more comprehensive functionality and control over the URL construction.
Typing things into your browser won't perform a post, regardless of what you put in the routes, it will only perform a get.
Creating something by a get is not RESTful, and you really shouldn't do it. That said, since you say you're just 'playing around with rails', you could do this:
If you want a get to create the thing, you have to set it that way in the routes. /teams/1/answers/purple
get '/teams/:team_id/answers/:answer_value' => 'answers#create'
then in your answers controller, create action, you could just check for a params[:team_id] and params[:answer value] and make sure that gets set before the save.
def create
#answer = Answer.new()
#answer.team_id=params[:team_id]
#answer.answer_value=params[:answer_value]
respond_to do |format|
if #answer.save
format.html { redirect_to #answer, notice: 'Answer was successfully created.' }
format.json { render json: #answer, status: :created, location: #answer }
else
format.html { render action: "new" }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end

How do I make a json request to a rails 3 website?

I know that if I have a url like
mysite/posts/1
The default type returned to me is html. I can get an xml version of the resource by just doing
mysite/posts/1.xml
But how do I get a json version? Is the following supposed to work?
mysite/posts/1.json
Reason I ask is because it doesn't seem to be working. So I figured I should find out if it's "supposed" to work this way before investigating further.
You're doing it right, but if the Controller isn't setup to respond to json requests you won't get anything. You'll have a respond_to block like this:
respond_to do |format|
format.html
format.xml { render :xml => #model_var.to_xml }
format.json { render :json => #model_var.to_json } #without this line, .json requests will go unanswered by the web server.
end

Rails - Custom Validation that requires current_user information

I'm having a very difficult rails problem and i thought to ask for some help. The situation is like this :
I'm using restful authentication for my User model. Now, user has a field named 'gold' that is a numeric value. There is another model named Book that has been created using scaffolding.
What i want to do is simple, yet i cannot see a way of doing it. I want to add some validation where if the user's gold is not, let's say 100, they cannot create a new book entry(from the scaffolding standard view).
Now the problem is that i need current_user information in order to validate this from my model. I need that in order to get the user id and therefore get their gold amount as well. I cannot find a good way (if any) to do that.
Another thought was doing that from a controller. However, the standard "if #book.save" block does not really allow me to insert my own error messages (inside scaffold create) :
if not User.has_the_needed_gold(current_user, 100)
flash[:goldError] = 'You do not have the needed gold to create this book.'
#end
respond_to do |format|
if #book.save
flash[:notice] = 'Book was successfully created.'
format.html { redirect_to(#book) }
format.xml { render :xml => #book, :status => :created, :location => #book }
else
format.html { render :action => "new" }
format.xml { render :xml => #book.errors, :status => :unprocessable_entity }
end
end
Now, i cannot output that message and abort the save of the new book as well. I've tried adding my own error to base, but it was cleared out(after save i guess). I'm quite confused with the situation and i've been searching around for a couple of hours with no results.
If anybody can help with that, please do so, you would spare me lots of trouble :)
Thanx for reading !
You could define a :user_gold virtual attribute for Book, set it in the controller where you have access to current_user and then incorporate that into your Book validation.
Look the user up when validating. It's likely the user lookup will have been cached by ActiveRecord, so it's not a performance hit to do so. Try something like this:
class Book
validate :check_gold
def check_gold
user = User.find(self.user_id)
self.errors.add(:user_id => "#{user.name} doesn't have enough gold!") if user.nil? or (user.gold < 100)
end
end

RoR - Rendering nested errors on XML

Good afternoon,
I'm trying to render as XML the complete ActiveRecord error list, problem is when you do something like:
respond_to do |format|
format.xml { render :xml => #object }
end
It does not render nested attributes if you don't say so, so either: you should create a template or calling explicity to_xml method and using ":include". This last option seems to work fine with nested attributes on model associations. But what if we got errors? This code does not work:
respond_to do |format|
format.xml { render :xml => #client.to_xml(:include => :errors }
end
I know I could do #client.errors and even hide .to_xml, but now i want to do something like:
respond_to do |format|
format.xml { render :xml => #client.to_xml(:include => {
:errors,
:client_contact => {:include => :errors } } )}
end
And supposedly I could obtain only in 1 xml, the errors from the client, and the errors from the client.client_contact! Let me know if i'm doing something wrong, or this :include is not supposed to work with errors
Regards
Have a look at the documentation for XML builder in the API docs. You can generate XML based on any number of conditions and output it however you like.
There's also a Railscasts episode showing you how to do a similar thing for RSS feeds.

Resources