Class: LesliShield::RolePrivilegeService
- Inherits:
-
Lesli::ApplicationLesliService
- Object
- Lesli::ApplicationLesliService
- LesliShield::RolePrivilegeService
- Defined in:
- app/services/lesli_shield/role_privilege_service.rb
Instance Method Summary collapse
-
#synchronize(role) ⇒ Object
Syncronize the descriptor privileges with the role privilege cache table.
Instance Method Details
#synchronize(role) ⇒ Object
Syncronize the descriptor privileges with the role privilege cache table
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'app/services/lesli_shield/role_privilege_service.rb', line 37 def synchronize role # bulk all the descriptor privileges # this script was built manually for performance, maintenance # and to make it easy to read for future changes, basically what it does # is get the controllers and actions assigned to a descriptor through the # system_descriptor_privileges table and create an array of hashes with # all the raw privileges (this includes duplicated privileges) # IMPORTANT: A descriptor privilege is evaluated as active if: # - the role has assigned the descriptor through the power association # - the descriptor has assigned the privilege through the controller actions table # - the power has active that group of actions, this means that, if the power has # not marked as active the pshow, pindex, etc column the power is not active # even if it is assigned and active to a descriptor records = Lesli::Role.joins(%( INNER JOIN "lesli_shield_role_actions" ON "lesli_shield_role_actions"."role_id" = "lesli_roles"."id" )).joins(%( INNER JOIN lesli_resources as resource_actions ON resource_actions.id = lesli_shield_role_actions.action_id )).joins(%( INNER JOIN lesli_resources as resource_controllers ON resource_controllers.id = resource_actions.parent_id )).select(%( lesli_shield_role_actions.role_id as role_id, resource_controllers.route as controller, resource_actions.action as action, lesli_shield_role_actions.deleted_at IS NULL as active )).with_deleted # get privileges only for the given role, this is needed to sync only modified roles records = records.where("lesli_shield_role_actions.role_id" => role.id) # get privileges only for the given role action, this is needed to sync only modified actions records = records.where("lesli_shield_role_actions.id" => @action.id) if @action # we use the deleted_at column to know if a privilege is enable or disable, NULL values # at the deleted_at column means privilege is active, so if we sort by deleted_at column # all the active privileges will be at the top, then the uniq method is going to take # always the active values, to completely disable a privilege for a specific controller/action # we have to disable in all the roles records = records.order("lesli_shield_role_actions.deleted_at DESC") # convert the results to json so it is easy to insert/update records = records.as_json(only: [:controller, :action, :role_id, :active]) # IMPORTANT: We must save only uniq privileges in the role_privilege table # this means that it does not matters how many times we defined a privilege dependency # we insert the privilege only once. # Example: If we defined that we need access to UsersController#index in 20 descriptors, # in the role_privileges will be only one record for that specific controller and action records = records.uniq do |privilege| # NOTE: If can disable a privilege that belongs to a descriptor, # however, if the same privilege is define in another active descriptor, # the role that has both descriptor will be able to access the resources # of that privilege, that is a normal and desire behavior. [privilege["controller"], privilege["action"], privilege["role_id"]] end # small check to ensure I have records to update/insert return if records.blank? # bulk update/insert into role privilege cache table # IMPORTANT: Due to the importance and how delicate this process is, it is better # to copy the controller name and actions from the system, instead of # just have a reference to the system_controller_actions table Role::Privilege.with_deleted.upsert_all(records, unique_by: [:controller, :action, :role_id]) end |