Class: ViewModel::AccessControl::Composed

Inherits:
ViewModel::AccessControl show all
Defined in:
lib/view_model/access_control/composed.rb

Overview

Provides access control as a combination of ‘x_if!` and `x_unless!` checks for each access check (visible, editable, edit_valid). An action is permitted if at least one `if` check and no `unless` checks succeed. For example:

edit_valid_if!("logged in as specified user") { ... }
edit_valid_unless!("user is on fire") { ... }

Direct Known Subclasses

Tree::Node

Defined Under Namespace

Classes: ComposedResult, NoRequiredConditionsError, PermissionsCheck

Constant Summary

Constants included from Callbacks

Callbacks::ALWAYS

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ViewModel::AccessControl

#editable!, #initialize, #visible!

Methods included from Callbacks

#ineligible, #run_callback, wrap_deserialize, wrap_serialize

Constructor Details

This class inherits a constructor from ViewModel::AccessControl

Class Attribute Details

.edit_valid_ifsObject (readonly)

Returns the value of attribute edit_valid_ifs.



99
100
101
# File 'lib/view_model/access_control/composed.rb', line 99

def edit_valid_ifs
  @edit_valid_ifs
end

.edit_valid_unlessesObject (readonly)

Returns the value of attribute edit_valid_unlesses.



99
100
101
# File 'lib/view_model/access_control/composed.rb', line 99

def edit_valid_unlesses
  @edit_valid_unlesses
end

.editable_ifsObject (readonly)

Returns the value of attribute editable_ifs.



99
100
101
# File 'lib/view_model/access_control/composed.rb', line 99

def editable_ifs
  @editable_ifs
end

.editable_unlessesObject (readonly)

Returns the value of attribute editable_unlesses.



99
100
101
# File 'lib/view_model/access_control/composed.rb', line 99

def editable_unlesses
  @editable_unlesses
end

.visible_ifsObject (readonly)

Returns the value of attribute visible_ifs.



99
100
101
# File 'lib/view_model/access_control/composed.rb', line 99

def visible_ifs
  @visible_ifs
end

.visible_unlessesObject (readonly)

Returns the value of attribute visible_unlesses.



99
100
101
# File 'lib/view_model/access_control/composed.rb', line 99

def visible_unlesses
  @visible_unlesses
end

Class Method Details

.each_check(check_name, include_ancestor = nil) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/view_model/access_control/composed.rb', line 163

def each_check(check_name, include_ancestor = nil)
  return enum_for(:each_check, check_name, include_ancestor) unless block_given?

  self.public_send(check_name).each { |x| yield x }

  visited = Set.new
  @included_checkers.each do |ancestor|
    next unless visited.add?(ancestor)
    next if include_ancestor && !include_ancestor.call(ancestor)

    ancestor.each_check(check_name, include_ancestor) { |x| yield x }
  end
end

.edit_valid_if!(reason, &block) ⇒ Object



149
150
151
# File 'lib/view_model/access_control/composed.rb', line 149

def edit_valid_if!(reason, &block)
  @edit_valid_ifs      << new_permission_check(reason, &block)
end

.edit_valid_unless!(reason, &block) ⇒ Object



153
154
155
# File 'lib/view_model/access_control/composed.rb', line 153

def edit_valid_unless!(reason, &block)
  @edit_valid_unlesses << new_permission_check(reason, &block)
end

.editable_if!(reason, &block) ⇒ Object



141
142
143
# File 'lib/view_model/access_control/composed.rb', line 141

def editable_if!(reason, &block)
  @editable_ifs        << new_permission_check(reason, &block)
end

.editable_unless!(reason, &block) ⇒ Object



145
146
147
# File 'lib/view_model/access_control/composed.rb', line 145

def editable_unless!(reason, &block)
  @editable_unlesses   << new_permission_check(reason, &block)
end

.include_from(ancestor) ⇒ Object

Configuration API



125
126
127
128
129
130
131
# File 'lib/view_model/access_control/composed.rb', line 125

def include_from(ancestor)
  unless ancestor < ViewModel::AccessControl::Composed
    raise ArgumentError.new("Invalid ancestor: #{ancestor}")
  end

  @included_checkers << ancestor
end

.inherited(subclass) ⇒ Object



106
107
108
109
# File 'lib/view_model/access_control/composed.rb', line 106

def inherited(subclass)
  super
  subclass.initialize_as_composed_access_control
end

.initialize_as_composed_access_controlObject



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/view_model/access_control/composed.rb', line 111

def initialize_as_composed_access_control
  @included_checkers = []

  @edit_valid_ifs      = []
  @edit_valid_unlesses = []

  @editable_ifs        = []
  @editable_unlesses   = []

  @visible_ifs         = []
  @visible_unlesses    = []
end

.inspectObject



177
178
179
180
181
182
# File 'lib/view_model/access_control/composed.rb', line 177

def inspect
  checks = inspect_checks
  checks << "includes checkers: #{@included_checkers.inspect}" if @included_checkers.present?

  super + '(' + checks.join(', ') + ')'
end

.inspect_checksObject



184
185
186
187
188
189
190
191
192
193
# File 'lib/view_model/access_control/composed.rb', line 184

def inspect_checks
  checks = []
  checks << "visible_if: #{@visible_ifs.map(&:reason)}"                if @visible_ifs.present?
  checks << "visible_unless: #{@visible_unlesses.map(&:reason)}"       if @visible_unlesses.present?
  checks << "editable_if: #{@editable_ifs.map(&:reason)}"              if @editable_ifs.present?
  checks << "editable_unless: #{@editable_unlesses.map(&:reason)}"     if @editable_unlesses.present?
  checks << "edit_valid_if: #{@edit_valid_ifs.map(&:reason)}"          if @edit_valid_ifs.present?
  checks << "edit_valid_unless: #{@edit_valid_unlesses.map(&:reason)}" if @edit_valid_unlesses.present?
  checks
end

.new_permission_check(reason, error_type: ViewModel::AccessControlError, &block) ⇒ Object

Implementation



159
160
161
# File 'lib/view_model/access_control/composed.rb', line 159

def new_permission_check(reason, error_type: ViewModel::AccessControlError, &block)
  PermissionsCheck.new(self.name&.demodulize, reason, error_type, block)
end

.visible_if!(reason, &block) ⇒ Object



133
134
135
# File 'lib/view_model/access_control/composed.rb', line 133

def visible_if!(reason, &block)
  @visible_ifs         << new_permission_check(reason, &block)
end

.visible_unless!(reason, &block) ⇒ Object



137
138
139
# File 'lib/view_model/access_control/composed.rb', line 137

def visible_unless!(reason, &block)
  @visible_unlesses    << new_permission_check(reason, &block)
end

Instance Method Details

#editable_check(traversal_env) ⇒ Object

final



202
203
204
# File 'lib/view_model/access_control/composed.rb', line 202

def editable_check(traversal_env)
  check_delegates(traversal_env, self.class.each_check(:editable_ifs), self.class.each_check(:editable_unlesses))
end

#valid_edit_check(traversal_env) ⇒ Object

final



207
208
209
# File 'lib/view_model/access_control/composed.rb', line 207

def valid_edit_check(traversal_env)
  check_delegates(traversal_env, self.class.each_check(:edit_valid_ifs), self.class.each_check(:edit_valid_unlesses))
end

#visible_check(traversal_env) ⇒ Object

final



197
198
199
# File 'lib/view_model/access_control/composed.rb', line 197

def visible_check(traversal_env)
  check_delegates(traversal_env, self.class.each_check(:visible_ifs), self.class.each_check(:visible_unlesses))
end