Class: Eaco::DSL::ACL

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

Overview

Block-less DSL to set up the ACL machinery onto an authorized Resource.

Instance Attribute Summary

Attributes inherited from Base

#options, #target

Instance Method Summary collapse

Methods inherited from Base

eval, #target_eval

Constructor Details

#initializenil

Performs ACL setup on the target Resource model.



28
29
30
31
32
33
34
35
36
37
# File 'lib/eaco/dsl/acl.rb', line 28

def initialize(*)
  super

  define_acl_subclass
  define_role_getters
  install_persistance
  install_strategy

  nil
end

Instance Method Details

#adapterClass (private)

Tries to identify which ORM adapter to use for the target class.

Returns:

  • (Class)

    the adapter implementation or nil if not available.



156
157
158
159
160
# File 'lib/eaco/dsl/acl.rb', line 156

def adapter
  { 'ActiveRecord::Base'     => Eaco::Adapters::ActiveRecord,
    'CouchRest::Model::Base' => Eaco::Adapters::CouchrestModel,
  }.fetch(orm.name, nil)
end

#define_acl_subclass (private)

This method returns an undefined value.

Creates the ACL constant on the target, inheriting from ACL. Removes if it is already set, so that a reload of the authorization rules refreshes also these constants.

The ACL subclass can be retrieved using the .acl singleton method on the Resource class.



51
52
53
54
55
56
57
58
59
60
# File 'lib/eaco/dsl/acl.rb', line 51

def define_acl_subclass
  target_eval do
    remove_const(:ACL) if constants.include?(:ACL)

    Class.new(Eaco::ACL).tap do |acl_class|
      define_singleton_method(:acl) { acl_class }
      const_set(:ACL, acl_class)
    end
  end
end

#define_role_getters (private)

This method returns an undefined value.

Define getter methods on the ACL for each role, syntactic sugar for calling ACL#find_by_role.

Example:

If a reader role is defined, allows doing resource.acl.readers and returns all the designators having the reader role set.



73
74
75
76
77
78
79
80
81
# File 'lib/eaco/dsl/acl.rb', line 73

def define_role_getters
  roles = self.target.roles

  target.acl.instance_eval do
    roles.each do |role|
      define_method(role.to_s.pluralize) { find_by_role(role) }
    end
  end
end

#install_authorized_collection_strategy (private)

This method returns an undefined value.

Looks up the authorized collection strategy within the Adapter, using the :using option given to the authorize Resource DSL

See Also:



145
146
147
148
149
# File 'lib/eaco/dsl/acl.rb', line 145

def install_authorized_collection_strategy
  if adapter && (strategy = adapter.strategies[ options.fetch(:using, nil) ])
    target.extend strategy
  end
end

#install_persistance (private)

This method returns an undefined value.

Sets up the persistance layer for ACLs (#acl and #acl=).

These APIs can be implemented directly in your Resource model, as long as the acl accessor accepts and returns the Resource model’s ACL subclass (see #define_acl_subclass)

See each adapter for the details of the extraction strategies they provide.



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/eaco/dsl/acl.rb', line 95

def install_persistance
  if adapter
    target.send(:include, adapter)
    install_authorized_collection_strategy

  elsif (target.instance_methods & [:acl, :acl=]).size != 2
    raise Malformed, <<-EOF
      Don't know how to persist ACLs using <#{target}>'s ORM
      (identified as <#{orm}>). Please define an `acl' instance
      accessor on <#{target}> that accepts and returns a <#{target.acl}>.
    EOF
  end
end

#install_strategy (private)

This method returns an undefined value.

Sets up the authorized collection extraction strategy (.accessible_by).

This API can be implemented directly in your model, as long as .accessible_by returns an Enumerable collection.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/eaco/dsl/acl.rb', line 118

def install_strategy
  unless target.respond_to?(:accessible_by)
    strategies = adapter ? adapter.strategies.keys : []

    raise Malformed, <<-EOF
      Don't know how to look up authorized records on <#{target}>'s
      ORM (identified as <#{orm}>). To authorize <#{target}>

      #{ if strategies.size > 0
        "either use one of the available strategies: #{strategies.join(', ')} or"
      end }

      please define your own #{target}.accessible_by method.
      You may at one point want to move this in a new strategy,
      and send a pull request :-).
    EOF
  end
end

#ormClass (private)

Tries to naively identify which ORM the target model is using.

TODO support more stuff

Returns:

  • (Class)

    the ORM base class.



169
170
171
172
173
174
175
# File 'lib/eaco/dsl/acl.rb', line 169

def orm
  if target.respond_to?(:base_class)
    target.base_class.superclass # Active Record
  else
    target.superclass # Naive
  end
end