Masked email: upstream's x:MaskedEmail API (ME-2, ME-3, ME-6a, ME-7a, ME-12 to ME-19)

x:MaskedEmail is no longer refused as unbuilt. Creates generate the address
on an allowed domain and check the prefix, maxMaskedAddresses and the create
rate; updates keep server-set fields; enabled reads and writes map to the
shared state; query filters on enabled, forDomain and text; a tenant
administrator reaches its tenant's accounts' masks.
This commit is contained in:
2026-09-18 16:20:39 -07:00
parent aaca8fe537
commit 3b052a57da
8 changed files with 444 additions and 6 deletions
+27 -3
View File
@@ -367,7 +367,8 @@ impl RequestHandler for Server {
}
GetRequestMethod::Registry(mut req) => {
resolve_account_id(&mut req.account_id, method_name.obj, access_token)?;
access_token.assert_is_member(req.account_id)?;
assert_registry_account(self, method_name.obj, access_token, req.account_id)
.await?;
Box::pin(self.registry_get(
method_name.obj.unwrap_registry(),
@@ -458,7 +459,8 @@ impl RequestHandler for Server {
}
QueryRequestMethod::Registry(mut req) => {
resolve_account_id(&mut req.account_id, method_name.obj, access_token)?;
access_token.assert_is_member(req.account_id)?;
assert_registry_account(self, method_name.obj, access_token, req.account_id)
.await?;
Box::pin(self.registry_query(
method_name.obj.unwrap_registry(),
@@ -574,7 +576,8 @@ impl RequestHandler for Server {
}
SetRequestMethod::Registry(mut req) => {
resolve_account_id(&mut req.account_id, method_name.obj, access_token)?;
access_token.assert_is_member(req.account_id)?;
assert_registry_account(self, method_name.obj, access_token, req.account_id)
.await?;
Box::pin(self.registry_set(
method_name.obj.unwrap_registry(),
@@ -716,6 +719,27 @@ impl RequestHandler for Server {
}
}
// inbuxa: ME-19: a tenant administrator reaches the masks of its tenant's
// accounts without impersonate, and a tenant principal never reaches beyond
// its tenant
async fn assert_registry_account(
server: &Server,
obj: MethodObject,
access_token: &AccessToken,
account_id: Id,
) -> trc::Result<()> {
if obj == MethodObject::Registry(registry::schema::prelude::ObjectType::MaskedEmail) {
crate::inbuxa::masked_email::assert_can_manage(
server,
access_token,
account_id.document_id(),
)
.await
} else {
access_token.assert_is_member(account_id).map(|_| ())
}
}
pub(crate) fn resolve_account_id(
account_id: &mut Id,
obj: MethodObject,