Module: Parse::AtlasSearch::Session
- Defined in:
- lib/parse/atlas_search/session.rb
Overview
Resolves session tokens to user identities and inherited role sets for ACL-scoped Atlas Search queries.
Atlas Search runs aggregations directly against MongoDB and therefore bypasses Parse Server's per-request ACL enforcement. To compile a +_rperm+ +$match+ stage (see Parse::ACL.read_predicate) the caller needs to know two things about the requesting session:
- The +_User.objectId+ that owns the session.
- The transitive upward closure of role names that user inherits permissions from (cf. Role.all_for_user).
Both lookups can be expensive — token → user requires a +/users/me+ round-trip, and user → roles can require multiple +_Role+ queries to walk the inheritance graph. Both are cached separately so a single agent turn that runs several Atlas Search tools amortizes the cost.
Two distinct caches:
+session_cache+: maps +session_token+ to +user_id+. Long TTL (1 hour default), invalidation profile is logout. Apps that need sub-TTL revocation must call Session.invalidate explicitly from their logout path.
+role_cache+: maps +user_id+ to a +Set+ of role names. Short TTL (2 minutes default), invalidation profile is role-graph mutation. Stale role data here yields incorrect ACL decisions, so the default is conservatively short.
The default cache implementation is process-local (MemoryCache) and guarded by a +Mutex+. Apps that need shared cross-process caching (Redis, Memcached) may install a replacement via session_cache= / role_cache=; the replacement must respond to +get(key)+, +set(key, value, ttl:)+, and +invalidate(key)+.
Defined Under Namespace
Classes: InvalidSession, MemoryCache, Resolved
Class Method Summary collapse
-
.invalidate(session_token) ⇒ Object
Forget a +session_token+ entry from the session-token cache.
-
.invalidate_user_roles(user_id) ⇒ Object
Forget cached role membership for a +user_id+.
-
.reset_caches! ⇒ Object
Drop every cached entry across both caches.
-
.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+.
Class Method Details
.invalidate(session_token) ⇒ Object
Forget a +session_token+ entry from the session-token cache. Apps that revoke sessions out-of-band (logout, password reset, admin revoke) should call this from the same path so subsequent Atlas Search requests don't act on the stale +user_id+ mapping. The +role_names+ cache is keyed on +user_id+ and is not affected — call invalidate_user_roles to clear that separately.
161 162 163 164 |
# File 'lib/parse/atlas_search/session.rb', line 161 def invalidate(session_token) return if session_token.nil? Parse::AtlasSearch.session_cache.invalidate(session_token.to_s) end |
.invalidate_user_roles(user_id) ⇒ Object
Forget cached role membership for a +user_id+. Call after any +_Role.users+ mutation that affects this user (role grant / revoke, role-graph reshape).
170 171 172 173 |
# File 'lib/parse/atlas_search/session.rb', line 170 def invalidate_user_roles(user_id) return if user_id.nil? Parse::AtlasSearch.role_cache.invalidate(user_id.to_s) end |
.reset_caches! ⇒ Object
Drop every cached entry across both caches. Useful in tests and in startup hooks for processes that fork after warming the cache.
178 179 180 181 |
# File 'lib/parse/atlas_search/session.rb', line 178 def reset_caches! Parse::AtlasSearch.session_cache.clear if Parse::AtlasSearch.session_cache.respond_to?(:clear) Parse::AtlasSearch.role_cache.clear if Parse::AtlasSearch.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+.
+nil+ or empty +session_token+ → anonymous Resolved with +user_id: nil+ and an empty +role_names+ set. The caller decides whether to refuse the request (the +require_session_token+ toggle on Parse::AtlasSearch) or treat as public-only.
Cache layering: token-to-user_id is checked first; on hit the slower +/users/me+ round-trip is skipped. User-to-roles is then checked independently (a single user shared across sessions amortizes the role lookup).
145 146 147 148 149 150 151 |
# File 'lib/parse/atlas_search/session.rb', line 145 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) role_names = lookup_role_names(user_id) Resolved.new(user_id, role_names) end |