class PolicyMachineStorageAdapter::Neography

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/neography.rb, line 138
def add_association(user_attribute, operation_set, object_attribute, policy_machine_uuid)
  remove_association(user_attribute, object_attribute, policy_machine_uuid)
  
  # TODO:  scope by policy machine uuid
  unique_identifier = user_attribute.unique_identifier + object_attribute.unique_identifier
  node_attrs = {
    :unique_identifier => unique_identifier,
    :policy_machine_uuid => policy_machine_uuid,
    :user_attribute_unique_identifier => user_attribute.unique_identifier,
    :object_attribute_unique_identifier => object_attribute.unique_identifier,
    :operations => operation_set.map(&:unique_identifier).to_json,
  }
  persisted_assoc = ::Neography::Node.create(node_attrs)
  persisted_assoc.add_to_index('associations', 'unique_identifier', unique_identifier)
  
  [user_attribute, object_attribute, *operation_set].each do |element|
    ::Neography::Relationship.create(:in_association, element, persisted_assoc)
  end

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

Assign src to dst in policy machine

# File lib/policy_machine_storage_adapters/neography.rb, line 56
def assign(src, dst)
  assert_persisted_policy_element(src)
  assert_persisted_policy_element(dst)
  
  e = ::Neography::Relationship.create(:outgoing, src, dst)
  
  if e.nil?
    false
  else
    unique_identifier = src.unique_identifier + dst.unique_identifier
    e.add_to_index('edges', 'unique_identifier', unique_identifier)
    true
  end
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/neography.rb, line 165
def associations_with(operation)
  operation.outgoing(:in_association).map do |association|
    user_attribute = ::Neography::Node.find('nodes', 'unique_identifier', association.user_attribute_unique_identifier)
    object_attribute = ::Neography::Node.find('nodes', 'unique_identifier', association.object_attribute_unique_identifier)
    
    operation_set = Set.new
    JSON.parse(association.operations).each do |op_unique_id|
      op_node = ::Neography::Node.find('nodes', 'unique_identifier', op_unique_id)
      operation_set << op_node
    end
    
    [user_attribute, operation_set, object_attribute]
  end      
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/neography.rb, line 74
def connected?(src, dst)
  assert_persisted_policy_element(src)
  assert_persisted_policy_element(dst)
  
  return true if src == dst
  
  neo_connection.execute_query("start n=node({id1}),m=node({id2}) return (n)-[*]->(m)", 
    {:id1 => src.neo_id.to_i, :id2 => dst.neo_id.to_i})['data'] != [[[]]]
end
delete(element) click to toggle source

Remove a persisted policy element

# File lib/policy_machine_storage_adapters/neography.rb, line 111
def delete(element)
  if %w[user_attribute object_attribute].include?(element.pe_type)
    element.outgoing(:in_association).each do |assoc|
      assoc.del
    end
  end
  element.del
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/neography.rb, line 130
def element_in_machine?(pe)
  found_node = ::Neography::Node.find('nodes', 'unique_identifier', pe.unique_identifier)
  !found_node.nil?
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/neography.rb, line 199
def policy_classes_for_object_attribute(object_attribute)
  find_all_of_type_policy_class.select do |pc|
    connected?(object_attribute, pc)
  end
end
remove_association(user_attribute, object_attribute, policy_machine_uuid) click to toggle source

Remove an existing association. Return true if the association was removed and false if it didn’t exist in the first place.

# File lib/policy_machine_storage_adapters/neography.rb, line 183
def remove_association(user_attribute, object_attribute, policy_machine_uuid)
  unique_identifier = user_attribute.unique_identifier + object_attribute.unique_identifier
  
  begin
    assoc_node = ::Neography::Node.find('associations', 'unique_identifier', unique_identifier)
    return false unless assoc_node
    assoc_node.del
    true
  rescue ::Neography::NotFoundException
    false
  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/neography.rb, line 218
def transaction
  raise NotImplementedError, "transactions are only available in neo4j 2.0 which #{self.class} is not compatible with"
end
unassign(src, dst) click to toggle source

Disconnect two policy elements in the machine

# File lib/policy_machine_storage_adapters/neography.rb, line 87
def unassign(src, dst)
  assert_persisted_policy_element(src)
  assert_persisted_policy_element(dst)
  
  unique_identifier = src.unique_identifier + dst.unique_identifier
  found_edges = ::Neography::Relationship.find('edges', 'unique_identifier', unique_identifier)
  
  if found_edges
    # Neography::Relationship doesn't respond to .to_a
    found_edges = [found_edges] unless found_edges.is_a?(Array)
    found_edges.each do |found_edge|
      # Unfortunately, we have to reload the edge as find isn't deserializing it properly.
      e = ::Neography::Relationship.load(found_edge.neo_id.to_i)
      e.del unless e.nil?
    end
    true
  else
    false
  end
end
update(element, changes_hash) click to toggle source

Update a persisted policy element

# File lib/policy_machine_storage_adapters/neography.rb, line 123
def update(element, changes_hash)
  element.neo_server.set_node_properties(element.neo_id, 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/neography.rb, line 208
def user_attributes_for_user(user)
  #Don't use this kind of query plan in a for-production adapter.
  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/neography.rb, line 226
def assert_persisted_policy_element(arg)
  raise(ArgumentError, "arg must be a Neography::Node; got #{arg.class.name}") unless arg.is_a?(::Neography::Node)
  raise(ArgumentError, "arg must be persisted") unless element_in_machine?(arg)
end
neo_connection() click to toggle source

Neo4j client

# File lib/policy_machine_storage_adapters/neography.rb, line 232
def neo_connection
  @neo_connection ||= ::Neography::Rest.new
end