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:
@@ -398,6 +398,13 @@ mod tests {
|
||||
) -> Result<Option<picloud_shared::AppUser>, picloud_shared::UsersError> {
|
||||
unimplemented!()
|
||||
}
|
||||
async fn email_available(
|
||||
&self,
|
||||
_: &picloud_shared::SdkCallCx,
|
||||
_: &str,
|
||||
) -> Result<bool, picloud_shared::UsersError> {
|
||||
unimplemented!()
|
||||
}
|
||||
async fn update(
|
||||
&self,
|
||||
_: &picloud_shared::SdkCallCx,
|
||||
|
||||
@@ -516,6 +516,23 @@ impl UsersService for UsersServiceImpl {
|
||||
Ok(Some(Self::to_app_user(row, roles)))
|
||||
}
|
||||
|
||||
async fn email_available(&self, cx: &SdkCallCx, email: &str) -> Result<bool, UsersError> {
|
||||
// Gated like `create` (the registration write path) so the probe
|
||||
// is available exactly where self-serve registration is — and,
|
||||
// crucially, WITHOUT find_by_email's anonymous-principal rejection.
|
||||
// It returns only a boolean, so it leaks no more than `create`'s
|
||||
// own uniqueness error already does (F-S-003: enumeration risk is
|
||||
// bounded to "exists / doesn't").
|
||||
self.require(cx.principal.as_ref(), Capability::AppUsersWrite(cx.app_id))
|
||||
.await?;
|
||||
let normalized = validate_email(email)?;
|
||||
Ok(self
|
||||
.users
|
||||
.find_by_email(cx.app_id, &normalized)
|
||||
.await?
|
||||
.is_none())
|
||||
}
|
||||
|
||||
async fn update(
|
||||
&self,
|
||||
cx: &SdkCallCx,
|
||||
|
||||
Reference in New Issue
Block a user