I'm using the rails recaptcha plugin found here: http://github.com/ambethia/recaptcha/tree/master
I have signed up for an account on recaptcha.com, obtained a public & private key, and the site is configured with a global key (for now).
In config/environment.rb I setup the environment variables:
ENV['RECAPTCHA_PUBLIC_KEY'] = 'xxxxxxxxxxxxxxxx'
ENV['RECAPTCHA_PRIVATE_KEY'] = 'XXXXXXXXXXXXXXxx'
In my view I render the captcha like this:
<%= recaptcha_tags %>
And in my controller processing this form I have this:
unless verify_recaptcha # <-- always returns false
flash[:error] = "Your captcha entry was invalid"
render :action=>'new'
return
end
My problem is that verify_recaptcha always returns false.
I must be missing something simple, but I don't see it. And before I get a smart-alec reply, YES I'm typing the correct words into the captcha box :)
Just as a note, make sure you didn't accidentally switch around the public and private keys; they are different.
I can't tell if you're already handling the possibility that it is correct, in which case you would want to have something like this:
if verify_recaptcha
#thing.save!
redirect_to success_path
else
flash[:error] = "There was an error with the recaptcha code below. Please re-enter the code and click submit."
render :action => 'new'
end
And remember to use:
<%= recaptcha_tags :ssl => true %>
If you are using SSL.
I went in and looked at the recaptcha plugin. The pertinent part reads something like this:
recaptcha = Net::HTTP.post_form URI.parse("http://#{server}/verify"), {
"privatekey" => private_key,
"remoteip" => request.remote_ip,
"challenge" => challenge,
"response" => response
}
This takes the challenge and response and returns a response. When I tried it with a challenge and response I generated, I got "true\nsuccess". The following lines of code return false if:
answer, error = recaptcha.body.split.map { |s| s.chomp }
unless answer == "true"
Since I got back "true\nsuccess", answer will be "true", and the code should therefore pass.
Can you try sending the response directly using Net::HTTP and seeing what response you get?
Related
I found a security risk in my application that I do not know how to fix. I just found this out while doing some checking on HTML and was playing with it.
So I have this code on a form tag
<%= form_tag("/spree/admin/workorders/#{#workorder.id}
/?workflow_id=#{workflow.id}
&name=workstep_name_{workflow.product_workstep.workstep.name}
&workstep_id=#{workflow.product_workstep.workstep.id}", method: "put")do%>
that query parameters will be caught by this method.
def update
#incoming_status = params[params[:name]]
# grab workflow, this is current data, use this to compare status to in comming status
#workflow = get_workorder_product_workstep(params[:workflow_id])
if is_workstep_for_shipping?
if #workorder.order.shipment_state.downcase == "shipped"
update_workflow
else
flash[:notice] = "Product not yet shipped"
end
else
update_workflow
end
redirect_to admin_workorder_path(#workorder)
end
def update_workflow
# check current status if its pending allow to update
if #workflow.send("can_#{#incoming_status}?")
# update status
#workflow.send(#incoming_status.to_s)
# updated attribute handled_by
#workflow.update_attributes(handled_by_id: #curr_user.id)
#workflow.save
else
flash[:notice] = 'Action not allowed'
end
end
and on the browser, the form that was created in view will render this.
<form action="/spree/admin/workorders/45/?workflow_id=141&name=workstep_name_w4&workstep_id=61" accept-charset="UTF-8" method="post">
</form>
now that form, those query parameters value can be changed. tried inputting wrong value and my backend crashed. how can fix this one? any idea or article that I could read? thank you.
UPDATE
While playing with the network. I also found this on network tab request payload
{spree_user: {email: "-----, password: "---"}}
spree_user: {email: "----", password: "----"}
everything is on plain text. I just changed my email and password to ----
If a person with a tech background they can easily spot this.
The code is from production. I think we are not using JWT here.
Awhile ago, I implemented an "undo" and "redo" button like in this railscasts on the paper_trail gem. Everything worked great until today when the "redo" stopped working. I haven't been able to figure out why.
Here is the relevant controller action:
def revert
#version = PaperTrail::Version.find(params[:id])
if #version.reify
#version.reify.save!(:validate => false)
view_context.reify_associations(#version)
else
#version.item.destroy
end
link_name = params[:redo] == "true" ? "undo" : "redo"
link = view_context.link_to(link_name, revert_version_path(#version.next, :redo => !params[:redo]), :method => :post)
if #version.event == "create"
flash[:success] = "Undid #{#version.event}. #{link}"
redirect_to :controller => session[:controller], action: :index
else
flash[:success] = "Undid #{#version.event}. #{link}"
redirect_to :back
end
end
It fails on the line: link = view_context.link_to(link_name, revert_version_path(#version.next, :redo => !params[:redo]), :method => :post)
With an error: ActionController:UrlGenerationError ... No route matches {:action=>"revert", :controller=>"versions", :format=>nil, :id=>nil, :redo=>false} missing required keys: [:id].
So, obviously, I followed the error to see why the :id wasn't being passed in, but it is.
In the parameters:
{"_method"=>"post",
"authenticity_token"=>"6/B1YDXqZ62+DqMMdcYTfCTIJGaVvc1RjKmxWW2GkeQ=",
"redo"=>"true",
"id"=>"29"}
The id is clearly defined and the first line of this controller finds the corresponding version in the table based on that id.
I cannot figure out what is wrong here so any help would be greatly appreciated.
For anyone finding this later on, the issue I was having was the first statement of my conditional (#version.reify) never returned nil. This is because I had overwritten the object attribute to add additional information to create events. To solve the problem, I simply changed the conditional to check the type of event, i.e.
if #version.event == "create"
...
end
PaperTrail's reify method looks at the object attribute of #version and recreates the object from the serialization. It returns nil whenever the object field is nil, otherwise it will return the object it unserialized.
I have a page that lets one create records - if the validations aren't satisfied, it redirects to the same page and shows an error message. Here's that snip from the controller:
def create
#signature = Signature.new(signature_params)
if #signature.save
redirect_to "/thanks"
else
redirect_to :back, :notice => error_messages(#signature)
end
end
The trouble is, this is resulting in a full page refresh - so the error message isn't visible because the input form is placed under the fold of the page. I can place it at the top of the page, of course, but is there a way to show the message without reloading the page? Thanks.
OK, so here's what I've settled on:
1) I'm handling validation on the client side with HTML5 "required" attributes - they were created for this explicit purpose and no other gems or plugins are needed. They are supported in all major browsers. Details in this article.
2) I've moved the error messages to the top of the page to handle the case in which a user either is on an old or mobile browser or has JavaScript disabled. Error messages must work with a complete request-response cycle (even if this means re-loading the page) before they work with anything else - this is the unobtrusive JavaScript approach.
3) For the AJAX version, I'm going to be using remote: => true on the form element as explained in the Rails guides. I might be making this open source once I'm done with the callback part of it, and will post a link here.
Obviously, handling errors with flash is the most uniform & DRY way to show the user what's going on, but if you're willing to think outside the box, you'll be able to use Ajax to accomplish a similar job by just handling the errors yourself:
Code Example
#app/controllers/signatures_controller.rb
def create
#signature = Signature.new(signature_params)
if #signature.save
#success = "true"
end
respond_to do |format|
format.js { #errors = error_messages(#signature) }
format.html {
if #success.defined?
redirect_to "/thanks"
else
redirect_to :back, :notice => error_messages(#signature)
end
}
end
end
#app/views/signatures/create.js.erb
<% unless #success.defined? %>
alert(<%=j #errors.inspect() %>)
<% end %>
#app/assets/javascripts/signatures.js
$(document).on("submit", "#signature_form", function() {
$.ajax({
url: "/signatures"
type: "POST"
data: $(this).parent().serialize(); //serialize the form (not the button)
error: function() {
alert("Sorry, there was an error!");
}
});
});
You'd actually be better using JSON for this. If you like the idea, I can refactor it to include JSON for you!
I want to know what the following code does. What is the use of request.referer?
#board = request.referer['dashboard'] if request.referer
request.referer gives you the previous URL or / if none. It is usually used to redirect the user back to the previous page (link)
More information here
Regarding your question, it is simply returning 'dashboard' if found in request.referer. Look at the following example:
> str = "hello world!"
=> "hello world!"
> str['hello']
=> "hello"
> str['lo wo']
=> "lo wo"
> str['foo']
=> nil
However, you should not depend on this method to redirect your user back. You can do this in your controller instead:
redirect_to :back
request.referer gives you the previous URL or / if none
In library you can see:
def referer
#env['HTTP_REFERER'] || '/'
end
You can use the referer technique for this, but you'll have to capture it when entering the form instead of when the form is submitted. Something like this:
<%= hidden_field_tag :referer, (params[:referer] || request.env['HTTP_REFERER']) %>
Then you can use params[:referer] in the controller to redirect back.
So I almost have a pingback sender ready for my rails app (people post links to content and donate to them). Almost.
I've borrowed heavily from the code here:
http://theadmin.org/articles/2007/12/04/mephisto-trackback-library/
I modified the slightly for my purposes:
require 'net/http'
require 'uri'
class Trackback
#data = { }
def initialize(link_id)
link = Link.find(link_id)
site = Link.website
if link.nil?
raise "Could not find link"
end
if link.created_at.nil?
raise "link not published"
end
#data = {
:title => link.name,
:excerpt => link.description,
:url => "http:://www.MyApp.org/links/#{link.to_param}/donations/new",
:blog_name => "My App"
}
end
def send(trackback_url)
u = URI.parse trackback_url
res = Net::HTTP.start(u.host, u.port) do |http|
http.post(u.request_uri, url_encode(#data), { 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8' })
end
RAILS_DEFAULT_LOGGER.info "TRACKBACK: #{trackback_url} returned a response of #{res.code} (#{res.body})"
return res
end
private
def url_encode(data)
return data.map {|k,v| "#{k}=#{v}"}.join('&')
end
end
Looks like I'm sending links successfully to my wordpress blog but when I look at the link displayed on the trackback I get this: http://www.theurl.com/that/my/browser/iscurrentlypointing/at/http:://www.MyApp.org/links/#{link.to_param}/donations/new"
All I want is the second half of this long string. Don't know why the current location on my browser is sneaking in there.
I've tried this on two of my blogs so it doesn't seem to be problem related to my wordpress installation.
UPDATE: Okay this is a little odd: I checked the page source and it shows the correct link. When I click on it, however, I get directed to the weird link I mentioned above. Is this a Wordpress Issue?
Whoops! Looks like it was just a syntax error. A sneaky double colon
This line
url => "http:://www.MyApp.org/links/#{link.to_param}/donations/new"
Should of course be like this
url => "http://www.MyApp.org/links/#{link.to_param}/donations/new",