Module: Walruz::Utils
- Included in:
- Policy
- Defined in:
- lib/walruz/utils.rb
Overview
This module provides pretty handy methods to do compositions of basic policies to create more complex ones.
Using a policies file to manage complex policies
It’s always a good idea to keep the policy composition in one place, you may place a file in your project where you manage all the authorization policies, and then you use them on your models.
Say for example you have a lib/policies.rb
in your project where you manage the composition of policies, and a lib/policies
folder where you create your custom policies.
The lib/policies.rb
file could be something like this:
module Policies
include Walruz::Utils
# Requiring basic Walruz::Policy classes
BASE = File.join(File.dirname(__FILE__), "policies") unless defined?(BASE)
require File.join(BASE, "actor_is_admin")
require File.join(BASE, "user_is_owner")
require File.join(BASE, "user_is_friend")
#####
# User Policies
#
UserCreatePolicy = ActorIsAdmin
UserReadPolicy = any(UserIsOwner, UserIsFriend, ActorIsAdmin)
UserUpdatePolicy = any(UserIsOwner, ActorIsAdmin)
UserDestroyPolicy = ActorIsAdmin
end
Using a policies file on your project, keeps all your authorization logic just in one place that way, when you change the authorizations you just have to go to one place only.
Defined Under Namespace
Modules: PolicyCompositionHelper
Class Method Summary collapse
-
.all(*policies) ⇒ Walruz::Policy
Generates a new policy that merges together different policies by an AND association.
-
.any(*policies) ⇒ Walruz::Policy
Generates a new policy that merges together different policies by an OR association.
-
.negate(policy) ⇒ Object
Generates a new policy that negates the result of the given policy.
Class Method Details
.all(*policies) ⇒ Walruz::Policy
Generates a new policy that merges together different policies by an AND association. This will execute every policy on the list, if all of them return true then the policy will succeed. This process will merge the parameters of each policy, so you may be able to use the parameters of previous policies, and at the end it will return all the parameters from every policy.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/walruz/utils.rb', line 108 def all(*policies) clazz = Class.new(Walruz::Policy) do # :nodoc: extend PolicyCompositionHelper def (actor, subject) # :nodoc: acum = [true, self.params || {}] self.class.policies.each do |policy| break unless acum[0] result = policy.new.set_params(acum[1]).(actor, subject) acum[0] &&= result[0] acum[1].merge!(result[1]) end acum[0] ? acum : acum[0] end def self.policy_keyword # :nodoc: (self.policies.map { |p| p.policy_keyword.to_s[0..-2] }.join('_and_') + "?").to_sym end end clazz.policies = policies clazz end |
.any(*policies) ⇒ Walruz::Policy
Generates a new policy that merges together different policies by an OR association. As soon as one of the policies succeed, the parameters of that policy will be returned.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/walruz/utils.rb', line 81 def any(*policies) clazz = Class.new(Walruz::Policy) do # :nodoc: extend PolicyCompositionHelper def (actor, subject) # :nodoc: result = nil self.class.policies.detect do |policy| result = policy.new.set_params(params).(actor, subject) result[0] end result[0] ? result : result[0] end end clazz.policies = policies clazz end |
.negate(policy) ⇒ Object
Generates a new policy that negates the result of the given policy.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/walruz/utils.rb', line 137 def negate(policy) clazz = Class.new(Walruz::Policy) do # :nodoc: extend PolicyCompositionHelper # :nodoc: def (actor, subject) result = self.class.policy.new.set_params(params).(actor, subject) result[0] = !result[0] result end def self.policy_keyword # :nodoc: keyword = self.policy.policy_keyword.to_s[0..-2] :"not(#{keyword})?" end end clazz.policy = policy clazz end |