Module: LcpRuby::Authorization::PageGate
- Defined in:
- lib/lcp_ruby/authorization/page_gate.rb
Overview
Pure-function gate that decides whether a request to a routable page should be allowed, denied, or treated as misconfigured. Controller-state-free; called by ‘LcpRuby::PageAuthorization`.
Returns one of ‘:allow / :deny / :misconfigured_no_gate / :misconfigured_malformed`. The concern maps the two misconfigured-* symbols to `record_error` codes AUTH-002-runtime (no gate) vs AUTH-003 (malformed). `LcpRuby::ConditionError` propagates uncaught — concern’s rescue handles the dev/prod split + AUTH-010.
See docs/design/authorization_hardening.md § “authorize_page! decision table”.
Constant Summary collapse
- PUBLIC_OPT_IN_ROLES =
Public-opt-in sentinel. Matches scalar (‘{ role: “any” }`) and single-element-array (`{ role: [“any”] }`) forms. Mixed arrays like `[“any”, “admin”]` fall through to literal role matching. NOTE: only PageGate honors `:any`; zone_resolution.rb:137-140 and parameter_definition.rb:90-95 treat `“any”` as a literal role name. Aligning those three sites is a follow-up.
[ "any" ].freeze
Class Method Summary collapse
Class Method Details
.evaluate(page, user:, record:) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/lcp_ruby/authorization/page_gate.rb', line 27 def evaluate(page, user:, record:) vw = page.visible_when if vw.nil? return :allow if page.any_zone_gated? return :allow unless page.standalone? return :misconfigured_no_gate end return :misconfigured_malformed unless Conditions::Validator.parseable?(vw) # Role-shortcut — PageGate handles `{ role: ... }` directly # because ConditionEvaluator.evaluate_any only recognizes # condition-object shapes (field/service/compound/collection). # `vw` is already stringify_deep'd; size==1 ensures extra keys # fall through to the evaluator instead of being ignored. if vw.size == 1 && vw.key?("role") required = Array(vw["role"]).map(&:to_s) return :allow if required == PUBLIC_OPT_IN_ROLES return :deny unless user return (LcpRuby.user_roles(user) & required).any? ? :allow : :deny end decision = ConditionEvaluator.evaluate_any( record, vw, context: { current_user: user } ) decision ? :allow : :deny end |