Module: RoleFu::Roleable

Extended by:
ActiveSupport::Concern
Defined in:
lib/role_fu/roleable.rb

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



212
213
214
215
216
217
218
# File 'lib/role_fu/roleable.rb', line 212

def method_missing(method_name, *args, &block)
  if (role_name = parse_dynamic_role_name(method_name))
    has_role?(role_name, *args)
  else
    super
  end
end

Instance Method Details

#add_role(role_name, resource = nil, expires_at: nil, meta: nil) ⇒ Object Also known as: grant



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/role_fu/roleable.rb', line 97

def add_role(role_name, resource = nil, expires_at: nil, meta: nil)
  role = find_or_create_role(role_name, resource)
  existing_assignment = role_assignments.find_by(role: role)

  if existing_assignment
    if expires_at || meta
      updates = {}
      updates[:expires_at] = expires_at if expires_at
      updates[:meta] = meta if meta
      existing_assignment.update(updates)
    end
    return role
  end

  run_role_fu_callback(:before_add, role)
  role_assignments.create!(role: role, expires_at: expires_at, meta: meta)
  roles.reload
  run_role_fu_callback(:after_add, role)

  role
end

#has_all_roles?(*role_names, resource: nil) ⇒ Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/role_fu/roleable.rb', line 193

def has_all_roles?(*role_names, resource: nil)
  role_names.flatten.all? { |role_name| has_role?(role_name, resource) }
end

#has_any_role?(resource = nil) ⇒ Boolean

Returns:

  • (Boolean)


188
189
190
191
# File 'lib/role_fu/roleable.rb', line 188

def has_any_role?(resource = nil)
  scope = resource ? roles.where(resource: resource) : roles
  filter_expired(scope).exists?
end

#has_any_role_of?(*role_names, resource: nil) ⇒ Boolean

Returns:

  • (Boolean)


197
198
199
# File 'lib/role_fu/roleable.rb', line 197

def has_any_role_of?(*role_names, resource: nil)
  role_names.flatten.any? { |role_name| has_role?(role_name, resource) }
end

#has_cached_role?(role_name, resource = nil) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/role_fu/roleable.rb', line 159

def has_cached_role?(role_name, resource = nil)
  role_name = role_name.to_s
  roles.to_a.any? do |role|
    next false unless role.name == role_name

    assignment = role_assignments.find { |ra| ra.role_id == role.id }
    next false if assignment&.respond_to?(:expires_at) && assignment.expires_at && assignment.expires_at <= Time.current

    if resource == :any
      true
    elsif resource.is_a?(Class)
      role.resource_type == resource.to_s && role.resource_id.nil?
    elsif resource
      role.resource_type == resource.class.name && role.resource_id == resource.id
    else
      role.resource_type.nil? && role.resource_id.nil?
    end
  end
end

#has_only_global_roles?Boolean

Returns:

  • (Boolean)


184
185
186
# File 'lib/role_fu/roleable.rb', line 184

def has_only_global_roles?
  filter_expired(roles).where.not(resource_type: nil).empty?
end

#has_role?(role_name, resource = nil) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/role_fu/roleable.rb', line 135

def has_role?(role_name, resource = nil)
  return false if role_name.nil?

  if resource == :any
    filter_expired(roles.where(name: role_name.to_s)).exists?
  else
    return true if filter_expired(find_roles(role_name, resource)).any?

    if RoleFu.configuration.global_roles_override && resource && !resource.is_a?(Class)
      return filter_expired(find_roles(role_name, nil)).any?
    end

    false
  end
end

#has_strict_role?(role_name, resource = nil) ⇒ Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/role_fu/roleable.rb', line 151

def has_strict_role?(role_name, resource = nil)
  filter_expired(find_roles(role_name, resource)).any?
end

#only_has_role?(role_name, resource = nil) ⇒ Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/role_fu/roleable.rb', line 155

def only_has_role?(role_name, resource = nil)
  has_role?(role_name, resource) && filter_expired(roles).count == 1
end

#remove_role(role_name, resource = nil) ⇒ Object Also known as: revoke



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/role_fu/roleable.rb', line 120

def remove_role(role_name, resource = nil)
  roles_to_remove_relation = find_roles(role_name, resource)
  return [] if roles_to_remove_relation.empty?

  removed_roles = roles_to_remove_relation.to_a
  removed_roles.each do |role|
    run_role_fu_callback(:before_remove, role)
    role_assignments.where(role_id: role.id).destroy_all
    run_role_fu_callback(:after_remove, role)
  end

  removed_roles
end

#resources(resource_class) ⇒ Object



201
202
203
204
205
206
207
208
209
210
# File 'lib/role_fu/roleable.rb', line 201

def resources(resource_class)
  assignment_table = RoleFu.role_assignment_class.table_name
  query = resource_class.joins(:roles).merge(roles.where(resource_type: resource_class.name))

  if RoleFu.role_assignment_class.column_names.include?("expires_at")
    query = query.where("#{assignment_table}.expires_at IS NULL OR #{assignment_table}.expires_at > ?", Time.current)
  end

  query.distinct
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/role_fu/roleable.rb', line 220

def respond_to_missing?(method_name, include_private = false)
  parse_dynamic_role_name(method_name) || super
end

#roles_name(resource = nil) ⇒ Object



179
180
181
182
# File 'lib/role_fu/roleable.rb', line 179

def roles_name(resource = nil)
  scope = resource ? roles.where(resource: resource) : roles
  filter_expired(scope).pluck(:name)
end