Class: RubyACL

Inherits:
Object
  • Object
show all
Defined in:
lib/Ruby-ACL.rb

Overview

RubyACL is library that handles access permisions. RubyACL offers to create and modify three ACL objects - three dimensions: Principal, Privilege, Resource object. Principal is someone or something that want to access. Privilege is level of access. (read, write etc.). Resource object is what is principal accessing. RubyACL uses API interface to communicate with database. This interface is described by class API_inteface. At the end of the class you can see set of examples. Also good source of information are testcases.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, connector, colpath = "/db/acl/", src_files_path = File.join(File.dirname(__FILE__),'.','src_files/'), report = false) ⇒ RubyACL

Creates new instance of Ruby-ACL. Ruby-ACL works if principals, privileges and resource object. With Ruby-ACL you can manage permsion to person for resource objects.

  • Args :

    • name -> name of the ACL

    • connector -> instance of connection manager with db. e.g. ExistAPI.new(“localhost:8080/exist/xmlrpc”, “admin”, “admin”)

    • colpath -> path of collection in db. e.g. “/db/acl/”

    • src_files_path -> path of source files in local location.

    • report -> boolean - if true Ruby-ACL

  • Returns :

    • instance of RubyACL

  • Raises :

    • RubyACLException -> Name is empty



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/Ruby-ACL.rb', line 45

def initialize(name, connector, colpath = "/db/acl/", 
    src_files_path = File.join(File.dirname(__FILE__),'.','src_files/'), 
    report = false)
  if(name == "")
    raise RubyACLException.new(self.class.name, __method__, "Name is empty", 0), caller
  end
  @name = name
  @connector = connector
  if(colpath[-1] != "/")
    colpath += "/"
  end
  @col_path = colpath
  @src_files_path = src_files_path
  @report = report
  @prin = Principal.new(@connector, @col_path, @report)
  @indi = Individual.new(@connector, @col_path, @report)
  @group = Group.new(@connector, @col_path, @report)
  @priv = Privilege.new(@connector, @col_path, @report)
  @res_obj = ResourceObject.new(@connector, @col_path, @report)
  @ace = Ace.new(@connector, @col_path, @report)
  create_acl_in_db()
  rename(name)
rescue => e
  raise e
end

Instance Attribute Details

#col_pathObject (readonly)

collection path in db, where ACL will be stored.



30
31
32
# File 'lib/Ruby-ACL.rb', line 30

def col_path
  @col_path
end

#nameObject (readonly)

name of the ACL



28
29
30
# File 'lib/Ruby-ACL.rb', line 28

def name
  @name
end

Class Method Details

.load(connector, colpath, src_files_path, report = false) ⇒ Object

It loads backuped acl data.

  • Args :

    • connector -> instance of connection manager with db. e.g. ExistAPI.new(“localhost:8080/exist/xmlrpc”, “admin”, “admin”)

    • colpath -> path of collection in db. e.g. “/db/acl/”

    • src_files_path -> path of source files in local location.

    • report -> boolean - if true Ruby-ACL

  • Returns : -new instance of Ruby-ACL

  • Raises :

    • nothin



348
349
350
351
352
353
354
355
356
357
# File 'lib/Ruby-ACL.rb', line 348

def RubyACL.load(connector, colpath, src_files_path, report = false)
  xmlfile = File.read(src_files_path+"acl.xml")
  startindex = xmlfile.index('"', xmlfile.index("aclname="))
  endindex = xmlfile.index('"', startindex+1)
  name = xmlfile[startindex+1..endindex-1]
  newacl = RubyACL.new(name, connector, colpath, src_files_path, report)
  return newacl
rescue => e
  raise e
end

Instance Method Details

#add_membership_principal(name, groups, existance = false) ⇒ Object

It adds principal into group(s) as member.

  • Args :

    • name -> name of the principal

    • groups -> array of groups, where principal will be member.

    • existance -> boolean. If you know that principal exists set true for existance.

  • Returns :

    • string, name of the principal

  • Raises :

    • nothing



676
677
678
679
680
# File 'lib/Ruby-ACL.rb', line 676

def add_membership_principal(name, groups, existance = false) 
  @prin.add_membership(name, groups, existance)
rescue => e
  raise e
end

#add_membership_privilege(name, groups, existance = false) ⇒ Object

It adds privilege into privilege(s). So you can gather privileges into tree.

  • Args :

    • name -> name of the privilege

    • groups -> array of privileges, where privilege will be member.

    • existance -> boolean. If you know that privielge exists set true for existance.

  • Returns :

    • string, name of the privilege

  • Raises :

    • nothing



693
694
695
696
697
# File 'lib/Ruby-ACL.rb', line 693

def add_membership_privilege (name, groups, existance = false) 
  @priv.add_membership(name, groups, existance)
rescue => e
  raise e
end

#change_of_res_ob_address(type, address, new_address) ⇒ Object

It changes resource object’s address. Address and type must be specified to identify resource object.

  • Args :

    • type -> type of resource object

    • address -> address of resource object

    • new_address -> new address of resource object

  • Returns :

    • string, original address

  • Raises :

    • nothing



613
614
615
616
617
# File 'lib/Ruby-ACL.rb', line 613

def change_of_res_ob_address(type, address, new_address)
  @res_obj.change_address(type, address, new_address)
rescue => e
  raise e
end

#change_of_res_ob_owner(type, address, new_owner) ⇒ Object

It changes resource object’s owner. Address and type must be specified to identify resource object.

  • Args :

    • type -> type of resource object

    • address -> address of resource object

    • new_owner -> new owner of resource object

  • Returns :

    • string, original owner

  • Raises :

    • nothing



631
632
633
634
635
# File 'lib/Ruby-ACL.rb', line 631

def change_of_res_ob_owner(type, address, new_owner)
  @res_obj.change_owner(type, address, new_owner)
rescue => e
  raise e
end

#change_res_ob_type(type, address, new_type) ⇒ Object

It changes resource object’s type. Address and type must be specified to identify resource object.

  • Args :

    • type -> type of resource object

    • address -> address of resource object

    • new_type -> new_type of resource object

  • Returns :

    • string, original type

  • Raises :

    • nothing



595
596
597
598
599
# File 'lib/Ruby-ACL.rb', line 595

def change_res_ob_type(type, address, new_type)
  @res_obj.change_type(type, address, new_type)
rescue => e
  raise e
end

#check(prin_name, priv_name, res_ob_type, res_ob_adr) ⇒ Object

Decides whether principal has privilege or not to resource object identified by access type and address. If the accessType of ace is allow - returns true. If accessType of ace is deny return false.

Priority of decision is as follows lower. Lowest number has highest priority:

  1. Owner

  2. Explicit Deny

  3. Explicit Allow

  4. Inherited Deny

  5. Inherited Allow

  6. If not found then Deny

  • Args :

    • prin_name -> name of the principal

    • priv_name -> name of the privilege

    • res_ob_type -> type of the resource object

    • res_ob_adr -> address of the resource object

  • Returns : -boolean - true - has privilege to resource object, false - has not

  • Raises :

    • nothing



382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/Ruby-ACL.rb', line 382

def check(prin_name, priv_name, res_ob_type, res_ob_adr)
  res_ob_id = @res_obj.find_res_ob(res_ob_type, res_ob_adr)
  #creates the set of resOb (wanted resOb and all resOb from root to address, unsorted)
  @res_obs = @res_obj.find_res_ob_parents(res_ob_type, res_ob_adr) 
  #adds resOb, which ends with /* + wanted resOb
  @res_obs = @res_obj.res_obs_grand2children(@res_obs) + [res_ob_id]  
  
  if(is_owner?(prin_name, @res_obs))
    #puts "owner"
    return true   #access allowed - owner can do everything
  end
  
  #creates the set of principals {wanted principal and all groups wanted principal is member of}
  prins = @prin.find_parents(prin_name) + [prin_name]    
  @privs = @priv.find_parents(priv_name) + [priv_name]   #same for privilege
  
  final_ace = nil
  for prin in prins
    #ask for principal with privilege or higher privileges and and resob or higher resob. 
    query = prepare_query(prin, @privs, @res_obs)   
    #puts query
    handle = @connector.execute_query(query)
    hits = @connector.get_hits(handle)
    #puts "hits #{hits}"
    if(hits > 0)   
      temp_id = @connector.retrieve(handle, 0)   #retrieve id of first Ace
      temp_ace = AceRule.new(temp_id, @ace, @connector)
      if(hits == 1)
        final_ace = compare(final_ace, temp_ace)
      else    #there are more rules
        hits.times { |i|
          temp_id = @connector.retrieve(handle, i)   #retrieve id of next Ace
          temp_ace.reload!(temp_id)
          final_ace = compare(final_ace, temp_ace)
        }
      end
    end
  end
  
  if(final_ace == nil)  #Rule doesnt exist = access denied
    #puts "nil"
    puts "Required rule 
(#{prin_name}, #{priv_name}, #{res_ob_type}, #{res_ob_adr}) does not exist. 
Access denied." if @report
    return false
  else
    return decide(final_ace.acc_type)
  end
rescue => e
  raise e
  #puts e.backtrace.join("\n")
  #raise RubyACLException.new(self.class.name, __method__, "Failed to check ACE", 3), caller
end

#create_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr, grand2children = false) ⇒ Object

Creates ace in acl. If resource object doesn’t exist it creates resource object first.

Address: If is used:

resource address /something/somethingelse and grand2children = true
then will be created access for somthingelse and its children

If is used:

only /something/somethingelse/*

then will be created access only to somethingelse’s children

  • Args :

    • prin_name -> name of the principal

    • acc_type -> access type. True = grant, false = revoke

    • priv_name -> name of the privilege

    • res_ob_type -> type of the resource object

    • res_ob_adr -> address of the resource object

    • grand2children -> boolean.

      True = grant to all children. 
      False = grant only to specified resource object
      
  • Returns :

    • string, id of the created ace

  • Raises :

    • nothing



494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'lib/Ruby-ACL.rb', line 494

def create_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr, grand2children = false)
  if(res_ob_adr[-2..-1] == "/*")
    id = insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr)
  else
    id = insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr)
    if(grand2children)
      res_ob_adr = res_ob_adr + "/*"
      insert_ace(prin_name, acc_type, priv_name, res_ob_type, res_ob_adr)
    end
  end
  return id
rescue => e
  raise e
end

#create_group(name, member_of = ["ALL"], members = []) ⇒ Object

Create group with name and membership in groups and members as groups or individual

Note: members can be groups or individuals; At first method check if the name already exist. Or if groups and members exist at all

  • Args :

    • name -> name of the new group

    • member_of -> array of groups where new group will be member.

    • members -> array of principals, who will be members of new group

      members can be groups or individuals; 
      check if it the name already exist. Or if groups and members exist at all
      
  • Returns :

    • string, name of the group

  • Raises :

    • nothing



542
543
544
545
546
# File 'lib/Ruby-ACL.rb', line 542

def create_group(name, member_of = ["ALL"], members = [])    
  @group.create_new(name, member_of, members)   
rescue => e
  raise e
end

#create_principal(name, groups = ["ALL"]) ⇒ Object

It creates principal with name and membership in groups.

  • Args :

    • name -> name of the princpal

    • groups -> array of groups where principal will be member.

  • Returns :

    • string, name of the principal

  • Raises :

    • nothing



519
520
521
522
523
# File 'lib/Ruby-ACL.rb', line 519

def create_principal(name, groups = ["ALL"])
  @indi.create_new(name, groups)
rescue => e
  raise e
end

#create_privilege(name, member_of = ["ALL_PRIVILEGES"]) ⇒ Object

It creates privilege with name and membership in specified privileges.

  • Args :

    • name -> name of the privilege

    • member_of -> array of privileges where new privilege will be member.

  • Returns :

    • string, name of the privilege

  • Raises :

    • nothing



558
559
560
561
562
# File 'lib/Ruby-ACL.rb', line 558

def create_privilege(name, member_of = ["ALL_PRIVILEGES"])
  @priv.create_new(name, member_of)
rescue => e
  raise e
end

#create_resource_object(type, address, owner) ⇒ Object

It creates resource object with type, address and owner.

  • Args :

    • type -> type of resource object. e.g. doc, room, file, collection

    • address -> address of the resource object. If it ends with /*, it means all children

    • owner -> owner of the resource object

  • Returns :

    • string, id of the created resource object

  • Raises :

    • nothing



575
576
577
578
579
580
581
# File 'lib/Ruby-ACL.rb', line 575

def create_resource_object(type, address, owner)
  #puts "type #{type} add #{address}"
  id = @res_obj.create_new(type, address, owner)
  return id
rescue => e
  raise e
end

#del_membership_principal(prin_name, groups) ⇒ Object

It removes principal from group(s) where principal is member.

  • Args :

    • name -> name of the principal

    • groups -> array of groups, where principal is member.

  • Returns :

    • string, name of the principal

  • Raises :

    • nothing



709
710
711
712
713
# File 'lib/Ruby-ACL.rb', line 709

def del_membership_principal(prin_name, groups) #deletes prin_name from group(s)
  @prin.del_membership(prin_name, groups)
rescue => e
  raise e
end

#del_membership_privilege(priv_name, groups) ⇒ Object

It removes the privilege from parental privilege(s) where the privilege is member.

  • Args :

    • name -> name of the privilege

    • groups -> array of groups, where privilege is member.

  • Returns :

    • string, name of the privilege

  • Raises :

    • nothing



725
726
727
728
729
# File 'lib/Ruby-ACL.rb', line 725

def del_membership_privilege(priv_name, groups) #deletes prin_name from group(s)
  @priv.del_membership(priv_name, groups)
rescue => e
  raise e
end

#delete_ace(ace_id) ⇒ Object

It deletes ACE from ACL.

  • Args :

    • ace_id -> id of the ACE

  • Returns : -string, name of the

  • Raises :

    • nothing



803
804
805
806
807
# File 'lib/Ruby-ACL.rb', line 803

def delete_ace(ace_id)
  @ace.delete(ace_id)
rescue => e
  raise e
end

#delete_principal(name) ⇒ Object

It deletes principal from ACL. It also deletes all linked ACEs.

  • Args :

    • name -> name of the principal

  • Returns : -string, name of the pricipal

  • Raises :

    • nothing



740
741
742
743
744
# File 'lib/Ruby-ACL.rb', line 740

def delete_principal(name)
  @prin.delete(name)
rescue => e
  raise e
end

#delete_privilege(name) ⇒ Object

It deletes privilege from ACL. It also deletes all linked ACEs.

  • Args :

    • name -> name of the privilege

  • Returns : -string, name of the privilege

  • Raises :

    • nothing



755
756
757
758
759
# File 'lib/Ruby-ACL.rb', line 755

def delete_privilege(name)
  @priv.delete(name)
rescue => e
  raise e
end

#delete_res_object(type, address) ⇒ Object

It deletes resource object from ACL. It also deletes all linked ACEs.

  • Args :

    • type -> type of the resource object

    • address -> address of the resource object

  • Returns : -string, name of the resource object

  • Raises :

    • nothing



771
772
773
774
775
776
777
# File 'lib/Ruby-ACL.rb', line 771

def delete_res_object(type, address)
  res_ob_id = @res_obj.find_res_ob(type, address)
  @res_obj.delete(res_ob_id)
  return res_ob_id
rescue => e
  raise e
end

#delete_res_object_by_id(id) ⇒ Object

It deletes resource object from ACL by id. It also deletes all linked ACEs.

  • Args :

    • id -> id of the resource object

  • Returns : -string, name of the resource object

  • Raises :

    • nothing



788
789
790
791
792
# File 'lib/Ruby-ACL.rb', line 788

def delete_res_object_by_id(id)
  @res_obj.delete(id)
rescue => e
  raise e
end

#rename(new_name) ⇒ Object

Renames acl (also in db)

  • Args :

    • new_name -> new name of acl

  • Returns : -int, handle of the query

  • Raises :

    • RubyACLException -> Failed to set new name



292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/Ruby-ACL.rb', line 292

def rename(new_name)
  query = "update value doc(\"#{@col_path}acl.xml\")/acl/@aclname with \"#{new_name}\""
  @connector.execute_query(query)
  query = "doc(\"#{@col_path}acl.xml\")/acl/string(@aclname)"
  handle = @connector.execute_query(query)
  if(new_name != @connector.retrieve(handle, 0))
    raise RubyACLException.new(self.class.name, __method__, "Failed to set new name", 2), caller
  end
rescue XMLRPC::FaultException => e
  raise e
rescue => e
  raise e
end

#rename_principal(old_name, new_name) ⇒ Object

It renames any principal. It means either individual or group.

  • Args :

    • old_name -> old name of principal

    • new_name -> new name of principal

  • Returns :

    • string, original name of the principal

  • Raises :

    • nothing



647
648
649
# File 'lib/Ruby-ACL.rb', line 647

def rename_principal(old_name, new_name)
  @prin.rename(old_name, new_name)
end

#rename_privilege(old_name, new_name) ⇒ Object

It renames privilege.

  • Args :

    • old_name -> old name of privilege

    • new_name -> new name of privilege

  • Returns :

    • string, original name of the privilege

  • Raises :

    • nothing



661
662
663
# File 'lib/Ruby-ACL.rb', line 661

def rename_privilege(old_name, new_name)
  @priv.rename(old_name, new_name)
end

#save(path, date = false) ⇒ Object

It saves/backs up acl

  • Args :

    • path -> to local location

  • Returns :

    • array of documents in ACL working collection

  • Raises :

    • nothing



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/Ruby-ACL.rb', line 315

def save(path, date = false)
  col = @connector.getcollection(@col_path)    
  docs = col.docs()
  if(date)
    path = path + Date.today.to_s + "/"
  end
  if(!File.exists?(path))
    Dir.mkdir(path)
  end
  docs.each{|doc| 
    document = col[doc] 
    #doc = doc + "_BU"
    filename = path + doc
    f = File.new(filename, 'w')
    f.puts(document.content)
    f.close
  }
rescue => e
  raise e
end

#show_permissions_for(prin_name) ⇒ Object

It shows permissions for principal all its parents.

  • Args :

    • prin_name -> name of the principal

  • Returns :

    • string -> all aces that has principal and all its parents.

  • Raises :

    • nothing



445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'lib/Ruby-ACL.rb', line 445

def show_permissions_for(prin_name)
  #creates the set of principals {wanted principal and all groups wanted principal is member of}
  prins = [prin_name] + @prin.find_parents(prin_name)
  
  #creates query, ask for principal permisions and all his parents permisions
  query = "for $ace in #{@ace.doc}//Ace where ("    
  for prin in prins
    query += "($ace/Principal/@idref=\"#{prin}\") or"
  end
  query = query[0..-4]    #delete last or
  query += ") return $ace"
  
  ace = ""  
  handle = @connector.execute_query(query)
  hits = @connector.get_hits(handle)
  hits.times { |i|
    ace = ace + @connector.retrieve(handle, i) + "\n"  #retrieve and add next ACE
  }
  ace = ace[0..-2]    #delete last \n
  return ace
rescue => e
  raise e
end