Created
February 25, 2010 17:53
-
-
Save andreasronge/314816 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'neo4j' | |
# include the Module so we can skip the Neo4j:: prefix | |
include Neo4j | |
# this node is accessible from Neo4j.ref_node | |
# add a relationship to the top principal = All principals | |
class Neo4j::ReferenceNode | |
has_one :top_principal | |
end | |
class Principal | |
include NodeMixin | |
has_n :members | |
has_one(:owner).from(Principal, :members) | |
property :name | |
def init_node(name, *members) | |
self.name = name | |
members.each {|m| self.members << m} | |
end | |
def distance_to_owner(principal) | |
dinstance = 0 | |
curr_owner = owner | |
while (curr_owner && owner != principal) do | |
distance += 1 | |
curr_owner = curr_owner.owner | |
end | |
curr_owner ? distance : -1 | |
end | |
def to_s | |
"Principal #{name}" | |
end | |
def self.top | |
Neo4j.ref_node.top_principal ||= Principal.new('ALL_PRINCIPALS') | |
end | |
end | |
class Content | |
include NodeMixin | |
property :name | |
has_one(:parent) | |
has_n(:children).from(Content, :parent) | |
has_n(:accesses) | |
def init_node(name, parent=nil) | |
self.name = name | |
self.parent = parent if parent | |
end | |
def access_for(principal, *flags) | |
security = accesses.new(principal) | |
# flags is varargs param, we expect first parameter to be an hash or nil | |
flags[0].each_pair {|key, value| security[key] = value} if flags[0] | |
end | |
def show_access(principal, flag) | |
if access?(principal, flag) | |
puts "#{principal} HAS access to #{self} with flag #{flag}" | |
else | |
puts "#{principal} has NOT access to #{self} with flag #{flag}" | |
end | |
end | |
def access?(principal, flag) | |
# Move from the content node and upwards through the file system structure and investigate | |
# each level for permission information. | |
access_for_parent?(self, principal, flag) | |
end | |
def access_for_parent?(content, principal, flag) | |
# On each level, see if there are any principals related to or identical with the principal concerned. | |
# Find all relationship accesses with the given flags | |
# using Ruby Enumerable Mixins find_all | |
found = content.accesses_rels.find_all{|access| access[flag] } | |
# Make sure to use the permission information from the principal closest to the principal concerned. | |
# found.min - see Ruby Enumerable#min | |
rel = found.min do |rel1, rel2| | |
principal.distance_to_owner(rel1.start_node) <=> principal.distance_to_owner(rel2.start_node) | |
end | |
# If permission information was found, return it; | |
# otherwise, continue traversing to the next level in the file system. | |
if rel | |
rel[flag] | |
else | |
access_for_parent?(content.parent, principal, flag) # recursive | |
end | |
end | |
def to_s | |
"Content #{name}" | |
end | |
end | |
Neo4j.start | |
Transaction.run do | |
root = Principal.new('root', Principal.top) | |
reg_users = Principal.new('Regualar user', Principal.top) | |
user1 = Principal.new('user1', reg_users) | |
user2 = Principal.new('user2', reg_users) | |
root_folder = Content.new('Root folder') | |
# All principals (top) have read access | |
root_folder.access_for(Principal.top, :r => true) | |
# Root principals have write access | |
root_folder.access_for(root, :w => true) | |
temp_folder = Content.new('Temp', root_folder) | |
# All principals have read access | |
temp_folder.access_for(Principal.top, :r => true) | |
home_folder = Content.new('Home', root_folder) | |
user1_home_folder = Content.new('user1 home', home_folder) | |
# regular user has no read and write access to user1 home folder | |
user1_home_folder.access_for(reg_users, :r => false, :w => false) | |
user1_home_folder.access_for(user1, :r => true, :w => true) | |
# user1 has both read and write access to user1 home folder | |
user2_home_folder = Content.new('user2 home', home_folder) | |
a_file = Content.new("MyFile.pdf", user1_home_folder) | |
home_folder.show_access(root, :w) | |
home_folder.show_access(user1, :w) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment