Rails 3 + Devise : issue with custom routes - ruby-on-rails-3

I've followed the Devise wiki to switch the login route from /users/sign_in to /login. My routes file looks like this:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
devise_scope :user do
get '/login' , :to => 'devise/sessions#new' , :as => :login
delete '/logout', :to => 'devise/sessions#destroy', :as => :logout
end
and my user model has this
class User < ActiveRecord::Base
devise :omniauthable, :database_authenticatable
end
I have a common scenario where a user is logged out, tries to access a restricted page, and then redirected to log himself in.
However, when that user is redirected, devise sends them to /users/sign_in path instead of /login.
The only way I could make the redirection to the /login url work is by adding this to the top of my routes.rb:
match "/users/sign_in" => redirect('/login')
which adds a redirect to my application, which in turn messes up tests - whenever I do something like this:
current_url.should == login_path
I get an error saying the expected path was "/login" and the actual was "/users/sign_in".
Did I miss something here - what's an elegant way to work around it? thanks.
side note
I only use :omniauthable to authenticate, but I added :database_authenticatable to devise configuration to force it to go to a dedicated login page.
Otherwise, devise always directs to the root path, so it would seem. If you know of a better way to do that, please - chime in.

Related

How do I redirect devise sign_in path to a configured URL?

In a rails 3 project with devise, how puts the login page /users/sign_in in the root path.
my application is placed in
URL like: http://host/my_app
I am using devise for authentication
when i call the URL, the URL should automatically redirect to
http://host/my_app/users/sign_in
but
my application is forwarding to
http://host/users/sign_in
how to redirect the devise authentication to http://host/my_app/users/sign_in?
Thanks in advance
The devise docs talk about how to update the sign-in and sign-out routes. You should be able to prepend my_app using the same procedure documented.
you can skip default routes, check it out here
# config/routes.rb
devise_for :users, :skip => [:sessions]
as :user do
get 'my_app/users/sign_in' => 'devise/sessions#new', :as => :new_user_session
post 'my_app/users/sign_in' => 'devise/sessions#create', :as => :user_session
delete 'my_app/users/signout' => 'devise/sessions#destroy', :as => :destroy_user_session
end

Devise custom user root is not working

After a user signs in, I want them to be redirected to /users/2 or users/44, like a normal resource. (That way an admin can easily view any user's profile page just by knowing their id.)
I have no idea what is going on in my routes file. When a user logs in, I can see in the logs that it authenticates properly, and that my application_controller's after_sign_in_path_for is called.
But this is the error that I am getting when I try to redirect_to user_path(current_user).
No route matches {:action=>"show", :controller=>"users", :user_id=>11}
My config/routes.rb
devise_for :users, :path_names => {:sign_in => 'signin', :sign_out => 'signout', :sign_up => 'signup' }
devise_scope :user do
get "signin", :to => "devise/sessions#new"
get "signout", :to => "devise/sessions#destroy", via: :delete
get "signup", :to => "devise/registrations#new"
end
resources :users do
member do
get 'settings', to: 'users#edit'
end
end
My application_controller.rb
class ApplicationController < ActionController::Base
...
def after_sign_in_path_for(resource)
redirect_to user_path(:user_id=>current_user.id)
end
end
Shouldn't the resource :users block take care of creating a user show path? I do have a show method in my users_controller.rb. Please help, I've been trying to get this working for 2 days now.
My problem was that I was redirecting in the after_sign_in_path(resource) method instead of just returning the path:
def after_sign_in_path_for(resource)
return user_path(:user_id=>current_user.id)
end
is the correct way to do this.

Devise redirect after signin with username in url

I'm struggling with getting devise to redirect to a user's profile page after signin. My routes file looks like this:
get "profiles/index"
get "users/index"
get "users/show"
authenticated :user do
root :to => 'home#index'
end
root :to => "home#index"
devise_for :users
resources :users
scope ":username", :as => "user" do
match '/', :to => 'profiles#index'
end
I would like it to redirect to /myusername which the user's profile page. Thanks for your guys' help.
If you want to change the sign in redirect you can override the after_sign_in_path_for method by adding a new SessionsController as so:
class SessionsController < Devise::SessionsController
#after_sign_in_path_for is called by devise
def after_sign_in_path_for(user)
"/users/#{user.username}" #adjust the returned path as needed
end
end
As Ashikata mentioned you need to change the devise routing to the following if you're changing the session controller.
devise_for :users, :controllers => { :sessions => 'sessions' }
Alternatively, adding that modified after_sign_in_path_for method to your application controller should do the trick.

Setting Devise omniauth_path_prefix doesn't work

I'm working on a Rails-based API. I recently started attempting to version it. (I'm using the Versionist gem, in case it matters) One version ('v2') uses Devise and Omniauth to authenticate users through Facebook/Twitter.
I want all the routes associated with this version to have the appropriate version prefix (so users/:username/foo becomes v2/users/:username/foo, etc.), but I've already found out that putting devise_for inside the api_version block prevents the Devise helpers (current_user, user_signed_in?, etc.) from working, so it continues to live outside the block:
routes.rb:
devise_for :user, :path => '', :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'}, :skip => [:registrations, :confirmations, :sessions, :passwords]
api_version(:module => "V2", :path=>"v2") do
resources :authentications, :only => [:update, :destroy]
devise_scope :user do
post 'login' => 'sessions#create', :as => 'user_session'
get 'logout' => 'sessions#destroy'
post 'password' => 'devise/passwords#create'
put 'password' => 'devise/passwords#update'
end
end
Everything seemed great... except the Devise-generated omniauth routes:
rake routes output:
user_omniauth_authorize /auth/:provider(.:format)
user_omniauth_callback /auth/:action/callback(.:format)
Now, some google-fu revealed that there's a devise configuration setting for this, so I added the following to our devise initializer (config/initializers/devise.rb):
Devise.setup do |config|
config.omniauth_path_prefix = 'v2/auth'
end
Now, rake routes produces paths that look sensible:
user_omniauth_authorize /v2/auth/:provider(.:format) v2/users/omniauth_callbacks#passthru {:provider=>/(?!)/}
user_omniauth_callback /v2/auth/:action/callback(.:format) v2/users/omniauth_callbacks#(?-mix:(?!))
However, when I attempt to access this route by calling api.localhost/v2/auth/facebook, I get a routing error:
ActionController::RoutingError (No route matches [GET] "/v2/auth/facebook")
Any idea what's going on here?
You are missing the provider name in the routes so they don't match the facebook part in /v2/auth/facebook. The correct route destination should look something like v2/users/omniauth_callbacks#(?-mix:facebook).
Have you specified the provider in the user model?
devise_for ..., :omniauthable, :omniauth_providers => [:facebook]
For the record, I'm using Rails 3.2 and Devise 3.0 and the altered route seems to work (I haven't gone further yet to see if something else will break).

redirecting users away from sign in page after login in Rails with Devise

I would like my users to be redirected to the home page if they visit "/users/sign_in" after they have already signed in. How could I do that?
In your controller action for the sign in page (registrations probably if you are using devise). You will have to override the controller if you haven't already.
def new
if current_user
redirect_to home_page_url
else
#current logic for sign in method (super) if you currently don't have it implemented
end
end
I also discovered a way of doing this from the router.rb file; that is much much easier than doing it from the router, which would require me to override the devise controllers.
authenticated :admin do
root :to => 'admin/dashboard#show'
end
authenticated do
root :to => 'dashboard#show'
end
root :to => 'landing#show'
http://rubydoc.info/github/plataformatec/devise/master/ActionDispatch/Routing/Mapper:authenticated
Add the following to your routes.rb:
match "user_root", :to => "site#show" # where SiteController#show is your home page