Class: Mxrb::Runtime::AccessControl
- Inherits:
-
Object
- Object
- Mxrb::Runtime::AccessControl
- Defined in:
- lib/mxrb/runtime/access_control.rb
Overview
Enforces Mendix project, document, entity, and member access rules. Unsupported XPath constructs are never treated as a successful match.
Constant Summary collapse
- RIGHTS =
rubocop:disable Metrics/ClassLength
{ 'none' => :none, 'readonly' => :read, 'readwrite' => :write }.freeze
Instance Attribute Summary collapse
-
#project ⇒ Object
readonly
Returns the value of attribute project.
-
#security_level ⇒ Object
readonly
Returns the value of attribute security_level.
Instance Method Summary collapse
- #admin?(context) ⇒ Boolean
- #authorize!(resource, action:, context:, kind: nil, member: nil, record: nil) ⇒ Object
- #authorized?(resource, action:, context:, kind: nil, member: nil, record: nil) ⇒ Boolean
- #context(user: nil, roles: [], user_roles: nil, module_roles: [], attributes: {}, variables: {}) ⇒ Object
- #entity_allowed?(entity, action:, context:, member: nil, record: nil) ⇒ Boolean
-
#evaluate_xpath(expression, record:, context:) ⇒ Object
Evaluates the deliberately small, safe XPath subset understood by the runtime.
- #filter_readable(entity, records, context:) ⇒ Object
-
#initialize(project) ⇒ AccessControl
constructor
A new instance of AccessControl.
- #member_allowed?(entity, member, action:, context:, record: nil) ⇒ Boolean
- #microflow_allowed?(microflow, context:) ⇒ Boolean
- #page_allowed?(page, context:) ⇒ Boolean
- #security_enabled? ⇒ Boolean
-
#xpath_constraints(entity, context:) ⇒ Object
Returns the constraints contributed by roles in the context.
Constructor Details
#initialize(project) ⇒ AccessControl
Returns a new instance of AccessControl.
46 47 48 49 50 51 |
# File 'lib/mxrb/runtime/access_control.rb', line 46 def initialize(project) @project = project @security = project_security @security_level = value(@security, 'SecurityLevel').to_s @role_map, @admin_roles = build_role_map end |
Instance Attribute Details
#project ⇒ Object (readonly)
Returns the value of attribute project.
44 45 46 |
# File 'lib/mxrb/runtime/access_control.rb', line 44 def project @project end |
#security_level ⇒ Object (readonly)
Returns the value of attribute security_level.
44 45 46 |
# File 'lib/mxrb/runtime/access_control.rb', line 44 def security_level @security_level end |
Instance Method Details
#admin?(context) ⇒ Boolean
70 71 72 |
# File 'lib/mxrb/runtime/access_control.rb', line 70 def admin?(context) !(normalized_context(context).user_roles & @admin_roles).empty? end |
#authorize!(resource, action:, context:, kind: nil, member: nil, record: nil) ⇒ Object
112 113 114 115 116 117 |
# File 'lib/mxrb/runtime/access_control.rb', line 112 def (resource, action:, context:, kind: nil, member: nil, record: nil) return true if (resource, action:, context:, kind:, member:, record:) name = resource.respond_to?(:name) ? resource.name : resource raise AuthorizationError, "not authorized to #{action} #{name}" end |
#authorized?(resource, action:, context:, kind: nil, member: nil, record: nil) ⇒ Boolean
100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/mxrb/runtime/access_control.rb', line 100 def (resource, action:, context:, kind: nil, member: nil, record: nil) inferred_kind = kind || resource_kind(resource) case inferred_kind&.to_sym when :microflow then microflow_allowed?(resource, context:) when :page then page_allowed?(resource, context:) when :entity entity_allowed?(resource, action:, context:, member:, record:) else false end end |
#context(user: nil, roles: [], user_roles: nil, module_roles: [], attributes: {}, variables: {}) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/mxrb/runtime/access_control.rb', line 57 def context(user: nil, roles: [], user_roles: nil, module_roles: [], attributes: {}, variables: {}) supplied = SecurityContext.new( user:, roles:, user_roles:, module_roles:, attributes:, variables: ) = supplied.user_roles.flat_map { @role_map.fetch(_1, []) } SecurityContext.new( user: supplied.user, user_roles: supplied.user_roles, module_roles: supplied.module_roles + , attributes: supplied.attributes, variables: supplied.variables ) end |
#entity_allowed?(entity, action:, context:, member: nil, record: nil) ⇒ Boolean
82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/mxrb/runtime/access_control.rb', line 82 def entity_allowed?(entity, action:, context:, member: nil, record: nil) entity = resolve(:entity, entity) return false unless entity ctx = normalized_context(context) return true unless security_enabled? return true if admin?(ctx) rules = applicable_rules(entity, ctx, record:) return false if rules.empty? entity_action_allowed?(rules, action, member) end |
#evaluate_xpath(expression, record:, context:) ⇒ Object
Evaluates the deliberately small, safe XPath subset understood by the runtime. nil means that the expression is unsupported.
137 138 139 140 141 142 143 |
# File 'lib/mxrb/runtime/access_control.rb', line 137 def evaluate_xpath(expression, record:, context:) source = expression.to_s.strip return true if source.empty? source = source[1...-1].strip if source.start_with?('[') && source.end_with?(']') evaluate_boolean(source, record, normalized_context(context)) end |
#filter_readable(entity, records, context:) ⇒ Object
129 130 131 132 133 |
# File 'lib/mxrb/runtime/access_control.rb', line 129 def filter_readable(entity, records, context:) Array(records).select do |record| entity_allowed?(entity, action: :read, context:, record:) end end |
#member_allowed?(entity, member, action:, context:, record: nil) ⇒ Boolean
96 97 98 |
# File 'lib/mxrb/runtime/access_control.rb', line 96 def member_allowed?(entity, member, action:, context:, record: nil) entity_allowed?(entity, action:, context:, member:, record:) end |
#microflow_allowed?(microflow, context:) ⇒ Boolean
74 75 76 |
# File 'lib/mxrb/runtime/access_control.rb', line 74 def microflow_allowed?(microflow, context:) document_allowed?(:microflow, microflow, context:) end |
#page_allowed?(page, context:) ⇒ Boolean
78 79 80 |
# File 'lib/mxrb/runtime/access_control.rb', line 78 def page_allowed?(page, context:) document_allowed?(:page, page, context:) end |
#security_enabled? ⇒ Boolean
53 54 55 |
# File 'lib/mxrb/runtime/access_control.rb', line 53 def security_enabled? !@security.nil? && !%w[CheckNothing Off None].include?(@security_level) end |
#xpath_constraints(entity, context:) ⇒ Object
Returns the constraints contributed by roles in the context. An empty string is a valid unconstrained rule and therefore remains in the list.
121 122 123 124 125 126 127 |
# File 'lib/mxrb/runtime/access_control.rb', line 121 def xpath_constraints(entity, context:) entity = resolve(:entity, entity) return [] unless entity applicable_rules(entity, normalized_context(context), evaluate_xpath: false) .map { value(_1, :xpath, 'XPathConstraint').to_s }.uniq.freeze end |