我有一个小应用程序,我实现了设计。我添加了Devise的模型是consultant
而不是user
。
class Consultant < ApplicationRecord
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :confirmable
def admin?
self.admin == true
end
end
我还添加了一个属性,例如建议here选项2来识别管理员用户。
我的目标是实现只有管理顾问可以随处访问。非管理员的顾问只能访问resources :tasks
和get '/tasks/consultants/:id/worked', to: 'tasks#worked'
。访客应该被重定向到sign_in。
为此,我在before_filter
中添加ApplicationController
,就像这样
class ApplicationController < ActionController::Base
before_filter :authenticate_admin!
skip_before_filter :authenticate_admin!, only: [:tasks]
private
def authenticate_admin!
current_consultant.try(:admin?)
end
end
并在tasks_controller.rb
我添加了此before_filter
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_consultant!
...
我的routes.rb
定义如下
Rails.application.routes.draw do
devise_for :consultants
devise_scope :consultant do
authenticated :consultant do
root 'tasks#index'
end
root to: "devise/sessions#new"
end
get '/home', to: 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/tasks/consultants/:id/worked', to: 'tasks#worked'
resources :tasks
resources :consultants
end
我不明白为什么不验证用户,任何用户都可以随时访问
更新1
只是一个小注释,我更改before_filter
的每个before_action
因为before_filter
已被弃用
@Raffael建议我将application_controller.rb
更新为
class ApplicationController < ActionController::Base
before_action :authenticate_admin!
def authenticate_admin!
unless current_consultant.try(:admin?)
flash[:error] = 'Shoo, this is not for you'
redirect_to root_path
end
end
end
但是我收到了错误
localhost重定向了你太多次了。
我认为这种情况正在发生,因为我正在从routes.rb
和application_controller.rb
重定向。当它试图访问devise/sessions#new
时需要进行认证。
我试图通过将以下内容添加到application_controller.rb
before_action :authenticate_admin!, :except => ['devise/sessions#new']
更新2:解决方案
最后这就是我所做的,首先我创建了一个名为admin_controller.rb
class AdminController < ApplicationController
before_action :authenticate_admin!
protect_from_forgery with: :null_session
def authenticate_admin!
unless current_consultant.try(:admin?)
flash[:error] = 'Shoo, this is not for you'
redirect_to root_path
end
end
end
对于需要管理员权限的控制器,我从新类扩展
class AnyController < AdminController
application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_consultant!, :except => ['devise/sessions#new']
protect_from_forgery with: :null_session
end
并在routes.rb
Rails.application.routes.draw do
devise_for :consultants
root to: 'tasks#index'
...
不是一个优雅的解决方案,但它的工作原理。例如,将所有管理控制器放在自己的命名空间中会更好。
答案 0 :(得分:1)
从过滤器链中返回一个falsey值不会再停止过滤器链(它在以前的Rails版本中也是如此)。
如果您希望before_filter
阻止执行控制器操作,则需要重定向或呈现。
例如:
def authenticate_admin!
unless current_consultant.try(:admin?)
flash[:error] = 'Shoo, this is not for you'
redirect_to root_path
end
end
或:
def authenticate_admin!
unless current_consultant.try(:admin?)
flash[:error] = 'You need to be logged in as an admin to use this resource'
render 'login_dialog'
end
end