Ruby-ACL 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/ACL_Object.rb +224 -0
- data/lib/Ruby-ACL.rb +908 -0
- data/lib/ace.rb +91 -0
- data/lib/ace_rule.rb +36 -0
- data/lib/group.rb +32 -0
- data/lib/individual.rb +14 -0
- data/lib/principal.rb +44 -0
- data/lib/privilege.rb +13 -0
- data/lib/resource_object.rb +208 -0
- data/lib/rubyacl_exception.rb +69 -0
- metadata +57 -0
data/lib/ACL_Object.rb
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
|
|
2
|
+
class ACL_Object
|
|
3
|
+
|
|
4
|
+
attr_reader :doc
|
|
5
|
+
attr_reader :col_path
|
|
6
|
+
|
|
7
|
+
def initialize(connector, col_path, report = false)
|
|
8
|
+
@connector = connector
|
|
9
|
+
@col_path = col_path
|
|
10
|
+
@report = report
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private #--------------PRIVATE-----------------------------------------------
|
|
14
|
+
|
|
15
|
+
def generate_expr(name)
|
|
16
|
+
expr = <<END
|
|
17
|
+
<#{self.class.name} id="#{name}">
|
|
18
|
+
<membership>
|
|
19
|
+
|
|
20
|
+
</membership>
|
|
21
|
+
</#{self.class.name}>
|
|
22
|
+
END
|
|
23
|
+
return expr
|
|
24
|
+
rescue => e
|
|
25
|
+
raise e
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def exists?(name, query = "#{@doc}//node()[@id=\"#{name}\"]")
|
|
29
|
+
handle = @connector.execute_query(query)
|
|
30
|
+
hits = @connector.get_hits(handle)
|
|
31
|
+
if(hits >= 1)
|
|
32
|
+
return true
|
|
33
|
+
else
|
|
34
|
+
return false
|
|
35
|
+
end
|
|
36
|
+
rescue => e
|
|
37
|
+
raise e
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def exist_membership?(name, member_of) #Is <name> member of <member_of>
|
|
41
|
+
expr = "#{@doc}//#{self.class.name}s/descendant::*[@id=\"#{name}\"]/membership/mgroup[@idref=\"#{member_of}\"]"
|
|
42
|
+
exists?(name, expr)
|
|
43
|
+
rescue => e
|
|
44
|
+
raise e
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
public #------------------PUBLIC----------------------------------------------
|
|
48
|
+
|
|
49
|
+
def create_new(name, groups)
|
|
50
|
+
bool=true
|
|
51
|
+
if(name == nil || name == '')
|
|
52
|
+
bool = false
|
|
53
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
54
|
+
"Name is empty", 110), caller
|
|
55
|
+
end
|
|
56
|
+
if(exists?(name))
|
|
57
|
+
bool = false
|
|
58
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
59
|
+
"#{self.class.name} \"#{name}\" already exist(s)", 111), caller
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if(bool)
|
|
63
|
+
expr = generate_expr(name)
|
|
64
|
+
expr_loc = "#{@doc}//#{self.class.name}s/#{self.class.name}[last()]"
|
|
65
|
+
@connector.update_insert(expr, "following", expr_loc)
|
|
66
|
+
if(exists?(name))
|
|
67
|
+
puts "New #{self.class.name} \"#{name}\" created." if @report
|
|
68
|
+
else
|
|
69
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
70
|
+
"#{self.class.name} \"#{name}\" was not able to create", 112), caller
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
if(groups.length > 0)
|
|
74
|
+
add_membership(name, groups, true)
|
|
75
|
+
end
|
|
76
|
+
return name
|
|
77
|
+
rescue XMLRPC::FaultException => e
|
|
78
|
+
raise e
|
|
79
|
+
rescue => e
|
|
80
|
+
raise e
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
#adds acl object into group(s); if you know prin exists set true for prin_exists
|
|
84
|
+
def add_membership(name, groups, ob_exists = false)
|
|
85
|
+
if(ob_exists || exists?(name))#, "#{@doc}//Individual[@id=\"#{name}\"]"))
|
|
86
|
+
for group in groups
|
|
87
|
+
if(!exists?(group))#, "#{@doc}//Group[@id=\"#{group}\"]"))
|
|
88
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
89
|
+
"Failed to add membership. Group \"#{group}\" does not exist.", 113), caller
|
|
90
|
+
end
|
|
91
|
+
query = "#{@doc}//node()[@id=\"#{name}\"]/membership/mgroup[@idref=\"#{group}\"]"
|
|
92
|
+
handle = @connector.execute_query(query)
|
|
93
|
+
hits = @connector.get_hits(handle)
|
|
94
|
+
if(hits == 0)
|
|
95
|
+
#protection against cycle in membership
|
|
96
|
+
if(find_parents(group).find_index(name).nil?)
|
|
97
|
+
expr = "<mgroup idref=\"#{group}\"/>"
|
|
98
|
+
expr_single = "#{@doc}//node()[@id=\"#{name}\"]/membership"
|
|
99
|
+
@connector.update_insert(expr, "into", expr_single)
|
|
100
|
+
else
|
|
101
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
102
|
+
"Failed to add membership. Membership is in cycle.", 118), caller
|
|
103
|
+
end
|
|
104
|
+
else
|
|
105
|
+
puts "Membership already exists." if @report
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
else
|
|
109
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
110
|
+
"Failed to add membership. #{self.class.name} \"#{name}\" does not exist.", 114), caller
|
|
111
|
+
end
|
|
112
|
+
return name
|
|
113
|
+
rescue => e
|
|
114
|
+
raise e
|
|
115
|
+
end #def add_membership
|
|
116
|
+
|
|
117
|
+
def del_membership(name, groups) #deletes prin_name from group(s)
|
|
118
|
+
if(exists?(name))
|
|
119
|
+
for group in groups
|
|
120
|
+
expr = "#{@doc}//#{self.class.name}s/descendant::*[@id=\"#{name}\"]/membership/mgroup[@idref=\"#{group}\"]"
|
|
121
|
+
@connector.update_delete(expr)
|
|
122
|
+
#end
|
|
123
|
+
if(!exists?(group))
|
|
124
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
125
|
+
"Failed to delete membership. Group \"#{group}\" does not exist.", 115), caller
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
else
|
|
129
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
130
|
+
"Failed to delete membership. #{self.class.name} \"#{name}\" does not exist.", 116), caller
|
|
131
|
+
end
|
|
132
|
+
return name
|
|
133
|
+
rescue => e
|
|
134
|
+
raise e
|
|
135
|
+
end #def del_membership
|
|
136
|
+
|
|
137
|
+
def delete(name)
|
|
138
|
+
if(exists?(name))
|
|
139
|
+
#deletes ACL_Object
|
|
140
|
+
expr = "#{@doc}//#{self.class.name}s/descendant::*[@id=\"#{name}\"]"
|
|
141
|
+
@connector.update_delete(expr)
|
|
142
|
+
#deletes references at ACL_Object
|
|
143
|
+
expr = "#{@doc}//node()[@idref=\"#{name}\"]"
|
|
144
|
+
@connector.update_delete(expr)
|
|
145
|
+
#deletes ACE mentioning ACL_Object
|
|
146
|
+
expr = "doc(\"#{@col_path}acl.xml\")//node()[@idref=\"#{name}\"]/parent::node()"
|
|
147
|
+
@connector.update_delete(expr)
|
|
148
|
+
else
|
|
149
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
150
|
+
"Failed to delete #{self.class.name}. #{self.class.name} \"#{name}\" does not exist.", 117), caller
|
|
151
|
+
end
|
|
152
|
+
return name
|
|
153
|
+
rescue => e
|
|
154
|
+
raise e
|
|
155
|
+
end #def delete
|
|
156
|
+
|
|
157
|
+
def rename(old_name, new_name)
|
|
158
|
+
if(!exists?(new_name))
|
|
159
|
+
|
|
160
|
+
expr = "#{@doc}//node()[@id=\"#{old_name}\"]/@id"
|
|
161
|
+
expr_single = "\"#{new_name}\""
|
|
162
|
+
@connector.update_value(expr, expr_single)
|
|
163
|
+
|
|
164
|
+
expr = "#{@doc}//node()[@idref=\"#{old_name}\"]/@idref"
|
|
165
|
+
expr_single = "\"#{new_name}\""
|
|
166
|
+
@connector.update_value(expr, expr_single)
|
|
167
|
+
|
|
168
|
+
expr = "doc(\"#{@col_path}acl.xml\")//node()[@idref=\"#{old_name}\"]/@idref"
|
|
169
|
+
expr_single = "\"#{new_name}\""
|
|
170
|
+
@connector.update_value(expr, expr_single)
|
|
171
|
+
|
|
172
|
+
query = "doc(\"#{@col_path}acl.xml\")//node()[@id=\"#{old_name}\"]"
|
|
173
|
+
handle = @connector.execute_query(query)
|
|
174
|
+
hits = @connector.get_hits(handle)
|
|
175
|
+
query = "#{@doc}//node()[@id=\"#{old_name}\"]"
|
|
176
|
+
handle = @connector.execute_query(query)
|
|
177
|
+
hits += @connector.get_hits(handle)
|
|
178
|
+
if(hits == 0)
|
|
179
|
+
puts "Rename succeeded." if @report
|
|
180
|
+
else
|
|
181
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
182
|
+
"Failed to rename", 120), caller
|
|
183
|
+
end
|
|
184
|
+
else
|
|
185
|
+
raise RubyACLException.new(self.class.name, __method__,
|
|
186
|
+
"Failed to rename #{self.class.name}. #{self.class.name} \"#{new_name}\" already exists.", 119), caller
|
|
187
|
+
end
|
|
188
|
+
return old_name
|
|
189
|
+
rescue XMLRPC::FaultException => e
|
|
190
|
+
raise e
|
|
191
|
+
rescue => e
|
|
192
|
+
raise e
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def ge(t, f)
|
|
196
|
+
if(t >= f)
|
|
197
|
+
return true
|
|
198
|
+
else
|
|
199
|
+
return false
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
#finds membership parrent and returns in sorted array by level,
|
|
204
|
+
#Root is first leaf is last.
|
|
205
|
+
#e.g. dog's parrent is mammal.
|
|
206
|
+
def find_parents(id)
|
|
207
|
+
query = "#{@doc}//node()[@id=\"#{id}\"]/membership/*/string(@idref)"
|
|
208
|
+
ids = []
|
|
209
|
+
handle = @connector.execute_query(query)
|
|
210
|
+
hits = @connector.get_hits(handle)
|
|
211
|
+
hits.times {
|
|
212
|
+
|i|
|
|
213
|
+
id_ref = @connector.retrieve(handle, i)
|
|
214
|
+
if(id_ref=="")
|
|
215
|
+
next #for unknown reason eXist returns 1 empty hit even any exists therefore unite is skipped (e.g. //node()[@id="all"]/membership/*/string(@idref)
|
|
216
|
+
end
|
|
217
|
+
ids = find_parents(id_ref) | ids | [id_ref] #unite arrays
|
|
218
|
+
}
|
|
219
|
+
return ids
|
|
220
|
+
rescue => e
|
|
221
|
+
raise e
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
end
|
data/lib/Ruby-ACL.rb
ADDED
|
@@ -0,0 +1,908 @@
|
|
|
1
|
+
$:.unshift("./lib")
|
|
2
|
+
$:.unshift(".")
|
|
3
|
+
$:.unshift('D:\\eXistAPI\\lib\\')
|
|
4
|
+
require 'ACL_Object'
|
|
5
|
+
require 'Principal'
|
|
6
|
+
require 'individual'
|
|
7
|
+
require 'group'
|
|
8
|
+
require 'privilege'
|
|
9
|
+
require 'resource_object'
|
|
10
|
+
require 'ace'
|
|
11
|
+
require 'date'
|
|
12
|
+
require 'ace_rule'
|
|
13
|
+
require 'rubyacl_exception'
|
|
14
|
+
|
|
15
|
+
#RubyACL is library that handles access permisions. RubyACL offers to create and modify three ACL objects - three dimensions: Principal, Privilege, Resource object.
|
|
16
|
+
#Principal is someone or something that want to access.
|
|
17
|
+
#Privilege is level of access. (read, write etc.).
|
|
18
|
+
#Resource object is what is principal accessing.
|
|
19
|
+
#RubyACL uses API interface to communicate with database. This interface is described by class API_inteface.
|
|
20
|
+
#At the end of the class you can see set of examples. Also good source of information are testcases.
|
|
21
|
+
class RubyACL
|
|
22
|
+
|
|
23
|
+
# name of the ACL
|
|
24
|
+
attr_reader :name
|
|
25
|
+
# collection path in db, where ACL will be stored.
|
|
26
|
+
attr_reader :col_path
|
|
27
|
+
|
|
28
|
+
#Creates new instance of Ruby-ACL. Ruby-ACL works if principals, privileges and resource object.
|
|
29
|
+
#With Ruby-ACL you can manage permsion to person for resource objects.
|
|
30
|
+
#
|
|
31
|
+
# * *Args* :
|
|
32
|
+
# - +name+ -> name of the ACL
|
|
33
|
+
# - +connector+ -> instance of connection manager with db. e.g. ExistAPI.new("http://localhost:8080/exist/xmlrpc", "admin", "admin")
|
|
34
|
+
# - +colpath+ -> path of collection in db. e.g. "/db/acl/"
|
|
35
|
+
# - +src_files_path+ -> path of source files in local location.
|
|
36
|
+
# - +report+ -> boolean - if true Ruby-ACL
|
|
37
|
+
# * *Returns* :
|
|
38
|
+
# - instance of RubyACL
|
|
39
|
+
# * *Raises* :
|
|
40
|
+
# - +RubyACLException+ -> Name is empty
|
|
41
|
+
def initialize(name, connector, colpath = "/db/acl/", src_files_path = "./src_files/", report = false)
|
|
42
|
+
if(name == "")
|
|
43
|
+
raise RubyACLException.new(self.class.name, __method__, "Name is empty", 0), caller
|
|
44
|
+
end
|
|
45
|
+
@name = name
|
|
46
|
+
@connector = connector
|
|
47
|
+
if(colpath[-1] != "/")
|
|
48
|
+
colpath += "/"
|
|
49
|
+
end
|
|
50
|
+
@col_path = colpath
|
|
51
|
+
@src_files_path = src_files_path
|
|
52
|
+
@report = report
|
|
53
|
+
@prin = Principal.new(@connector, @col_path, @report)
|
|
54
|
+
@indi = Individual.new(@connector, @col_path, @report)
|
|
55
|
+
@group = Group.new(@connector, @col_path, @report)
|
|
56
|
+
@priv = Privilege.new(@connector, @col_path, @report)
|
|
57
|
+
@res_obj = ResourceObject.new(@connector, @col_path, @report)
|
|
58
|
+
@ace = Ace.new(@connector, @col_path, @report)
|
|
59
|
+
create_acl_in_db()
|
|
60
|
+
rename(name)
|
|
61
|
+
rescue => e
|
|
62
|
+
raise e
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private # private methods follow
|
|
66
|
+
|
|
67
|
+
def create_acl_in_db()
|
|
68
|
+
if(!@connector.existscollection?(@col_path))
|
|
69
|
+
#puts "Collection doesn't exist. Creating collection."
|
|
70
|
+
@connector.createcollection(@col_path)
|
|
71
|
+
end
|
|
72
|
+
col = @connector.getcollection(@col_path)
|
|
73
|
+
sfs = missing_src_files(col)
|
|
74
|
+
if(sfs != []) #creates array of documents that dont exist in collection
|
|
75
|
+
missing_files = ""
|
|
76
|
+
sfs.each { |sf|
|
|
77
|
+
missing_files = missing_files + '"'+sf+'"'
|
|
78
|
+
if(sf != sfs.last())
|
|
79
|
+
missing_files = missing_files + ", "
|
|
80
|
+
end
|
|
81
|
+
}
|
|
82
|
+
#Creating new source file(s)
|
|
83
|
+
for sfile in sfs
|
|
84
|
+
xmlfile = File.read(@src_files_path + sfile)
|
|
85
|
+
@connector.storeresource(xmlfile, @col_path + sfile)
|
|
86
|
+
end
|
|
87
|
+
col = @connector.getcollection(@col_path)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if(col.name == @col_path && missing_src_files(col) == [])
|
|
91
|
+
puts "ACL collection with source files created." if @report
|
|
92
|
+
else
|
|
93
|
+
raise RubyACLException.new(self.class.name, __method__, "Failed to create ACL in database", 1), caller
|
|
94
|
+
end
|
|
95
|
+
rescue XMLRPC::FaultException => e
|
|
96
|
+
raise e
|
|
97
|
+
rescue => e
|
|
98
|
+
raise e
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def missing_src_files(col) #returns array of files that are not present in acl collection
|
|
102
|
+
files = []
|
|
103
|
+
if(col['acl.xml'] == nil)
|
|
104
|
+
files.push('acl.xml')
|
|
105
|
+
end
|
|
106
|
+
if(col['Principals.xml'] == nil)
|
|
107
|
+
files.push('Principals.xml')
|
|
108
|
+
end
|
|
109
|
+
if(col['Privileges.xml'] == nil)
|
|
110
|
+
files.push('Privileges.xml')
|
|
111
|
+
end
|
|
112
|
+
if(col['ResourceObjects.xml'] == nil)
|
|
113
|
+
files.push('ResourceObjects.xml')
|
|
114
|
+
end
|
|
115
|
+
return files
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def decide(res)
|
|
119
|
+
#puts "decide"
|
|
120
|
+
if(res == "allow")
|
|
121
|
+
return true
|
|
122
|
+
elsif(res == "deny")
|
|
123
|
+
return false
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#Returns ACE that has higher priority.
|
|
128
|
+
#Lowest number has highest priority:
|
|
129
|
+
#1. Owner - owner is handled in method check
|
|
130
|
+
#2. Explicit Deny
|
|
131
|
+
#3. Explicit Allow
|
|
132
|
+
#4. Inherited Deny
|
|
133
|
+
#5. Inherited Allow
|
|
134
|
+
#6. If not found then Access denied
|
|
135
|
+
#
|
|
136
|
+
# * *Args* :
|
|
137
|
+
# - +final_ace+ -> first ace to compare
|
|
138
|
+
# - +temp_ace+ -> second ace to compare
|
|
139
|
+
# * *Returns* :
|
|
140
|
+
# - returns ace that has higher priority
|
|
141
|
+
# * *Raises* :
|
|
142
|
+
# - +RubyACLException+ -> Failed to create ACL in database
|
|
143
|
+
#
|
|
144
|
+
def compare(final_ace, temp_ace) #returns ace that has higher priority
|
|
145
|
+
if(final_ace == nil)
|
|
146
|
+
return temp_ace
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
if(@prin.eq(temp_ace, final_ace) && final_ace.acc_type == "deny")
|
|
150
|
+
if(@priv.ge(temp_ace, final_ace, @privs) && @res_obj.ge(temp_ace, final_ace, @res_obs))
|
|
151
|
+
final_ace = temp_ace
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
if(@prin.ne(temp_ace, final_ace))
|
|
156
|
+
if(@priv.ge(temp_ace, final_ace, @privs) && @res_obj.ge(temp_ace, final_ace, @res_obs))
|
|
157
|
+
final_ace = temp_ace
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
return final_ace
|
|
161
|
+
rescue => e
|
|
162
|
+
raise e
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
#Prepares query in xQuery language. This query selects all ace that has
|
|
166
|
+
#principale && one of the privileges && one of the resource objects.
|
|
167
|
+
#
|
|
168
|
+
#
|
|
169
|
+
# * *Args* :
|
|
170
|
+
# - +prin+ -> principal
|
|
171
|
+
# - +privs+ -> privilege and all parental privileges
|
|
172
|
+
# - +res_obs+ -> resource object and all parental resource objects
|
|
173
|
+
# * *Returns* :
|
|
174
|
+
# - string, created query
|
|
175
|
+
# * *Raises* :
|
|
176
|
+
# - +nothing+
|
|
177
|
+
#
|
|
178
|
+
def prepare_query(prin, privs, res_obs)
|
|
179
|
+
query = <<END
|
|
180
|
+
for $ace in #{@ace.doc}//Ace
|
|
181
|
+
where (
|
|
182
|
+
END
|
|
183
|
+
|
|
184
|
+
query += "($ace/Principal/@idref=\"#{prin}\")"
|
|
185
|
+
|
|
186
|
+
query += " and ("
|
|
187
|
+
for priv in privs
|
|
188
|
+
query += "$ace/Privilege/@idref=\"#{priv}\""
|
|
189
|
+
if(priv != privs.last)
|
|
190
|
+
query+=" or "
|
|
191
|
+
else
|
|
192
|
+
query+=") "
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
query += " and ("
|
|
197
|
+
for res_ob in res_obs
|
|
198
|
+
query += "$ace/ResourceObject/@idref=\"#{res_ob}\""
|
|
199
|
+
if(res_ob != res_obs.last)
|
|
200
|
+
query+=" or "
|
|
201
|
+
else
|
|
202
|
+
query+=") "
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
query+=")"
|
|
206
|
+
query += "return $ace/string(@id)"
|
|
207
|
+
return query
|
|
208
|
+
rescue => e
|
|
209
|
+
raise e
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
#In array res_obs are all optencial resource objects.
|
|
213
|
+
#It transform array into string (id="something" or id=... and so on)
|
|
214
|
+
def is_owner?(prin_name, res_obs)
|
|
215
|
+
res_obs = prepare_res_obs(res_obs)
|
|
216
|
+
#Select only those resOb that have wanted owner.
|
|
217
|
+
query = "#{@res_obj.doc}//ResourceObject[#{res_obs} and owner/string(@idref)=\"#{prin_name}\"]"
|
|
218
|
+
#puts query
|
|
219
|
+
handle = @connector.execute_query(query)
|
|
220
|
+
hits = @connector.get_hits(handle)
|
|
221
|
+
if(hits>0) #if owner exist, lets grand access
|
|
222
|
+
return true
|
|
223
|
+
else
|
|
224
|
+
return false
|
|
225
|
+
end
|
|
226
|
+
rescue => e
|
|
227
|
+
raise e
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
#Creates part of the query. Inserts "or" between each of resource object and whole string is in ()
|
|
231
|
+
#
|
|
232
|
+
# * *Args* :
|
|
233
|
+
# - +res_obs+ -> array of resource objects
|
|
234
|
+
# * *Returns* :
|
|
235
|
+
# -string
|
|
236
|
+
# * *Raises* :
|
|
237
|
+
# - +nothing+
|
|
238
|
+
#
|
|
239
|
+
def prepare_res_obs(res_obs)
|
|
240
|
+
str = "("
|
|
241
|
+
for res_ob in res_obs
|
|
242
|
+
str = str + "@id=\""
|
|
243
|
+
str += res_ob
|
|
244
|
+
str += "\" or "
|
|
245
|
+
end
|
|
246
|
+
str = str[0..-4] #delete last " OR "
|
|
247
|
+
str += ")"
|
|
248
|
+
return str
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
#Creates ace in acl.xml in db
|
|
252
|
+
#
|
|
253
|
+
# * *Args* :
|
|
254
|
+
# - +prin_name+ -> name of the principal
|
|
255
|
+
# - +acc_type+ -> access type. allow to allow. deny to revoke
|
|
256
|
+
# - +priv_name+ -> name of the privilege
|
|
257
|
+
# - +res_ob_type+ -> type of resource object
|
|
258
|
+
# - +res_ob_adrs+ -> address of resource object.
|
|
259
|
+
# * *Returns* :
|
|
260
|
+
# -id of ace
|
|
261
|
+
# * *Raises* :
|
|
262
|
+
# - +nothing+
|
|
263
|
+
#
|
|
264
|
+
def insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adrs)
|
|
265
|
+
res_ob_id = @res_obj.find_res_ob(res_ob_type, res_ob_adrs)
|
|
266
|
+
if(res_ob_id == nil)
|
|
267
|
+
res_ob_id = @res_obj.create_new(res_ob_type, res_ob_adrs, prin_name)
|
|
268
|
+
end
|
|
269
|
+
id = @ace.create_new(prin_name, acc_type, priv_name, res_ob_id)
|
|
270
|
+
return id
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
protected
|
|
274
|
+
|
|
275
|
+
public # follow public methods
|
|
276
|
+
|
|
277
|
+
#Renames acl (also in db)
|
|
278
|
+
#
|
|
279
|
+
# * *Args* :
|
|
280
|
+
# - +new_name+ -> new name of acl
|
|
281
|
+
# * *Returns* :
|
|
282
|
+
# -int, handle of the query
|
|
283
|
+
# * *Raises* :
|
|
284
|
+
# - +RubyACLException+ -> Failed to set new name
|
|
285
|
+
#
|
|
286
|
+
def rename(new_name)
|
|
287
|
+
query = "update value doc(\"#{@col_path}acl.xml\")/acl/@aclname with \"#{new_name}\""
|
|
288
|
+
@connector.execute_query(query)
|
|
289
|
+
query = "doc(\"#{@col_path}acl.xml\")/acl/string(@aclname)"
|
|
290
|
+
handle = @connector.execute_query(query)
|
|
291
|
+
if(new_name != @connector.retrieve(handle, 0))
|
|
292
|
+
raise RubyACLException.new(self.class.name, __method__, "Failed to set new name", 2), caller
|
|
293
|
+
end
|
|
294
|
+
rescue XMLRPC::FaultException => e
|
|
295
|
+
raise e
|
|
296
|
+
rescue => e
|
|
297
|
+
raise e
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
#It saves/backs up acl
|
|
301
|
+
#
|
|
302
|
+
# * *Args* :
|
|
303
|
+
# - +path+ -> to local location
|
|
304
|
+
# * *Returns* :
|
|
305
|
+
# - array of documents in ACL working collection
|
|
306
|
+
# * *Raises* :
|
|
307
|
+
# - +nothing+
|
|
308
|
+
#
|
|
309
|
+
def save(path, date = false)
|
|
310
|
+
col = @connector.getcollection(@col_path)
|
|
311
|
+
docs = col.docs()
|
|
312
|
+
if(date)
|
|
313
|
+
path = path + Date.today.to_s + "/"
|
|
314
|
+
end
|
|
315
|
+
if(!File.exists?(path))
|
|
316
|
+
Dir.mkdir(path)
|
|
317
|
+
end
|
|
318
|
+
docs.each{|doc|
|
|
319
|
+
document = col[doc]
|
|
320
|
+
#doc = doc + "_BU"
|
|
321
|
+
filename = path + doc
|
|
322
|
+
f = File.new(filename, 'w')
|
|
323
|
+
f.puts(document.content)
|
|
324
|
+
f.close
|
|
325
|
+
}
|
|
326
|
+
rescue => e
|
|
327
|
+
raise e
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
#It loads backuped acl data.
|
|
331
|
+
#
|
|
332
|
+
# * *Args* :
|
|
333
|
+
# - +connector+ -> instance of connection manager with db. e.g. ExistAPI.new("http://localhost:8080/exist/xmlrpc", "admin", "admin")
|
|
334
|
+
# - +colpath+ -> path of collection in db. e.g. "/db/acl/"
|
|
335
|
+
# - +src_files_path+ -> path of source files in local location.
|
|
336
|
+
# - +report+ -> boolean - if true Ruby-ACL
|
|
337
|
+
# * *Returns* :
|
|
338
|
+
# -new instance of Ruby-ACL
|
|
339
|
+
# * *Raises* :
|
|
340
|
+
# - +nothin+
|
|
341
|
+
#
|
|
342
|
+
def RubyACL.load(connector, colpath, src_files_path, report = false)
|
|
343
|
+
xmlfile = File.read(src_files_path+"acl.xml")
|
|
344
|
+
startindex = xmlfile.index('"', xmlfile.index("aclname="))
|
|
345
|
+
endindex = xmlfile.index('"', startindex+1)
|
|
346
|
+
name = xmlfile[startindex+1..endindex-1]
|
|
347
|
+
newacl = RubyACL.new(name, connector, colpath, src_files_path, report)
|
|
348
|
+
return newacl
|
|
349
|
+
rescue => e
|
|
350
|
+
raise e
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
#Decides whether principal has privilege or not to resource object identified
|
|
354
|
+
#by access type and address. If the accessType of ace is allow - returns true.
|
|
355
|
+
#If accessType of ace is deny return false.
|
|
356
|
+
#
|
|
357
|
+
#Priority of decision is as follows lower.
|
|
358
|
+
#Lowest number has highest priority:
|
|
359
|
+
#1. Owner
|
|
360
|
+
#2. Explicit Deny
|
|
361
|
+
#3. Explicit Allow
|
|
362
|
+
#4. Inherited Deny
|
|
363
|
+
#5. Inherited Allow
|
|
364
|
+
#6. If not found then Deny
|
|
365
|
+
#
|
|
366
|
+
# * *Args* :
|
|
367
|
+
# - +prin_name+ -> name of the principal
|
|
368
|
+
# - +priv_name+ -> name of the privilege
|
|
369
|
+
# - +res_ob_type+ -> type of the resource object
|
|
370
|
+
# - +res_ob_adr+ -> address of the resource object
|
|
371
|
+
# * *Returns* :
|
|
372
|
+
# -boolean - true - has privilege to resource object, false - has not
|
|
373
|
+
# * *Raises* :
|
|
374
|
+
# - +nothing+
|
|
375
|
+
#
|
|
376
|
+
def check(prin_name, priv_name, res_ob_type, res_ob_adr)
|
|
377
|
+
res_ob_id = @res_obj.find_res_ob(res_ob_type, res_ob_adr)
|
|
378
|
+
#creates the set of resOb (wanted resOb and all resOb from root to address, unsorted)
|
|
379
|
+
@res_obs = @res_obj.find_res_ob_parents(res_ob_type, res_ob_adr)
|
|
380
|
+
#adds resOb, which ends with /* + wanted resOb
|
|
381
|
+
@res_obs = @res_obj.res_obs_grand2children(@res_obs) + [res_ob_id]
|
|
382
|
+
|
|
383
|
+
if(is_owner?(prin_name, @res_obs))
|
|
384
|
+
#puts "owner"
|
|
385
|
+
return true #access allowed - owner can do everything
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
#creates the set of principals {wanted principal and all groups wanted principal is member of}
|
|
389
|
+
prins = @prin.find_parents(prin_name) + [prin_name]
|
|
390
|
+
@privs = @priv.find_parents(priv_name) + [priv_name] #same for privilege
|
|
391
|
+
|
|
392
|
+
final_ace = nil
|
|
393
|
+
for prin in prins
|
|
394
|
+
#ask for principal with privilege or higher privileges and and resob or higher resob.
|
|
395
|
+
query = prepare_query(prin, @privs, @res_obs)
|
|
396
|
+
#puts query
|
|
397
|
+
handle = @connector.execute_query(query)
|
|
398
|
+
hits = @connector.get_hits(handle)
|
|
399
|
+
#puts "hits #{hits}"
|
|
400
|
+
if(hits > 0)
|
|
401
|
+
temp_id = @connector.retrieve(handle, 0) #retrieve id of first Ace
|
|
402
|
+
temp_ace = AceRule.new(temp_id, @ace, @connector)
|
|
403
|
+
if(hits == 1)
|
|
404
|
+
final_ace = compare(final_ace, temp_ace)
|
|
405
|
+
else #there are more rules
|
|
406
|
+
hits.times { |i|
|
|
407
|
+
temp_id = @connector.retrieve(handle, i) #retrieve id of next Ace
|
|
408
|
+
temp_ace.reload!(temp_id)
|
|
409
|
+
final_ace = compare(final_ace, temp_ace)
|
|
410
|
+
}
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
if(final_ace == nil) #Rule doesnt exist = access denied
|
|
416
|
+
#puts "nil"
|
|
417
|
+
puts "Required rule
|
|
418
|
+
(#{prin_name}, #{priv_name}, #{res_ob_type}, #{res_ob_adr}) does not exist.
|
|
419
|
+
Access denied." if @report
|
|
420
|
+
return false
|
|
421
|
+
else
|
|
422
|
+
return decide(final_ace.acc_type)
|
|
423
|
+
end
|
|
424
|
+
rescue => e
|
|
425
|
+
raise e
|
|
426
|
+
#puts e.backtrace.join("\n")
|
|
427
|
+
#raise RubyACLException.new(self.class.name, __method__, "Failed to check ACE", 3), caller
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
#It shows permissions for principal all its parents.
|
|
431
|
+
#
|
|
432
|
+
# * *Args* :
|
|
433
|
+
# - +prin_name+ -> name of the principal
|
|
434
|
+
# * *Returns* :
|
|
435
|
+
# - string -> all aces that has principal and all its parents.
|
|
436
|
+
# * *Raises* :
|
|
437
|
+
# - +nothing+
|
|
438
|
+
#
|
|
439
|
+
def show_permissions_for(prin_name)
|
|
440
|
+
#creates the set of principals {wanted principal and all groups wanted principal is member of}
|
|
441
|
+
prins = [prin_name] + @prin.find_parents(prin_name)
|
|
442
|
+
|
|
443
|
+
#creates query, ask for principal permisions and all his parents permisions
|
|
444
|
+
query = "for $ace in #{@ace.doc}//Ace where ("
|
|
445
|
+
for prin in prins
|
|
446
|
+
query += "($ace/Principal/@idref=\"#{prin}\") or"
|
|
447
|
+
end
|
|
448
|
+
query = query[0..-4] #delete last or
|
|
449
|
+
query += ") return $ace"
|
|
450
|
+
|
|
451
|
+
ace = ""
|
|
452
|
+
handle = @connector.execute_query(query)
|
|
453
|
+
hits = @connector.get_hits(handle)
|
|
454
|
+
hits.times { |i|
|
|
455
|
+
ace = ace + @connector.retrieve(handle, i) + "\n" #retrieve and add next ACE
|
|
456
|
+
}
|
|
457
|
+
ace = ace[0..-2] #delete last \n
|
|
458
|
+
return ace
|
|
459
|
+
rescue => e
|
|
460
|
+
raise e
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
#Creates ace in acl. If resource object doesn't exist it creates resource object first.
|
|
464
|
+
#
|
|
465
|
+
#Address:
|
|
466
|
+
#If is used:
|
|
467
|
+
# resource address /something/somethingelse and grand2children = true
|
|
468
|
+
# then will be created access for somthingelse and its children
|
|
469
|
+
#If is used:
|
|
470
|
+
# only /something/somethingelse/*
|
|
471
|
+
# then will be created access only to somethingelse's children
|
|
472
|
+
#
|
|
473
|
+
#
|
|
474
|
+
# * *Args* :
|
|
475
|
+
# - +prin_name+ -> name of the principal
|
|
476
|
+
# - +acc_type+ -> access type. True = grant, false = revoke
|
|
477
|
+
# - +priv_name+ -> name of the privilege
|
|
478
|
+
# - +res_ob_type+ -> type of the resource object
|
|
479
|
+
# - +res_ob_adr+ -> address of the resource object
|
|
480
|
+
# - +grand2children+ -> boolean.
|
|
481
|
+
# True = grant to all children.
|
|
482
|
+
# False = grant only to specified resource object
|
|
483
|
+
# * *Returns* :
|
|
484
|
+
# - string, id of the created ace
|
|
485
|
+
# * *Raises* :
|
|
486
|
+
# - +nothing+
|
|
487
|
+
#
|
|
488
|
+
def create_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr, grand2children = false)
|
|
489
|
+
if(res_ob_adr[-2..-1] == "/*")
|
|
490
|
+
id = insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr)
|
|
491
|
+
else
|
|
492
|
+
id = insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr)
|
|
493
|
+
if(grand2children)
|
|
494
|
+
res_ob_adr = res_ob_adr + "/*"
|
|
495
|
+
insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr)
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
return id
|
|
499
|
+
rescue => e
|
|
500
|
+
raise e
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
#It creates principal with name and membership in groups.
|
|
504
|
+
#
|
|
505
|
+
# * *Args* :
|
|
506
|
+
# - +name+ -> name of the princpal
|
|
507
|
+
# - +groups+ -> array of groups where principal will be member.
|
|
508
|
+
# * *Returns* :
|
|
509
|
+
# - string, name of the principal
|
|
510
|
+
# * *Raises* :
|
|
511
|
+
# - +nothing+
|
|
512
|
+
#
|
|
513
|
+
def create_principal(name, groups = ["ALL"])
|
|
514
|
+
@indi.create_new(name, groups)
|
|
515
|
+
rescue => e
|
|
516
|
+
raise e
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
#Create group with name and membership in groups and members as groups or individual
|
|
520
|
+
#
|
|
521
|
+
#Note:
|
|
522
|
+
# members can be groups or individuals;
|
|
523
|
+
# At first method check if the name already exist. Or if groups and members exist at all
|
|
524
|
+
#
|
|
525
|
+
# * *Args* :
|
|
526
|
+
# - +name+ -> name of the new group
|
|
527
|
+
# - +member_of+ -> array of groups where new group will be member.
|
|
528
|
+
# - +members+ -> array of principals, who will be members of new group
|
|
529
|
+
# members can be groups or individuals;
|
|
530
|
+
# check if it the name already exist. Or if groups and members exist at all
|
|
531
|
+
# * *Returns* :
|
|
532
|
+
# - string, name of the group
|
|
533
|
+
# * *Raises* :
|
|
534
|
+
# - +nothing+
|
|
535
|
+
#
|
|
536
|
+
def create_group(name, member_of = ["ALL"], members = [])
|
|
537
|
+
@group.create_new(name, member_of, members)
|
|
538
|
+
rescue => e
|
|
539
|
+
raise e
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
#It creates privilege with name and membership in specified privileges.
|
|
543
|
+
#
|
|
544
|
+
# * *Args* :
|
|
545
|
+
# - +name+ -> name of the privilege
|
|
546
|
+
# - +member_of+ -> array of privileges where new privilege will be member.
|
|
547
|
+
# * *Returns* :
|
|
548
|
+
# - string, name of the privilege
|
|
549
|
+
# * *Raises* :
|
|
550
|
+
# - +nothing+
|
|
551
|
+
#
|
|
552
|
+
def create_privilege(name, member_of = ["ALL_PRIVILEGES"])
|
|
553
|
+
@priv.create_new(name, member_of)
|
|
554
|
+
rescue => e
|
|
555
|
+
raise e
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
#It creates resource object with type, address and owner.
|
|
559
|
+
#
|
|
560
|
+
# * *Args* :
|
|
561
|
+
# - +type+ -> type of resource object. e.g. doc, room, file, collection
|
|
562
|
+
# - +address+ -> address of the resource object. If it ends with /*, it means all children
|
|
563
|
+
# - +owner+ -> owner of the resource object
|
|
564
|
+
# * *Returns* :
|
|
565
|
+
# - string, id of the created resource object
|
|
566
|
+
# * *Raises* :
|
|
567
|
+
# - +nothing+
|
|
568
|
+
#
|
|
569
|
+
def create_resource_object(type, address, owner)
|
|
570
|
+
#puts "type #{type} add #{address}"
|
|
571
|
+
id = @res_obj.create_new(type, address, owner)
|
|
572
|
+
return id
|
|
573
|
+
rescue => e
|
|
574
|
+
raise e
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
#It changes resource object's type.
|
|
578
|
+
#Address and type must be specified to identify resource object.
|
|
579
|
+
#
|
|
580
|
+
# * *Args* :
|
|
581
|
+
# - +type+ -> type of resource object
|
|
582
|
+
# - +address+ -> address of resource object
|
|
583
|
+
# - +new_type+ -> new_type of resource object
|
|
584
|
+
# * *Returns* :
|
|
585
|
+
# - string, original type
|
|
586
|
+
# * *Raises* :
|
|
587
|
+
# - +nothing+
|
|
588
|
+
#
|
|
589
|
+
def change_res_ob_type(type, address, new_type)
|
|
590
|
+
@res_obj.change_type(type, address, new_type)
|
|
591
|
+
rescue => e
|
|
592
|
+
raise e
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
#It changes resource object's address.
|
|
596
|
+
#Address and type must be specified to identify resource object.
|
|
597
|
+
#
|
|
598
|
+
# * *Args* :
|
|
599
|
+
# - +type+ -> type of resource object
|
|
600
|
+
# - +address+ -> address of resource object
|
|
601
|
+
# - +new_address+ -> new address of resource object
|
|
602
|
+
# * *Returns* :
|
|
603
|
+
# - string, original address
|
|
604
|
+
# * *Raises* :
|
|
605
|
+
# - +nothing+
|
|
606
|
+
#
|
|
607
|
+
def change_of_res_ob_address(type, address, new_address)
|
|
608
|
+
@res_obj.change_address(type, address, new_address)
|
|
609
|
+
rescue => e
|
|
610
|
+
raise e
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
#It changes resource object's owner.
|
|
614
|
+
#Address and type must be specified to identify resource object.
|
|
615
|
+
#
|
|
616
|
+
# * *Args* :
|
|
617
|
+
# - +type+ -> type of resource object
|
|
618
|
+
# - +address+ -> address of resource object
|
|
619
|
+
# - +new_owner+ -> new owner of resource object
|
|
620
|
+
# * *Returns* :
|
|
621
|
+
# - string, original owner
|
|
622
|
+
# * *Raises* :
|
|
623
|
+
# - +nothing+
|
|
624
|
+
#
|
|
625
|
+
def change_of_res_ob_owner(type, address, new_owner)
|
|
626
|
+
@res_obj.change_owner(type, address, new_owner)
|
|
627
|
+
rescue => e
|
|
628
|
+
raise e
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
#It renames any principal. It means either individual or group.
|
|
632
|
+
#
|
|
633
|
+
# * *Args* :
|
|
634
|
+
# - +old_name+ -> old name of principal
|
|
635
|
+
# - +new_name+ -> new name of principal
|
|
636
|
+
# * *Returns* :
|
|
637
|
+
# - string, original name of the principal
|
|
638
|
+
# * *Raises* :
|
|
639
|
+
# - +nothing+
|
|
640
|
+
#
|
|
641
|
+
def rename_principal(old_name, new_name)
|
|
642
|
+
@prin.rename(old_name, new_name)
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
#It renames privilege.
|
|
646
|
+
#
|
|
647
|
+
# * *Args* :
|
|
648
|
+
# - +old_name+ -> old name of privilege
|
|
649
|
+
# - +new_name+ -> new name of privilege
|
|
650
|
+
# * *Returns* :
|
|
651
|
+
# - string, original name of the privilege
|
|
652
|
+
# * *Raises* :
|
|
653
|
+
# - +nothing+
|
|
654
|
+
#
|
|
655
|
+
def rename_privilege(old_name, new_name)
|
|
656
|
+
@priv.rename(old_name, new_name)
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
#It adds principal into group(s) as member.
|
|
660
|
+
#
|
|
661
|
+
# * *Args* :
|
|
662
|
+
# - +name+ -> name of the principal
|
|
663
|
+
# - +groups+ -> array of groups, where principal will be member.
|
|
664
|
+
# - +existance+ -> boolean. If you know that principal exists set true for existance.
|
|
665
|
+
# * *Returns* :
|
|
666
|
+
# - string, name of the principal
|
|
667
|
+
# * *Raises* :
|
|
668
|
+
# - +nothing+
|
|
669
|
+
#
|
|
670
|
+
def add_membership_principal(name, groups, existance = false)
|
|
671
|
+
@prin.add_membership(name, groups, existance)
|
|
672
|
+
rescue => e
|
|
673
|
+
raise e
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
#It adds privilege into privilege(s). So you can gather privileges into tree.
|
|
677
|
+
#
|
|
678
|
+
# * *Args* :
|
|
679
|
+
# - +name+ -> name of the privilege
|
|
680
|
+
# - +groups+ -> array of privileges, where privilege will be member.
|
|
681
|
+
# - +existance+ -> boolean. If you know that privielge exists set true for existance.
|
|
682
|
+
# * *Returns* :
|
|
683
|
+
# - string, name of the privilege
|
|
684
|
+
# * *Raises* :
|
|
685
|
+
# - +nothing+
|
|
686
|
+
#
|
|
687
|
+
def add_membership_privilege (name, groups, existance = false)
|
|
688
|
+
@priv.add_membership(name, groups, existance)
|
|
689
|
+
rescue => e
|
|
690
|
+
raise e
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
#It removes principal from group(s) where principal is member.
|
|
694
|
+
#
|
|
695
|
+
# * *Args* :
|
|
696
|
+
# - +name+ -> name of the principal
|
|
697
|
+
# - +groups+ -> array of groups, where principal is member.
|
|
698
|
+
# * *Returns* :
|
|
699
|
+
# - string, name of the principal
|
|
700
|
+
# * *Raises* :
|
|
701
|
+
# - +nothing+
|
|
702
|
+
#
|
|
703
|
+
def del_membership_principal(prin_name, groups) #deletes prin_name from group(s)
|
|
704
|
+
@prin.del_membership(prin_name, groups)
|
|
705
|
+
rescue => e
|
|
706
|
+
raise e
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
#It removes the privilege from parental privilege(s) where the privilege is member.
|
|
710
|
+
#
|
|
711
|
+
# * *Args* :
|
|
712
|
+
# - +name+ -> name of the privilege
|
|
713
|
+
# - +groups+ -> array of groups, where privilege is member.
|
|
714
|
+
# * *Returns* :
|
|
715
|
+
# - string, name of the privilege
|
|
716
|
+
# * *Raises* :
|
|
717
|
+
# - +nothing+
|
|
718
|
+
#
|
|
719
|
+
def del_membership_privilege(priv_name, groups) #deletes prin_name from group(s)
|
|
720
|
+
@priv.del_membership(priv_name, groups)
|
|
721
|
+
rescue => e
|
|
722
|
+
raise e
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
#It deletes principal from ACL. It also deletes all linked ACEs.
|
|
726
|
+
#
|
|
727
|
+
# * *Args* :
|
|
728
|
+
# - +name+ -> name of the principal
|
|
729
|
+
# * *Returns* :
|
|
730
|
+
# -string, name of the pricipal
|
|
731
|
+
# * *Raises* :
|
|
732
|
+
# - +nothing+
|
|
733
|
+
#
|
|
734
|
+
def delete_principal(name)
|
|
735
|
+
@prin.delete(name)
|
|
736
|
+
rescue => e
|
|
737
|
+
raise e
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
#It deletes privilege from ACL. It also deletes all linked ACEs.
|
|
741
|
+
#
|
|
742
|
+
# * *Args* :
|
|
743
|
+
# - +name+ -> name of the privilege
|
|
744
|
+
# * *Returns* :
|
|
745
|
+
# -string, name of the privilege
|
|
746
|
+
# * *Raises* :
|
|
747
|
+
# - +nothing+
|
|
748
|
+
#
|
|
749
|
+
def delete_privilege(name)
|
|
750
|
+
@priv.delete(name)
|
|
751
|
+
rescue => e
|
|
752
|
+
raise e
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
#It deletes resource object from ACL. It also deletes all linked ACEs.
|
|
756
|
+
#
|
|
757
|
+
# * *Args* :
|
|
758
|
+
# - +type+ -> type of the resource object
|
|
759
|
+
# - +address+ -> address of the resource object
|
|
760
|
+
# * *Returns* :
|
|
761
|
+
# -string, name of the resource object
|
|
762
|
+
# * *Raises* :
|
|
763
|
+
# - +nothing+
|
|
764
|
+
#
|
|
765
|
+
def delete_res_object(type, address)
|
|
766
|
+
res_ob_id = @res_obj.find_res_ob(type, address)
|
|
767
|
+
@res_obj.delete(res_ob_id)
|
|
768
|
+
return res_ob_id
|
|
769
|
+
rescue => e
|
|
770
|
+
raise e
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
#It deletes resource object from ACL by id. It also deletes all linked ACEs.
|
|
774
|
+
#
|
|
775
|
+
# * *Args* :
|
|
776
|
+
# - +id+ -> id of the resource object
|
|
777
|
+
# * *Returns* :
|
|
778
|
+
# -string, name of the resource object
|
|
779
|
+
# * *Raises* :
|
|
780
|
+
# - +nothing+
|
|
781
|
+
#
|
|
782
|
+
def delete_res_object_by_id(id)
|
|
783
|
+
@res_obj.delete(id)
|
|
784
|
+
rescue => e
|
|
785
|
+
raise e
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
#It deletes ACE from ACL.
|
|
789
|
+
#
|
|
790
|
+
# * *Args* :
|
|
791
|
+
# - +ace_id+ -> id of the ACE
|
|
792
|
+
# * *Returns* :
|
|
793
|
+
# -string, name of the
|
|
794
|
+
# * *Raises* :
|
|
795
|
+
# - +nothing+
|
|
796
|
+
#
|
|
797
|
+
def delete_ace(ace_id)
|
|
798
|
+
@ace.delete(ace_id)
|
|
799
|
+
rescue => e
|
|
800
|
+
raise e
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
#TODO Vzorovou tridu API s vyhazovanim vyjimek must be implemented
|
|
807
|
+
#TODO ptam se jestli nekdo kdo neexistuje ma pristup. Pozor na vyjimku, mel bych vratit rovnou false.
|
|
808
|
+
#TODO Lze pridat privilege do principal a naopak? test na to by byl peknej :)
|
|
809
|
+
|
|
810
|
+
##Usage example. Also very good source of information are test cases.
|
|
811
|
+
#puts "start"
|
|
812
|
+
#$:.unshift("../../eXistAPI/lib")
|
|
813
|
+
#require 'eXistAPI' #must require 'eXistAPI' to comunicated with eXist-db
|
|
814
|
+
#
|
|
815
|
+
##create instance of ExistAPI
|
|
816
|
+
#@db = ExistAPI.new("http://localhost:8080/exist/xmlrpc", "admin", "admin")
|
|
817
|
+
#@col_path = "/db/test_acl/" #sets the collection where you want to have ACL in db
|
|
818
|
+
#@src_files_path = "./src_files/" #path to source files
|
|
819
|
+
#if(@db.existscollection?(@col_path))
|
|
820
|
+
# @db.remove_collection(@col_path) #Deleting old ACL from db
|
|
821
|
+
#end
|
|
822
|
+
#report = false
|
|
823
|
+
#@my_acl = RubyACL.new("my_acl", @db, @col_path, @src_files_path, report)
|
|
824
|
+
#
|
|
825
|
+
##it's good to create some principals at the begging
|
|
826
|
+
#@my_acl.create_principal("Sheldon")
|
|
827
|
+
#@my_acl.create_principal("Leonard")
|
|
828
|
+
#@my_acl.create_principal("Rajesh")
|
|
829
|
+
#@my_acl.create_principal("Howarda")
|
|
830
|
+
#@my_acl.create_principal("Penny")
|
|
831
|
+
#@my_acl.create_principal("Kripkie")
|
|
832
|
+
#
|
|
833
|
+
##Besides given privileges you can create your owns
|
|
834
|
+
#@my_acl.create_privilege("WATCH")
|
|
835
|
+
#@my_acl.create_privilege("SIT")
|
|
836
|
+
#
|
|
837
|
+
##You can create resource object and get id of it.
|
|
838
|
+
#resource_id = @my_acl.create_resource_object("mov", "/Movies", "Sheldon")
|
|
839
|
+
#@my_acl.create_resource_object("couch", "/livingroom", "Sheldon")
|
|
840
|
+
#@my_acl.create_resource_object("seat", "/livingroom/couch/Sheldon's_spot", "Sheldon")
|
|
841
|
+
#
|
|
842
|
+
##Now we have everything we need to create a rule.
|
|
843
|
+
##Lets see what we must hand over
|
|
844
|
+
##1) One individual or group that (principal)
|
|
845
|
+
##2) will or won't have access (access type = {allow, deny})
|
|
846
|
+
##3) to do something with (privilege)
|
|
847
|
+
##4) which type of (resource type)
|
|
848
|
+
##5) resource. (resource object)
|
|
849
|
+
##6) And if we needs to grand all this to children of resource. (grant to children)
|
|
850
|
+
#@my_acl.create_ace("Sheldon", "allow", "DELETE", "mov", "/Movies", true)
|
|
851
|
+
#@my_acl.create_ace("Sheldon", "allow", "SIT", "seat", "/livingroom/couch/Sheldon's_spot")
|
|
852
|
+
#
|
|
853
|
+
#
|
|
854
|
+
##You can easily check e.g. if Penny may delete all movies.
|
|
855
|
+
#@my_acl.check("Penny", "DELETE", "mov", "/Movies")
|
|
856
|
+
#
|
|
857
|
+
##Next method call returns deny
|
|
858
|
+
#@my_acl.check("Penny", "SIT", "seat", "/livingroom/couch/Sheldon's_spot")
|
|
859
|
+
#
|
|
860
|
+
##You can create group and immidiatly insert members or do it later.
|
|
861
|
+
#@my_acl.create_group("4th_floor", ["ALL"], ["Sheldon","Leonard","Penny"])
|
|
862
|
+
##Here are other possible ways of creating group
|
|
863
|
+
##@my_acl.create_group("4th_floor")
|
|
864
|
+
##@my_acl.create_group("4th_floor", ["ALL"])
|
|
865
|
+
##
|
|
866
|
+
##Create access control entry with group as principal.
|
|
867
|
+
#ace_id = @my_acl.create_ace("4th_floor", "allow", "WATCH", "mov", "/Movies/*")
|
|
868
|
+
#
|
|
869
|
+
##You can show all privileges connected with principal
|
|
870
|
+
#perm = @my_acl.show_permissions_for("Penny")
|
|
871
|
+
#puts perm
|
|
872
|
+
#
|
|
873
|
+
##EXCEPTION EXAMPLE
|
|
874
|
+
#@my_acl.create_group("Scientists") #you must create group before you use it
|
|
875
|
+
#@my_acl.add_membership_principal("Sheldon", ["Scientists"])
|
|
876
|
+
#
|
|
877
|
+
##You also must create privileges before you use them
|
|
878
|
+
#@my_acl.create_privilege("TALK")
|
|
879
|
+
#@my_acl.create_privilege("COMUNICATE")
|
|
880
|
+
##You can gather privileges in treelike structure
|
|
881
|
+
#@my_acl.add_membership_privilege("TALK", ["COMUNICATE"])
|
|
882
|
+
#
|
|
883
|
+
##You can delete membership of principal and privilege,
|
|
884
|
+
##ace, principal, privilege, resource object, if exists.
|
|
885
|
+
##Otherwise you will get exception
|
|
886
|
+
#@my_acl.del_membership_principal("Sheldon", ["Scientists"])
|
|
887
|
+
#@my_acl.del_membership_privilege("TALK", ["COMUNICATE"])
|
|
888
|
+
#@my_acl.delete_ace(ace_id)
|
|
889
|
+
#@my_acl.delete_principal("Kripkie")
|
|
890
|
+
#@my_acl.delete_privilege("SIT")
|
|
891
|
+
#@my_acl.delete_res_object("couch", "/livingroom")
|
|
892
|
+
#@my_acl.delete_res_object_by_id(resource_id)
|
|
893
|
+
#
|
|
894
|
+
#@my_acl.create_resource_object("mov", "/Movies", "Sheldon") #create again for demonstration purposes
|
|
895
|
+
##You can rename principal, privilege and change every part of resource object.
|
|
896
|
+
#@my_acl.rename_principal("Kripkie", "Kwipkie")
|
|
897
|
+
#@my_acl.rename_privilege("TALK", "CHAT")
|
|
898
|
+
#@my_acl.change_of_res_ob_address("mov", "/Movies", "/Films")
|
|
899
|
+
#@my_acl.change_of_res_ob_owner("mov", "/Films", "Leonard")
|
|
900
|
+
#@my_acl.change_res_ob_type("mov", "/Films", "motion picture")
|
|
901
|
+
#
|
|
902
|
+
#You can save or load ACL
|
|
903
|
+
#@my_acl.save('C:\\storage')
|
|
904
|
+
#RubyACL.load(@db, "C:\\backup")
|
|
905
|
+
#
|
|
906
|
+
##You can rename ACL
|
|
907
|
+
#@my_acl.rename("my_beloved_acl")
|
|
908
|
+
#puts "finished"
|