Skip to content

Commit 7fb2d40

Browse files
committed
Link secondary devices as primary device
1 parent 6125534 commit 7fb2d40

File tree

6 files changed

+74
-8
lines changed

6 files changed

+74
-8
lines changed

presage-cli/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,9 @@ async fn run<C: Store + 'static>(subcommand: Cmd, config_store: C) -> anyhow::Re
503503
async move {
504504
match provisioning_link_rx.await {
505505
Ok(url) => {
506-
qr2term::print_qr(url.to_string()).expect("failed to render qrcode")
506+
println!("Please scan in the QR code:");
507+
qr2term::print_qr(url.to_string()).expect("failed to render qrcode");
508+
println!("Alternatively, use the URL: {}", url);
507509
}
508510
Err(e) => log::error!("Error linking device: {e}"),
509511
}

presage-store-sled/src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,12 @@ impl SledStore {
122122

123123
#[cfg(feature = "encryption")]
124124
let cipher = passphrase
125+
.as_ref()
125126
.map(|p| Self::get_or_create_store_cipher(&database, p.as_ref()))
126127
.transpose()?;
127128

129+
dbg!(cipher.is_some());
130+
128131
#[cfg(not(feature = "encryption"))]
129132
if passphrase.is_some() {
130133
panic!("A passphrase was supplied but the encryption feature flag is not enabled")
@@ -299,7 +302,7 @@ fn migrate(
299302

300303
let run_migrations = move || {
301304
let mut store = SledStore::new(db_path, passphrase)?;
302-
let schema_version = store.schema_version();
305+
let schema_version = dbg!(store.schema_version());
303306
for step in schema_version.steps() {
304307
match &step {
305308
SchemaVersion::V1 => {
@@ -374,11 +377,11 @@ impl Store for SledStore {
374377
/// State
375378
376379
fn load_state(&self) -> Result<Option<Registered>, SledStoreError> {
377-
self.get(SLED_TREE_STATE, SLED_KEY_REGISTRATION)
380+
dbg!(self.get(SLED_TREE_STATE, SLED_KEY_REGISTRATION))
378381
}
379382

380383
fn save_state(&mut self, state: &Registered) -> Result<(), SledStoreError> {
381-
self.insert(SLED_TREE_STATE, SLED_KEY_REGISTRATION, state)?;
384+
self.insert(SLED_TREE_STATE, SLED_KEY_REGISTRATION, dbg!(state))?;
382385
Ok(())
383386
}
384387

@@ -656,8 +659,10 @@ impl SledContactsIter {
656659
#[cfg(feature = "encryption")]
657660
fn decrypt_value<T: DeserializeOwned>(&self, value: &[u8]) -> Result<T, SledStoreError> {
658661
if let Some(cipher) = self.cipher.as_ref() {
662+
log::trace!("Decrypt with cipher");
659663
Ok(cipher.decrypt_value(value)?)
660664
} else {
665+
log::trace!("Decrypt no cipher");
661666
Ok(serde_json::from_slice(value)?)
662667
}
663668
}

presage/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ authors = ["Gabriel Féron <g@leirbag.net>"]
66
edition = "2021"
77

88
[dependencies]
9-
libsignal-service = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "454d234" }
10-
libsignal-service-hyper = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "454d234" }
9+
libsignal-service = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "aa84243" }
10+
libsignal-service-hyper = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "aa84243" }
1111

1212
base64 = "0.12"
1313
futures = "0.3"

presage/src/errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ pub enum Error<S: std::error::Error> {
6666
RequestingCodeForbidden(libsignal_service::push_service::RegistrationSessionMetadataResponse),
6767
#[error("Unverified registration session (i.e. wrong verification code)")]
6868
UnverifiedRegistrationSession,
69+
#[error("Failed to link secondary device")]
70+
ServiceLinkError(#[from] libsignal_service::LinkError),
71+
#[error("An operation was requested that requires the registration to be primary, but it was only secondary")]
72+
NotPrimaryDevice,
6973
}
7074

7175
impl<S: StoreError> From<S> for Error<S> {

presage/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ mod serde;
55
mod store;
66

77
pub use errors::Error;
8-
pub use manager::{Confirmation, Linking, Manager, Registered, Registration, RegistrationOptions};
8+
pub use manager::{
9+
Confirmation, Linking, Manager, Registered, Registration, RegistrationOptions, RegistrationType,
10+
};
911
pub use store::{ContentTimestamp, Store, StoreError, Thread};
1012

1113
#[deprecated(note = "Please help use improve the prelude module instead")]

presage/src/manager.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize};
1717
use url::Url;
1818

1919
use libsignal_service::proto::EditMessage;
20-
use libsignal_service::push_service::{RegistrationMethod, VerificationTransport};
20+
use libsignal_service::push_service::{DeviceInfo, RegistrationMethod, VerificationTransport};
2121
use libsignal_service::{
2222
attachment_cipher::decrypt_in_place,
2323
cipher,
@@ -74,6 +74,12 @@ impl<Store, State: fmt::Debug> fmt::Debug for Manager<Store, State> {
7474
}
7575
}
7676

77+
#[derive(Clone, Debug, PartialEq, Eq)]
78+
pub enum RegistrationType {
79+
Primary,
80+
Secondary,
81+
}
82+
7783
#[derive(Clone, Serialize, Deserialize)]
7884
pub struct RegistrationOptions<'a> {
7985
pub signal_servers: SignalServers,
@@ -1287,6 +1293,53 @@ impl<C: Store> Manager<C, Registered> {
12871293
}
12881294
}
12891295

1296+
/// Returns how this client was registered, either as a primary or secondary device.
1297+
pub fn registration_type(&self) -> RegistrationType {
1298+
if self.state.device_name.is_some() {
1299+
RegistrationType::Secondary
1300+
} else {
1301+
RegistrationType::Primary
1302+
}
1303+
}
1304+
1305+
/// As a primary device, link a secondary device.
1306+
pub async fn link_secondary(&self, secondary: Url) -> Result<(), Error<C::Error>> {
1307+
// XXX: What happens if secondary device? Possible to use static typing to make this method call impossible in that case?
1308+
if self.registration_type() != RegistrationType::Primary {
1309+
return Err(Error::NotPrimaryDevice);
1310+
}
1311+
1312+
let credentials = self.credentials()?.ok_or(Error::NotYetRegisteredError)?;
1313+
let mut account_manager =
1314+
AccountManager::new(self.push_service()?, Some(self.state.profile_key));
1315+
let store = &self.config_store;
1316+
1317+
account_manager
1318+
.link_device(secondary, store, credentials)
1319+
.await?;
1320+
Ok(())
1321+
}
1322+
1323+
/// As a primary device, unlink a secondary device.
1324+
pub async fn unlink_secondary(&self, device_id: i64) -> Result<(), Error<C::Error>> {
1325+
// XXX: What happens if secondary device? Possible to use static typing to make this method call impossible in that case?
1326+
if self.registration_type() != RegistrationType::Primary {
1327+
return Err(Error::NotPrimaryDevice);
1328+
}
1329+
self.push_service()?.unlink_device(device_id).await?;
1330+
Ok(())
1331+
}
1332+
1333+
/// As a primary device, list all the devices.
1334+
// XXX: Also shows the current device?
1335+
pub async fn linked_devices(&self) -> Result<Vec<DeviceInfo>, Error<C::Error>> {
1336+
// XXX: What happens if secondary device? Possible to use static typing to make this method call impossible in that case?
1337+
if self.registration_type() != RegistrationType::Primary {
1338+
return Err(Error::NotPrimaryDevice);
1339+
}
1340+
Ok(self.push_service()?.devices().await?)
1341+
}
1342+
12901343
#[deprecated = "use Manager::contact_by_id"]
12911344
pub fn get_contacts(
12921345
&self,

0 commit comments

Comments
 (0)