Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion crates/lance-graph-dir-sim/src/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,10 @@ pub struct Snapshot {
pub(crate) groups: Population,
/// `proxyAddresses` of the users, as rows.
pub(crate) proxies: ProxyRelation,
/// `proxyAddresses` of the groups, as rows (owner = group ordinal).
/// Read only by the provisioning plane: delivery reads a group's primary
/// SMTP address alone.
pub(crate) group_proxies: ProxyRelation,
pub(crate) m_user: Vec<u32>,
pub(crate) m_group: Vec<u32>,
pub(crate) m_all: Vec<u64>,
Expand Down Expand Up @@ -637,7 +641,12 @@ impl Snapshot {
if proxies.len() >= u32::MAX as usize {
return Err(BuildError::TooManyProxies);
}
let groups = Population::build(&groups, d);
let group_nodes = groups;
let groups = Population::build(&group_nodes, d);
let group_proxies = ProxyRelation::build(&group_nodes, &groups, d);
if group_proxies.len() >= u32::MAX as usize {
return Err(BuildError::TooManyProxies);
}
let mut rows: Vec<(u16, u16)> = Vec::with_capacity(obs.members.len());
let mut unresolved = Vec::new();
for (u, g) in &obs.members {
Expand All @@ -660,6 +669,7 @@ impl Snapshot {
users,
groups,
proxies,
group_proxies,
m_user,
m_group,
m_all,
Expand Down
20 changes: 17 additions & 3 deletions crates/lance-graph-dir-sim/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,7 @@ pub struct ProvisioningConflict {
/// mailbox-less account's leftover SMTP and proxies, and a group all claim
/// their values. The claims read here are each present user's UPN, primary
/// and secondary SMTP and routing address, and each live group's primary
/// SMTP, in one address space as [`address_rules`] reads it. `mail` claims
/// nothing.
/// and secondary SMTP, in one address space. `mail` claims nothing.
///
/// This is a separate plane from the Exchange one. It does not feed
/// [`address_owner`], [`address_recipient`] or [`validate`], so a conflict
Expand All @@ -680,7 +679,22 @@ pub struct ProvisioningConflict {
/// real tenant and are not in this plane.
pub fn provisioning_conflicts(v: &View<'_>) -> Vec<ProvisioningConflict> {
let present = v.existing(NodeKind::User);
let rows = rows_over(v, &present, &present, &mut Vec::new());
let mut rows = rows_over(v, &present, &present, &mut Vec::new());
// A group's secondary SMTP proxies claim too. A group created in a
// version carries none (a `Change` sets no proxy).
let gp = &v.snap.group_proxies;
for i in 0..v.snap.groups.len() {
let Some(g) = v.guid_in(NodeKind::Group, i) else {
continue;
};
for r in gp.owner_rows(i as u32) {
if gp.meta[r] == meta::SMTP_SECONDARY {
rows.push((gp.key[r], g, AddressRole::SecondarySmtp));
}
}
}
rows.sort_unstable();
rows.dedup();
rows.chunk_by(|a, b| a.0 == b.0)
.filter(|run| run.iter().any(|r| r.1 != run[0].1))
.map(|run| ProvisioningConflict {
Expand Down
32 changes: 32 additions & 0 deletions crates/lance-graph-dir-sim/tests/provisioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,35 @@ fn distinct_claims_and_one_object_under_two_roles_are_not_conflicts() {
let view = st.view(v).unwrap();
assert_eq!(provisioning_conflicts(&view), vec![]);
}

// A group's secondary SMTP proxy claims like any other address: another
// object carrying it is a provisioning conflict. Delivery still reads a
// group by its primary address only, so the user keeps the address there.
#[test]
fn a_groups_secondary_proxy_claims_its_address() {
let mut grp = group("team@x.test");
grp.proxies = vec!["smtp:sales@x.test".into()];
let (mut st, v) = store(vec![
(g(0xB0), grp),
(
g(0xA1),
ObservedNode::user("alice.upn@x.test", "sales@x.test"),
),
]);
let key = {
let id = st.intern("sales@x.test");
st.key_of(id).unwrap()
};
let view = st.view(v).unwrap();
assert_eq!(address_owner(&view, key), Ok(Some(g(0xA1))));
assert_eq!(
provisioning_conflicts(&view),
vec![ProvisioningConflict {
key,
claims: vec![
(g(0xA1), AddressRole::PrimarySmtp),
(g(0xB0), AddressRole::SecondarySmtp),
],
}]
);
}
Loading