How do I use Devise to secure the delayed_job_web interface? - ruby

I'm using the delayed_job_web gem to monitor delayed jobs. https://github.com/ejschmitt/delayed_job_web
It is accessible using this line in my routes.rb:
match "/delayed_job" => DelayedJobWeb, :anchor => false
Every other area of my site requires a login using the Devise gem. How do I make this require a login too?
In the readme, they suggest adding the following to the config.rb:
if Rails.env.production?
DelayedJobWeb.use Rack::Auth::Basic do |username, password|
username == 'username'
password == 'password'
end
end
But that just uses plain text browser authentication.
UPDATE:
I tried something similar to the railscast on resque, and I think it's on the verge of working but giving me a redirect loop now:
authenticate :admin do
mount DelayedJobWeb, :at => "/delayed_job"
end
Any thoughts on why would it be giving a redirect loop?
Thanks,

Use authenticated instead of authenticate as described here: http://excid3.com/blog/rails-tip-5-authenticated-root-and-dashboard-routes-with-devise/
Works for me!

You could do something like this define this inside config/routes.rb file
authenticate_user = lambda do |request|
request.env['warden'].authenticate?
end
constraints authenticate_user do
mount DelayedJobWeb, :at => "/delayed_job"
end
Alternately if you have cancan for any other role management library you could do it something like this
I have used both of this in my applications to control access to resque-web depending on the needs of the application
Hope this help

Now it's 2017 I tried the other solutions and they didn't work, but the following admin check does work:
authenticated :user, -> user { user.admin? } do
mount DelayedJobWeb, at: "/delayed_job"
end

Related

Unable to login with Google plus using omniauth-google-oauth2

I am using gem "omniauth-google-oauth2" in my application built on spree(ruby-on-rails) to integrate Google plus login on to our site.I am getting a very strange error here,It's working fine in development(localhost),
but in production I am getting this error
"auth/google_oauth2/callback?state=35ad3c2e3f8327a5b96df7ce7e2439a77b90dfebc41f8463&code=4/p5l-nug7FU3P8lfnSHNF8Uy_tYXcLyqc0bnABoGo0EI#".
For integrating Google plus ,I have done following
a.) I created a WebApplication App in google developers console by adding necessary javascript origin and redirect url's
b.) I have added client id, secret in my coonfig file
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, 'my cient id', 'secret'
end
c.) I have added a route 'auth/google_oauth2/callback'
I am really struck here for quiet some time.
I have done google-omniauth-oauth2 for quite a few apps.
Based on my experience I am giving you some hints.
Some of the possible reasons could be
You have added ur production url to google console, but may have missed out on callback url for production.
Check for routes and see if you have added a callback route. Normally it should point to method 'sessions#create' in your SessionsController.
Try the following in omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET
{
:access_type => 'offline',
:prompt => 'consent'
}
Here is my sessions#create method for your reference
def create
auth = request.env['omniauth.auth']
#user = User.find_by_email(auth.info.email) || User.create_with_omniauth(auth)
if !#user.country
#user.country = request.location.country
end
#user.update_tokens auth
reset_session
session[:user_id] = #user.id
redirect_to new_video_path, :notice => 'Signed In!'
end
For more help check this link.

Sessions in sinatra app being shared across browsers

I'm using Sinatra framework to make a very simple web app that requires a session for login.
I can login just fine, but when my friends visit the site they are logged in as me. I had a friend sign-up. When I re-visited the site I was logged in as her!! We're 3000 miles apart on different devices.
Here is the gist of my login code..
require 'rubygems'
require 'sinatra'
# I have tried enabling/disabling the :session_secret
# set :session_secret, 'my_secret'
enable :sessions
before '*' do
begin
User.login(User.find(session[:me])) if session[:me]
end
end
post '/login' do
user = User.find_by_email!(params[:email]).authenticate!(params[:password])
session[:me] = user.id
User.login user
200
end
I also tried adding this to my rackup file
use Rack::Session::Cookie,
:key => 'my_app_key',
:path => '/',
:expire_after => 14400, # seconds
:secret => 'secret_stuff'
The issue is both on production and development environments.
Sinatra documentation does not recommend any config beyond enable :sessions
http://www.sinatrarb.com/faq.html#sessions
User.login(User.find(session[:me])) if session[:me]
class User
def self.login(user)
##me = user
end
end
Here's your problem. Class variables persist, even between requests.
You login
User ##me gets set to your user
Someone elses visits the site.
session[:me] is nil since there is no session yet
User.login is not called, which would either set User ##me to a user or to nil.
So when there is no session[:me], User ##me doesn't get changed.
In short, do not use class variables to store information that should only persist for a single request.

Use HTTP Digest Authentication for a Single Route

I'd like to use HTTP Digest authentication for a specific route in my modular Sinatra App.
The examples listed within the sinatra recipes website simply describe how to enable digest auth for an entire app. The solution presented for getting this to work for specific routes is to create two separate apps, (one with digest auth and another without) placing the protected and unprotected routes in their respective applications.
That would require something like the following:
require 'sinatra/base'
class Protected < Sinatra::Base
use Rack::Auth::Basic, "Protected Area" do |username, password|
username == 'foo' && password == 'bar'
end
get '/' do
"secret"
end
end
class Public < Sinatra::Base
get '/' do
"public"
end
end
This seems like overkill to me.
Is there a way to protect a single route in a modular sinatra app without having to create an entirely new app?
There is an example in the FAQ which references creating an instance of Rack::Auth::Basic::Request and passing in the environment but doing something like this with digest auth would differ greatly and be much more of a manual authentication procedure.
Here is the basic authentication example:
def authorized?
#auth ||= Rack::Auth::Basic::Request.new(request.env)
#auth.provided? &&
#auth.basic? &&
#auth.credentials &&
#auth.credentials == ['admin', 'admin']
end
Does anyone have thoughts on how this could be done?
Using a before Filters. Do you need different behaviour for the same route?

Rails 3- Active_admin and CanCan integration

The title is very explanatory.
How can I integrate active_admin gem with cancan?
I need administrative roles.
Thanks
You may want to follow this guide
Robbie
for a simple case, assuming there are 2 roles: normal_user , admin,
if you just want to "admin" to access "/admin" (activeadmin's default namespace), while "normal_user" can not, I suggest you take a look a hook method:
# config/initializers/active_admin.rb
config.before_filter :check_user_role
# define this method in applicaton_controller.rb
def check_user_role
redirect_to root_path unless current_user.role == "admin"
end
Following link is also helpful to set cancan with activeadmin.
https://github.com/gregbell/active_admin/wiki/How-to-work-with-cancan
Nowadays there is a gem that do the work: https://github.com/11factory/activeadmin-cancan

Using Cucumber to test controller without a view in Rails

I'm a ruby/rails newbie and the application I'm developing starts with a HTTP post from another website which passes in some data and then displays some data capture screens before calling a web service.
I want to start this project using an outside in approach using Cucumber for integration tests and rspec for functional/unit testing.
Using Cucumber how do I simulate the post from the external website so that I can test the flows with the application.
It doesn't really matter to the application where the call originated; only that the parameters supplied match the expected ones from the referring page. If you depend on a specific HTTP_REFERER being set, check out this answer on how to set a header in Cucumber.
add_headers({'HTTP_REFERER' => 'http://referringsite.com'})
Since you already know which query parameters/headers your app expects from the referring site you can create a setup block that will set these appropriately for each cuke.
If you are using Cucumber with Capybara you can do a HTTP POST like this.
When /^I sign in$/ do
#user = Factory(:user)
get "/login"
page.driver.post sessions_path, :username => #user.username, :password => #user.password
end
Alternatively if you have a view it would be something like this.
When /^I sign in$/ do
#user = Factory(:user)
visit "/login"
fill_in "Username", :with => #user.username
fill_in "Password", :with => #user.password
click_button "Log in"
end

Resources