Class: Eaco::ACL

Inherits:
Hash
  • Object
show all
Defined in:
lib/eaco/acl.rb

Overview

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 Also:

Instance Method Summary collapse

Constructor Details

#initialize(definition = {}) ⇒ ACL

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

Parameters:

  • definition (Hash) (defaults to: {})

    the ACL hash


27
28
29
30
31
# File 'lib/eaco/acl.rb', line 27

def initialize(definition = {})
  (definition || {}).each do |designator, role|
    self[designator] = role.intern
  end
end

Instance Method Details

#actors_by_role(name) ⇒ Set

Returns Actors having the given role.

Parameters:

  • name (Symbol)

    the role name

Returns:

  • (Set)

    Actors having the given role.

See Also:


123
124
125
126
127
# 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) ⇒ ACL

Gives the given Designator access as the given role.

Parameters:

  • role (Symbol)

    the role to grant

  • designator (Variadic)

    (see #identify)

Returns:

  • (ACL)

    this ACL


41
42
43
44
45
46
47
# File 'lib/eaco/acl.rb', line 41

def add(role, *designator)
  identify(*designator).each do |key|
    self[key] = role
  end

  self
end

#allSet

Returns all Designators in the ACL, regardless of their role.

Returns:

  • (Set)

    all Designators in the ACL, regardless of their role.


82
83
84
85
86
# 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) ⇒ ACL

Removes access from the given Designator.

Parameters:

Returns:

  • (ACL)

    this ACL

See Also:


58
59
60
61
62
63
# 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) ⇒ Hash

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.

Parameters:

  • name (Symbol)

    The role name

Returns:

  • (Hash)

    keyed by designator with Set of Actors as values

See Also:


104
105
106
107
108
109
110
111
112
113
# 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) ⇒ Set

Returns A set of Designators having the given role.

Parameters:

  • name (Symbol)

    The role name

Returns:

  • (Set)

    A set of Designators having the given role.

See Also:


73
74
75
76
77
# 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

#identify(designator, actor_or_id = nil) ⇒ Object (protected)

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
     | }
    

Parameters:

  • designator (Designator)

    the designator to grant

  • actor_or_id (Actor) (defaults to: nil)

    or [String] the actor


185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# 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

#inspectObject Also known as: pretty_print_inspect

Pretty prints this ACL in your console.


132
133
134
# File 'lib/eaco/acl.rb', line 132

def inspect
  "#<#{self.class.name}: #{super}>"
end

#pretty_inspectObject

Pretty print for pry.


140
141
142
# File 'lib/eaco/acl.rb', line 140

def pretty_inspect
  "#{self.class.name}\n#{super}"
end