filter child record by the parent.
Info: My models and association. I got a ServiceUser ( Manager ) model,User model, ServiceCompany model, Employee model and a Project model. A ServiceCompany can have many projects, employees and many ServiceUSer. A ServiceUser can be assign to a project and employees work at a project. Im using devise for authentication and cancan.
Models: https://gist.github.com/Frank004/c578864985b77fe284d4
Second info: My routes
resources :service_companies, shallow: true do
resources :service_users
end
resources :projects, shallow: true do
resources :employees
end
My problem: I got different companies and each one has his projects with different employees on each project. I can filter the project of the current user as a (client or as a manager). my problem start in the url anybody can change the ids of companies, projects or employees and view info from the other company. employee controller: https://gist.github.com/Frank004/b013218c4d4103a7ee55
Im looking for a way to only allow the information of the current project that is view and if he change the ids it wont show the other projects or parts of the projects like the employees list.
Im trying to find a way to get the project
@project
and then filter the employees by the project
The best way to handle that is authorization with Pundit. You can load up the project and verify if the current user has access to the project based upon the associations set. They will be able to change the ID in the url, but Pundit will throw an error if they try to access one they aren't a part of. Here's an episode on Authorization With Pundit that I did a while back.
Absolutely can. I'm a fan of Pundit over CanCan, but choose whichever one you are more comfortable with.
How can I do this achive this with cancan at the moment. I like to move to pundit but have to get this setup as fast as I can.
This my ability file
class Ability
include CanCan::Ability
def initialize(user)
#-----------------------------------------------------------------
if user.role == "super_admin"
can :manage, [ServiceCompany,User] #,:dashboard]
cannot :manage,[ClientCompany,Company,Project,Employee,Inspection,InspectionSection,
InspectionComponent,Section,Reply,ServiceUser,ClientUser,TaskArea,TaskSection,TaskItem,Accident,
Incident,Training,Workorder,Turnover,:help,:project_report,:report,Complaint,Payroll]
#-----------------------------------------------------------------
elsif user.role == "admin"
can :manage, [ClientCompany,Company,Employee,Inspection,InspectionSection,InspectionComponent,Section,Reply,ServiceUser,ClientUser,TaskArea,TaskSection,TaskItem,:help]
can :manage,[Project]
can [:read,:index,:destroy,:edit,:update,:create], [Accident,Incident,Training,Workorder,Turnover,Payroll]
# can [:read,:index], Payroll
can [:read,:edit,:update,:remove_photo], ServiceCompany
can [:read,:edit,:update,:index,:destroy],Complaint
can [:index,:trainings,:inspections_total,:workorders,:incidents,:accidents,:turnovers],:project_report
can [:index,:trainings,:inspections],:report
can :read, ServiceCompany
#---------Cannot----------
cannot :index, ServiceCompany
#-----------------------------------------------------------------
elsif user.role == "auditor"
can [:read, :index], [Project,Complaint,:project_report,:report,:help]
#---------Cannot----------
cannot :index, ServiceCompany
#-----------------------------------------------------------------
elsif user.role == "cliente"
can [:create, :read, :index], [Complaint,Reply]
can [:show], [ClientCompany]
cannot :index, ClientCompany
cannot :index, InspectionSection
can [:index,:inspections],:report
can [:index,:read,:detail], Inspection
can [:report_table], InspectionSection
can [:index,:trainings,:inspections_total,:workorders,:incidents,:accidents,:turnovers],:project_report
can [:read, :index], [Project,:help]
#---------Cannot----------
cannot :index, ClientCompany
#-----------------------------------------------------------------
elsif user.role == "gerente"
can [:create,:read,:update,:destroy,:edit,:signature,:detail], [Accident,Incident,Training,Workorder,Turnover,Inspection,InspectionComponent,Reply,Payroll,Employee]
can [:create,:read,:update,:destroy,:edit,:report_table],InspectionSection
can [:index,:show],[Project,TaskArea,TaskSection,ClientCompany,:help]
can [:index,:trainings,:inspections_total,:workorders,:incidents,:accidents,:turnovers],:project_report
can [:index,:trainings,:inspections],:report
can [:read,:index,:edit,:update], [TaskItem,Complaint]
can :read, ServiceCompany
#---------Cannot----------
cannot :index, ServiceCompany
#-----------------------------------------------------------------
else user.role == "administración"
can [:index,:show,:read,:signature,:detail],[ClientCompany,Company,Project,Employee,Inspection,
InspectionComponent,Section,Reply,ServiceUser,ClientUser,TaskArea,TaskSection,TaskItem,Accident,Incident,Training,
Workorder,Turnover,:help,Payroll]
can [:index,:show,:read,:report_table], InspectionSection
can [:index,:trainings,:inspections],:report
can [:index,:trainings,:inspections_total,:workorders,:incidents,:accidents,:turnovers],:project_report
can [:create, :read, :index], Reply
can [:edit,:update,:read, :index],Complaint
can :read, ServiceCompany
#---------Cannot----------
cannot :index, ServiceCompany
end
end
end
You'll need to use a block and filter by the ID in the user's list.
This isn't exactly what you'll need, but this is one way of checking if a project is in the user's associated list. You can modify this for your authorization.
can :manage, Project do |project|
user.projects.map(&:id).include? project.id
end
And here's more information on this: https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks
Thank I found a way to do it but its going to make the file to big can I create some tipe of partical like??
So I can clean the class ability
example:
class Ability
include CanCan::Ability
include super_admin_ability
def initialize(user)
if user.role == "super_admin"
super_admin_ability
end
end
end
Class SuperAdminAbility
def super_admin_ability
can :manage, [ServiceCompany,User]
end
end
That's exactly what I do. Mine is a little different, but just make sure you return a class that inherits from CanCan::Ability and you'll be fine.
module Abilities
def self.ability_for(user)
if user
if user.admin?
AdminAbility.new(user)
elsif user.editor?
EditorAbility.new(user)
elsif user.member?
MemberAbility.new(user)
end
else
GuestAbility.new
end
end
end