Class: Shark::Permissions::List

Inherits:
Object
  • Object
show all
Defined in:
lib/shark/permissions/list.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rules = {}) ⇒ List

Returns a new instance of List.



11
12
13
14
15
16
17
18
19
20
# File 'lib/shark/permissions/list.rb', line 11

def initialize(rules = {})
  case rules
  when Shark::Permissions::List
    @rules = to_permission_rules(rules.as_json)
  when Hash
    @rules = to_permission_rules(rules)
  else
    raise ArgumentError, 'Rules must be a subtype of Hash'
  end
end

Instance Attribute Details

#rulesObject (readonly)

Returns the value of attribute rules.



9
10
11
# File 'lib/shark/permissions/list.rb', line 9

def rules
  @rules
end

Class Method Details

.dump(list) ⇒ String

For Serializaton

Returns:

  • (String)


261
262
263
# File 'lib/shark/permissions/list.rb', line 261

def self.dump(list)
  list&.to_json
end

.load(json) ⇒ Shark::Permissions::List

For Deserializaton



249
250
251
252
253
254
255
# File 'lib/shark/permissions/list.rb', line 249

def self.load(json)
  if json.nil?
    new
  else
    new(JSON.parse(json))
  end
end

Instance Method Details

#<<(rule) ⇒ Object



29
30
31
# File 'lib/shark/permissions/list.rb', line 29

def <<(rule)
  @rules[rule.resource] = rule
end

#==(other) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/shark/permissions/list.rb', line 24

def ==(other)
  rules == other.rules
end

#as_json(*args) ⇒ Hash

Returns:

  • (Hash)


241
242
243
# File 'lib/shark/permissions/list.rb', line 241

def as_json(*args)
  rules.as_json(*args)
end

#authorized?(privilege, *resources) ⇒ Boolean

@example:

list.authorized?(:admin, :paragraph, :contracts)
# => true
list.authorized?([:read, :write], :datenraum, :berlin)
# => false

Returns:

  • (Boolean)


185
186
187
188
189
190
191
192
193
# File 'lib/shark/permissions/list.rb', line 185

def authorized?(privilege, *resources)
  if privilege == Shark::Permissions.any_matcher
    privileges(*resources).present?
  else
    privilege_array = Array(privilege).map(&:to_s)
    privileges_for_resource = privileges(*resources)
    privilege_array.any? { |p| privileges_for_resource.fetch(p, false) }
  end
end

#changesObject



39
40
41
42
# File 'lib/shark/permissions/list.rb', line 39

def changes
  changed_rules = rules.select { |_key, rule| rule.changed? }.to_h
  self.class.new(changed_rules)
end

#clonePermissions::List

Returns a new Permissions::List with same rules.

Returns:



48
49
50
51
52
53
# File 'lib/shark/permissions/list.rb', line 48

def clone
  cloned_rules = {}
  rules.each { |k, rule| cloned_rules[k] = rule.clone }

  self.class.new(cloned_rules)
end

#compactPermissions::List

Returns a new Permissions::List without any rules that have no privileges.

Returns:



59
60
61
62
63
64
65
66
67
68
# File 'lib/shark/permissions/list.rb', line 59

def compact
  new_rules = {}

  rules.keys.sort.each do |k|
    rule = rules[k].clone
    new_rules[k] = rule unless rule.empty?
  end

  self.class.new(new_rules)
end

#delete(key) ⇒ Object



70
71
72
73
74
75
76
77
78
79
# File 'lib/shark/permissions/list.rb', line 70

def delete(key)
  case key
  when String
    rules.delete(key)
  when Permissions::Rule
    rules.delete(key.resource)
  else
    raise ArgumentError, 'Argument must be a String or Permissions::Rule'
  end
end

#map(&block) ⇒ Array

Returns:

  • (Array)


35
36
37
# File 'lib/shark/permissions/list.rb', line 35

def map(&block)
  rules.values.map(&block)
end

#merge(other_list) ⇒ Hash

Parameters:

Returns:

  • (Hash)


113
114
115
# File 'lib/shark/permissions/list.rb', line 113

def merge(other_list)
  clone.merge!(other_list)
end

#merge!(other_list) ⇒ Hash

Merges another list into this list. Allowed privileges are not removed. Changes are not tracked.

Parameters:

Returns:

  • (Hash)


123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/shark/permissions/list.rb', line 123

def merge!(other_list)
  other_list.each do |resource, rule|
    if rules.key?(resource)
      privileges = rules[resource].privileges
      rule.privileges.each { |k, v| privileges[k] = privileges[k] || v }
    else
      rules[resource] = rule.clone
    end
  end

  self
end

#privileges(*resources) ⇒ Hash

@example:

list.privileges(:paragraph, :contracts)
# => { 'admin' => true, 'edit' => true }

Returns:

  • (Hash)


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/shark/permissions/list.rb', line 157

def privileges(*resources)
  matching_resources = matching_resources(*resources)
  privileges_set = Set.new

  matching_resources.each do |name|
    rule = rules[name]

    next unless rule

    case rule.effect
    when 'ALLOW'
      privileges_set.merge(rule.privileges_as_array)
    when 'DENY'
      privileges.subtract(rule.privileges_as_array)
    end
  end

  privileges_set.map { |k| [k, true] }.to_h
end

#reject(names) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/shark/permissions/list.rb', line 97

def reject(names)
  filtered_rules = {}

  rejected_keys = select(names).keys
  rules.each do |name, rule|
    next if rejected_keys.include?(name)

    filtered_rules[rule.resource] = rule.clone
  end

  self.class.new(filtered_rules)
end

#remove_inherited_rulesPermissions::List

Returns new list without inherited privileges and empty rules.

Returns:



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/shark/permissions/list.rb', line 222

def remove_inherited_rules
  new_list = self.class.new({})

  rules.keys.sort.each do |name|
    new_rule = Permissions::Rule.new(resource: name)
    parent = new_rule.parent

    rules[name].privileges.each do |k, v|
      new_rule.privileges[k] = v if v && !new_list.authorized?(k, parent)
    end

    new_list << new_rule unless new_rule.empty?
  end

  new_list
end

#select(names) ⇒ Object Also known as: filter



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/shark/permissions/list.rb', line 81

def select(names)
  filtered_rules = {}

  Array(names).each do |filter_name|
    filter_resource = Permissions::Resource.new(filter_name)
    rules.each do |name, rule|
      next unless filter_resource.super_resource_of?(name)

      filtered_rules[rule.resource] = rule.clone
    end
  end

  self.class.new(filtered_rules)
end

#set_inherited_privileges!Permissions::List

Correctly set privileges for subresources.

Returns:



209
210
211
212
213
214
215
216
# File 'lib/shark/permissions/list.rb', line 209

def set_inherited_privileges!
  rules.each do |resource, rule|
    privileges = privileges(resource)
    privileges.each { |k, v| rule.privileges[k] = v if rule.privileges.key?(k) }
  end

  self
end

#subresource_authorized?(privilege, *resources) ⇒ Boolean

@example:

list.subresource_authorized?(:admin, :paragraph, :contracts)
# => true

Returns:

  • (Boolean)


201
202
203
# File 'lib/shark/permissions/list.rb', line 201

def subresource_authorized?(privilege, *resources)
  authorized?(privilege, *resources, Shark::Permissions.any_matcher)
end

#update(other_list) ⇒ Hash

Updates this list with rules from another list. All affected rules are updated and changes are tracked.

Parameters:

Returns:

  • (Hash)


142
143
144
145
146
147
148
149
# File 'lib/shark/permissions/list.rb', line 142

def update(other_list)
  other_list.each do |resource, other_rule|
    rules[resource] = Permissions::Rule.new(resource: resource) unless rules.key?(resource)
    rules[resource].update(other_rule)
  end

  self
end