feat(sdk): users::email_available for anonymous registration pre-check (S1)
`users::find_by_email` requires an authenticated principal (F-S-003, anti-enumeration), so the natural check-then-create register pattern 502s for anonymous public scripts. Add `users::email_available(email) -> bool`, gated like `create` (the registration write path) but without the anonymous rejection: it leaks only a single boolean — no more than `create`'s own uniqueness error already does — so self-serve register scripts can pre-check. Also document find_by_email's principal requirement in the SDK doc-comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,12 @@
|
||||
//! // CRUD
|
||||
//! let u = users::create(#{ email: "a@b", password: "hunter22a", display_name: "Alice" });
|
||||
//! let u = users::get(id); // map or ()
|
||||
//! let u = users::find_by_email("a@b"); // map or ()
|
||||
//! let u = users::find_by_email("a@b"); // map or () — REQUIRES an
|
||||
//! // authenticated principal
|
||||
//! // (anti-enumeration); forbidden
|
||||
//! // for anonymous public scripts.
|
||||
//! let free = users::email_available("a@b"); // bool — anonymous-safe pre-check
|
||||
//! // for self-serve registration.
|
||||
//! users::update(id, #{ display_name: "Alicia" });
|
||||
//! let removed = users::delete(id); // bool
|
||||
//! let page = users::list(#{ "$limit": 50, cursor: () });
|
||||
@@ -56,6 +61,7 @@ pub(super) fn register(engine: &mut RhaiEngine, services: &Services, cx: Arc<Sdk
|
||||
bind_create(&mut module, &svc, &cx);
|
||||
bind_get(&mut module, &svc, &cx);
|
||||
bind_find_by_email(&mut module, &svc, &cx);
|
||||
bind_email_available(&mut module, &svc, &cx);
|
||||
bind_update(&mut module, &svc, &cx);
|
||||
bind_delete(&mut module, &svc, &cx);
|
||||
bind_list(&mut module, &svc, &cx);
|
||||
@@ -136,6 +142,27 @@ fn bind_find_by_email(module: &mut Module, svc: &Arc<dyn UsersService>, cx: &Arc
|
||||
);
|
||||
}
|
||||
|
||||
/// `users::email_available(email)` → `bool`. Anonymous-safe pre-check for
|
||||
/// self-serve registration (unlike `find_by_email`, which forbids
|
||||
/// anonymous callers). Lets a public register script branch on a free vs
|
||||
/// taken email without relying on `create`'s uniqueness error/502.
|
||||
fn bind_email_available(module: &mut Module, svc: &Arc<dyn UsersService>, cx: &Arc<SdkCallCx>) {
|
||||
let svc = svc.clone();
|
||||
let cx = cx.clone();
|
||||
module.set_native_fn(
|
||||
"email_available",
|
||||
move |email: &str| -> Result<bool, Box<EvalAltResult>> {
|
||||
let email = email.to_string();
|
||||
let svc = svc.clone();
|
||||
let cx = cx.clone();
|
||||
block_on(
|
||||
"users",
|
||||
async move { svc.email_available(&cx, &email).await },
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn bind_update(module: &mut Module, svc: &Arc<dyn UsersService>, cx: &Arc<SdkCallCx>) {
|
||||
let svc = svc.clone();
|
||||
let cx = cx.clone();
|
||||
|
||||
Reference in New Issue
Block a user