module PIM::Authorization

Constants

ALL
ALL_UI_RIGHTS
ANY
CONTEXT_DEFAULT_VALUE
DEFAULT_MATCH_MODE
DEFAULT_ROLES
MATCH_MODES

Supported values for the role-level match: keyword. Controls when a role contributes a verdict to the cross-role evaluation (see has_permission? on the data model):

  • :allow (default) - role fires only when its decisive matching permission is an allow. Any matching deny is ignored for the purpose of cross-role aggregation. Preserves legacy “any-allow-wins” semantics.

  • :deny - role fires only when its decisive matching permission is a deny. Any matching allow on such a role is ignored.

  • :any - role fires on either; allow contributes an allow, deny contributes a deny.

Within-role evaluation (last matching permission wins) is unchanged.

SYSTEM_ROLE_NAME_PREFIX

Reserved name prefix for Java-authored system roles. Names starting with this prefix are rejected by the DSL: system roles can only be defined in Java (see ‘com.lansa.lax.auth.SystemRoles`), never from a data model.

Public Instance Methods

all_roles() click to toggle source
# File pim.rb, line 7980
def all_roles
  roles = {}
  roles.merge!(@module_roles) if @module_roles
  add_parent_objects(roles) { |p| p.module_roles }
  roles
end
all_roles_as_json(opts = {}) click to toggle source
# File pim.rb, line 7972
def all_roles_as_json opts = {}
  json = {}
  all_roles.each_pair do |name, role|
    json[name] = role.as_json(opts)
  end
  json
end
default_permissions(&block) click to toggle source
# File pim.rb, line 8037
def default_permissions &block
  @default_permissions = block if block
  return @default_permissions || get_parent_object { |p| p.default_permissions }
end
has_permission?(roles, object_type, action, context = nil) click to toggle source

Evaluates a permission tuple across a collection of roles. The verdict is an accumulator over all roles (commutative - the order of roles does not change the result) and uses a cross-role “deny wins” tiebreak: if any role contributes a deny, the whole result is false, regardless of allows contributed by other roles. Otherwise the result is true when at least one role contributes an allow, else false.

A role’s contribution depends on its match_mode (see MATCH_MODES): the within-role decisive permission (last matching one, reverse order) only fires when its polarity matches the role’s configured mode. Roles without an opinion on the tuple (no matching permission) are silently skipped.

With every role defaulting to :allow, this reduces to the legacy “any-allow-wins” behavior: any_deny stays false and the verdict is purely the OR of allow contributions.

# File pim.rb, line 8011
def has_permission? roles, object_type, action, context = nil
  if not is_array?(roles)
    if roles.respond_to?(:roles)
      roles = roles.roles
    else
      roles = [roles.to_s]
    end
  end
  any_allow = false
  any_deny = false
  roles.each do |role_name|
    role = role(role_name)
    next unless role
    matching = role.matching_permission(object_type, action, context)
    next unless matching
    mode = role.match_mode || DEFAULT_MATCH_MODE
    if matching.is_allowed?
      any_allow = true if mode == :allow || mode == :any
    else
      any_deny = true if mode == :deny || mode == :any
    end
  end
  return false if any_deny
  any_allow
end
hide_roles(*roles) click to toggle source
# File pim.rb, line 8042
def hide_roles *roles
  roles.each do |role_name|

    unless stringified_value(role_name) == "admin"
      role_to_hide = role(role_name)

      unless role_to_hide.nil?
        role_to_hide.hide
      else
        raise "Role '#{stringified_value(role_name)}' does not exist"
      end
    else
      raise "The 'admin' role can't be hidden"
    end

  end
end
module_roles() click to toggle source
# File pim.rb, line 7987
def module_roles
  @module_roles ||= {}
end
role(name, match: DEFAULT_MATCH_MODE, default_permissions: true, &block) click to toggle source

Defines (with a block) or looks up (without a block) a role.

Keyword arguments (only when authoring with a block):

  • match: - one of :allow (default), :deny, :any. Controls when the role contributes a verdict to the cross-role evaluator (see +DataModel#has_permission?+ and the MATCH_MODES doc).

  • default_permissions: - when true (default) the role is prepended with the data module’s (or parent module’s) default_permissions block, preserving the historical “every role inherits the standard allow/deny scaffolding” behavior. Set to false to opt out, which is necessary for +match: :deny+ / +match: :any+ roles whose decisive permission would otherwise be shadowed by an unrelated default permission added in front of their own deny/allow definitions (LAX-9663).

# File pim.rb, line 7924
def role name, match: DEFAULT_MATCH_MODE, default_permissions: true, &block

  name = stringified_value(name)

  if block

    if name.start_with?(SYSTEM_ROLE_NAME_PREFIX)
      raise "Role '#{name}' uses the reserved system role prefix " \
            "'#{SYSTEM_ROLE_NAME_PREFIX}' and must be defined in Java."
    end

    unless MATCH_MODES.include?(match)
      raise "Invalid match mode #{match.inspect} for role '#{name}'. " \
            "Allowed values are #{MATCH_MODES.inspect}."
    end

    if module_roles.has_key?(name) and not data_module.has_option?(:ignore_defined_roles)
      raise "Role #{name} is already defined in data model #{self}"
    end

    # Use +self.default_permissions+ so the bare-name reference still
    # dispatches to the DSL accessor method even though the
    # +default_permissions:+ keyword shadows it as a local variable
    # for the duration of this method body.
    defaults_block = self.default_permissions
    builder = RoleBuilder.new(self, defaults_block)
    role = builder.build(name,
                         match_mode: match,
                         default_permissions: default_permissions,
                         &block)
    module_roles[name] = role
    role

  elsif name.is_a?(PIM::Authorization::Role)
    name
  else
    all_roles[name]
  end

end
roles(*roles) click to toggle source
# File pim.rb, line 7965
def roles *roles
  if not is_empty?(roles)
    legacy_roles(*roles)
  end
  all_roles
end
roles_as_json() click to toggle source
# File pim.rb, line 7991
def roles_as_json
  as_json(Hash[all_roles_as_json.sort])
end