class PolicyMachineStorageAdapter::InMemory

Constants

POLICY_ELEMENT_TYPES

Public Instance Methods

add_association(user_attribute, operation_set, object_attribute, policy_machine_uuid) click to toggle source

Add the given association to the policy map. If an association between user_attribute and object_attribute already exists, then replace it with that given in the arguments.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 106
def add_association(user_attribute, operation_set, object_attribute, policy_machine_uuid)
  # TODO:  scope by policy machine uuid
  associations[user_attribute.unique_identifier + object_attribute.unique_identifier] =
    [user_attribute, operation_set, object_attribute]

  true
end
assign(src, dst) click to toggle source

Assign src to dst in policy machine

# File lib/policy_machine_storage_adapters/in_memory.rb, line 44
def assign(src, dst)
  assert_persisted_policy_element(src)
  assert_persisted_policy_element(dst)

  assignments << [src, dst]
  true
end
associations_with(operation) click to toggle source

Return all associations in which the given operation is included Returns an array of arrays. Each sub-array is of the form

user_attribute, operation_set, object_attribute
# File lib/policy_machine_storage_adapters/in_memory.rb, line 118
def associations_with(operation)
  matching = associations.values.select do |assoc|
    assoc[1].include?(operation)
  end

  matching.map{ |m| [m[0], m[1], m[2]] }
end
connected?(src, dst) click to toggle source

Determine if there is a path from src to dst in the policy machine

# File lib/policy_machine_storage_adapters/in_memory.rb, line 55
def connected?(src, dst)
  assert_persisted_policy_element(src)
  assert_persisted_policy_element(dst)

  return true if src == dst

  distances = dijkstra(src, dst)
  distances.nil? ? false : true
end
delete(element) click to toggle source

Remove a persisted policy element

# File lib/policy_machine_storage_adapters/in_memory.rb, line 84
def delete(element)
  assignments.delete_if{ |assgn| assgn.include?(element) }
  associations.delete_if { |_,assoc| assoc.include?(element) }
  policy_elements.delete(element)
end
element_in_machine?(pe) click to toggle source

Determine if the given node is in the policy machine or not.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 99
def element_in_machine?(pe)
  policy_elements.member?( pe )
end
policy_classes_for_object_attribute(object_attribute) click to toggle source

Return array of all policy classes which contain the given object_attribute (or object). Return empty array if no such policy classes found.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 129
def policy_classes_for_object_attribute(object_attribute)
  find_all_of_type_policy_class.select do |pc|
    connected?(object_attribute, pc)
  end
end
transaction() { || ... } click to toggle source

Execute the passed-in block transactionally: any error raised out of the block causes all the block’s changes to be rolled back.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 147
def transaction
  old_state = dup
  instance_variables.each do |var|
    value = instance_variable_get(var)

    if (value.respond_to?(:dup))
      old_state.instance_variable_set(var, value.dup)
    end
  end

  begin
    yield
  rescue Exception
    instance_variables.each do |var|
      value = old_state.instance_variable_get(var)
      instance_variable_set(var, value)
    end
    raise
  end
end
unassign(src, dst) click to toggle source

Disconnect two policy elements in the machine

# File lib/policy_machine_storage_adapters/in_memory.rb, line 68
def unassign(src, dst)
  assert_persisted_policy_element(src)
  assert_persisted_policy_element(dst)

  assignment = assignments.find{|assgn| assgn[0] == src && assgn[1] == dst}
  if assignment
    assignments.delete(assignment)
    true
  else
    false
  end
end
update(element, changes_hash) click to toggle source

Update a persisted policy element

# File lib/policy_machine_storage_adapters/in_memory.rb, line 93
def update(element, changes_hash)
  element.send(:extra_attributes).merge!(changes_hash)
end
user_attributes_for_user(user) click to toggle source

Return array of all user attributes which contain the given user. Return empty array if no such user attributes are found.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 138
def user_attributes_for_user(user)
  find_all_of_type_user_attribute.select do |user_attribute|
    connected?(user, user_attribute)
  end
end

Private Instance Methods

assert_persisted_policy_element(arg) click to toggle source

Raise argument error if argument is not suitable for consumption in public methods.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 173
def assert_persisted_policy_element(arg)
  raise(ArgumentError, "arg must be a PersistedPolicyElement; got #{arg.class.name}") unless arg.is_a?(PersistedPolicyElement)
  raise(ArgumentError, "arg must be persisted") unless element_in_machine?(arg)
end
assignments() click to toggle source

The policy element assignments in the persisted policy machine.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 184
def assignments
  @assignments ||= []
end
associations() click to toggle source

All persisted associations

# File lib/policy_machine_storage_adapters/in_memory.rb, line 189
def associations
  @associations ||= {}
end
dijkstra(src, dst = nil) click to toggle source
# File lib/policy_machine_storage_adapters/in_memory.rb, line 193
def dijkstra(src, dst = nil)
  nodes = policy_elements

  distances = {}
  previouses = {}
  nodes.each do |vertex|
    distances[vertex] = nil # Infinity
    previouses[vertex] = nil
  end
  distances[src] = 0
  vertices = nodes.clone
  until vertices.empty?
    nearest_vertex = vertices.inject do |a, b|
      next b unless distances[a]
      next a unless distances[b]
      next a if distances[a] < distances[b]
      b
    end
    break unless distances[nearest_vertex] # Infinity
    if dst and nearest_vertex == dst
      return distances[dst]
    end
    neighbors = neighbors(nearest_vertex)
    neighbors.each do |vertex|
      alt = distances[nearest_vertex] + 1
      if distances[vertex].nil? or alt < distances[vertex]
        distances[vertex] = alt
        previouses[vertices] = nearest_vertex
        # decrease-key v in Q # ???
      end
    end
    vertices.delete nearest_vertex
  end

  return nil
end
neighbors(pe) click to toggle source

Find all nodes which are directly connected to node

# File lib/policy_machine_storage_adapters/in_memory.rb, line 232
def neighbors(pe)
  neighbors = []
  assignments.each do |assignment|
    neighbors.push assignment[1] if assignment[0] == pe
  end
  return neighbors.uniq
end
policy_elements() click to toggle source

The policy elements in the persisted policy machine.

# File lib/policy_machine_storage_adapters/in_memory.rb, line 179
def policy_elements
  @policy_elements ||= []
end