2013-09-15 3 views
1

У меня есть модель Ticket, модель Employee и модель User.CanCan для сотрудников и пользователей

Пользователи и сотрудники могут создавать билеты, но у сотрудников также есть назначенные им билеты. Таким образом, 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.

ответ

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 
+0

И что о назначенном сотруднике, как он мог видеть только назначенные билеты? (сотрудник также является пользователем, но я не знаю, правильно ли он связан с пользователем). Надеюсь, вы могли бы мне помочь, я застрял на этом в течение 3 дней –

+0

также мне нужно скрыть индекс, для Например, мы заставили пользователя показать только то, что он создал, также мне нужно скрыть то, что он не создал из индекса –

+1

@Dexter. Я дал вам пример того, как ограничить доступ для чтения для пользователя к билетам, которые он «владеет» ». Только те билеты появятся в индексе, потому что они запрашиваются с условием '" tickets.user_id = # {user.id} "'. – graywh

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 
+0

Я все еще получаю весь список индексов, есть ли еще файлы, которые вы хотите увидеть? Я добавил <% if can? : manage, Ticket%> таблица билетов <% end %> в мой index.html.erb –

+0

обратите внимание: employee_id не совпадает с идентификатором пользователя –

0

вы будете видеть все билеты, потому что в индексных действиях внутри контроллера вы звоните:

@tickets = Ticket.all 

вы можете попробовать это:

@tickets = Ticket.accessible_by(current_ability) 

с помощью этого метода CURRENT_USER увидите все билеты, которые current_user имеет доступ к

Update

вы можете определить определенный доступ в 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 
+0

. Доступный вызов не может использоваться с определением «can» блока. –

+1

проверить это https://github.com/ryanb/cancan/wiki/Authorizing-Controller-Actions#index-action access_by должно быть по умолчанию при вызове load_and_authorize_resource, но вы переопределяете его, вызывая Ticket.all для вашего ресурсы – syaifulsabril

+0

'd_and_authorize_resource \t индекс четкости \t \t @tickets_grid = initialize_grid (билетов, \t \t \t: включают в себя => [{: пользователь =>: user_type},: EMPLOYEE_DEPARTMENT,: состояние]) \t \t end' это мой индекс сейчас и все еще получаю все inde x не назначен только –

Смежные вопросы