Devise with rails 4 authenticated root route not working - ruby-on-rails

What I'm trying to do
I want to send a user to the registrations#new page if they aren't logged in.
After you enter login info and click submit, I want you to be sent to the registrations#show page.
What is happening
It sends you to the registrations#new page when you're not logged in (correct so far). But when you submit the login form, it sends errors out with a redirect loop. The server's output is just this block repeated over and over:
Started GET "/" for 127.0.0.1 at 2013-09-25 02:31:59 -0400
Processing by RegistrationsController#new as HTML
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = 8 ORDER BY "users"."id" ASC LIMIT 1
Redirected to http://lvh.me:3000/
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 2ms (ActiveRecord: 0.7ms)
I can't seem to figure it out. It does log you in, as I can see that by manually navigating to a different page, but the authenticated root path is not working correctly. I've tried a few different combinations in my routes file and can't seem to get it. The code I'm using is based off of this thread
My code
In my application controller I have before_filter :authenticate_user!
My routes file:
devise_for :users, :controllers => {
:registrations => "registrations"
}
devise_scope :user do
root to: "registrations#new"
end
authenticated :user do
root to: "registrations#show", :as => "profile"
end
unauthenticated do
root to: "registrations#new", :as => "unauthenticated"
end

First, you should customize Devise::RegistrationsController (you can add file app/controllers/registrations_controller.rb)
And see prepend_before_filter on devise registrations_controller.rb
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
Add show action to prepend_before_filter :authenticate_scope!
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy, :show]
# GET /resource/sign_up
def new
super
end
# POST /resource
def create
super
end
# GET /resource/edit
def edit
super
end
def update
super
end
# DELETE /resource
def destroy
super
end
def show
end
protected
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
end
Also copy the view of devise registration (edit and new template) to /app/views/registrations/ and You can make a file show.html.erb in /app/views/registrations/ folder for a profile page.
For routes of devise looks like :
devise_for :users, :skip => [:registrations]
devise_for :users, :controllers => {
:registrations => "registrations"
}
authenticated :user do
devise_scope :user do
root to: "registrations#show", :as => "profile"
end
end
unauthenticated do
devise_scope :user do
root to: "registrations#new", :as => "unauthenticated"
end
end
Last, you to set a "path" in after_sign_in_path_for(resource) and after_sign_out_path_for(resource_or_scope) at file application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
private
def after_sign_in_path_for(resource)
# After you enter login info and click submit, I want you to be sent to the registrations#show page
profile_path
end
def after_sign_out_path_for(resource_or_scope)
new_user_session_path
end
end
Note: I have tried this (to make sample apps), and it works. See log when sign in here, and log sign out here

The redirect to registration#new is default so all you need to do is this (in your route file):
devise_for :users, :controllers => {
:registrations => "registrations"
}
devise_scope :user do
root to: "registrations#show" # This is the root path of the user when you are logged in
end
unauthenticated do
root to: "registrations#new", :as => "unauthenticated"
end
# I dont't think this part is neccesary... Try if it works without
authenticated :user do
root to: "registrations#show", :as => "profile"
end

Do not use routes to do the jobs belonging to controller.
To redirect an user to certain page after signing up, use Devise built-in after_sign_up_path_for and override it.
class ApplicationController
def after_sign_up_path_for(resource)
faked_user_profile_path(resource)
end
end
For routes, I'm not very aware of all of them except devise_for part. But for the redirecting feature, this overriding should be enough.

Related

session.destroy in controller

I am trying to create a log out for my app and in my controller this piece of code is not working. Any solution would be helpful.
def destroy
#user = user.find(params[:id])
#user.destroy
end
This is my destroy method in my sessions controller(the fact that i am destroying my user in my sessions controller might be the problem)
class UsersController < ApplicationController
def new
end
def create
#user = User.create(password: params[:password],
email: params[:email],
firstname: params[:firstname],
lastname: params[:lastname])
redirect_to user_path(#user)
end
def show
#user = User.find(params[:id])
end
end
routes.rb:
Rails.application.routes.draw do
# Fubyonrails.org/routing.html
root :to => 'static#welcome'
resources :users, only: [:new, :create, :show]
resources :session, :only => [:new, :create, :destroy]
resources :studios
end
Routes file
uninitialized constant SessionController
is the error im getting
First, don't destroy your user. It deletes it from the database, you want them to be able to login again without creating a new user right?
You need to update your routes.rb file to be:
Rails.application.routes.draw do
# Fubyonrails.org/routing.html
root :to => 'static#welcome'
resources :users, only: [:new, :create, :show]
resources :sessions, :only => [:new, :create, :destroy] # changed to sessions
resources :studios
get 'logout' => 'sessions#destroy'
end
If you don't already, you need to define a SessionsController.
class SessionsController < ApplicationController
def destroy
# insert logic that actually logs them out, the below may already be enough
# for this purpose though
redirect_to root_url, notice: "Logged Out Successfully"
end
end
When the user clicks "Logout" it gets routed to the SessionsController#destroy action which redirects them to the root URL ('static#welcome')
There is more to it then that (i.e. the views and all that jazz) but this should be helpful enough

How to set rails devise sign_in path as a root url

devise_for :admins, path: 'admins'
devise_scope :admin do
root to: "devise/sessions#new"
end
http://localhost:3000/
I want to redirect admins/sign_in path when I just enter above url, login page is opening sometimes but after click on login button every time I get this error and not sign in. How to solve this problem?
error:
Filter chain halted as :require_no_authentication rendered or
redirected
look like you're trying to log in the same user again without a sign out
devise_for :admins, path: 'admins'
devise_scope :admin do
authenticated :admin do
root 'home#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
You can achieve the same with this
routes.rb
root "home#index"
devise_for :admins, path: 'admins'
home_controller.rb
class HomeController < ApplicationController
def index
if not admin_signed_in?
redirect_to admin_session_path
end
end
A logged user can't sign in again...
You can try this, in your session_controller.rb add
class Users::SessionsController < Devise::SessionsController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
end

Error on Devise redirections : "Filter chain halted as :check_user rendered or redirected"

I'm working on a small Rails(5) app, using Devise for auth. I followed the multi-model tutorial (https://github.com/plataformatec/devise/wiki/How-to-Setup-Multiple-Devise-User-Models), and now I want to customize redirections, particularly the after_sign_in_path... But then, I noticed the following error, which comes after signing in:
Started POST "/athlete/login" for 127.0.0.1 at 2019-03-25 17:03:32 +0100
Processing by Athletes::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xsZXnYOPJKLpveg1xr5D10i8DF5HGCH50pstEg85p+Y1OLIAmKMunYIV+BV5PJtgd51upy6i22VBMlQr5gtpEQ==", "athlete"=>{"email"=>"athlete#test.me", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Connexion"}
Athlete Load (8.0ms) SELECT "athletes".* FROM "athletes" WHERE "athletes"."email" = $1 ORDER BY "athletes"."id" ASC LIMIT $2 [["email", "athlete#test.me"], ["LIMIT", 1]]
↳ app/controllers/concerns/accessible.rb:13
Redirected to http://localhost:3000/athlete/onboarding
Filter chain halted as :check_user rendered or redirected
Completed 302 Found in 387ms (ActiveRecord: 8.0ms)
The result is that the after_sign_in_path_for method is never called, but I don't know why... I guess it could be related to the controller customization I've made (I added actions), but if so how could I fix this? I'm starting on Rails, so any help would be very welcome!
Thx in advance!
Here is my code (hope this will be helpful):
registrations_controller.rb
class Athletes::RegistrationsController < Devise::RegistrationsController
include Accessible
skip_before_action :check_user, except: [:new, :create]
before_action :configure_account_update_params, only: [:update]
# GET /resource/onboarding
def onboarding
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
end
# GET /resource/profile
def profile
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
end
# GET /resource/physical_profile
def physical_profile
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
end
protected
def after_sign_up_path_for(resource)
onboarding_athlete_registration_path
end
def update_resource(resource, params)
resource.update_without_password(params)
end
def configure_account_update_params
added_attrs = [
:avatar,
:firstname,
:lastname,
:birthdate,
:gender,
:phone,
:city,
:subscribe_newsletter,
:goal,
:practice_frequency,
:height,
:weight,
training_zone_attributes: [:id, :name, :address, :zip_code, :city]
]
devise_parameter_sanitizer.permit(:account_update, keys: added_attrs)
end
end
sessions_controller.rb
class Athletes::SessionsController < Devise::SessionsController
include Accessible
skip_before_action :check_user, only: :destroy
protected
def after_sign_in_path_for(resource)
if resource.profile_completion < 100
onboarding_athlete_registration_path
else
athlete_dashboard_path
end
end
end
routes.rb
Rails.application.routes.draw do
get '/coach/settings', to: redirect('/coach/settings/profile')
get '/athlete/settings', to: redirect('/athlete/settings/profile')
devise_for :athletes, path: "athlete", path_names: {
sign_in: "login",
sign_out: "logout",
sign_up: "register",
edit: "settings"
}, controllers: {
sessions: "athletes/sessions",
registrations: "athletes/registrations",
confirmations: "athletes/confirmations",
passwords: "athletes/passwords",
unlocks: "athletes/unlocks",
invitations: "athletes/invitations"
}
devise_for :coaches, path: "coach", path_names: {
sign_in: "login",
sign_out: "logout",
sign_up: "register",
edit: "settings"
}, controllers: {
sessions: "coaches/sessions",
registrations: "coaches/registrations",
confirmations: "coaches/confirmations",
passwords: "coaches/passwords",
unlocks: "coaches/unlocks"
}
as :athlete do
get "athlete/onboarding", to: "athletes/registrations#onboarding", as: "onboarding_athlete_registration"
get "athlete/settings/profile", to: "athletes/registrations#profile", as: "profile_athlete_registration"
get "athlete/settings/physical_profile", to: "athletes/registrations#physical_profile", as: "physical_profile_athlete_registration"
get "athlete/onboarding", to: "athletes/registrations#onboarding", as: :authenticated_athlete_root
end
as :coach do
get "coach/onboarding", to: "coaches/registrations#onboarding", as: "onboarding_coach_registration"
get "coach/settings/profile", to: "coaches/registrations#profile", as: "profile_coach_registration"
get "coach/settings/trainings", to: "coaches/registrations#trainings", as: "trainings_coach_registration"
get "coach/settings/infos", to: "coaches/registrations#infos", as: "infos_coach_registration"
get "coach/settings/subscription", to: "coaches/registrations#subscription", as: "subscription_coach_registration"
get "coach/onboarding", to: "coaches/registrations#onboarding", as: :authenticated_coach_root
end
scope "coach", as: "coach" do
resource :calendar, only: [:show, :update]
get "calendar", to: "calendars#edit"
get "dashboard", to: "coaches#dashboard"
end
scope "athlete", as: "athlete" do
get "dashboard", to: "athletes#dashboard"
end
resources :coaches, only: [:show] do
resource :calendar, only: :show, defaults: { format: :json }
resources :events, only: [:index, :update], defaults: { format: :json }
end
scope "booking", as: "booking" do
resources :coaches, only: [:index, :show]
resources :events, except: :index do
get "/training", to: "events#training"
get "/confirm", to: "events#confirm"
end
end
root to: "welcome#index"
end
accessible.rb
module Accessible
extend ActiveSupport::Concern
included do
before_action :check_user
end
protected
def check_user
if current_coach
flash.clear
redirect_to(authenticated_coach_root_path) && return
elsif current_athlete
flash.clear
redirect_to(authenticated_athlete_root_path) && return
end
end
end
You were quite right #fanta, even if the problem was maybe longer to solve... I had to change the rule as follows: skip_before_action :check_user, only: [:destroy, :create], like you said, but also to change my controllers. Instead of having my custom actions for users inside the Devise controllers, I created standard Rails controllers for these.
I guess I messed up with the Devise routing, and now it seems working nicely :)

Devise users create other users while logged in

In devise I'm trying to make it so that a Logged in user can create a new user via the Devise signup form.
Currently I've tried overriding the controller but it keeps redirecting me back to the root page due to me being logged in.
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
skip_before_action :require_no_authentication, only: [:new, :create, :cancel]
protected
def create
User.create!({:email => params[:email], :roles => [''], :password => params[:password], :password_confirmation => params[:password_confirmation] })
end
def sign_up(resource_name, resource)
end
end
routes.rb
devise_for :users, controllers: { registrations: "registrations" }, skip: [:sessions]
Am I missing something obvious, because I assumed the code below would allow it so I could view the form when I'm logged in?
skip_before_action :require_no_authentication, only: [:new, :create, :cancel]
Solution:
I was being too specific in my signup route it was set as devise/registration#new instead of registrations#new
If anyone reading this in future gets stuck, let me know and i'll try my best to help! :)

Devise root - disable must sign-in

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.

Resources