我有Ticket
模型,Employee
模型和User
模型。
用户和员工可以创建票证,但员工也可以分配票证。因此user_id
指的是故障单的创建者,employee_id
指的是指定的员工(我不确定这是否是最佳方式)。
Ticket.rb
class Ticket < ActiveRecord::Base
before_save :default_values
after_commit :close_solved
after_commit :close_canceled
before_create :assign_state
attr_accessible :description, :title, :employee_department_id, :user_id, :first_name, :last_name , :email, :state_id, :employee_id, :ticket_state, :assign_state
belongs_to :employee_department
belongs_to :user
belongs_to :state
belongs_to :employee
has_many :replies
def default_values
self.state_id = 3 if self.state_id.nil?
end
def to_label
ticket_state.to_s
end
def close_solved
if self.ticket_state == "solved"
self.update_column(:ticket_state, "closed (solved)")
self.save!
end
end
def close_canceled
if self.ticket_state == "canceled"
self.update_column(:ticket_state, "closed (canceled)")
self.save!
end
end
def assign_state
if self.employee_id.nil?
self.assign_state = "un-assigned"
else
self.assign_state = "assigned"
end
end
Ticket.all.each do |ticket|
if ticket.ticket_state.blank?
ticket.ticket_state = 'open'
end
ticket.save
end
end
Employee.rb
class Employee < ActiveRecord::Base
# attr_accessible :title, :body
after_create :add_to_users
attr_accessible :employee_number, :joining_date, :first_name, :middle_name, :last_name,
:gender, :job_title, :employee_department_id, :qualification, :experience_detail,
:experience_year, :experience_month, :status_description, :date_of_birth, :marital_status,
:children_count, :father_name, :mother_name, :husband_name, :blood_group, :nationality_id,
:home_address_line1, :home_address_line2, :home_city, :home_state, :home_pin_code,
:office_address_line1, :office_address_line2, :office_city, :office_state, :office_pin_code,
:office_phone1, :office_phone2, :mobile_phone, :home_phone, :email, :fax, :user_id, :school_id,
:employee_category_id, :employee_position_id, :reporting_manager_id, :employee_grade_id,
:office_country_id, :home_country_id
belongs_to :employee_department
belongs_to :employee_category
belongs_to :employee_position
belongs_to :employee_grade
belongs_to :nationality, class_name: 'Country'
belongs_to :reporting_manager, class_name: "Employee"
belongs_to :school
belongs_to :user
has_many :tickets
def add_to_users
new_user = User.new
new_user.user_name = self.first_name
new_user.first_name = self.first_name
new_user.last_name = self.last_name
new_user.email = self.email
new_user.password = "123456"
new_user.password_confirmation = "123456"
new_user.user_type_id = 2
new_user.save
t = Employee.find(self.id)
t.user_id = new_user.id
t.save
end
def to_label
full_name = first_name + " " + last_name
end
def full_name
full_name = first_name + " " + last_name
end
end
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :validatable,:confirmable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :lockable, :timeoutable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :user_name, :first_name, :last_name, :password, :password_confirmation, :remember_me,
:role_ids, :current_password, :user_type
attr_accessor :current_password
# attr_accessible :title, :body
has_many :assignments
has_many :roles, :through => :assignments
has_many :articles
has_many :comments
has_many :students
has_many :guardians
has_many :employees
has_many :tickets
has_many :permissions
accepts_nested_attributes_for :tickets
def has_role?(role_sym)
roles.any? { |r| r.role_name.underscore.to_sym == role_sym }
end
end
Ability.rb
class Ability
include CanCan::Ability
def initialize(user)
@user = user || User.new
if user.has_role? :administrator
can :manage, :all
end
if user.has_role? :admission_manager
can :manage, Student
end
if user.has_role? :news_manager
can :manage, Article
end
if user.has_role? :ticket_manager
can :manage, Ticket
end
if user.has_role? :student_viewer
can :read, Student
end
if user.has_role? :news_viewer
can :read, Article
end
if user.has_role? :ticket_viewer #he should be able to create tickets and see what he has created.
can :create, Ticket
can :read, Ticket
end
end
end
Ticket_controller.rb
class TicketsController < ApplicationController
load_and_authorize_resource
def index
@tickets = Ticket.all
@tickets_grid = initialize_grid(Ticket, :include => [{:user => :user_type}, :employee_department, :state])
end
def show
@ticket = Ticket.find(params[:id])
@reply = @ticket.replies.build # this for comments on ticket
@state = State.all # this for a model called State which describe the priority of the ticket (Emergency / High / Normal )
end
def new
@ticket = Ticket.new
end
def create
@ticket = Ticket.new(params[:ticket])
if @ticket.save
flash[:notice] = 'Support ticket request created.'
redirect_to @ticket
else
flash[:error] = 'An error occurred please try again!'
redirect_to '/dashboard'
end
end
def edit
@ticket = Ticket.find(params[:id])
end
def update
@ticket = Ticket.find(params[:id])
if @ticket.update_attributes(params[:ticket])
flash[:notice] = 'Successfuly updated.'
redirect_to tickets_path
else
flash[:error] = 'An error occurred please try again!'
render @ticket
end
end
end
我需要允许Employees
能够管理他们分配的门票,我需要门票的创建者才能看到他创建的门票。
如何使用CanCan
执行此操作?如果用CanCan
无法完成,我会接受其他建议。
答案 0 :(得分:1)
要让用户能够阅读他们创建的门票,您只需要添加一个能力条件(见下文)。您可以在:create
能力上使用相同的条件,cancan会在为#new
或#create
操作构建新对象时为您预先填充这些属性。
# app/models/ticket.rb
class Ticket < ActiveRecord::Base
# <snip>
belongs_to :user
belongs_to :employee
# <snip>
end
# app/models/user.rb
class User < ActiveRecord::Base
has_one :employee
end
# app/models/ability.rb
class Ability
# <snip>
if user.has_role? :ticket_viewer
can :create, Ticket
can :read, Ticket, :user_id => user.id
end
if user.employee # && any other necessary conditions
can :create, Ticket
can :read, Ticket, :employee_id => user.employee.id
end
end
# app/controllers/tickets_controller.rb
controller TicketsController < ApplicationController
load_and_authorize_resource
def index
# @tickets = Ticket.accessible_by(current_ability) # cancan's
# load_and_authorize resource will take care of loading ticket(s) for
# all controller actions, so I've commented them out
@tickets_grid = initialize_grid(@tickets, :include => [{:user => :user_type}, :employee_department, :state])
end
def show
# @ticket = Ticket.find(params[:id])
@reply = @ticket.replies.build # this for comments on ticket
@state = State.all # this for a model called State which describe the priority of the ticket (Emergency / High / Normal )
end
def new
# @ticket = Ticket.new
end
def create
# @ticket = Ticket.new(params[:ticket])
if @ticket.save
flash[:notice] = 'Support ticket request created.'
redirect_to @ticket
else
flash[:error] = 'An error occurred please try again!'
redirect_to '/dashboard'
end
end
def edit
# @ticket = Ticket.find(params[:id])
end
def update
# @ticket = Ticket.find(params[:id])
if @ticket.update_attributes(params[:ticket])
flash[:notice] = 'Successfuly updated.'
redirect_to tickets_path
else
flash[:error] = 'An error occurred please try again!'
render @ticket
end
end
end
答案 1 :(得分:0)
使用CanCan实现起来非常简单。以下是使用您所包含的能力文件的修改子部分的快速示例:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
# Full access if you're the assigned employee
if user.has_role? :support_manager
can :manage, Ticket do |ticket|
ticket.try(employee) == user
end
end
# Read access only if you created the ticket
can :read, Ticket do |ticket|
ticket.try(user) == user
end
end
end
答案 2 :(得分:0)
您将看到所有票证,因为您在控制器内的索引操作中调用:
@tickets = Ticket.all
你可以试试这个:
@tickets = Ticket.accessible_by(current_ability)
通过使用此方法,current_user将查看current_user有权访问的所有票证
<强>更新强>
您可以在accessible_method
中定义特定访问权限@tickets = Ticket.accessible_by(current_ability, :manage)
其余的是你如何定义访问
https://github.com/ryanb/cancan/wiki/Fetching-Records
定义访问的示例:
if user.has_role? :ticket_manager
can :manage, Ticket, employee: {:user_id => user.id}
end