Intercepting mail sent with the Pony gem, in a development environment - ruby

I'm using the Pony gem for ruby on rails, and am wondering if there's a way to intercept mail in the development and staging environments (any non-production environment) and send it to a controlled address, like you can do with ActionMailer.
I know with ActionMailer you just can just use an interceptor...

I personally use mailcatcher as an interceptor (I'm not sure if I'm using "interceptor" to mean the same thing you are though). Then you just need to set the default Pony.options :via_options to smtp://127.0.0.1:1025 and the mail will get sent to mailcatcher.

Just patch the mail method in the Pony object for your environment. Something like this...
class Pony
alias_method :original_mail, :mail
def mail(args)
args[:to] = 'intercept#example.com'
original_mail(args)
end
end

Related

Difference in cookie content using Sinatra session & Rack::Session::EncryptedCookie

I'm learning Sinatra framework & developing a login system. I came across two ways of using cookies.
A simple Sinatra inbuilt way:
enable :sessions
set :session_secret, 'random-key'
This approach produces following cookie content while logged in (used session.inspect to get the output):
{"session_id"=>"6be0b9a31831604ba51114d265ba952482e0b2da6ced6c54e15ebe7f212858ca",
"tracking"=>{"HTTP_USER_AGENT"=>"b8c1e8f89eeaea0b825bed0d811f0c7678e98c74",
"HTTP_ACCEPT_ENCODING"=>"a0bfc876d68fe7aea700da5ea8925abac6f2f794",
"HTTP_ACCEPT_LANGUAGE"=>"dd065ed263c67d799f943ab6c39b55c5e008cbb5"},
"csrf"=>"b480324f510e4f391d15cee8236a8fb74a5aaa5ce2f9ad38e4dbb025a823b16e",
"name"=>"john"}
Another approach is using an encrypted cookie :
require 'sinatra'
require 'encrypted_cookie'
use Rack::Session::EncryptedCookie, :secret => "random-key"
But this approach produces following cookie content while logged in (used session.inspect here too):
{:name=>"john"}
Why enable :sessions is creating such a big cookie with all that information & why is it required (especially those HTTP_... parts?) Because Rack::Session::EncryptedCookie isn't generating any of it.
Do you think that using enable :sessions should be preferred because it has csrf token & session id? Or do you think that Rack::Session::EncryptedCookie is enough since it is encrypted?
I have following versions of gems installed :
encrypted_cookie (0.0.4)
rack (1.5.2)
rack_csrf (2.4.0)
sinatra (1.4.3)
thin (1.5.1)
Please tell me if you need more information...
Because Sinatra will use rack-protection middleware when you enable :sessions. It makes cookie bigger but more secure.
Relevant snippet:
def setup_default_middleware(builder)
builder.use ExtendedRack
builder.use ShowExceptions if show_exceptions?
builder.use Rack::MethodOverride if method_override?
builder.use Rack::Head
setup_logging builder
setup_sessions builder
setup_protection builder
end
def setup_sessions(builder)
return unless sessions?
options = {}
options[:secret] = session_secret if session_secret?
options.merge! sessions.to_hash if sessions.respond_to? :to_hash
builder.use session_store, options
end
def setup_protection(builder)
return unless protection?
options = Hash === protection ? protection.dup : {}
options = {
img_src: "'self' data:",
font_src: "'self'"
}.merge options
protect_session = options.fetch(:session) { sessions? }
options[:without_session] = !protect_session
options[:reaction] ||= :drop_session
builder.use Rack::Protection, options
end
sessions? returns true if you enable :sessions
session_store is Rack::Session::Cookie by default
The difference between Rack::Session::EncryptedCookie
That is, if you want to use Rack::Session::EncryptedCookie with rack-production, it can be easily done by:
enable :sessions
set :session_store, Rack::Session::EncryptedCookie
FYI, since encrypted_cookie is lack of some features (secret rotation, custom serializer, etc) and no longer under maintenance, I made another one to replace it.
Hope it helps.
Because Rack::Session::EncryptedCookie requires that your secret be at least 16 bits long. In the README, they recommend using OpenSSL for generating the secret, like so:
ruby -ropenssl -e "puts OpenSSL::Random.random_bytes(16).inspect"
If you open your inspector, you'll see a cookie named 'rack.session', and its contents obfuscated.
As I know, when using Rack::Session::Cookie in Sinatra, and write session_secret as an environment variable, the session which has created won't destroy after the project deploy. I think this is a risk in Single Page Application.

How do I access Thin::Connection from inside rack middleware?

I would like to run set_comm_inactivity_timeout(0) on my EM Connection from inside Rack Middleware.
This will allow me to have one timeout for my upgraded web sockets and another for the rails app.
My web sockets are all first in the middleware chain so it is not wreaking havoc with Rack::Lock and such.
I see that some simply go for an infinite timeout in Thin and then inject something like Rack::Timeout after.
Is there a way to access EM::Connection or the signature of the connection from Rack middleware?
Only way to do this is monkey patch thin:
class Thin::Connection
alias :thin_process :process
def process
set_comm_inactivity_timeout(0)
thin_process
end
end

How do I set/get session vars in a Rack app?

use Rack::Session::Pool
...
session[:msg]="Hello Rack"
EDIT: The word session doesn't seem to resolve. I included the Session pool middleware in my config.ru, and try to set a variable in an ERB file (I'm using Ruby Serve) and it complains "undefined local variable or method `session'"
Thanks!
session is a method that is part of some web frameworks, for example Sinatra and Rails both have session methods. Plain rack applications don’t have a session method, unless you add one yourself.
The session hash is stored in the rack env hash under the key rack.session, so you can access it like this (assuming you’ve named the rack environment to your app env):
env['rack.session'][:msg]="Hello Rack"
Alternatively, you could use Rack’s built in request object, like this:
request = Rack::Request.new(env)
request.session[:msg]="Hello Rack"
You need to load rack::session module next probably cookie like here
http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html
This like explains it with example.

Automatically add rack middleware with a gem

I have a gem that provides some rack middleware, the only way I can get it to work is to place this in my application.rb
config.middleware.use "TBBC::Editor::Middleware"
How can I make it so that this middleware is automatically used when my gem is used in an apps Gemfile?
If you intend your gem to be used with Rails 3, you could provide a Railtie. You can then automatically load it in case Rails is used.
Assuming your gem's name is tbbc, place this in lib/tbbc/railtie.rb:
module TBBC
class Railtie < Rails::Railtie
initializer "tbbc.insert_middleware" do |app|
app.config.middleware.use "TBBC::Editor::Middleware"
end
end
end
In lib/tbbc.rb:
require "tbbc/railtie" if defined? Rails
You can't automatically add the middleware to generic Rack apps. For non-Rails applications, this will be something the user has to do.

Devise with Sinatra

Does anyone had installed Devise gem with Sinatra?
Devise is based on Warden and so it should work on Sinatra, I couldn't find any related info about how to implement it.
Devise is really just a Rails-centric wrapper with nice helpers for warden, which is the underlying Rack authentication framework. So if you're using Sinatra in conjunction with Rails, you can use Devise in your Rails app, and use warden directly in your Sinatra app, and they will see the same user session data.
So no, you can't use Devise directly within your Sinatra app, but if you're building a modular app with some pieces in Rails, and other pieces in Sinatra, you can use Devise/Warden among the components.
Devise is designed for Rails only. You can't use it with Sinatra.
You can check out:
https://github.com/maxjustus/sinatra-authentication
http://www.gittr.com/index.php/archive/sinatra-basic-authentication-selectively-applied/
https://gist.github.com/243611
There is also https://github.com/jsmestad/sinatra_warden available.
I was able to get it working. There were a few main aspects:
Get Devise working with Rails (Devise is a Rails app, won't work without it)
Setup the mapping (route) on Rack level to support both Rails and Sinatra
Share the sessions between Rails and Sinatra
Setup Warden and make it available to Sinatra
Here is most relevant part of code from /config.ru:
#
# ...
# Rest with Rails
map "/" do
run MyApp::Application
end
# Anything urls starting with /slim will go to Sinatra
map "/slim" do
# make sure :key and :secret be in-sync with initializers/secret_store.rb initializers/secret_token.rb
use Rack::Session::Cookie, :key => '<< see, initializers/secret_store.rb >>', :secret => '<< copy from initializers/secret_token.rb >>'
# Point Warden to the Sinatra App
use Warden::Manager do |manager|
manager.failure_app = AppMain
manager.default_scope = Devise.default_scope
end
# Borrowed from https://gist.github.com/217362
Warden::Manager.before_failure do |env, opts|
env['REQUEST_METHOD'] = "POST"
end
run AppMain
end
See, http://labnote.beedesk.com/sinatra-warden-rails-devise for a complete solution.

Resources