I'm running into a strange issue with my Rails 6 app. I'm using devise for two different models and have each scoped appropriately (I believe). I have an authenticated_root path set up in my devise scope:
devise_scope :tenant do
authenticated :tenant do
namespace :tenants do
get 'home/my_key', as: :authenticated_root
get 'home/guest_pass_list'
end
end
end
In the controller:
class Tenants::HomeController < ApplicationController
before_action :authenticate_tenant!, only: %i[my_key, guest_pass_list]
This works perfectly fine when the tenant follows the typical sign in path, but when a user tries do open /tenants/home/my_key directly when not signed in, a routing error is thrown. It seems like it should instead, redirect to the tenants/sign_in path.
What am I missing here? This has to be a configuration issue on my end.
You'll need to define the namespace :tenants outside the authenticated :tenant block, because the authenticated macro defines the routes only for "authenticated" accounts. So, for an "unauthenticated" account, the route doesn't exist and it throws a routing exception.
More info: https://github.com/heartcombo/devise/wiki/How-To:-Define-resource-actions-that-require-authentication-using-routes.rb
The redirect will be handled by the before_action :authenticate_tenant! callback in your controller. By the way, you should also change %i[my_key, guest_pass_list] to %i[my_key guest_pass_list] (note the , removal):
>> %i[my_key, guest_pass_list]
=> [:"my_key,", :guest_pass_list]
>> %i[my_key guest_pass_list]
=> [:my_key, :guest_pass_list]
Related
I have used devise numerous times but currently facing an issue at the moment.
I used this devise wiki to set up devise with multiple user models which i have done multiple times. https://github.com/heartcombo/devise/wiki/How-to-Setup-Multiple-Devise-User-Models
In my admins_controller.rb i have the following code
class AdminsController < ApplicationController
before_action :authenticate_admin!
end
My routes.rb
Rails.application.routes.draw do
devise_for :admins, path: 'admins', controllers: {sessions: "admins/sessions", registrations: "admins/registrations"}
namespace :admins do
root "dashboards#index"
end
end
Everything else works well but after i try to sign in as an admin, it should redirect to my admins root but i always get this error
You need to sign in or sign up before continuing.
But when i do admin_signed_in? or current_admin. I get true and my admin record accordingly. Which means the admin is already signed in.
When i comment the before_action code, then it works perfectly.
Currently stuck and cannot think of why and how to solve this issue.
I'm building an admin control panel (attempting to ;) ).
I have been looking at Backend administration in Ruby on Rails and as suggested I am trying to make Admin::AdminController that checks for admin and sets the layout etc.
But I'm also trying to set a route in it that routes /admin to /admin/dash
From my understanding of reading http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing , specifically section 2.6,
Admin::AdminController
tells rails that Admin is the name space, AdminController is the controller which is a subclass (extension?, implementation of the interface?) of ApplicationController. Which would imply the controller should live in app/controllers/admin/ and be called admin_controller.rb.
But what I want is
AdminController
I get errors like:
uninitialized constant Admin::Controller
My code for the route:
match :admin, :to => 'admin/admin#dash'
namespace :admin do
# Directs to /admin/resources/*
match '/dash', to: '#dash'
resources :users, :pictures
end
I have put the controller in app/controllers/admin, app/controllers and the combinations with
class Admin::AdminController < ApplicationController
before_filter :admin_user
# / ** STATIC ADMIN PAGES ** /
def dash
end
end
or class AdminController < ApplicationController.
Edit: Maybe it's my understanding of routing.
Example:
namespace :admin do
get "/dash"
vs.
namespace :admin do
match "/dash" to "admin#dash"
vs.
namespace...
match "/dash" to "#dash"
The first one makes it so i can display a dash via the controller, i.e. admin/dash would be controlled by
AdminController < ApplicationControler
def dash
end
Does the second one route admin/admin/dash to admin/dash?
TL/DR:
I think my confusion comes from syntax or my poor understanding of RESTful practices or maybe even class / object inheritance in ruby.
Thanks for helping this n00b out. :)
Side question: can I change my code to be minimized until someone opens it like a spoiler so it doesn't crowd things up if I find more information and add it?
I think your initial approach was correct, but you need to change it a little.
1) insert the /admin => /admin/dash inside the namespace (imho, its better to redirect it)
match 'admin' => redirect('admin/dash')
or
namespace :admin do
match '/', to: 'admin#dash'
end
2) You can't match '/dash' to '#dash' since you're not inside a resource block, you're inside a namespace block, so it doesnt' have implied controller.
namespace :admin do
match 'dash', to: 'admin#dash'
# This will go to Admin::AdminController#dash
# (first Admin because of the namespace,
# and the second because of the controller name)
end
hope it works :D
What you want is "scope" in routing.
scope "/admin" do
resources :articles
end
Which will route /admin/articles to ArticlesController (without Admin:: prefix)
Documentation covers almost every possible case.
http://edgeguides.rubyonrails.org/routing.html
I want to redirect an inactive user to the registration path to collect some information. Here are two approaches I took but neither is working:
I overrode the devise after_sign_in_path method as follows (in application_controller.rb):
def after_sign_in_path_for(resource)
debugger
if(account_active)
return root_path;
else
return edit_user_registration_path(resource)
end
end
When I hooked the code upto debugger, I see that devise does call after_sign_in_path_for. Also, the correct url is being generated by this call:
(rdb:2) after_sign_in_path_for(resource)
"/users/edit.1"
However, when I look at the server logs, there is no attempt being made to redirect to "/users/edit.1" under any circumstances.
I have tried moving the above method to application_helper.rb, session_controller.rb (by extending Devise::SessionController) and session_helper.rb
The issue is that devise does call this method to retrieve the url but it never attempts the redirect. I checked the web server logs, and devise directly goes to the user_root url.
Here is the relevant devise configuration from routes.rb:
devise_for :users do
resource :registration,
only: [:new, :create, :edit, :update],
path: 'users',
path_names: { new: 'sign_up' },
controller: 'devise/registrations',
as: :user_registration do
get :cancel
end
root :to => "home#index"
end
match '/user' => "products#index", :as => 'user_root'
Any suggestions on what I should try?
Thanks,
Tabrez
Are you sure you want to redirect to /users/edit.1? Rails will pick that up as if you're trying to access the 1 mime-type instead of html.
The user registration path doesn't need an id, because it always belongs to the currently signed in user. This should be enough:
def after_sign_in_path_for(resource)
if account_active
root_path
else
edit_user_registration_path
end
end
Also, placing it in the ApplicationController is the right spot. If you have your own sessions controller, like Users::SessionsController, which inherits from Devise::SessionsController, than it can go in there too.
So either the account_active method doesn't do what you think it does, or you've screwed up the routes file. Try working with a more vanilla configuration in your routes to see if that is the case:
devise_for :users
PS. as a complete an utterly unrelated side note: please try to use Ruby coding conventions, like no semicolons when they're not needed, no parenthesis in if statements, 2-spaces indenting and no unneeded return statements.
This may not apply to you, but in my recent use of devise + active_admin, I ran into the same problems you are describing. I added the devise override while my development rails server was running, and assumed rails/devise would automatically pick up the method. Apparently not since the problem was solved when I restarted my server.
It seems that devise is cherry picking these methods off ApplicationController when it initializes, though I havent looked at the source.
I am using devise and I have a root pointing home#index, now I want to override devise when a user register or login to redirect to project#show instead of the root(home#index). What method do I put in the overidden devise controller? Also do I have to add anything in the routes.rb?
Thank you in advance!
class RegistrationsController < Devise::RegistrationsController
end
routes.rb
Parks::Application.routes.draw do
resources :home, :project
devise_for :users
root :to => "home#index"
end
available path
show_project_path
I think the after_sign_in_path_for hook is what you're looking for: http://rdoc.info/github/plataformatec/devise/master/Devise/Controllers/Helpers:after_sign_in_path_for
As you can see from the docs, you can define a route that will automatically be used (by the original implementation of the hook) or you can override it completely.
I'm working on a rails site using devise, where we do not want user sign ups just yet. User authentication is so we can login to access restricted parts of the site and add/edit things as we see fit. So for now, I created the following controller:
class Users::RegistrationController < Devise::SessionsController
def new
end
end
And setup my routes in this fashion:
devise_for :users, :controllers => { :registration => "users/registration" }
However, when I run rake routes, I still see a returned value for the create action on the registration controller. Any ideas on how to get rid of it?
Try using :registrations instead of :registration. Also, it seems like your custom controller class should be defined via:
class Users::RegistrationsController < Devise::RegistrationsController