@@ -37,7 +37,9 @@ import com.duckduckgo.sync.impl.CodeType.UNKNOWN
37
37
import com.duckduckgo.sync.impl.ExchangeResult.*
38
38
import com.duckduckgo.sync.impl.Result.Error
39
39
import com.duckduckgo.sync.impl.Result.Success
40
+ import com.duckduckgo.sync.impl.SyncAccountRepository.AuthCode
40
41
import com.duckduckgo.sync.impl.pixels.*
42
+ import com.duckduckgo.sync.impl.ui.qrcode.SyncBarcodeUrlWrapper
41
43
import com.duckduckgo.sync.store.*
42
44
import com.squareup.anvil.annotations.*
43
45
import com.squareup.moshi.*
@@ -59,16 +61,28 @@ interface SyncAccountRepository {
59
61
fun logout (deviceId : String ): Result <Boolean >
60
62
fun deleteAccount (): Result <Boolean >
61
63
fun latestToken (): String
62
- fun getRecoveryCode (): Result <String >
64
+ fun getRecoveryCode (): Result <AuthCode >
63
65
fun getThisConnectedDevice (): ConnectedDevice ?
64
66
fun getConnectedDevices (): Result <List <ConnectedDevice >>
65
- fun getConnectQR (): Result <String >
67
+ fun getConnectQR (): Result <AuthCode >
66
68
fun pollConnectionKeys (): Result <Boolean >
67
- fun generateExchangeInvitationCode (): Result <String >
69
+ fun generateExchangeInvitationCode (): Result <AuthCode >
68
70
fun pollSecondDeviceExchangeAcknowledgement (): Result <Boolean >
69
71
fun pollForRecoveryCodeAndLogin (): Result <ExchangeResult >
70
72
fun renameDevice (device : ConnectedDevice ): Result <Boolean >
71
73
fun logoutAndJoinNewAccount (stringCode : String ): Result <Boolean >
74
+
75
+ data class AuthCode (
76
+ /* *
77
+ * A code that is suitable for displaying in a QR code.
78
+ */
79
+ val qrCode : String ,
80
+
81
+ /* *
82
+ * Just the code (b64-encoded)
83
+ */
84
+ val rawCode : String ,
85
+ )
72
86
}
73
87
74
88
@ContributesBinding(AppScope ::class )
@@ -85,6 +99,7 @@ class AppSyncAccountRepository @Inject constructor(
85
99
private val dispatcherProvider : DispatcherProvider ,
86
100
private val syncFeature : SyncFeature ,
87
101
private val deviceKeyGenerator : DeviceKeyGenerator ,
102
+ private val syncCodeUrlWrapper : SyncBarcodeUrlWrapper ,
88
103
) : SyncAccountRepository {
89
104
90
105
/* *
@@ -300,13 +315,14 @@ class AppSyncAccountRepository @Inject constructor(
300
315
)
301
316
}
302
317
303
- override fun getRecoveryCode (): Result <String > {
318
+ override fun getRecoveryCode (): Result <AuthCode > {
304
319
val primaryKey = syncStore.primaryKey ? : return Error (reason = " Get Recovery Code: Not existing primary Key" ).alsoFireAccountErrorPixel()
305
320
val userID = syncStore.userId ? : return Error (reason = " Get Recovery Code: Not existing userId" ).alsoFireAccountErrorPixel()
306
- return Success (Adapters .recoveryCodeAdapter.toJson(LinkCode (RecoveryCode (primaryKey, userID))).encodeB64())
321
+ val b64Encoded = Adapters .recoveryCodeAdapter.toJson(LinkCode (RecoveryCode (primaryKey, userID))).encodeB64()
322
+ return Success (AuthCode (qrCode = b64Encoded, rawCode = b64Encoded))
307
323
}
308
324
309
- override fun generateExchangeInvitationCode (): Result <String > {
325
+ override fun generateExchangeInvitationCode (): Result <AuthCode > {
310
326
// Sync: InviteFlow - A (https://app.asana.com/0/72649045549333/1209571867429615)
311
327
Timber .d(" Sync-exchange: InviteFlow - A. Generating invitation code" )
312
328
@@ -321,14 +337,19 @@ class AppSyncAccountRepository @Inject constructor(
321
337
val invitationWrapper = InvitationCodeWrapper (invitationCode)
322
338
323
339
return kotlin.runCatching {
324
- val code = Adapters .invitationCodeAdapter.toJson(invitationWrapper).encodeB64()
325
- Success (code)
340
+ val b64Encoded = Adapters .invitationCodeAdapter.toJson(invitationWrapper).encodeB64()
341
+ val qrCode = if (syncFeature.syncSetupBarcodeIsUrlBased().isEnabled()) {
342
+ syncCodeUrlWrapper.decorateCode(b64Encoded)
343
+ } else {
344
+ b64Encoded
345
+ }
346
+ Success (AuthCode (qrCode = qrCode, rawCode = b64Encoded))
326
347
}.getOrElse {
327
348
Error (code = EXCHANGE_FAILED .code, reason = " Error generating invitation code" ).alsoFireAccountErrorPixel()
328
349
}
329
350
}
330
351
331
- override fun getConnectQR (): Result <String > {
352
+ override fun getConnectQR (): Result <AuthCode > {
332
353
val prepareForConnect = kotlin.runCatching {
333
354
nativeLib.prepareForConnect().also {
334
355
it.checkResult(" Creating ConnectQR code failed" )
@@ -344,7 +365,13 @@ class AppSyncAccountRepository @Inject constructor(
344
365
LinkCode (connect = ConnectCode (deviceId = deviceId, secretKey = prepareForConnect.publicKey)),
345
366
) ? : return Error (reason = " Error generating Linking Code" ).alsoFireAccountErrorPixel()
346
367
347
- return Success (linkingQRCode.encodeB64())
368
+ val b64Encoded = linkingQRCode.encodeB64()
369
+ val qrCode = if (syncFeature.syncSetupBarcodeIsUrlBased().isEnabled()) {
370
+ syncCodeUrlWrapper.decorateCode(b64Encoded)
371
+ } else {
372
+ b64Encoded
373
+ }
374
+ return Success (AuthCode (qrCode = qrCode, rawCode = b64Encoded))
348
375
}
349
376
350
377
private fun connectDevice (connectKeys : ConnectCode ): Result <Boolean > {
@@ -465,7 +492,7 @@ class AppSyncAccountRepository @Inject constructor(
465
492
466
493
// recovery code comes b64 encoded, so we need to decode it, then encrypt, which automatically b64 encodes the encrypted form
467
494
return kotlin.runCatching {
468
- val json = recoveryCode.data.decodeB64()
495
+ val json = recoveryCode.data.rawCode. decodeB64()
469
496
val encryptedJson = nativeLib.seal(json, publicKey)
470
497
syncApi.sendEncryptedMessage(keyId, encryptedJson)
471
498
}.getOrElse {
0 commit comments