Class: Lesli::RoleDescriptorOperator

Inherits:
ApplicationLesliService show all
Defined in:
app/operators/lesli/role_descriptor_operator.rb

Instance Method Summary collapse

Methods inherited from ApplicationLesliService

#create, #delete, #error, #errors, #errors_as_sentence, #find, #found?, #index, #list, #result, #show, #successful?, #update

Constructor Details

#initialize(*roles) ⇒ RoleDescriptorOperator

Returns a new instance of RoleDescriptorOperator.



38
39
40
# File 'app/operators/lesli/role_descriptor_operator.rb', line 38

def initialize *roles
    @roles = roles
end

Instance Method Details

#synchronizeObject

Syncronize the descriptor privileges with the role privilege cache table



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
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'app/operators/lesli/role_descriptor_operator.rb', line 43

def synchronize 

    # 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 = Descriptor.joins(%(
        INNER JOIN lesli_descriptor_privileges
        ON lesli_descriptor_privileges.descriptor_id = lesli_descriptors.id
    )).joins(%(
        INNER JOIN lesli_system_controller_actions 
        ON lesli_system_controller_actions.id = lesli_descriptor_privileges.action_id
    )).joins(%(
        INNER JOIN lesli_system_controllers 
        ON lesli_system_controllers.id = lesli_system_controller_actions.system_controller_id
    )).joins(%(
        INNER JOIN lesli_role_powers 
        ON lesli_role_powers.descriptor_id = lesli_descriptors.id
    )).select(%(
        lesli_system_controllers.route as controller, 
        lesli_system_controller_actions.name as action,
        case 
        when lesli_role_powers.deleted_at is not null then false
        when NULLIF(lesli_system_controller_actions.name = 'list' and lesli_role_powers.plist = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'index' and lesli_role_powers.pindex = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'show' and lesli_role_powers.pshow = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'new' and lesli_role_powers.pcreate = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'create' and lesli_role_powers.pcreate = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'edit' and lesli_role_powers.pupdate = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'update' and lesli_role_powers.pupdate = true, false) then true
        when NULLIF(lesli_system_controller_actions.name = 'destroy' and lesli_role_powers.pdestroy = true, false) then true
        else false 
        end as active,
        lesli_role_powers.role_id as role_id
    )).with_deleted


    # get privileges only for the given role, this is needed to sync only modified roles
    records = records.where("lesli_role_powers.role_id" => @roles)

    # 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 descriptors
    records = records.order("lesli_role_powers.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
    Lesli::Role::Privilege.with_deleted.upsert_all(records, unique_by: [:controller, :action, :role_id])
end