class Eaco::ACL

An ACL is an Hash whose keys are Designator string representations and values are the role symbols defined in the Resource permissions configuration.

Example:

authorize Document do
  roles :reader, :editor
end

@see Actor @see Resource

Public Class Methods

new(definition = {}) click to toggle source

Builds a new ACL object from the given Hash representation with strings as keys and values.

@param definition [Hash] the ACL hash

@return [ACL] this ACL

# File lib/eaco/acl.rb, line 27
def initialize(definition = {})
  (definition || {}).each do |designator, role|
    self[designator] = role.intern
  end
end

Public Instance Methods

actors_by_role(name) click to toggle source

@param name [Symbol] the role name

@return [Set] Actors having the given role.

@see Actor @see Resource

# File lib/eaco/acl.rb, line 123
def actors_by_role(name)
  find_by_role(name).inject(Set.new) do |set, designator|
    set |= Array.new(designator.resolve)
  end.to_a
end
add(role, *designator) click to toggle source

Gives the given Designator access as the given role.

@param role [Symbol] the role to grant @param designator [Variadic] (see {#identify})

@return [ACL] this ACL

# File lib/eaco/acl.rb, line 41
def add(role, *designator)
  identify(*designator).each do |key|
    self[key] = role
  end

  self
end
all() click to toggle source

@return [Set] all Designators in the ACL, regardless of their role.

# File lib/eaco/acl.rb, line 82
def all
  self.inject(Set.new) do |ret, (designator,_)|
    ret.add Designator.parse(designator)
  end
end
del(*designator) click to toggle source

Removes access from the given Designator.

@param designator [Variadic] (see {#identify})

@return [ACL] this ACL

@see Designator

# File lib/eaco/acl.rb, line 58
def del(*designator)
  identify(*designator).each do |key|
    self.delete(key.to_s)
  end
  self
end
designators_map_for_role(name) click to toggle source

Gets a map of Actors in the ACL having the given role.

This is a useful starting point for an Enterprise summary page of who is granted to access a resource. Given that actor resolution is dynamic and handled by the application's Designators implementation, you can rely on your internal organigram APIs to resolve actual people out of positions, groups, department of assignment, etc.

@param name [Symbol] The role name

@return [Hash] keyed by designator with Set of Actors as values

@see Actor @see Resource

# File lib/eaco/acl.rb, line 104
def designators_map_for_role(name)
  find_by_role(name).inject({}) do |ret, designator|
    actors = designator.resolve

    ret.tap do
      ret[designator] ||= Set.new
      ret[designator].merge Array.new(actors)
    end
  end
end
find_by_role(name) click to toggle source

@param name [Symbol] The role name

@return [Set] A set of Designators having the given role.

@see Designator @see Resource

# File lib/eaco/acl.rb, line 73
def find_by_role(name)
  self.inject(Set.new) do |ret, (designator, role)|
    ret.tap { ret.add Designator.parse(designator) if role == name }
  end
end
inspect() click to toggle source

Pretty prints this ACL in your console.

# File lib/eaco/acl.rb, line 132
def inspect
  "#<#{self.class.name}: #{super}>"
end
Also aliased as: pretty_print_inspect
pretty_inspect() click to toggle source

Pretty print for pry.

# File lib/eaco/acl.rb, line 140
def pretty_inspect
  "#{self.class.name}\n#{super}"
end
pretty_print_inspect()
Alias for: inspect

Protected Instance Methods

identify(designator, actor_or_id = nil) click to toggle source

There are three ways of specifying designators:

  • Passing an Designator instance obtained from somewhere else:

    >> designator
    => #<Designator(User) value:42>
    
    >> resource.acl.add :reader, designator
    => #<Resource::ACL {"user:42"=>:reader}>
  • Passing a designator type and an unique ID valid in the designator's namespace:

    >> resource.acl.add :reader, :user, 42
    => #<Resource::ACL {"user:42"=>:reader}>
  • Passing a designator type and an Actor instance, will add all designators of the given type owned by the Actor.

    >> actor
    => #<User id:42 name:"Ethan Siegel">
    
    >> actor.designators
    => #<Set:{
     |   #<Designator(User) value:42>,
     |   #<Designator(Group) value:"astrophysicists">,
     |   #<Designator(Group) value:"medium bloggers">
     | }>
    
    >> resource.acl.add :editor, :group, actor
    => #<Resource::ACL {
     |   "group:astrophysicists"=>:editor,
     |   "group:medium bloggers"=>:editor
     | }

@param designator [Designator] the designator to grant @param actor_or_id [Actor] or [String] the actor

# File lib/eaco/acl.rb, line 185
    def identify(designator, actor_or_id = nil)
      if designator.is_a?(Eaco::Designator)
        [designator]

      elsif designator && actor_or_id.respond_to?(:designators)
        designator = designator.to_sym
        actor_or_id.designators.select {|d| d.type == designator}

      elsif designator.is_a?(Symbol)
        [Eaco::Designator.make(designator, actor_or_id)]

      else
        raise Error, <<-EOF
          Cannot infer designator
          from #{designator.inspect}
          and #{actor_or_id.inspect}
        EOF
      end
    end