Rails Devise roots, what's the difference between namespace and authenticated? - ruby-on-rails

In a Rails 3.2 app I have two user models set up using Devise: Admin and User.
I have an Admin-specific root page defined in my routes file.
namespace :admin do
root :to => "pages#welcome"
end
I have also seen this written as
authenticated :user do
root :to => 'pages#welcome'
end
I have not been able to find a clear description of the difference between using namespace and authenticated, and what implications this may have for security.
I'd be very grateful if someone could enlighten me, or point me towards a clear description.
Thanks!

Namespace routes will always exist -- meaning you can always call
/admin and it will route to pages#welcome
Authenticated routes will only exist if the :user is logged in.
I use it to create a root_path that's a dashboard for a logged in user, but the marketing pages#welcome for non logged in:
authenticated :user do
root :to => 'profile#show'
end
root :to => 'pages#welcome'

Here is a link to devise doc for the method authenticated, which should answer your question : http://rdoc.info/github/plataformatec/devise/ActionDispatch/Routing/Mapper#authenticated-instance_method

Related

`add_route': Invalid route name, already in use: 'root' (ArgumentError)

Im using rails 4.1.1 and ruby 2.1.1 and am having an issue with devise, namely my routes..I have used this many times before
devise_for :users
get 'pages/index'
# Route to Devise Login Page
devise_scope :user do
root to: "devise/sessions#new"
end
# Directing the user after login
authenticated :user do
root :to => 'pages#index'
end
But i get the error
`add_route': Invalid route name, already in use: 'root' (ArgumentError)
when trying to start the server.. I can see that root is being used twice, but like i said i have been able to do this in the past.. Is there a way around this
Thanks
Found this helpful comment here on stackoverflow
For Rails 4.0 you have to make sure you have unique names for the path
helpers, like root to: "dashboard#show", as: :authenticated_root.
Otherwise the authenticated root and the normal root route end up
having the same name for their path helpers, which Rails 4.0 no longer
allows
so I changed my authenticated root to helper like so
# Directing the user after login
authenticated :user do
root :to => 'pages#index', as: :authenticated_root
end

Devise not redirecting where I would expect

Just migrated from Authlogic to Devise, and having a redirect issue.
I have the following:
root :to => "welcome#index"
authenticated :user do
root :to => "dashboard#show"
end
However, after loggin in, I end up on welcome#index, and not on dashboard#show as I would expect.
The devise documentation says:
After signing in a user, confirming the account or updating the
password, Devise will look for a scoped root path to redirect.
Example: For a :user resource, it will use user_root_path if it
exists, otherwise default root_path will be used.
Which only reinforces my expectation.
def after_sign_in_path_for(resource_or_scope)
new_order_path
end
Define this in your applications controller. This will route your user to a particular path after sign_in.
Additional tidbit:
If you want to route the user to a particular page after confirming through email use this in your applications controller.
def after_confirmation_path_for(resource_or_scope)
end
Try this:
resources :dashboard
authenticated :user do
root :to => "dashboard#show"
end
make sure the
root :to => "path"
after the above code and not below that.

Trying to set root to devise/sessions#new results in routes mapping error

Going demented with an issue here :-(
My requirement is as follows,
If a user visits myapp.com the root of my app is defaulted to promotional pages & sign-up form. This is achieved by checking for the presence of a subdomain.
If the user is not logged in and tries to visit their account at test.myapp.com they will be directed to test.myapp.com/users/sign_in -aka- devise/sessions#new
If the user is logged in (devise) and visits test.myapp.com the root of the application will be the application dashboard.
Here is what I am trying to use in my routes.rb
constraints(Subdomain) do
authenticated do
root :to => 'dashboard#index'
end
root :to => 'devise/sessions#new'
end
root :to => 'promo_pages#index'
Currently I have the following, you will note that the devise bit is not included.
constraints(Subdomain) do
authenticated do
root :to => 'dashboard#index'
end
end
root :to => 'promo_pages#index'
My problem with the latter is that when a user who is not logged in first visits test.myapp.com they are redirected to test.myapp.com/users/sign_in and an error message is displayed saying "You need to sign in or sign up before continuing." This is because I am enforcing a logon requirement for the dashboard pages.
However I don't want the user to get an error message the first time they visit the page, as it is ugly and makes it look like they have done something wrong when they have not.
My expectation is that if the user is not logged in then they will be directed straight to the logon page and not get an error notification. But when I use my amended version the following happens,
I can visit myapp.com just fine and it is routed to the promo pages
but if I try to visit test.myapp.com I get the following message in the browser
**Unknown action**
Could not find devise mapping for path "/". Maybe you forgot to wrap your route inside the scope block? For example: devise_scope :user do match "/some/route" => "some_devise_controller" end
Please advise what I am doing wrong (if anything) as I am going crackers trying to understand what to do.
Ps: I have found similar errors in stackoverflow and various googling but the solutions just don't seem to work for me. I expect that the solution to the problem lies in the error message that I have included above, but I can't figure out how to apply it.
Finally here is the log entry version of the error above, it is in an easier to read form.
Started GET "/" for 127.0.0.1 at 2012-01-15 21:44:42 +0000
Processing by Devise::SessionsController#new as HTML
[Devise] Could not find devise mapping for path "/".
Maybe you forgot to wrap your route inside the scope block? For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
Completed 404 Not Found in 1ms
AbstractController::ActionNotFound (Could not find devise mapping for path "/".
Maybe you forgot to wrap your route inside the scope block? For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
):
All help is appreciated, and additional details can be provided.
Thanks for reading
Update
I have just noticed that the 'authenticated' check does not appear to be working.
If it was working correctly then when using the second batch of working config, the logged in user visiting test.myapp.com would always be directed to the promo_pages, whereas at the moment he is able to access the dashboard..
I found the devise 'authenticated' method here
https://github.com/plataformatec/devise/pull/1147
Without the constraint, this will cause a Could not find devise mapping for path "/" error. This simple addition fixed it.
devise_scope :user do
authenticated :user do
root :to => 'dashboard#index'
end
unauthenticated :user do
root :to => 'devise/sessions#new'
end
root :to => 'dashboard#index'
end
I have got it sorted,
Ok, firstly the reason I was getting the devise error was that I needed to place the devise root statement inside the "devise_for :users" block
Secondly,
The authenticated check was not working because I failed to include a scope as I was under the mistaken impression it was not necessary.
Here is the finalised code, note that in rails routing the priority is based on order of creation, first created is highest priority. Thus in this case the promo_pages controller is only considered root if nothing else was previously specified.
constraints(Subdomain) do
authenticated :user do
root :to => 'dashboard#index'
end
unauthenticated :user do
root :to => 'devise/sessions#new'
end
end
root :to => 'promo_pages#index'

Active Admin Causing Issues with having different 'root' for logged in and logged out users with Devise [duplicate]

Active Admin is a gem used for having an admin dashboard in your application. It uses Devise for logging in users and creates a separate admin_user model for the admins. My application already uses devise and has its users as the user model. Ever since I started using the active admin gem, in my routes file the following line keeps resolving to home#index and not users#dashboard even when my user is logged in. This used to work fine earlier where logged in users were taken to users#dashboard as the root url.
root :to => 'users#dashboard', :constraints => lambda {|r| r.env["warden"].authenticate? }
root :to => 'home#index'
What is happening is that the .authenticate? is checking for the admin_user (belonging to Active Admin) being logged in or not but not my user model which is what I need to check for, so when I am logged in to active admin interface, my site root becomes users#dashboard instead without checking if the user is logged in or not. How can I make .authenticate? check for the user being logged in and not admin_user ?
Any help or clues will be very much appreciated
I was able to solve this. The issue was related to Devise expecting a single user model in the application. Here is how to fix it.
In the config/initializers/devise.rb file, add:
config.scoped_views = true
and
config.default_scope = :user #or whichever is your regular default user model
thats it, warden checks the :user for being logged in and not :admin_user
Why are you using the get "/"? You should remove it. I'm using a definition pretty similar to yours and works fine with me. Use just:
root :to => 'users#dashboard', :constraints => lambda {|r| r.env["warden"].authenticate? }
root :to => 'home#index'
I am not sure, but you can try something like
root :to => proc { |env| [ 302, {'Location'=> env["warden"].authenticate? ? "users/dashboard" : "/home" }, [] ] }
What worked for me is:
constraint = lambda { |request| request.env["warden"].authenticate? and request.env['warden'].user.instance_of?(AdminUser) }

Active Admin authentication conflicting with User authentication

Active Admin is a gem used for having an admin dashboard in your application. It uses Devise for logging in users and creates a separate admin_user model for the admins. My application already uses devise and has its users as the user model. Ever since I started using the active admin gem, in my routes file the following line keeps resolving to home#index and not users#dashboard even when my user is logged in. This used to work fine earlier where logged in users were taken to users#dashboard as the root url.
root :to => 'users#dashboard', :constraints => lambda {|r| r.env["warden"].authenticate? }
root :to => 'home#index'
What is happening is that the .authenticate? is checking for the admin_user (belonging to Active Admin) being logged in or not but not my user model which is what I need to check for, so when I am logged in to active admin interface, my site root becomes users#dashboard instead without checking if the user is logged in or not. How can I make .authenticate? check for the user being logged in and not admin_user ?
Any help or clues will be very much appreciated
I was able to solve this. The issue was related to Devise expecting a single user model in the application. Here is how to fix it.
In the config/initializers/devise.rb file, add:
config.scoped_views = true
and
config.default_scope = :user #or whichever is your regular default user model
thats it, warden checks the :user for being logged in and not :admin_user
Why are you using the get "/"? You should remove it. I'm using a definition pretty similar to yours and works fine with me. Use just:
root :to => 'users#dashboard', :constraints => lambda {|r| r.env["warden"].authenticate? }
root :to => 'home#index'
I am not sure, but you can try something like
root :to => proc { |env| [ 302, {'Location'=> env["warden"].authenticate? ? "users/dashboard" : "/home" }, [] ] }
What worked for me is:
constraint = lambda { |request| request.env["warden"].authenticate? and request.env['warden'].user.instance_of?(AdminUser) }

Resources