Skip to content

Commit

Permalink
Add groups storage (#88)
Browse files Browse the repository at this point in the history
* add groups storage

* review and linting fixes

* remove unused wrapper

* WIP

* It works

* Point to commit in libsignal-service

* Bump version

* Add checkbox in README

* Also print description

* Cleanup

* More

---------

Co-authored-by: Gabriel Féron <g@leirbag.net>
  • Loading branch information
nanu-c and gferon authored Jan 29, 2023
1 parent d1d72ab commit 57e2aa5
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 100 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# VSCode debugger config
.vscode/launch.json
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
# be a sign or warning of (an imminent event, typically an unwelcome one).
name = "presage"
version = "0.4.1-dev"
version = "0.5.0-dev"
authors = ["Gabriel Féron <g@leirbag.net>"]
edition = "2021"

[dependencies]
libsignal-service = { git = "/~https://github.com/whisperfish/libsignal-service-rs", rev = "ddccf7431d7fe848ef8fbed487fc0d33fe385b23" }
libsignal-service-hyper = { git = "/~https://github.com/whisperfish/libsignal-service-rs.git", rev = "ddccf7431d7fe848ef8fbed487fc0d33fe385b23" }
libsignal-service = { git = "/~https://github.com/whisperfish/libsignal-service-rs", rev = "bfc293000e058924771c0651c16bb19fb778c4ef" }
libsignal-service-hyper = { git = "/~https://github.com/whisperfish/libsignal-service-rs", rev = "bfc293000e058924771c0651c16bb19fb778c4ef" }

async-trait = "0.1"
base64 = "0.12"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Features:
- [x] Local storage (using [sled](/~https://github.com/spacejam/sled))
- [x] Registration/linking
- [x] Contacts
- [x] Groups
- [x] Messages
- [x] Local encryption (using [matrix-sdk-store-encryption](https://crates.io/crates/matrix-sdk-store-encryption))
- [x] Registration
Expand Down
80 changes: 36 additions & 44 deletions examples/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use directories::ProjectDirs;
use env_logger::Env;
use futures::{channel::oneshot, future, pin_mut, StreamExt};
use libsignal_service::{groups_v2::Group, push_service::ProfileKey};
use log::{debug, info};
use log::{debug, error, info};
use presage::{
prelude::{
content::{Content, ContentBody, DataMessage, GroupContextV2, SyncMessage},
proto::sync_message::Sent,
Contact, GroupMasterKey, SignalServers,
Contact, SignalServers,
},
prelude::{phonenumber::PhoneNumber, ServiceAddress, Uuid},
Manager, MessageStore, MigrationConflictStrategy, Registered, RegistrationOptions, SledStore,
Expand Down Expand Up @@ -102,12 +102,7 @@ enum Cmd {
UpdateContact,
#[clap(about = "Receive all pending messages and saves them to disk")]
Receive,
/// Get information about a group
GetGroup {
#[clap(long, short = 'k', value_parser = parse_base64_master_key)]
group_master_key: GroupMasterKey,
},
#[clap(about = "List group memberships")]
#[clap(about = "List groups")]
ListGroups,
#[clap(about = "List contacts")]
ListContacts,
Expand Down Expand Up @@ -246,16 +241,13 @@ async fn receive<C: Store + MessageStore>(
)
} else {
println!("Message from {:?}: {:?}", metadata, message);
// fetch the groups v2 info here, just for testing purposes
if let Some(group_v2) = message.group_v2 {
let master_key_bytes: [u8; 32] =
group_v2.master_key.clone().unwrap().try_into().unwrap();
let master_key = GroupMasterKey::new(master_key_bytes);
let group = manager.get_group_v2(master_key).await?;
let group_changes = manager.decrypt_group_context(group_v2)?;
println!("Group v2: {:?}", group.title);
println!("Group change: {:?}", group_changes);
println!("Group master key: {:?}", hex::encode(master_key_bytes));
if let Some(GroupContextV2 {
master_key: Some(master_key),
..
}) = message.group_v2
{
let Group { title, .. } = manager.get_group(&master_key)?.unwrap();
println!("\tin group {title}");
}
}

Expand Down Expand Up @@ -390,16 +382,8 @@ async fn run<C: Store + MessageStore>(subcommand: Cmd, config_store: C) -> anyho
..Default::default()
};

let group = manager
.get_group_v2(GroupMasterKey::new(master_key))
.await?;

manager
.send_message_to_group(
group.members.into_iter().map(|m| m.uuid).map(Into::into),
data_message,
timestamp,
)
.send_message_to_group(&master_key, data_message, timestamp)
.await?;
}
Cmd::Unregister => unimplemented!(),
Expand Down Expand Up @@ -444,7 +428,31 @@ async fn run<C: Store + MessageStore>(subcommand: Cmd, config_store: C) -> anyho
Cmd::Block => unimplemented!(),
Cmd::Unblock => unimplemented!(),
Cmd::UpdateContact => unimplemented!(),
Cmd::ListGroups => unimplemented!(),
Cmd::ListGroups => {
let manager = Manager::load_registered(config_store)?;
for group in manager.get_groups()? {
match group {
Ok((
_,
Group {
title,
description,
version,
members,
..
},
)) => {
println!(
"{title}: {description:?} / version {version} / {} members",
members.len()
);
}
Err(error) => {
error!("Error: failed to deserialize group, {error}");
}
};
}
}
Cmd::ListContacts => {
let manager = Manager::load_registered(config_store)?;
for contact in manager.get_contacts()? {
Expand Down Expand Up @@ -497,26 +505,10 @@ async fn run<C: Store + MessageStore>(subcommand: Cmd, config_store: C) -> anyho
println!("{}: {:?}", msg.metadata.sender.identifier(), msg);
}
}
Cmd::GetGroup { group_master_key } => {
let manager = Manager::load_registered(config_store)?;
let group = manager.get_group_v2(group_master_key).await?;
println!("{:#?}", DebugGroup(&group));
for member in &group.members {
let profile_key = base64::encode(member.profile_key.bytes);
println!("{member:#?} => profile_key = {profile_key}",);
}
}
};
Ok(())
}

fn parse_base64_master_key(s: &str) -> anyhow::Result<GroupMasterKey> {
let bytes = base64::decode(s)?
.try_into()
.map_err(|_| anyhow!("group master key of invalid length"))?;
Ok(GroupMasterKey::new(bytes))
}

fn parse_base64_profile_key(s: &str) -> anyhow::Result<ProfileKey> {
let bytes = base64::decode(s)?
.try_into()
Expand Down
2 changes: 2 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub enum Error {
AttachmentCipherError(#[from] libsignal_service::attachment_cipher::AttachmentCipherError),
#[error("message is missing a uuid")]
ContentMissingUuid,
#[error("unknown group")]
UnknownGroup,
#[error("database migration is not supported")]
MigrationConflict,
#[error("I/O error: {0}")]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use store::sled::{MigrationConflictStrategy, SledStore};
pub use errors::Error;
pub use manager::{Confirmation, Linking, Manager, Registered, Registration, RegistrationOptions};
pub use proto::ContentProto;
pub use store::{ContactsStore, MessageStore, StateStore, Store, Thread};
pub use store::{ContactsStore, GroupsStore, MessageStore, StateStore, Store, Thread};

#[deprecated(note = "Please help use improve the prelude module instead")]
pub use libsignal_service;
Expand Down
Loading

0 comments on commit 57e2aa5

Please sign in to comment.