If a user is logged in with Devise, I'd like to redirect them to their Posts index.
/username/posts
According to the Devise docs
I can use an authenticated block.
authenticated :user do
....
end
But I need the user's username to redirect there. Something like this.
authenticated :user do |user|
get '/', to: user_posts(user)
end
But this is not supported.
How to redirect with the current user to an authenticated root?
Edit:
NOT trying to do a after sign in Devise path. Trying to achieve a permanent root for logged in users and one for logged out users.
Try that:
class ApplicationController < ActionController::Base
def after_sign_in_path_for(user)
user_posts_url(user)
end
end
So you can do something like this
in your routes:
#config/routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => {
...
}
authenticate :user do
namespace :users do
...
root :to => 'posts#index' # /users/posts # this will only be accessible to login users
end
end
root :to => 'pages#index' #/pages this is accessible to all people
end
you will need:
#app/controllers/user_controller.rb
class UserController < ApplicationController
before_action :authenticate_user!
end
and
#app/controllers/users/posts_controller.rb
class Users::PostsController < UserController
def index
#posts = current_user.posts
end
...
end
I hope that this helps
Related
In my question How to have root view when user is not logged in rails? max answered that we can use authenticated to make routes available only when someone is authenticated. I am having a probem that how can I structure this:
Rails.application.routes.draw do
devise_for :users
authenticated :user do
# when authenticated allow all action on student
resources :subjects do
resources :students
end
end
# when not only allow read on student
resources :subjects do
resources :students, only: [:get]
end
root "home#index"
end
The problem is I don't want to allow any unauthenticated action on :subjects how to stop that?
If you want to limit access to subjects you should do it on the controller layer - not in the routes. Using before_action :authenticate_user! will give a 401 Unauthorized response and redirect to the sign in.
class ApplicationController
# secure by default
before_action :authenticate_user!, unless: :devise_controller?
end
class SubjectsController < ApplicationController
# whitelist actions that should not require authentication
skip_before_action :authenticate_user!, only: [:show, :index]
# ...
end
Rails.application.routes.draw do
devise_for :users
resources :subjects do
resources :students
end
root "home#index"
end
Using the authenticated and unauthenticated route helpers are useful when you want the have different responses for the same route for authenticated and unauthenticated users but is not how you should structure your application.
If you simply use authenticated in your routes unauthenticated users will get a 404 Not Found response instead of being prompted to sign in. Which is not helpful.
Also resources :students, only: [:get] does not generate any routes at all. The onlyoption is for limiting the actions (show, index, edit, update ...) not the HTTP method. Use rake routes to see the routes in your app.
Here is the simple way to structure authenticated and unauthenticated routes.
In app/controllers/application_controller.rb, add
"before_action :authenticate_user!".
My app/controllers/application_controller.rb file:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end
My config/routes.rb:
Rails.application.routes.draw do
devise_for :users
root "home#index"
devise_for :users, controllers: {
:sessions => "users/sessions",
:registrations => "users/registrations" }
authenticated :user do
resources :students
end
unauthenticated :user do
#Some route
end
end
I've been working with Rails, Active Addmin and cancancan. Everything is working fine except one thing. Recently I have added separate namespaces for my admin type users and clients.
Before that change, I redirected all authenticated users to the same active admin dashboard in such way (routes.rb):
devise_scope :user do
authenticated :user do
root :to => 'admin/dashboard#index', as: :authenticated_root
end
unauthenticated :user do
root :to => 'pages#index', as: :unauthenticated_root
end
end
Currently I need to somehow add additional condition that will be checking if authenticated user has role admin or client.
My idea was to make sth like that:
devise_scope :user do
authenticated :user do
if current_user.role?(:Architect) || current_user.role?(:Admin)
root :to => 'admin/dashboard#index', as: :authenticated_root
else
root :to => 'clients/dashboard#index', as: :authenticated_client
end
end
unauthenticated :user do
root :to => 'pages#index', as: :unauthenticated_root
end
end
But I am getting error: undefined local variable or method `current_user'
Does anybody know how I can check user's role in routes? Is there any better way to do that?
The root is a config file responsible for routes definition, you can't access any session variables in config files.
If you want to redirect user after sign in you can use after_sign_in_path_for method in Devise::SessionsController
class SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
if resource.role?(:Architect) || resource.role?(:Admin)
authenticated_root_url
else
authenticated_client_url
end
end
end
In your route you need to indicate the custom sessions_controller
devise_for :user, :controllers => {:sessions => "sessions"}
Page Controller :
class PageController < ApplicationController
before_filter :check_route, :only => [:index]
def check_route
return unless user_signed_in?
if current_user.role?(:Architect) || current_user.role?(:Admin)
redirect_to :controller => 'admin/dashboard', :action => 'index'
else
redirect_to :controller => 'clients/dashboard', :action => 'index'
end
end
end
routes.rb:
root :to => 'pages#index', as: :unauthenticated_root
Whenever I access my home page or root, I'm redirected to Devise's /users/sign_in/. I've played with the routes.rb file a fair amount and I'm unable to figure out why Devise kicks in for the pages controller. The Pages controller is effectively empty.
routes.rb
Rails.application.routes.draw do
resources :pages
root 'pages#index'
resources :events do
member do
get :create_attendee
delete :destroy_attendee
end
end
devise_for :users
devise_scope :user do
authenticated :user do
root 'events#index', as: :authenticated_root
end
unauthenticated do
root 'pages#index', as: :unauthenticated_root
end
end
pages_controller.rb
class PagesController < ApplicationController
def index
end
end
Add before_filter :authenticate_user!, except: [:index] to your pages_controller.rb and it'll skip the auth.
The authenticate_user! action is triggered for all controller method calls except index, i.e, for create, update... That way, you don't to go through log in page.
This app is being built on Devise 3.0 and Rails 4.1
I have a User object with two subclasses (Lender and Business) through STI. After a Business registers and confirms their email address, they are redirected to a form to fill out more information about themselves (This data is stored in a new object called SuppForm).
A business object has_one supp_form. I'm getting an error when the business confirms their email and is redirected to the form.
The error
ActionController::RoutingError (uninitialized constant SuppFormsController)
routes.rb (I used [ ] for business routes because I don't want them overlapping with the routes used in other places of the application)
# User type routes, needed to define specific sign out route to allow get request, not delete request
devise_for :users, skip: :registrations do get '/users/sign_out' => 'devise/sessions#destroy' end
devise_for :lenders, skip: :sessions, :controllers => {:registrations => "lenders/registrations"}
devise_for :businesses, skip: :sessions, :controllers => {:registrations => "businesses/registrations"}
resources :businesses, :only => [] do
resource :supp_form
end
business.rb
class Business < User
has_one :supp_form
accepts_nested_attributes_for :supp_form
end
supp_form.rb
class SuppForm < ActiveRecord::Base
belongs_to :business
end
supp_form_controller.rb
class SuppFormController < ApplicationController
before_filter :authenticate_user!
def new
#suppform = SuppForm.new
end
private
def supp_form_params
params.require(:supp_form).permit(:first_name, :last_name, :work_phone_number, :business_address, :business_postal_code)
end
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def account_url
return new_user_session_url unless user_signed_in?
case current_user.class.name
when "Business"
business_root_path
when "Lender"
lender_root_path
else
root_path
end if user_signed_in?
end
def after_sign_in_path_for(resource)
if resource.sign_in_count == 1 && resource.type == "Business"
new_business_supp_form_path(resource.id)
else
stored_location_for(resource) || account_url
end
end
You can see in application_controller.rb I redirect the business to the supp_form based on the number of times they've logged in. I also try and pass through the business's ID by calling resource.id and passing that through the request. The URL when I get the error is: http://xxxxxxxxxx/businesses/14/supp_form/new
Looks like a pluralization problem. Change the controller to a plural name.
class SuppFormsController < ApplicationController
before_filter :authenticate_user!
# etc
end
Does sound weird though since there really is only a single supp_form generated from the controller. You could also try to setup inflections to prevent rails from attempting to pluralize the word supp_form in config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w( supp_form )
end
I am currently using Cancan and my users basically have different 'roles'.
I only want people to be able to register 'consumer' user accounts and for business accounts admins will be doing that.
So now, I have this in my ability.rb
def initialize(user)
user ||= User.new
...
# You can only create accounts that are consumers
can :create, User do |user|
user.role? :consumer
end
and in my controller/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
load_and_authorize_resource
end
and config/routes.rb:
devise_for :users, :controllers => {
:registrations => "users/registrations"
}
Now when I visit the registration page, I am seeing "uninitialized constant Registration" with NO stack trace whatsoever. Any ideas?
My code example
class ApplicationController < ActionController::Base
authorize_resource
check_authorization
end
class Users::SessionsController < Devise::SessionsController
skip_authorize_resource
skip_authorization_check
end
For load_and_authorize_resource you will need skip_load_and_authorize_resource. And all this code is applicable for custom devise's controller. Just create one.
The issue is with the routes, please follow the following steps
1. $ rake routes, you will see the list of routes
2. In your config/routes.rb write the route you need, In my case the route to create a new user was,
devise_for :users, :controllers => { :new_user_registration => "users/registrations#new" }
3. restart rails server