Skip to content

Commit

Permalink
Merge branch 'main' into cv/01-10-json_deserialization_for_legacy_rea…
Browse files Browse the repository at this point in the history
…ctions
  • Loading branch information
cameronvoell authored Jan 17, 2025
2 parents 6be91c6 + 191b8f3 commit 62248ee
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 45 deletions.
81 changes: 76 additions & 5 deletions bindings_ffi/src/mls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ pub struct FfiListConversationsOptions {
pub created_after_ns: Option<i64>,
pub created_before_ns: Option<i64>,
pub limit: Option<i64>,
pub consent_state: Option<FfiConsentState>,
pub consent_states: Option<Vec<FfiConsentState>>,
pub include_duplicate_dms: bool,
}

Expand All @@ -623,7 +623,9 @@ impl From<FfiListConversationsOptions> for GroupQueryArgs {
created_before_ns: opts.created_before_ns,
created_after_ns: opts.created_after_ns,
limit: opts.limit,
consent_state: opts.consent_state.map(Into::into),
consent_states: opts
.consent_states
.map(|vec| vec.into_iter().map(Into::into).collect()),
include_duplicate_dms: opts.include_duplicate_dms,
..Default::default()
}
Expand Down Expand Up @@ -920,6 +922,62 @@ impl FfiConversations {
Ok(Arc::new(convo.into()))
}

pub async fn create_group_with_inbox_ids(
&self,
inbox_ids: Vec<String>,
opts: FfiCreateGroupOptions,
) -> Result<Arc<FfiConversation>, GenericError> {
log::info!(
"creating group with account inbox ids: {}",
inbox_ids.join(", ")
);

if let Some(FfiGroupPermissionsOptions::CustomPolicy) = opts.permissions {
if opts.custom_permission_policy_set.is_none() {
return Err(GenericError::Generic {
err: "CustomPolicy must include policy set".to_string(),
});
}
} else if opts.custom_permission_policy_set.is_some() {
return Err(GenericError::Generic {
err: "Only CustomPolicy may specify a policy set".to_string(),
});
}

let metadata_options = opts.clone().into_group_metadata_options();

let group_permissions = match opts.permissions {
Some(FfiGroupPermissionsOptions::Default) => {
Some(xmtp_mls::groups::PreconfiguredPolicies::Default.to_policy_set())
}
Some(FfiGroupPermissionsOptions::AdminOnly) => {
Some(xmtp_mls::groups::PreconfiguredPolicies::AdminsOnly.to_policy_set())
}
Some(FfiGroupPermissionsOptions::CustomPolicy) => {
if let Some(policy_set) = opts.custom_permission_policy_set {
Some(policy_set.try_into()?)
} else {
None
}
}
_ => None,
};

let convo = if inbox_ids.is_empty() {
let group = self
.inner_client
.create_group(group_permissions, metadata_options)?;
group.sync().await?;
group
} else {
self.inner_client
.create_group_with_inbox_ids(&inbox_ids, group_permissions, metadata_options)
.await?
};

Ok(Arc::new(convo.into()))
}

pub async fn create_dm(
&self,
account_address: String,
Expand All @@ -932,6 +990,18 @@ impl FfiConversations {
.map_err(Into::into)
}

pub async fn create_dm_with_inbox_id(
&self,
inbox_id: String,
) -> Result<Arc<FfiConversation>, GenericError> {
log::info!("creating dm with target inbox_id: {}", inbox_id);
self.inner_client
.create_dm_by_inbox_id(inbox_id)
.await
.map(|g| Arc::new(g.into()))
.map_err(Into::into)
}

pub async fn process_streamed_welcome_message(
&self,
envelope_bytes: Vec<u8>,
Expand Down Expand Up @@ -959,13 +1029,14 @@ impl FfiConversations {

pub async fn sync_all_conversations(
&self,
consent_state: Option<FfiConsentState>,
consent_states: Option<Vec<FfiConsentState>>,
) -> Result<u32, GenericError> {
let inner = self.inner_client.as_ref();
let provider = inner.mls_provider()?;
let consent: Option<ConsentState> = consent_state.map(|state| state.into());
let consents: Option<Vec<ConsentState>> =
consent_states.map(|states| states.into_iter().map(|state| state.into()).collect());
let num_groups_synced: usize = inner
.sync_all_welcomes_and_groups(&provider, consent)
.sync_all_welcomes_and_groups(&provider, consents)
.await?;
// Convert usize to u32 for compatibility with Uniffi
let num_groups_synced: u32 = num_groups_synced
Expand Down
39 changes: 30 additions & 9 deletions xmtp_mls/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,20 @@ where
Ok(group)
}

pub async fn create_group_with_inbox_ids(
&self,
inbox_ids: &[InboxId],
permissions_policy_set: Option<PolicySet>,
opts: GroupMetadataOptions,
) -> Result<MlsGroup<Self>, ClientError> {
tracing::info!("creating group");
let group = self.create_group(permissions_policy_set, opts)?;

group.add_members_by_inbox_id(inbox_ids).await?;

Ok(group)
}

/// Create a new Direct Message with the default settings
pub async fn create_dm(&self, account_address: String) -> Result<MlsGroup<Self>, ClientError> {
tracing::info!("creating dm with address: {}", account_address);
Expand All @@ -563,25 +577,26 @@ where
}
};

self.create_dm_by_inbox_id(&provider, inbox_id).await
self.create_dm_by_inbox_id(inbox_id).await
}

/// Create a new Direct Message with the default settings
pub(crate) async fn create_dm_by_inbox_id(
pub async fn create_dm_by_inbox_id(
&self,
provider: &XmtpOpenMlsProvider,
dm_target_inbox_id: InboxId,
) -> Result<MlsGroup<Self>, ClientError> {
tracing::info!("creating dm with {}", dm_target_inbox_id);
let provider = self.mls_provider()?;

let group: MlsGroup<Client<ApiClient, V>> = MlsGroup::create_dm_and_insert(
provider,
&provider,
Arc::new(self.clone()),
GroupMembershipState::Allowed,
dm_target_inbox_id.clone(),
)?;

group
.add_members_by_inbox_id_with_provider(provider, &[dm_target_inbox_id])
.add_members_by_inbox_id_with_provider(&provider, &[dm_target_inbox_id])
.await?;

// notify any streams of the new group
Expand Down Expand Up @@ -943,11 +958,11 @@ where
pub async fn sync_all_welcomes_and_groups(
&self,
provider: &XmtpOpenMlsProvider,
consent_state: Option<ConsentState>,
consent_states: Option<Vec<ConsentState>>,
) -> Result<usize, ClientError> {
self.sync_welcomes(provider).await?;
let query_args = GroupQueryArgs {
consent_state,
consent_states,
include_sync_groups: true,
include_duplicate_dms: true,
..GroupQueryArgs::default()
Expand Down Expand Up @@ -1331,7 +1346,10 @@ pub(crate) mod tests {

// Sync with `Unknown`: Bob should not fetch new messages
let bob_received_groups_unknown = bo
.sync_all_welcomes_and_groups(&bo.mls_provider().unwrap(), Some(ConsentState::Allowed))
.sync_all_welcomes_and_groups(
&bo.mls_provider().unwrap(),
Some([ConsentState::Allowed].to_vec()),
)
.await
.unwrap();
assert_eq!(bob_received_groups_unknown, 0);
Expand Down Expand Up @@ -1364,7 +1382,10 @@ pub(crate) mod tests {

// Sync with `None`: Bob should fetch all messages
let bob_received_groups_all = bo
.sync_all_welcomes_and_groups(&bo.mls_provider().unwrap(), Some(ConsentState::Unknown))
.sync_all_welcomes_and_groups(
&bo.mls_provider().unwrap(),
Some([ConsentState::Unknown].to_vec()),
)
.await
.unwrap();
assert_eq!(bob_received_groups_all, 2);
Expand Down
7 changes: 3 additions & 4 deletions xmtp_mls/src/groups/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2148,14 +2148,13 @@ pub(crate) mod tests {

let bo_wallet = generate_local_wallet();
let bo = ClientBuilder::new_test_client(&bo_wallet).await;
let bo_provider = bo.mls_provider().unwrap();

let bo_dm = bo
.create_dm_by_inbox_id(&bo_provider, alix.inbox_id().to_string())
.create_dm_by_inbox_id(alix.inbox_id().to_string())
.await
.unwrap();
let alix_dm = alix
.create_dm_by_inbox_id(&alix_provider, bo.inbox_id().to_string())
.create_dm_by_inbox_id(bo.inbox_id().to_string())
.await
.unwrap();

Expand Down Expand Up @@ -3604,7 +3603,7 @@ pub(crate) mod tests {

// Amal creates a dm group targetting bola
let amal_dm = amal
.create_dm_by_inbox_id(&amal.mls_provider().unwrap(), bola.inbox_id().to_string())
.create_dm_by_inbox_id(bola.inbox_id().to_string())
.await
.unwrap();

Expand Down
37 changes: 29 additions & 8 deletions xmtp_mls/src/storage/encrypted_store/conversation_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl DbConnection {
created_before_ns,
limit,
conversation_type,
consent_state,
consent_states,
include_sync_groups,
include_duplicate_dms,
} = args.as_ref();
Expand Down Expand Up @@ -111,8 +111,12 @@ impl DbConnection {
query = query.filter(conversation_list_dsl::conversation_type.eq(conversation_type));
}

let mut conversations = if let Some(consent_state) = consent_state {
if *consent_state == ConsentState::Unknown {
let mut conversations = if let Some(consent_states) = consent_states {
if consent_states
.iter()
.any(|state| *state == ConsentState::Unknown)
{
// Include both `Unknown`, `null`, and other specified states
let query = query
.left_join(
consent_dsl::consent_records.on(sql::<diesel::sql_types::Text>(
Expand All @@ -123,27 +127,36 @@ impl DbConnection {
.filter(
consent_dsl::state
.is_null()
.or(consent_dsl::state.eq(ConsentState::Unknown)),
.or(consent_dsl::state.eq(ConsentState::Unknown))
.or(consent_dsl::state.eq_any(
consent_states
.iter()
.filter(|state| **state != ConsentState::Unknown)
.cloned()
.collect::<Vec<_>>(),
)),
)
.select(conversation_list::all_columns())
.order(conversation_list_dsl::created_at_ns.asc());

self.raw_query(|conn| query.load::<ConversationListItem>(conn))?
} else {
// Only include the specified states
let query = query
.inner_join(
consent_dsl::consent_records.on(sql::<diesel::sql_types::Text>(
"lower(hex(conversation_list.id))",
)
.eq(consent_dsl::entity)),
)
.filter(consent_dsl::state.eq(*consent_state))
.filter(consent_dsl::state.eq_any(consent_states.clone()))
.select(conversation_list::all_columns())
.order(conversation_list_dsl::created_at_ns.asc());

self.raw_query(|conn| query.load::<ConversationListItem>(conn))?
}
} else {
// Handle the case where `consent_states` is `None`
self.raw_query(|conn| query.load::<ConversationListItem>(conn))?
};

Expand Down Expand Up @@ -338,22 +351,30 @@ pub(crate) mod tests {

let allowed_results = conn
.fetch_conversation_list(
GroupQueryArgs::default().consent_state(ConsentState::Allowed),
GroupQueryArgs::default().consent_states([ConsentState::Allowed].to_vec()),
)
.unwrap();
assert_eq!(allowed_results.len(), 2);

let allowed_unknown_results = conn
.fetch_conversation_list(
GroupQueryArgs::default()
.consent_states([ConsentState::Allowed, ConsentState::Unknown].to_vec()),
)
.unwrap();
assert_eq!(allowed_unknown_results.len(), 3);

let denied_results = conn
.fetch_conversation_list(
GroupQueryArgs::default().consent_state(ConsentState::Denied),
GroupQueryArgs::default().consent_states([ConsentState::Denied].to_vec()),
)
.unwrap();
assert_eq!(denied_results.len(), 1);
assert_eq!(denied_results[0].id, test_group_2.id);

let unknown_results = conn
.fetch_conversation_list(
GroupQueryArgs::default().consent_state(ConsentState::Unknown),
GroupQueryArgs::default().consent_states([ConsentState::Unknown].to_vec()),
)
.unwrap();
assert_eq!(unknown_results.len(), 1);
Expand Down
Loading

0 comments on commit 62248ee

Please sign in to comment.