@@ -216,7 +216,10 @@ mod tests;
216216#[ cfg( feature = "e2e-encryption" ) ]
217217use self :: cross_process:: { CrossProcessRefreshLockGuard , CrossProcessRefreshManager } ;
218218#[ cfg( feature = "e2e-encryption" ) ]
219- use self :: qrcode:: { GrantLoginWithGeneratedQrCode , LoginWithGeneratedQrCode , LoginWithQrCode } ;
219+ use self :: qrcode:: {
220+ GrantLoginWithGeneratedQrCode , GrantLoginWithScannedQrCode , LoginWithGeneratedQrCode ,
221+ LoginWithQrCode ,
222+ } ;
220223pub use self :: {
221224 account_management_url:: { AccountManagementActionFull , AccountManagementUrlBuilder } ,
222225 auth_code_builder:: { OAuthAuthCodeUrlBuilder , OAuthAuthorizationData } ,
@@ -1537,7 +1540,7 @@ pub struct GrantLoginWithQrCodeBuilder<'a> {
15371540#[ cfg( feature = "e2e-encryption" ) ]
15381541impl < ' a > GrantLoginWithQrCodeBuilder < ' a > {
15391542 /// Create a new builder with the default device creation timeout.
1540- pub fn new ( client : & ' a Client ) -> Self {
1543+ fn new ( client : & ' a Client ) -> Self {
15411544 Self { client, device_creation_timeout : Duration :: from_secs ( 10 ) }
15421545 }
15431546
@@ -1552,6 +1555,86 @@ impl<'a> GrantLoginWithQrCodeBuilder<'a> {
15521555 self
15531556 }
15541557
1558+ /// This method allows you to grant login to a new device by scanning a
1559+ /// QR code generated by the new device.
1560+ ///
1561+ /// The new device needs to display the QR code which this device can
1562+ /// scan and call this method to grant the login.
1563+ ///
1564+ /// A successful login grant using this method will automatically mark the
1565+ /// new device as verified and transfer all end-to-end encryption
1566+ /// related secrets, like the private cross-signing keys and the backup
1567+ /// key from this device device to the new device.
1568+ ///
1569+ /// For the reverse flow where this device generates the QR code
1570+ /// for the new device to scan, use
1571+ /// [`GrantLoginWithQrCodeBuilder::generate`].
1572+ ///
1573+ /// # Arguments
1574+ ///
1575+ /// * `data` - The data scanned from a QR code.
1576+ ///
1577+ /// # Example
1578+ ///
1579+ /// ```no_run
1580+ /// use anyhow::bail;
1581+ /// use futures_util::StreamExt;
1582+ /// use matrix_sdk::{
1583+ /// Client, authentication::oauth::{
1584+ /// qrcode::{GrantLoginProgress, QrCodeData, QrCodeModeData, QrProgress},
1585+ /// }
1586+ /// };
1587+ /// use std::{error::Error, io::stdin};
1588+ /// # _ = async {
1589+ /// # let bytes = unimplemented!();
1590+ /// // You'll need to use a different library to scan and extract the raw bytes from the QR
1591+ /// // code.
1592+ /// let qr_code_data = QrCodeData::from_bytes(bytes)?;
1593+ ///
1594+ /// // Build the client as usual.
1595+ /// let client = Client::builder()
1596+ /// .server_name_or_homeserver_url("matrix.org")
1597+ /// .handle_refresh_tokens()
1598+ /// .build()
1599+ /// .await?;
1600+ ///
1601+ /// let oauth = client.oauth();
1602+ ///
1603+ /// // Subscribing to the progress is necessary to capture
1604+ /// // the checkcode in order to display it to the other device and to obtain the verification URL to
1605+ /// // open it in a browser so the user can consent to the new login.
1606+ /// let mut grant = oauth.grant_login_with_qr_code().scan(&qr_code_data);
1607+ /// let mut progress = grant.subscribe_to_progress();
1608+ ///
1609+ /// // Create a task which will show us the progress and allows us to receive
1610+ /// // and feed back data.
1611+ /// let task = tokio::spawn(async move {
1612+ /// while let Some(state) = progress.next().await {
1613+ /// match state {
1614+ /// GrantLoginProgress::Starting | GrantLoginProgress::SyncingSecrets => (),
1615+ /// GrantLoginProgress::EstablishingSecureChannel(QrProgress { check_code }) => {
1616+ /// println!("Please enter the checkcode on your other device: {:?}", check_code);
1617+ /// }
1618+ /// GrantLoginProgress::WaitingForAuth { verification_uri } => {
1619+ /// println!("Please open {verification_uri} to confirm the new login")
1620+ /// },
1621+ /// GrantLoginProgress::Done => break,
1622+ /// }
1623+ /// }
1624+ /// Ok::<(), Box<dyn Error + Send + Sync>>(())
1625+ /// });
1626+ ///
1627+ /// // Now run the future to grant the login.
1628+ /// grant.await?;
1629+ /// task.abort();
1630+ ///
1631+ /// println!("Successfully granted login");
1632+ /// # anyhow::Ok(()) };
1633+ /// ```
1634+ pub fn scan ( self , data : & ' a QrCodeData ) -> GrantLoginWithScannedQrCode < ' a > {
1635+ GrantLoginWithScannedQrCode :: new ( self . client , data, self . device_creation_timeout )
1636+ }
1637+
15551638 /// This method allows you to grant login to a new device by generating a QR
15561639 /// code on this device to be scanned by the new device.
15571640 ///
0 commit comments