Skip to content

Commit be097cc

Browse files
committed
Link secondary devices as primary device
1 parent e3a6084 commit be097cc

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
@@ -485,7 +485,9 @@ async fn run<C: Store + 'static>(subcommand: Cmd, config_store: C) -> anyhow::Re
485485
async move {
486486
match provisioning_link_rx.await {
487487
Ok(url) => {
488-
qr2term::print_qr(url.to_string()).expect("failed to render qrcode")
488+
println!("Please scan in the QR code:");
489+
qr2term::print_qr(url.to_string()).expect("failed to render qrcode");
490+
println!("Alternatively, use the URL: {}", url);
489491
}
490492
Err(e) => log::error!("Error linking device: {e}"),
491493
}

presage-store-sled/src/lib.rs

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

119119
#[cfg(feature = "encryption")]
120120
let cipher = passphrase
121+
.as_ref()
121122
.map(|p| Self::get_or_create_store_cipher(&database, p.as_ref()))
122123
.transpose()?;
123124

125+
dbg!(cipher.is_some());
126+
124127
#[cfg(not(feature = "encryption"))]
125128
if passphrase.is_some() {
126129
panic!("A passphrase was supplied but the encryption feature flag is not enabled")
@@ -295,7 +298,7 @@ fn migrate(
295298

296299
let run_migrations = move || {
297300
let mut store = SledStore::new(db_path, passphrase)?;
298-
let schema_version = store.schema_version();
301+
let schema_version = dbg!(store.schema_version());
299302
for step in schema_version.steps() {
300303
match &step {
301304
SchemaVersion::V1 => {
@@ -370,11 +373,11 @@ impl Store for SledStore {
370373
/// State
371374
372375
fn load_state(&self) -> Result<Option<Registered>, SledStoreError> {
373-
self.get(SLED_TREE_STATE, SLED_KEY_REGISTRATION)
376+
dbg!(self.get(SLED_TREE_STATE, SLED_KEY_REGISTRATION))
374377
}
375378

376379
fn save_state(&mut self, state: &Registered) -> Result<(), SledStoreError> {
377-
self.insert(SLED_TREE_STATE, SLED_KEY_REGISTRATION, state)?;
380+
self.insert(SLED_TREE_STATE, SLED_KEY_REGISTRATION, dbg!(state))?;
378381
Ok(())
379382
}
380383

@@ -654,8 +657,10 @@ impl SledContactsIter {
654657
#[cfg(feature = "encryption")]
655658
fn decrypt_value<T: DeserializeOwned>(&self, value: &[u8]) -> Result<T, SledStoreError> {
656659
if let Some(cipher) = self.cipher.as_ref() {
660+
log::trace!("Decrypt with cipher");
657661
Ok(cipher.decrypt_value(value)?)
658662
} else {
663+
log::trace!("Decrypt no cipher");
659664
Ok(serde_json::from_slice(value)?)
660665
}
661666
}

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 = "8305357" }
10-
libsignal-service-hyper = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "8305357" }
9+
libsignal-service = { git = "https://github.com/Schmiddiii/libsignal-service-rs", rev = "76705ea7f70d458011b22cc1d3617756e75bd77a" }
10+
libsignal-service-hyper = { git = "https://github.com/Schmiddiii/libsignal-service-rs", rev = "76705ea7f70d458011b22cc1d3617756e75bd77a" }
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::{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
@@ -16,7 +16,7 @@ use rand::{
1616
use serde::{Deserialize, Serialize};
1717
use url::Url;
1818

19-
use libsignal_service::push_service::{RegistrationMethod, VerificationTransport};
19+
use libsignal_service::push_service::{DeviceInfo, RegistrationMethod, VerificationTransport};
2020
use libsignal_service::{
2121
attachment_cipher::decrypt_in_place,
2222
cipher,
@@ -73,6 +73,12 @@ impl<Store, State: fmt::Debug> fmt::Debug for Manager<Store, State> {
7373
}
7474
}
7575

76+
#[derive(Clone, Debug, PartialEq, Eq)]
77+
pub enum RegistrationType {
78+
Primary,
79+
Secondary,
80+
}
81+
7682
#[derive(Clone, Serialize, Deserialize)]
7783
pub struct RegistrationOptions<'a> {
7884
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)