Class: Hoodoo::Services::Permissions

Inherits:
Object
  • Object
show all
Defined in:
lib/hoodoo/services/services/permissions.rb

Overview

The Permissions class provides a way to store and recall information on action behaviour for resources. It is just a way to store and query this information; actually enforcing the result is up to the caller.

Permissions are based on the standard actions - list, show, create, update and delete - with defined permissions of constants DENY (prohibit access), ALLOW (allow access) and ASK. The intention of ASK is that some other component - usually a service application - should be passed details of the request and asked if it should be permitted.

Callers must ensure they only use the DENY, ALLOW and ASK constants defined herein, without making assumptions about their assigned values.

There is both a default set of permissions in addition to per-resource permissions and there is a fallback for cases where a permission for a particular action has not been defined. This lets you define the baseline behaviour in the fallback cases and only describe exceptions to that baseline through the Permissions interface, minimising caller workload.

Hoodoo::Services::Middleware uses an instance of this class to determine whether or not it should pass on inbound requests to service applications.

Example:

Here, an object is created with a default fallback of DENY, then has the action “list” allowed for all resources and says that resource “Member” must ask someone for permission if its “show” action is requested. Another resource “Ping” allows any action unconditionally.

p = Hoodoo::Services::Permissions.new
p.set_default( :list, Hoodoo::Services::Permissions::ALLOW )
p.set_resource( :Member, :show, Hoodoo::Services::Permissions::ASK )
p.set_resource_fallback( :Ping, Hoodoo::Services::Permissions::ALLOW )

puts JSON.pretty_generate( p.to_h() )

# Yields...
#
# {
#   "default": {
#     "else": "deny",
#     "actions": {
#       "list": "allow"
#     }
#   },
#   "resources": {
#     "Member": {
#       "actions": {
#         "show": "ask"
#       }
#     },
#     "Ping": {
#       "else": "allow"
#     }
#   }
# }

Constant Summary collapse

DENY =

Permission is denied; the action should not be permitted.

'deny'
ALLOW =

Permission is granted; the action should be permitted.

'allow'
ASK =

Something else (e.g. a service application) needs to be asked to see if it permits the action.

'ask'
ALLOWED_POLICIES =

All currently known (allowed/supported) permission policies.

[
  DENY,
  ALLOW,
  ASK
]

Instance Method Summary collapse

Constructor Details

#initialize(hash = nil) ⇒ Permissions

Create a new Permissions instance, optionally from a Hash of the format returned by #to_h.

By default the object is initialised with a default fallback which denies all actions for all resources.



98
99
100
101
102
103
104
105
# File 'lib/hoodoo/services/services/permissions.rb', line 98

def initialize( hash = nil )
  if hash.nil?
    @permissions = {}
    set_default_fallback( DENY )
  else
    from_h!( hash )
  end
end

Instance Method Details

#from_h!(hash) ⇒ Object

Overwrite this instances’s permissions with those from the given Hash.

hash

Permissions hash, which must come (directly or indirectly) from a #to_h call.



214
215
216
# File 'lib/hoodoo/services/services/permissions.rb', line 214

def from_h!( hash )
  @permissions = Hoodoo::Utilities.stringify( hash )
end

#merge!(hash) ⇒ Object

Merge the permissions described by the given Hash with those inside this instance. This will add to, or overwrite permissions with those from the given input Hash.

hash

Permissions hash, which must come (directly or indirectly) from a #to_h call.



225
226
227
228
229
230
# File 'lib/hoodoo/services/services/permissions.rb', line 225

def merge!( hash )
  @permissions = Hoodoo::Utilities.deep_merge_into(
    @permissions,
    Hoodoo::Utilities.stringify( hash )
  )
end

#permitted?(resource_name, action_name) ⇒ Boolean

For the given resource, is the given action permitted? Returns one of the ALLOW, DENY or ASK constant values.

resource_name

Resource name as a Symbol or String, e.g. “Purchase” or :Member.

action_name

Action as a String or Symbol, from: list, show, create, update or delete.

Returns:

  • (Boolean)


183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/hoodoo/services/services/permissions.rb', line 183

def permitted?( resource_name, action_name )
  resource_name = resource_name.to_s
  action_name   = action_name.to_s

  tree = if @permissions.has_key?( 'resources' )
    @permissions[ 'resources' ][ resource_name ]
  end || {}

  result = permitted_in?( tree, action_name )

  if result.nil?
    tree = @permissions[ 'default' ] || {}
    result = permitted_in?( tree, action_name )
  end

  return result || DENY
end

#set_default(action_name, permission) ⇒ Object

Set the default permission for the given action. If a resource does not have a specific entry for it in the Permissions object but the action matches the given name, then this permission is used.

action_name

Action as a String or Symbol, from: list, show, create, update or delete.

permission

DENY, ALLOW or ASK.



129
130
131
132
133
134
135
# File 'lib/hoodoo/services/services/permissions.rb', line 129

def set_default( action_name, permission )
  action_name = action_name.to_s

  @permissions[ 'default' ] ||= {}
  @permissions[ 'default' ][ 'actions' ] ||= {}
  @permissions[ 'default' ][ 'actions' ][ action_name ] = permission
end

#set_default_fallback(permission) ⇒ Object

Set the default fallback for actions. If a resource does not have a specific entry for it in the Permissions object and if the action does not have a default permission, then this permission used.

permission

DENY, ALLOW or ASK.



113
114
115
116
117
118
# File 'lib/hoodoo/services/services/permissions.rb', line 113

def set_default_fallback( permission )
  action_name = action_name.to_s

  @permissions[ 'default' ] ||= {}
  @permissions[ 'default' ][ 'else' ] = permission
end

#set_resource(resource_name, action_name, permission) ⇒ Object

Set the permissions an action on a resource.

resource_name

Resource name as a Symbol or String, e.g. “Purchase” or :Member.

action_name

Action as a String or Symbol, from: list, show, create, update or delete.

permission

DENY, ALLOW or ASK.



164
165
166
167
168
169
170
171
172
# File 'lib/hoodoo/services/services/permissions.rb', line 164

def set_resource( resource_name, action_name, permission )
  resource_name = resource_name.to_s
  action_name   = action_name.to_s

  @permissions[ 'resources' ] ||= {}
  @permissions[ 'resources' ][ resource_name ] ||= {}
  @permissions[ 'resources' ][ resource_name ][ 'actions' ] ||= {}
  @permissions[ 'resources' ][ resource_name ][ 'actions' ][ action_name ] = permission
end

#set_resource_fallback(resource_name, permission) ⇒ Object

Set the default fallback for a resource. If the resource is asked to perform an action that’s not otherwise listed in the resource’s entry in the Permissions object, then this permission is used.

resource_name

Resource name as a Symbol or String, e.g. “Purchase” or :Member.

permission

DENY, ALLOW or ASK.



146
147
148
149
150
151
152
# File 'lib/hoodoo/services/services/permissions.rb', line 146

def set_resource_fallback( resource_name, permission )
  resource_name = resource_name.to_s

  @permissions[ 'resources' ] ||= {}
  @permissions[ 'resources' ][ resource_name ] ||= {}
  @permissions[ 'resources' ][ resource_name ][ 'else' ] = permission
end

#to_hObject

Return a Hash representative of this permissions object, which can be stored elsewhere, used to initialise another instance or written to an existing instance with #from_h!.



205
206
207
# File 'lib/hoodoo/services/services/permissions.rb', line 205

def to_h
  @permissions
end