Module: Card::Set::All::Permissions

Extended by:
Card::Set
Defined in:
card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb,
card/tmpsets/set/mod009-card-mod-permissions/all/permissions.rb

Overview

Set: All cards (Permissions)

Defined Under Namespace

Modules: ClassMethods

Constant Summary

Constants included from Helpers

Helpers::SET_PATTERN_TEST_REGEXP

Constants included from Event::Api

Event::Api::OPTIONS

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Card::Set

reset_modules

Methods included from I18nScope

#mod_name, #scope

Methods included from Loader

#clean_empty_module_from_hash, #clean_empty_modules, #extended, #process_base_modules, #register_set

Methods included from Helpers

#method_missing, #num_set_parts, #pattern_code, #respond_to_missing?, #set_name_parts, #shortname, #underscore

Methods included from Card::Set::AdvancedApi

#attachment, #define_set_from_error, #ensure_set, #setting_opts, #stage_method

Methods included from Format

#before, #format, layout_method_name, #view, view_method_name, view_setting_method_name, wrapper_method_name

Methods included from Inheritance

#include_set, #include_set_formats

Methods included from Basket

#abstract_basket, #add_to_basket, #basket, #unshift_basket

Methods included from Trait

#card_accessor, #card_reader, #card_writer, #require_field

Methods included from Event::Api

#event

Class Method Details

.source_locationObject



7
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 7

def self.source_location; "/Users/ethan/dev/decko/gem/card-mod-permissions/set/all/permissions.rb"; end

Instance Method Details

#action_for_permission_checkObject



224
225
226
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 224

def action_for_permission_check
  commenting? ? :update : action
end

#add_to_read_rule_update_queue(updates) ⇒ Object



214
215
216
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 214

def add_to_read_rule_update_queue updates
  @read_rule_update_queue = Array.wrap(@read_rule_update_queue).concat updates
end

#anyone_can?(action) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 50

def anyone_can? action
  who_can(action).include? AnyoneID
end

#deny_because(why) ⇒ Object



100
101
102
103
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 100

def deny_because why
  @permission_errors << why if @permission_errors
  false
end

#direct_rule_card(action) ⇒ Object



54
55
56
57
58
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 54

def direct_rule_card action
  direct_rule_id = rule_card_id action
  require_permission_rule! direct_rule_id, action
  Card.quick_fetch direct_rule_id
end

#each_field_as_bot(&block) ⇒ Object



185
186
187
188
189
190
191
192
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 185

def each_field_as_bot
  # find all cards with me as trunk and update their read_rule
  # (because of *type plus right)
  # skip if name is updated because will already be resaved
  Auth.as_bot do
    fields.each { |field| yield field }
  end
end

#event: check_permissionsObject



218
219
220
221
222
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 218

event :check_permissions, :validate do
  track_permission_errors do
    ok? action_for_permission_check
  end
end

#event: set_field_read_rulesObject



174
175
176
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 174

event :set_field_read_rules, after: :set_read_rule, on: :update, changed: :type_id do
  each_field_as_bot(&:update_read_rule)
end

#event: set_read_ruleObject

don’t know why we introduced this but we have to preserve read rules to make delete acts visible in recent changes -pk event :clear_read_rule, :store, on: :delete do self.read_rule_id = self.read_rule_class = nil end



168
169
170
171
172
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 168

event :set_read_rule, :store, on: :save, changed: %i[type_id name] do
  read_rule_id, read_rule_class = permission_rule_id_and_class(:read)
  self.read_rule_id = read_rule_id
  self.read_rule_class = read_rule_class
end

#event: update_read_ruleObject



201
202
203
204
205
206
207
208
209
210
211
212
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 201

event :update_read_rule do
  without_timestamps do
    reset_patterns # why is this needed?
    rcard_id, rclass = permission_rule_id_and_class :read
    # these two are just to make sure vals are correct on current object
    self.read_rule_id = rcard_id
    self.read_rule_class = rclass
    Card.where(id: id).update_all read_rule_id: rcard_id, read_rule_class: rclass
    expire :hard
    update_field_read_rules
  end
end

#left_permission_rule_id(action) ⇒ Object



72
73
74
75
76
77
78
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 72

def left_permission_rule_id action
  lcard = left_or_new(skip_virtual: true, skip_modules: true)
  if action == :create && lcard.real? && lcard.action != :create
    action = :update
  end
  lcard.permission_rule_id action
end

#ok!(action) ⇒ Object



42
43
44
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 42

def ok! action
  raise Card::Error::PermissionDenied, self unless ok? action
end

#ok?(action) ⇒ Boolean

ok? and ok! are public facing methods to approve one action at a time

fetching: if the optional :trait parameter is supplied, it is passed to fetch and the test is perfomed on the fetched card, therefore:

 trait: :account      would fetch this card plus a tag codenamed :account
 trait: :roles, new: {} would initialize a new card with default ({}) options.

Returns:

  • (Boolean)


32
33
34
35
36
37
38
39
40
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 32

def ok? action
  @ok ||= {}
  aok = @ok[Auth.as_id] ||= {}
  if (cached = aok[action])
    cached
  else
    aok[action] = send "ok_to_#{action}"
  end
end

#ok_to_createObject



124
125
126
127
128
129
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 124

def ok_to_create
  return false unless permit :create
  return true if simple?

  %i[left right].find { |side| !ok_to_create_side side } ? false : true
end

#ok_to_create_side(side) ⇒ Object



131
132
133
134
135
136
137
138
139
140
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 131

def ok_to_create_side side
  # left is supercard; create permissions will get checked there.
  return true if side == :left && superleft
  part_card = send side, new: {}
  # if no card, there must be other errors
  return true unless part_card&.new_card? && !part_card.ok?(:create)

  deny_because you_cant("create #{part_card.name}")
  false
end

#ok_to_deleteObject



157
158
159
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 157

def ok_to_delete
  permit :delete
end

#ok_to_readObject



142
143
144
145
146
147
148
149
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 142

def ok_to_read
  return true if Auth.always_ok?

  self.read_rule_id ||= permission_rule_id :read
  return true if Auth.as_card.read_rules_hash[read_rule_id]

  deny_because you_cant "read this"
end

#ok_to_updateObject



151
152
153
154
155
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 151

def ok_to_update
  return false unless permit(:update)
  return true unless type_id_changed? && !permitted?(:create)
  deny_because you_cant("change to this type (need create permission)")
end

#permission_rule_card(action) ⇒ Object



80
81
82
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 80

def permission_rule_card action
  Card.fetch permission_rule_id(action)
end

#permission_rule_id(action) ⇒ Object



60
61
62
63
64
65
66
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 60

def permission_rule_id action
  if junction? && rule(action).match?(/^\[?\[?_left\]?\]?$/)
    left_permission_rule_id action
  else
    rule_card_id(action)
  end
end

#permission_rule_id_and_class(action) ⇒ Object



68
69
70
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 68

def permission_rule_id_and_class action
  [permission_rule_id(action), direct_rule_card(action).rule_class_name]
end

#permit(action, verb = nil) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 112

def permit action, verb=nil
  # not called by ok_to_read
  if Card.config.read_only
    deny_because "Currently in read-only mode"
    return false
  end

  return true if permitted? action
  verb ||= action.to_s
  deny_because you_cant("#{verb} #{name.present? ? name : 'this'}")
end

#permitted?(action) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
108
109
110
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 105

def permitted? action
  return false if Card.config.read_only # :read does not call #permit
  return true if Auth.always_ok?

  Auth.as_card.among? who_can(action)
end

#repair_permissions!Object



18
19
20
21
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 18

def repair_permissions!
  rule_id, rule_class = permission_rule_id_and_class :read
  update_columns read_rule_id: rule_id, read_rule_class: rule_class
end

#require_permission_rule!(rule_id, action) ⇒ Object



84
85
86
87
88
89
90
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 84

def require_permission_rule! rule_id, action
  return if rule_id
  # RULE missing.  should not be possible.
  # generalize this to handling of all required rules
  errors.add :permission_denied, tr(:error_no_action_rule, action: action, name: name)
  raise Card::Error::PermissionDenied, self
end

#rule_class_nameObject



92
93
94
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 92

def rule_class_name
  trunk.type_id == SetID ? name.trunk_name.tag : nil
end

#track_permission_errorsObject



228
229
230
231
232
233
234
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 228

def track_permission_errors
  @permission_errors = []
  result = yield
  @permission_errors.each { |msg| errors.add :permission_denied, msg }
  @permission_errors = nil
  result
end

#update_field_read_rulesObject



178
179
180
181
182
183
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 178

def update_field_read_rules
  return unless type_id_changed? || read_rule_id_changed?
  each_field_as_bot do |field|
    field.update_read_rule if field.rule(:read) == "_left"
  end
end

#who_can(action) ⇒ Object



46
47
48
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 46

def who_can action
  permission_rule_card(action).item_cards.map(&:id)
end

#without_timestampsObject



194
195
196
197
198
199
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 194

def without_timestamps
  Card.record_timestamps = false
  yield
ensure
  Card.record_timestamps = true
end

#you_cant(what) ⇒ Object



96
97
98
# File 'card/tmpsets/set/mod010-card-mod-permissions/all/permissions.rb', line 96

def you_cant what
  "You don't have permission to #{what}"
end