I have this in my routes file:
devise_for :users, :controllers => { :registrations => "users/registrations",
:sessions => "users/sessions",
:omniauth_callbacks => "users/omniauth_callbacks" }
devise_scope :user do
get 'sign_in', :to => 'users/sessions#new', :as => :new_user_session
get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
end
and now I added:
resources :users
because I want an admin user to be able to see all the users.
In CanCan I have this:
class Ability
include CanCan::Ability
def initialize(user)
if user
if user.admin?
can :manage, :all
end
can [:read, :edit, :update], User, :id => user.id
end
can [:create], User
end
end
Is this secure enough? Should I also add a before_filter in the UserController to block calls to the newly created route? Something like this? Problem with this is that users can't change their own profile anymore...
before_filter :check_rights
private
def check_rights
unless current_user.admin
redirect_to root_path
end
end
Found the solution. The before_filter is completely correct.
I had added
resources :users
before the devise part, you need to put it behind that part then users can still alter their own profile but can't go to index for example.
Related
First, see my routes :
Rails.application.routes.draw do
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
devise_for :users, controllers: {
registrations: "registrations",
sessions: "sessions"
}
devise_scope :user do
authenticated :user do
root 'appointments#index', as: :authenticated_root
end
unauthenticated do
root 'sessions#new', as: :unauthenticated_root
end
match '/logout', :to => 'devise/sessions#destroy', via: :all
end
resources :appointments do
get :available_slots, on: :collection
resources :notes
resources :images, only: [:show]
end
#patch 'appointments/:id' => "appointments#update_status", as: :update_status
match 'appointments/:id/update_status' => "appointments#update_status", :via => :post
match 'appointments/:id/visited_patient_appointment' => "appointments#visited_patient_appointment", :via => :post
get 'archive' => "appointments#archive"
end
Now, how to redirect to appointments_path after user sign in? There is one devise method called after_sign_in_path_for(resource) which I override in Appointments Controller but still it is not working.
You trying to override in Appointments Controller which is wrong, it will be sessions_controller.rb or application_controller.rb
Try the following in the sessions_controller.rb or application_controller.rb
protected
def after_sign_in_path_for(resource)
stored_location_for(resource) || appointments_path
end
If not have stored_location then he will redirect to appointments_path
If you need to redirect all time to the same page like appointments_path then
protected
def after_sign_in_path_for(resource)
appointments_path
end
See the Devise wiki
I'm getting this error when I try to logout an user. I checked many posts of this same error but no one solved my error, I hope you can help me.
The error is as follows:
ActiveRecord::RecordNotFound in UsersController#destroy
Couldn't find User with 'id'=sign_out
The following is my code:
users_controller.rb
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to unauthenticated_root_path }
format.json { head :no_content }
end
end
private
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
view/users/index.html.erb
<li>
<%= link_to "Logout", destroy_user_session_path, :method => :delete %>
</li>
routes.rb
Rails.application.routes.draw do
get 'admin/index'
resources :contacts
resources :afections
resources :injuries
resources :allergies
resources :trainers
resources :idusuarios
resources :diseases
resources :weights
resources :diets
resources :exercices
resources :profiles
resources :users
devise_for :users
get '/users/sign_out' => 'devise/sessions#destroy'
devise_scope :user do
authenticated :user do
root 'pagina#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
end
move get '/users/sign_out' => 'devise/sessions#destroy' above resources :users in your routes. Routes are given priority in terms of their order in the routes file.
When you use resources :users in your routes, you have this routes:
/users
/users/:id
/users/:id/edit
and ...
So when /users/sign_out is called, , thinks the sign_out is an ID.
so change /users/sign_out to /user/sign_out for example.
BUT
if you want customize your session paths, you can do this:
customize your session paths:
as :user do
get 'user/signin' => 'devise/sessions#new', :as => :new_user_session
post 'user/signin' => 'devise/sessions#create', :as => :user_session
delete 'user/signout' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:delete, :get]
end
and skip session in devise:
devise_for :users, :skip => [:sessions]
if you want user registration, you must skip it in devise and then can use user scaffold:
as :user do
get 'user/signin' => 'devise/sessions#new', :as => :new_user_session
post 'user/signin' => 'devise/sessions#create', :as => :user_session
delete 'user/signout' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:delete, :get]
end
scope "admin" do
resources :users
devise_for :users, :skip => [:sessions, :registrations]
end
I am using rails 4 along with devise my routes.rb reads :
devise_for :users, :path => '',
:path_names => {:sign_in => 'login', :sign_out => 'logout', :sign_up => 'register'},
controllers: { registrations: "registrations", omniauth_callbacks: 'omniauth_callbacks' } do
get "/login" => "devise/sessions#new"
get "/signup" => "devise/registrations#new"
get "/logout" => "devise/sessions#destroy"
get "/login" => "devise/sessions#new"
end
resources :users, :only => [:show, :index], :path => "bloggers" do
resources :posts, :path => "articles"
end
Now when I create a new post as the currently signed in user (lets say the id is 1). The URL on the Post -> New action reads - > https://localhost:3000/bloggers/1/articles/new but I want to show
https://localhost:3000/articles/new, as the new action on the post should always be associated to the current_user.
I would imagine this being possible, but no clue how to do it.
Also a user has_many posts.
Help, please?
Authentication
Very simple actually:
#config/routes.rb
# If you have overridden "path_names", you don't need other paths for Devise
devise_for :users, :path => '',
:path_names => {:sign_in => 'login', :sign_out => 'logout', :sign_up => 'register'},
controllers: { registrations: "registrations", omniauth_callbacks: 'omniauth_callbacks' }
resources :posts, as: "articles", path: "articles"
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!, except: :index
def index
#Stuff here
end
end
The bottom line here is that whenever you want to use an authenticated area (especially with Devise), you just need to "protect" the controller#actions which you want to limit access to. The beauty is that you can use the authenticate_user! helper method to make these work
Further to that, you will then be able to just call current_user in your controller (not having to set the user, as you're doing now):
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def new
#post = current_user.posts.new
end
def create
#post = current_user.posts.new post_params
#post.save
end
private
def post_params
params.require(:post).permit(:x, :y, :z)
end
end
Referenced the online documents for Devise but my override is still not working. Any one got any suggestions why not? It just goes to the root after sign in. Sign up works though.
Routes:
root :to => 'pages#index'
get "pages/index"
devise_for :users, :path => 'accounts', :controllers => { :registrations => "registrations" }
match 'profile' => 'profiles#show', :as => 'current_profile'
match 'profile/edit' => 'profiles#edit', :as => 'edit_current_profile'
put 'profile' => 'profiles#update'
resources :users do
resources :profiles
end
Registration Controller:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
edit_current_profile_path
end
def after_sign_in_path_for(resource)
current_profile_path
end
end
def after_sign_in_path_for(resource)
current_profile_path
end
This goes in the application_controller, not the override class.
My devise set up was working fine before, but now, for some reason, whenever I try to sign up a new user, it tries to call users#create instead of registrations#create. I think it must be a problem with my routes.rb file. I recently added a new resource, "preferences", to my application, so the routing might be wonky:
Indexer2::Application.routes.draw do
resources :preferences
get "home/index"
resources :posts
resources :users
devise_for :users, :controllers => {:registrations => 'registrations', :invitations => 'invitations'}, :except => [:show] do
get "/signup" => "devise/registrations#new", :as => 'user_signup'
get '/logout' => 'devise/sessions#destroy', :as => 'user_logout'
get '/login' => "devise/sessions#new", :as => 'user_login'
end
match '/welcome' => 'pages#welcome'
resources :preferences, :except => [:destory, :edit, :create, :new, :index, :show] do
collection do
post "make_feed_preference"
post "change_preference"
end
end
root :to => "home#index"
end
Your UsersController should have create method.
If you don't want to write your own registration logic just do inheritance from Devise::RegistrationsController < DeviseController:
controller UsersController < Devise::RegistrationsController
#....
end
This will include default Devise methods.