Class: Walruz::Policy

Inherits:
Object
  • Object
show all
Extended by:
Utils
Defined in:
lib/walruz/policy.rb

Overview

One of the cores of the framework, its purpose is to encapsulate an authorization logic with a given actor and subject. It’s main method authorized?(actor, subject) verifies that an actor is authorized to manage the subject.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

all, any, negate

Class Method Details

.depends_on(*other_policies) ⇒ Object

Stablish other Policy dependencies, so that they are executed before the current one, giving chances to receive the previous policies return parameters.

Examples:

class FriendEditProfilePolicy
  depends_on FriendPolicy

  def authorized?(actor, subject)
    # The FriendPolicy returns a hash with a key of :friend_relationship
    # this will be available via the params method.
    params[:friend_relationship].can_edit? # for friend metadata
  end

end

Parameters:

  • Policies (Array<Walruz::Policies>)

    in wich this policy depends on.

Returns:

  • self



96
97
98
# File 'lib/walruz/policy.rb', line 96

def self.depends_on(*other_policies)
  self.policy_dependencies = (other_policies << self)
end

.for_subject(key, &block) ⇒ Walruz::Policy

Creates a new policy class based on an existing one, you may use this method when you want to reuse a Policy class for a subject’s association.

Parameters:

  • Name (Symbol)

    of the association that will be the subject of the policy.

Returns:

  • (Walruz::Policy)

    New generated policy that will pass the association as the subject of the original policy.

See Also:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/walruz/policy.rb', line 38

def self.for_subject(key, &block)
  
  clazz = Class.new(Walruz::Policy) do # :nodoc:
    extend Walruz::Utils::PolicyCompositionHelper
    
    def authorized?(actor, subject) # :nodoc:
      params = self.class.params
      new_subject = subject.send(params[:key])
      result = self.class.policy.new.safe_authorized?(actor, new_subject)
      params[:callback].call(result[0], result[1], actor, subject) if params[:callback]
      result
    end
    
  end
  clazz.policy = self
  clazz.set_params(:key => key, :callback => block)
  clazz
end

.inherited(child) ⇒ Object

:nodoc:



12
13
14
15
16
17
# File 'lib/walruz/policy.rb', line 12

def self.inherited(child) # :nodoc:
  @policies ||= {}
  unless child.policy_label.nil?
    @policies[child.policy_label] = child
  end
end

.policiesObject

See Also:



25
26
27
# File 'lib/walruz/policy.rb', line 25

def self.policies
  @policies || {}
end

.policy_dependenciesObject

Utility for depends_on macro



106
107
108
# File 'lib/walruz/policy.rb', line 106

def self.policy_dependencies # :nodoc:
  @_policy_dependencies
end

.policy_dependencies=(dependencies) ⇒ Object

Utility for depends_on macro



101
102
103
# File 'lib/walruz/policy.rb', line 101

def self.policy_dependencies=(dependencies) # :nodoc:
  @_policy_dependencies = dependencies
end

.policy_keywordSymbol

Returns the identifier of the Policy that will be setted on the policy params hash once the authorization is executed.

Returns:

  • (Symbol)

    By default it will return a symbol with the name of the Policy class in underscore (unless the policy label was setted, in that case the policy label will be used) with an ‘?’ appended.



153
154
155
156
157
158
159
160
# File 'lib/walruz/policy.rb', line 153

def self.policy_keyword
  if self.policy_label.nil?
    nil
  else
    :"#{self.policy_label}?"
  end
  
end

.policy_labelObject

Returns the label assigned to the policy



165
166
167
# File 'lib/walruz/policy.rb', line 165

def self.policy_label
  @policy_label ||= ((name.nil? || name.empty?) ? nil : :"#{self.underscore(self.name)}")
end

.return_policyObject

Utility for depends_on macro



111
112
113
114
115
116
117
# File 'lib/walruz/policy.rb', line 111

def self.return_policy # :nodoc:
  if policy_dependencies.nil?
    self
  else
    all(*policy_dependencies)
  end
end

.set_policy_label(label) ⇒ Object

Sets the identifier of the Policy for using on the ‘satisfies?` method

Parameters:

- label: Symbol that represents the policy


175
176
177
178
179
180
181
182
183
184
# File 'lib/walruz/policy.rb', line 175

def self.set_policy_label(label)
  if self.policy_label.nil? || 
     self.policy_label.to_s.empty? || 
     Walruz.policies[self.policy_label].nil?
    Walruz.policies[label] = self
  else
    Walruz.policies[label] = Walruz.policies.delete(self.policy_label)
  end
  @policy_label = label
end

.underscore(camel_cased_word) ⇒ Object

Utility method (from ActiveSupport)



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/walruz/policy.rb', line 120

def self.underscore(camel_cased_word) # :nodoc:
  if camel_cased_word.empty?
    camel_cased_word
  else
    camel_cased_word.to_s.split('::').last.
            gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
            gsub(/([a-z\d])([A-Z])/,'\1_\2').
            tr("-", "_").
            downcase
  end
end

.with_actor(actor) ⇒ Proc

Returns a Proc with a curried actor, making it easier to perform validations of a policy in an Array of subjects.

Examples:

subjects.select(&PolicyXYZ.with_actor(some_user))

Parameters:

Returns:

  • (Proc)

    A proc that receives as a parameter subject and returns what the authorized? method returns.

See Also:



69
70
71
72
73
74
# File 'lib/walruz/policy.rb', line 69

def self.with_actor(actor)
  policy_instance = self.new
  lambda do |subject|
    policy_instance.safe_authorized?(actor, subject)[0]
  end
end

Instance Method Details

#authorized?(actor, subject) ⇒ Boolean

Verifies if the actor is authorized to interact with the subject

Parameters:

Returns:

  • (Boolean)

    It may return a Boolean, or an Array with the first position being a boolean and the second being a Hash of parameters returned from the policy.

Raises:

  • (NotImplementedError)


142
143
144
# File 'lib/walruz/policy.rb', line 142

def authorized?(actor, subject)
  raise NotImplementedError.new("You need to implement policy")
end

#halt(msg = "You are not authorized") ⇒ Object

Raises:



19
20
21
# File 'lib/walruz/policy.rb', line 19

def halt(msg="You are not authorized")
  raise PolicyHalted.new(msg)
end

#paramsObject



198
199
200
# File 'lib/walruz/policy.rb', line 198

def params
  @params ||= {}
end

#safe_authorized?(actor, subject) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


186
187
188
189
190
191
# File 'lib/walruz/policy.rb', line 186

def safe_authorized?(actor, subject) # :nodoc:
  result = Array(authorized?(actor, subject))
  result[1] ||= {}
  result[1][self.class.policy_keyword] = result[0] unless self.class.policy_keyword.nil?
  result
end

#set_params(params) ⇒ Object

:nodoc:



193
194
195
196
# File 'lib/walruz/policy.rb', line 193

def set_params(params) # :nodoc:
  @params = params
  self
end