rack-attack configure text on blacklist page - ruby-on-rails

Im using rack-attack to block an ip.
# Block requests from 1.2.3.4
Rack::Attack.blocklist('block 1.2.3.4') do |req|
# Requests are blocked if the return value is truthy
'1.2.3.4' == req.ip
end
The IP gets successfully blocked. The person can view a white page with the word "forbidden" on the upper-left corner. Is there any way to change the string "forbidden" ?
EDIT :
Tried using this. All my other error pages are also configured similarly.
https://mattbrictson.com/dynamic-rails-error-pages
But it doesn't seen to work on the rack attack 403 forbidden page.

To customize the response of blocklisted and throttled requests, use an object that adheres to the Rack app interface.
Rack::Attack.blocklisted_response = lambda do |env|
# Using 503 because it may make the attacker think that he had successfully
# DOSed the site. Rack::Attack returns 403 for blocklists by default
[ 503, {}, ['Your custom string here']]
end
see the relevant documentation

Overwrite blocklisted_response.
#Tony Vincent is correct. I thought I would just elaborate a little further.
You just need to overwrite the default value for blocklisted_response.
You can see the default value here:
#blocklisted_response = lambda { |_env| [403, { 'Content-Type' => 'text/plain' }, ["Forbidden\n"]] }
So in your rack_attack.rb initializer, you can do the following:
Rack::Attack.blocklisted_response = lambda{ |_env| [ 403, { "Content-Type" => "text/plain" }, [ "You have been blocked from the system. If you think this has been done in error, please contact Support at support#system.com. Thank you." ] ] }

Overwrite blocklisted_response
You can display HTML pages also
So in your rack_attack.rb initializer, you can do the following:
Rack::Attack.blocklisted_response = lambda{ |_env| [ 403, { "Content-Type" => "text/html" }, [ "<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<meta name='viewport' content='width=device-width,initial-scale=1'>
</head>
<body class='rails-default-error-page'>
<!-- This file lives in public/404.html -->
<div class='dialog'>
<div>
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>
" ] ] }

Related

Api response is an HTML redirect page, while I expect a JSON response

I'm using the Faraday gem to request some data from the LibreNMS API. But when i display the response body I get some HTML code that looks like a redirect page to the libreNMS login.
I have the following code (BaseService class):
def libre_connection
Faraday.new(url: 'https://librenms.mydomain.nl') do |conn|
conn.path_prefix = "/api/v0"
conn.response :json, :content_type => /\bjson$/, :parser_options => { :symbolize_names => true }
conn.headers['X-Auth-Token'] = Rails.application.credentials[:libre][:key]
conn.headers["Content-Type"] = "application/json"
conn.adapter Faraday.default_adapter
end
And then this in a class that extends BaseService
def call()
response = libre_connection.get "/ports/25008.json"
end
For some reason this gives the following response:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta http-equiv="refresh" content="0;url=https://librenms.mydomain.nl/login" /> <title>Redirecting to https://librenms.mydomain.nl/login</title> </head> <body> Redirecting to https://librenms.mydomain.nl/login. </body> </html>
I know the token works because when I do the following curl command I get the JSON response I expect
curl -H 'X-Auth-Token: MYAPITOKEN' https://librenms.mydomain.nl/api/v0/ports/25008
Anyone have any idea what I'm doing wrong?
You're trying to connect over HTTPS. For local development you can try:
def libre_connection
Faraday.new(url: 'https://librenms.mydomain.nl') do |conn|
conn.ssl.verify = false # DONT DO THIS IN PRODUCTION
conn.path_prefix = "/api/v0"
conn.response :json, :content_type => /\bjson$/, :parser_options => { :symbolize_names => true }
conn.headers['X-Auth-Token'] = Rails.application.credentials[:libre][:key]
conn.headers["Content-Type"] = "application/json"
conn.adapter Faraday.default_adapter
end
end
For production see https://github.com/lostisland/faraday/wiki/Setting-up-SSL-certificates for how to properly configure SSL.
Thanks for the reply's guys, I figured it out. The problem was in the class that extends BaseService this is what it looks like now:
class LibrenmsApi::ConnectionsService < LibrenmsApi::BaseService
def call()
response = libre_connection.get "ports/25008"
end
end
note the "ports/25008" part. I removed the '/' at the beginning and that fixed it.

cannot make API call on paymill - 302 found as a response - rails

I used the examples on the paymill page to get the token with no problem. I'm passing the token using an ajax call. But I cannot make the API to make the final call. I cannot really understand how to use the code from the paymill-ruby or paymill-rails code at github, so I went trough the code and found the API call -which is what I'm missing-, but cannot make it work. All I want to do is a simple payment. No subscription, no user. Just a credit card payment. Here is the code from my controller:
token = params[:token]
params = {'amount' => '#{##amount}', 'currency' => 'EUR', 'token' => '#{token}', 'description' => 'description'}
https = Net::HTTP.new('api.paymill.de', 80)
https.use_ssl = false
https.start do |connection|
url = "/v2/transactions"
https_request = Net::HTTP::Post.new(url)
https_request.basic_auth(Paymill.api_key,"")
https_request.set_form_data(params)
#response = https.request(https_request)
end
puts #response.body
puts #response.header
render :action => "confirm"
The response is
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
#<Net::HTTPFound:0x00000004a98400>
And I cannot figure out what's wrong... a few weeks ago I didn't know what ajax was... can anybody give a hand?
I'm not a rails expert but ...
... you are connecting to our API at port 80 without using SSL. We only allow SSL requests to the api so you'll have to connect using port 443 and having SSL enabled.
Hope that solves your issues.

How to send mail in HTML format in Rails 2.3.11?

I've only found solutions that work in Rails 3, so far. How can I force emails sent with ActionMailer to be formatted as HTML, rather than plaintext?
/app/models/franklin.rb (the mailer)
class Franklin < ActionMailer::Base
def activation(user)
recipients user.email
from "activation#rit.oncampusapp.net"
content_type = "text/html"
subject "OnCampus # RIT Registration"
body :user => user
end
end
/app/views/franklin/activation.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
</head>
<body>
Hi <%= #user.full_name %>,
This is your activation email for OnCampus # RIT. All you have to do is click the link below, and you'll be able to log in.
<%= link_to "Activate My Account!", "http://rit.oncampusapp.net/admin/activate?key=#{#user.activation_key}"%>
We hope to see you soon! :D
-- The OnCampus Team
</body>
</html>
Have you tried setting in the activation action content_type "text/html" instead of content_type = "text/html"
Just paste this in your notifier/mailer model method - this will solve your problem
content_type "text/html"

Mechanize - How to follow or "click" Meta refreshes in rails

I have a bit trouble with Mechanize.
When a submit a form with Mechanize. I am come to a page with one meta refresh and there is no links.
My question is how do i follow the meta refresh?
I have tried to allow meta refresh but then i get a socket error.
Sample code
require 'mechanize'
agent = WWW::Mechanize.new
agent.get("http://euroads.dk")
form = agent.page.forms.first
form.username = "username"
form.password = "password"
form.submit
page = agent.get("http://www.euroads.dk/system/index.php?showpage=login")
agent.page.body
The response:
<html>
<head>
<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL=index.php?showpage=m_frontpage\">
</head>
</html>
Then I try:
redirect_url = page.parser.at('META[HTTP-EQUIV=\"Refresh\"]')[
"0;URL=index.php?showpage=m_frontpage\"][/url=(.+)/, 1]
But I get:
NoMethodError: Undefined method '[]' for nil:NilClass
Internally, Mechanize uses Nokogiri to handle parsing of the HTML into a DOM. You can get at the Nokogiri document so you can use either XPath or CSS accessors to dig around in a returned page.
This is how to get the redirect URL with Nokogiri only:
require 'nokogiri'
html = <<EOT
<html>
<head>
<meta http-equiv="refresh" content="2;url=http://www.example.com/">
</meta>
</head>
<body>
foo
</body>
</html>
EOT
doc = Nokogiri::HTML(html)
redirect_url = doc.at('meta[http-equiv="refresh"]')['content'][/url=(.+)/, 1]
redirect_url # => "http://www.example.com/"
doc.at('meta[http-equiv="refresh"]')['content'][/url=(.+)/, 1] breaks down to: Find the first occurrence (at) of the CSS accessor for the <meta> tag with an http-equiv attribute of refresh. Take the content attribute of that tag and return the string following url=.
This is some Mechanize code for a typical use. Because you gave no sample code to base mine on you'll have to work from this:
agent = Mechanize.new
page = agent.get('http://www.examples.com/')
redirect_url = page.parser.at('meta[http-equiv="refresh"]')['content'][/url=(.+)/, 1]
page = agent.get(redirect_url)
EDIT: at('META[HTTP-EQUIV=\"Refresh\"]')
Your code has the above at(). Notice that you are escaping the double-quotes inside a single-quoted string. That results in a backslash followed by a double-quote in the string which is NOT what my sample uses, and is my first guess for why you're getting the error you are. Nokogiri can't find the tag because there is no <meta http-equiv=\"Refresh\"...>.
EDIT: Mechanize has a built-in way to handle meta-refresh, by setting:
agent.follow_meta_refresh = true
It also has a method to parse the meta tag and return the content. From the docs:
parse(content, uri)
Parses the delay and url from the content attribute of a meta tag. Parse requires the uri of the current page to infer a url when no url is specified. If a block is given, the parsed delay and url will be passed to it for further processing.
Returns nil if the delay and url cannot be parsed.
# <meta http-equiv="refresh" content="5;url=http://example.com/" />
uri = URI.parse('http://current.com/')
Meta.parse("5;url=http://example.com/", uri) # => ['5', 'http://example.com/']
Meta.parse("5;url=", uri) # => ['5', 'http://current.com/']
Meta.parse("5", uri) # => ['5', 'http://current.com/']
Meta.parse("invalid content", uri) # => nil
Mechanize treats meta refresh elements just like links without text. Thus, your code can be as simple as this:
page = agent.get("http://www.euroads.dk/system/index.php?showpage=login")
page.meta_refresh.first.click

Problem generating pdfs with acts_as_flying_saucer

I'm using the rails plugin acts_as_flying_saucer to generate a pdf, but the pdf doesn't work: i can save it ok, but when i try to open it i get this error message:
Unable to open document
File type SOR File (text/plain) is not supported
Here's my set up. I'm using rails 2.3.4 and the latest version of the acts_as_flying_saucer plugin. I have this route:
map.all_help '/help/all.:format', :controller => "help", :action => "all"
which goes to this controller action:
class HelpController < ApplicationController
acts_as_flying_saucer
def all
respond_to do |format|
format.html {
render :action => "all", :layout => "help_pdf"
}
format.js
format.pdf {
render_pdf :template => 'help/all.html.erb',
:layout => "help_pdf",
:send_file => { :filename => "my-filename.pdf", :type => "application/pdf"}
}
end
end
end
and i also have this mime type defined:
Mime::Type.register "application/pdf", :pdf
When i go to the page, /help/all.pdf, it generates a 0 byte pdf (which i can save ok) and i get the error message from the top of this post when i try to open it.
Going to the standard web page version of the page (/help/all) works fine. I thought maybe my java vm wasn't set up but it seems to be fine:
max-laptop:millionaire[subjects]$ java -version
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
I'm out of ideas at this point...grateful for any advice! max
EDIT: Just noticed that a bunch of error output is in my mongrel-running tab:
ERROR: 'Premature end of file.'
Exception in thread "main" org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException: Premature end of file.
at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.createXMLResource(XMLResource.java:191)
at org.xhtmlrenderer.resource.XMLResource.load(XMLResource.java:71)
at org.xhtmlrenderer.swing.NaiveUserAgent.getXMLResource(NaiveUserAgent.java:205)
at org.xhtmlrenderer.pdf.ITextRenderer.loadDocument(ITextRenderer.java:102)
at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:106)
at Xhtml2Pdf.main(Xhtml2Pdf.java:19)
Caused by: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: Premature end of file.
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:719)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313)
at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.createXMLResource(XMLResource.java:189)
... 5 more
Caused by: org.xml.sax.SAXParseException: Premature end of file.
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707)
... 7 more
I'm wondering now if there's something wrong with the page i'm trying to convert to pdf. I ran the html version of the page past the w3c validator and the page validates ok. So now i'm stumped again...
EDIT 2: i think i'm getting closer now: looking in my log, i see
Rendering help/all.html.erb
html file: /tmp/ff4c8ff01d544500ea4bfea43e6108c1.html
Sending X-Sendfile header /tmp/ff4c8ff01d544500ea4bfea43e6108c1.pdf
So, i'd expect /tmp/ff4c8ff01d544500ea4bfea43e6108c1.html to have the html version of my page in it, but it's just a four line empty text file. No wonder flying saucer can't convert it. I don't know why it's saving an empty html file though.
EDIT 3: here's the html i'm currently trying to convert
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Help for Millionaire For Schools</title>
</head>
<body class="pdf">
<div id="bgeffect"></div>
<div id="pageWrapper" class="mainHelpPages">
<div id="helpContent">
<div id="helpPane">
<div class="inner">
<p>Welcome to my pdf</p>
</div>
</div>
</div>
</div>
</body>
</html>
Didn't you solve this problem a year ago by setting x_sendfile to false?
I solved this, it turned out to be really simple (and dumb). The problem was this: i was pointing to the layout i wanted to use in the normal railsy way,
:layout => "help_pdf",
But, it looks like you have to spell out the full file name: when i changed it to this, it worked:
:layout => "help_pdf.html.erb",
ARRRGGHHH!!!!!! Ah well at least it's working now. Thanks a lot John for having a look.
max

Resources