Class: Parse::Authorization::Context
- Inherits:
-
Object
- Object
- Parse::Authorization::Context
- Defined in:
- lib/parse/authorization.rb
Overview
Per-client authorization state: the two caches, their TTLs, and the optional upstream-role reader.
One of these is owned by each Client. It deliberately does NOT
own the HTTP client: it holds a back-reference and asks the client to
make the /users/me call, so there is exactly one place that knows how
to talk to a Parse application and it is the client itself.
Constant Summary collapse
- DEFAULT_IDENTITY_TTL =
3600- DEFAULT_ROLE_TTL =
30- ROLE_GRAPH_MAX_DEPTH =
Depth cap for the role-graph walk. Bounds a cyclic or pathological hierarchy; see Role.all_for_user.
10
Instance Attribute Summary collapse
-
#client ⇒ Parse::Client
readonly
The client this context authorizes for.
-
#compare_upstream_roles ⇒ Boolean
When true, and a reader is set, every role resolution also reads the upstream closure and emits a
parse.cache.role_compareevent. -
#identity_cache ⇒ Object
The identity plane.
-
#identity_cache_ttl ⇒ Integer
Identity-entry TTL in seconds.
-
#role_cache ⇒ Object
The role plane.
-
#role_cache_ttl ⇒ Integer
Role-entry TTL in seconds.
-
#upstream_role_reader ⇒ #roles_for?
Read-only reader for Parse Server's own role cache.
Instance Method Summary collapse
-
#configure(identity_cache: nil, role_cache: nil, identity_cache_ttl: nil, role_cache_ttl: nil, upstream_role_reader: nil, compare_upstream_roles: nil) ⇒ self
Apply settings, leaving anything not passed unchanged.
-
#initialize(client:) ⇒ Context
constructor
A new instance of Context.
- #inspect ⇒ Object
-
#invalidate(session_token) ⇒ Object
Forget one session token.
-
#invalidate_user_roles(user_id) ⇒ Object
Forget one user's cached role closure.
-
#reset_caches! ⇒ Object
Drop every entry in both planes.
-
#resolve(session_token) ⇒ Resolved
Resolve a session token to the requesting user and the transitive set of role names whose
role:NAMEpermission strings should be checked against_rperm. -
#resolve_user(user_id) ⇒ Resolved
Resolve a user id that is already trusted, skipping
/users/me.
Constructor Details
#initialize(client:) ⇒ Context
Returns a new instance of Context.
171 172 173 174 175 176 177 178 179 |
# File 'lib/parse/authorization.rb', line 171 def initialize(client:) @client = client @identity_cache = MemoryCache.new @role_cache = MemoryCache.new @identity_cache_ttl = DEFAULT_IDENTITY_TTL @role_cache_ttl = DEFAULT_ROLE_TTL @upstream_role_reader = nil @compare_upstream_roles = false end |
Instance Attribute Details
#client ⇒ Parse::Client (readonly)
Returns the client this context authorizes for.
162 163 164 |
# File 'lib/parse/authorization.rb', line 162 def client @client end |
#compare_upstream_roles ⇒ Boolean
Returns when true, and a reader is set, every role
resolution also reads the upstream closure and emits a
parse.cache.role_compare event. The comparison NEVER changes what
#resolve returns. The upstream value would become an authorization
input the moment it were consumed, and it comes from a database this
SDK does not own, so it stays observable-only until the two closures
have been reconciled against real traffic.
159 160 161 |
# File 'lib/parse/authorization.rb', line 159 def compare_upstream_roles @compare_upstream_roles end |
#identity_cache ⇒ Object
Returns the identity plane. Maps session token to user id.
137 138 139 |
# File 'lib/parse/authorization.rb', line 137 def identity_cache @identity_cache end |
#identity_cache_ttl ⇒ Integer
Returns identity-entry TTL in seconds.
143 144 145 |
# File 'lib/parse/authorization.rb', line 143 def identity_cache_ttl @identity_cache_ttl end |
#role_cache ⇒ Object
Returns the role plane. Maps user id to a Set of role names.
140 141 142 |
# File 'lib/parse/authorization.rb', line 140 def role_cache @role_cache end |
#role_cache_ttl ⇒ Integer
Returns role-entry TTL in seconds.
146 147 148 |
# File 'lib/parse/authorization.rb', line 146 def role_cache_ttl @role_cache_ttl end |
#upstream_role_reader ⇒ #roles_for?
Returns read-only reader for Parse Server's own role cache. Never consumed for authorization; see #compare_upstream_roles.
150 151 152 |
# File 'lib/parse/authorization.rb', line 150 def upstream_role_reader @upstream_role_reader end |
Instance Method Details
#configure(identity_cache: nil, role_cache: nil, identity_cache_ttl: nil, role_cache_ttl: nil, upstream_role_reader: nil, compare_upstream_roles: nil) ⇒ self
Apply settings, leaving anything not passed unchanged.
183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/parse/authorization.rb', line 183 def configure(identity_cache: nil, role_cache: nil, identity_cache_ttl: nil, role_cache_ttl: nil, upstream_role_reader: nil, compare_upstream_roles: nil) @identity_cache = identity_cache unless identity_cache.nil? @role_cache = role_cache unless role_cache.nil? @identity_cache_ttl = identity_cache_ttl unless identity_cache_ttl.nil? @role_cache_ttl = role_cache_ttl unless role_cache_ttl.nil? @upstream_role_reader = upstream_role_reader unless upstream_role_reader.nil? @compare_upstream_roles = compare_upstream_roles unless compare_upstream_roles.nil? self end |
#inspect ⇒ Object
253 254 255 |
# File 'lib/parse/authorization.rb', line 253 def inspect "#<Parse::Authorization::Context client=#{@client.respond_to?(:application_id) ? @client.application_id : @client.class}>" end |
#invalidate(session_token) ⇒ Object
Forget one session token. Call from a logout path that revokes
out-of-band; Parse::Cache::Invalidation does this automatically from
the _Session after_logout trigger when webhooks are installed.
The role plane is keyed by user id and is unaffected; use #invalidate_user_roles for that.
234 235 236 237 |
# File 'lib/parse/authorization.rb', line 234 def invalidate(session_token) return if session_token.nil? @identity_cache.invalidate(session_token.to_s) end |
#invalidate_user_roles(user_id) ⇒ Object
Forget one user's cached role closure. Call after any _Role.users
mutation affecting them.
242 243 244 245 |
# File 'lib/parse/authorization.rb', line 242 def invalidate_user_roles(user_id) return if user_id.nil? @role_cache.invalidate(user_id.to_s) end |
#reset_caches! ⇒ Object
Drop every entry in both planes.
248 249 250 251 |
# File 'lib/parse/authorization.rb', line 248 def reset_caches! @identity_cache.clear if @identity_cache.respond_to?(:clear) @role_cache.clear if @role_cache.respond_to?(:clear) end |
#resolve(session_token) ⇒ Resolved
Resolve a session token to the requesting user and the transitive set
of role names whose role:NAME permission strings should be checked
against _rperm.
A nil or empty token yields an anonymous Resolved. The caller
decides whether that is acceptable; Parse::ACLScope.require_session_token
and Parse::AtlasSearch.require_session_token are where that policy
lives.
The two lookups are cached independently, so several sessions belonging to one user share a single role-graph walk.
210 211 212 213 214 215 |
# File 'lib/parse/authorization.rb', line 210 def resolve(session_token) return Resolved.new(nil, Set.new) if session_token.nil? || session_token.to_s.empty? user_id = lookup_user_id(session_token.to_s) Resolved.new(user_id, lookup_role_names(user_id)) end |
#resolve_user(user_id) ⇒ Resolved
Resolve a user id that is already trusted, skipping /users/me.
Used by the acl_user: path, which has a User pointer rather than a
token.
222 223 224 225 |
# File 'lib/parse/authorization.rb', line 222 def resolve_user(user_id) return Resolved.new(nil, Set.new) if user_id.nil? || user_id.to_s.empty? Resolved.new(user_id.to_s, lookup_role_names(user_id.to_s)) end |