Routing error when opening authenticated root when not signed in - ruby-on-rails

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

Devise before_action :authenticate_admin! not authenticating admin user

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.

Namespace, static pages, and inherited controllers, what files in what folders?

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

Rails Devise after_sign_in_path_for(resource) method not functioning as expected

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.

How to override devise to redirect to a different URL other than the root when user login or register?

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.

Setup devise with custom registration controller

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

Resources