class Object

Public Instance Methods

action_for_permission_check() click to toggle source
# File set/all/permissions.rb, line 221
def action_for_permission_check
  commenting? ? :update : action
end
add_to_read_rule_update_queue(updates) click to toggle source
# File set/all/permissions.rb, line 211
def add_to_read_rule_update_queue updates
  @read_rule_update_queue = Array.wrap(@read_rule_update_queue).concat updates
end
all_members() click to toggle source
# File set/right/read.rb, line 53
def all_members
  rule_set.item_cards limit: 0
end
anyone_can?(action) click to toggle source
# File set/all/permissions.rb, line 43
def anyone_can? action
  who_can(action).include? AnyoneID
end
core_inherit_content() click to toggle source
# File set/abstract/permission.rb, line 98
def core_inherit_content
  text = if in_context_of_self_set?
           core_inherit_for_content_for_self_set
         else
           "Inherit from left card"
         end
  %(<span class="inherit-perm">#{text}</span>)
end
core_inherit_for_content_for_self_set() click to toggle source
# File set/abstract/permission.rb, line 113
def core_inherit_for_content_for_self_set
  task = card.tag.codename
  ancestor = Card[@set_context.trunk_name.trunk_name]
  links = ancestor.who_can(task).map do |card_id|
    link_to_card card_id, nil, target: args[:target]
  end * ", "
  "Inherit ( #{links} )"
rescue StandardError
  "Inherit"
end
deny_because(why) click to toggle source
# File set/all/permissions.rb, line 93
def deny_because why
  @permission_errors << why if @permission_errors
  false
end
direct_rule_card(action) click to toggle source
# File set/all/permissions.rb, line 47
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) click to toggle source
# File set/all/permissions.rb, line 182
def each_field_as_bot &block
  # 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.compact.each(&block)
  end
end
each_member(&block) click to toggle source
# File set/right/read.rb, line 47
def each_member &block
  Auth.as_bot do
    all_members.each_with_object(::Set.new, &block)
  end
end
group_options() click to toggle source
# File set/abstract/permission.rb, line 64
def group_options
  Auth.as_bot do
    Card.search({ type_id: RoleID, sort: "name" }, "roles by name")
  end
end
groups(item_names) click to toggle source
# File set/abstract/permission.rb, line 47
  def groups item_names
    group_options.map do |option|
      checked = !item_names.delete(option.name).nil?
      icon = icon_tag "open_in_new", "link-muted"
      option_link = link_to_card option.name, icon, target: "decko_role"
      box = check_box_tag "#{option.key}-perm-checkbox",
                          option.name, checked, class: "perm-checkbox-button"
      <<-HTML
        <div class="form-check checkbox">
          <label class="form-check-label">
            #{box} #{option.name} #{option_link}
          </label>
        </div>
      HTML
    end * "\n"
  end
in_context_of_self_set?() click to toggle source
# File set/abstract/permission.rb, line 107
def in_context_of_self_set?
  return false unless @set_context

  @set_context.to_name.tag_name.key == Card[:self].key
end
inheritable?() click to toggle source
# File set/abstract/permission.rb, line 70
def inheritable?
  @inheritable ||=
    begin
      set_name = card.name.trunk_name
      set_card = Card.fetch(set_name)
      not_set = set_card && set_card.type_id != SetID
      not_set ? false : set_card.inheritable?
    end
end
inheritance_checkbox() click to toggle source
# File set/abstract/permission.rb, line 84
  def inheritance_checkbox
    return unless inheritable?

    <<-HTML
      <div class="perm-inheritance perm-section">
        #{check_box_tag 'inherit', 'inherit', inheriting?}
        <label>
          #{core_inherit_content}
          #{wrap_with(:a, title: "use left's #{card.name.tag} rule") { '?' }}
        </label>
      </div>
    HTML
  end
inheriting?() click to toggle source
# File set/abstract/permission.rb, line 80
def inheriting?
  @inheriting ||= inheritable? && card.content == "_left"
end
invalid_pattern_id(pattern_id) click to toggle source
# File set/right/read.rb, line 71
def invalid_pattern_id pattern_id
  Rails.logger.info "invalid pattern id for read rule: #{pattern_id}"
end
left_permission_rule_id(action) click to toggle source
# File set/all/permissions.rb, line 65
def left_permission_rule_id action
  lcard = left_or_new(skip_virtual: true, skip_modules: true)
  action = :update if action == :create && lcard.real? && lcard.action != :create
  lcard.permission_rule_id action
end
member_has_overriding_rule?(member) click to toggle source
# File set/right/read.rb, line 31
def member_has_overriding_rule? member
  pattern_index(Card.fetch_id(member.read_rule_class)) < rule_pattern_index
end
ok!(action) click to toggle source
# File set/all/permissions.rb, line 35
def ok! action
  raise Card::Error::PermissionDenied, self unless ok? action
end
ok?(action) click to toggle source

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.

# File set/all/permissions.rb, line 25
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_create() click to toggle source
# File set/all/permissions.rb, line 118
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) click to toggle source
# File set/all/permissions.rb, line 125
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_delete() click to toggle source
# File set/all/permissions.rb, line 153
def ok_to_delete
  permit :delete
end
ok_to_read() click to toggle source
# File set/all/permissions.rb, line 137
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_update() click to toggle source
# File set/all/permissions.rb, line 146
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
options_rule_card() click to toggle source
# File set/abstract/permission.rb, line 5
def options_rule_card
  Card[:cards_with_account]
end
pattern_ids() click to toggle source
# File set/right/read.rb, line 67
def pattern_ids
  @pattern_ids ||= set_patterns.map(&:pattern_id)
end
pattern_index(pattern_id) click to toggle source
# File set/right/read.rb, line 63
def pattern_index pattern_id
  pattern_ids.index(pattern_id) || invalid_pattern_id(pattern_id)
end
permission_rule_card(action) click to toggle source
# File set/all/permissions.rb, line 71
def permission_rule_card action
  Card.fetch permission_rule_id(action)
end
permission_rule_id(action) click to toggle source
# File set/all/permissions.rb, line 53
def permission_rule_id action
  if compound? && rule(action).match?(/^\[?\[?_left\]?\]?$/)
    left_permission_rule_id action
  else
    rule_card_id(action)
  end
end
permission_rule_id_and_class(action) click to toggle source
# File set/all/permissions.rb, line 61
def permission_rule_id_and_class action
  [permission_rule_id(action), direct_rule_card(action).rule_class_name]
end
permit(action, verb=nil) click to toggle source
# File set/all/permissions.rb, line 105
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) click to toggle source
# File set/all/permissions.rb, line 98
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!() click to toggle source
# File set/all/permissions.rb, line 11
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) click to toggle source
# File set/all/permissions.rb, line 75
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,
             t(:permission_error_no_action_rule, action: action, name: name)
  raise Card::Error::PermissionDenied, self
end
rule_class_name() click to toggle source
# File set/all/permissions.rb, line 85
def rule_class_name
  trunk.type_id == SetID ? name.trunk_name.tag : nil
end
rule_pattern_index() click to toggle source
# File set/right/read.rb, line 57
def rule_pattern_index
  return if trash

  @rule_pattern_index ||= pattern_index rule_set&.tag&.id
end
standardize_items() click to toggle source
Calls superclass method
# File set/abstract/permission.rb, line 1
def standardize_items
  super unless content == "_left"
end
track_permission_errors() { || ... } click to toggle source
# File set/all/permissions.rb, line 225
def track_permission_errors
  @permission_errors = []
  result = yield
  @permission_errors.each { |msg| errors.add :permission_denied, msg }
  @permission_errors = nil
  result
end
update_cards_with_read_rule_id(processed) click to toggle source

cards with this card as a read_rule_id These may include cards that are no longer set members if the card was renamed (edge case)

# File set/right/read.rb, line 38
def update_cards_with_read_rule_id processed
  processed ||= ::Set.new
  Card::Auth.as_bot do
    Card.search(read_rule_id: id) do |card|
      card.update_read_rule unless processed.include?(card.key)
    end
  end
end
update_field_read_rules() click to toggle source
# File set/all/permissions.rb, line 174
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
update_read_ruled_cards() click to toggle source
# File set/right/read.rb, line 11
def update_read_ruled_cards
  Card::Rule.clear_read_rule_cache
  Card.cache.reset # maybe be more surgical, just Auth.user related
  expire # probably shouldn't be necessary,
  # but was sometimes getting cached version when card should be in the
  # trash.  could be related to other bugs?

  processed = update_read_rules_of_set_members
  update_cards_with_read_rule_id processed unless new?
end
update_read_rules_of_set_members() click to toggle source
# File set/right/read.rb, line 22
def update_read_rules_of_set_members
  return unless rule_pattern_index

  each_member do |member, processed|
    processed << member.key
    member.update_read_rule unless member_has_overriding_rule?(member)
  end
end
who_can(action) click to toggle source
# File set/all/permissions.rb, line 39
def who_can action
  permission_rule_card(action).item_cards.map(&:id)
end
without_timestamps() { || ... } click to toggle source
# File set/all/permissions.rb, line 191
def without_timestamps
  Card.record_timestamps = false
  yield
ensure
  Card.record_timestamps = true
end
you_cant(what) click to toggle source
# File set/all/permissions.rb, line 89
def you_cant what
  "You don't have permission to #{what}"
end