我有一个小应用程序,可以在其中实现设计。在这里我补充设计出模型consultant
来代替user
。
class Consultant < ApplicationRecord
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :confirmable
def admin?
self.admin == true
end
end
我还添加了一个属性,例如在这里建议使用选项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
但我得到一个错误
本地主机将您重定向了太多次。
我认为这是因为我正在从routes.rb
和重定向application_controller.rb
。尝试访问时,devise/sessions#new
需要进行身份验证。
我试图通过将以下内容添加到的before_action中来避免这种情况 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'
...
这不是一个优雅的解决方案,但它可以工作。例如,最好将所有管理控制器都放在自己的名称空间中。
从过滤器返回一个假值不会再终止过滤器链(在以前的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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句