Add info() to fetch the authenticated record user#190
Conversation
Adds Surreal.info() and Surreal.info(Class<T>) returning the record of the currently-authenticated record user (the record pointed to by the $auth parameter), for parity with the JS SDK's auth() (info() in the v1 JS SDK) and the info RPC method. Implemented as a native JNI method mirroring selectRecordId: it runs SELECT * FROM $auth (deliberately without ONLY, so an unauthenticated session yields an empty array mapped to Optional.empty() instead of the "Expected a single result output when using the ONLY keyword" error) and returns the single record when present. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
emmanuel-keller
left a comment
There was a problem hiding this comment.
Review — approve with nits.
Clean and faithful to the existing select(RecordId) pattern on both sides. I checked the failure modes: get_surreal_ref! (not the cloning variant) is used so $auth resolves on the real session; unauthenticated / system-user (root/ns/db) sessions yield [] → Optional.empty() on both sides; there's no unwrap/expect and all error paths route through the exception sink; the returned Value is owned/cleaned up exactly like select.
Two points:
- Version:
build.gradleis still2.1.2, which is already released (commit bc3812c). This net-new public API needs a minor bump (e.g.2.2.0-SNAPSHOT) — but that's really a batch decision across the currently-open PRs, not just this one. - Test gap: no explicit system-user (root/ns/db) case asserting empty — low risk since
info_unauthenticated_returnsEmptyhits the same$auth=NONE path, but worth adding (use a ns/db user, since the memory engine may reject root sign-in).
| * | ||
| * @return an Optional containing the authenticated record user's Value, or an | ||
| * empty Optional when the session is not authenticated as a record user | ||
| * (e.g. unauthenticated, invalidated, or a system user) or the record |
There was a problem hiding this comment.
The Javadoc says empty is also returned when "the record is not visible to it" (permissions). That's plausible but untested and server-version-dependent — the only permissions case covered is the permissive WHERE id = $auth.id. Consider softening the wording or adding a test.
There was a problem hiding this comment.
Added a test rather than softening the wording: info_recordNotVisibleToUser_returnsEmpty (8e375e8) signs up a record user against a table defined with PERMISSIONS FOR select NONE, asserts the session is still authenticated (RETURN $auth yields a user record id), and then asserts both info() and info(Class) return an empty Optional. So the behavior matches the Javadoc on the embedded engine (SurrealDB 3.1.5): SELECT * FROM $auth returns an empty result set when permissions hide the record, which info() maps to Optional.empty(). Kept the Javadoc as-is now that the claim is pinned by a test.
Review follow-up: the info() Javadoc claims an empty Optional is also returned when table permissions hide the record from the authenticated user, but only the permissive `WHERE id = $auth.id` case was covered. Adds a test signing up a record user against a table defined with `PERMISSIONS FOR select NONE` and asserts that, while the session is still authenticated ($auth is set), info() and info(Class) both return empty — confirming the documented behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The gap
The Java SDK had no way to fetch the currently-authenticated record user. The JS SDK (golden reference) exposes this as
auth()(calledinfo()in the v1 JS SDK), implemented asSELECT * FROM ONLY $auth; SurrealDB also exposes it as theinfoRPC method. Java users had to hand-write the$authquery.Reproduction
On the embedded
memoryengine (server v3.x semantics), with a record access and ausertable readable by its own record user:After
signup(new RecordCredential(...)):query("SELECT * FROM ONLY $auth").take(0)returns the record object ({ email, id, pass }) — the underlying capability works.invalidate(), theONLYform throwsInternalException: Expected a single result output when using the ONLY keyword(because$authis NONE), while the plainSELECT * FROM $authreturns an empty array in both states and[record]when authenticated.The fix
Surreal.info()returningOptional<Value>andSurreal.info(Class<T>)returningOptional<T>, following theselect(RecordId)/select(Class, RecordId)conventions.Java_com_surrealdb_Surreal_infoinsrc/main/rust/surreal.rs) mirroringselectRecordId: it runsSELECT * FROM $authvia the sharedsurrealdb_queryhelper and returns 0 for an empty result (mapped toOptional.empty()). This matches how the codebase structures such accessors (run(),selectRecordIdare native query-formatting methods) rather than composing Java-sidequery()calls.ONLYform is used deliberately so an unauthenticated or invalidated session cleanly yieldsOptional.empty()instead of theONLY-keyword error, while returning the same record as the JS SDK'sSELECT * FROM ONLY $authwhen authenticated.Tests
New
InfoTests(memory engine, patterned afterCredentialTests), plus a smallUsertest POJO:info_afterSignup_returnsAuthenticatedRecord— signup theninfo()returns the record with the expectedemail, and itsidequalsRETURN $auth.info_typed_hydratesPojo—info(User.class)hydrates a POJO (RecordId id,String email).info_unauthenticated_returnsEmpty— both overloads returnOptional.empty().info_afterInvalidate_returnsEmpty— present after signup, empty afterinvalidate().Full suite: 337 tests, 0 failures.
🤖 Generated with Claude Code