mirror of
https://github.com/twofas/2fas-android.git
synced 2025-01-05 14:05:30 +01:00
Import from Authenticator Pro
This commit is contained in:
parent
a996a59707
commit
699c45a7e0
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -70,11 +70,12 @@ class Strings(c: Context) {
|
||||
|
||||
val externalImportTitle = c.getString(R.string.settings__external_import)
|
||||
val externalImportHeader = c.getString(R.string.externalimport_select_app)
|
||||
val externalImportNotice = c.getString(R.string.externalimport_description)
|
||||
val externalImportGoogleAuthenticator = c.getString(R.string.externalimport_google_authenticator)
|
||||
val externalImportAegis = c.getString(R.string.externalimport_aegis)
|
||||
val externalImportRaivo = c.getString(R.string.externalimport_raivo)
|
||||
val externalImportLastPass = c.getString(R.string.externalimport_lastpass)
|
||||
val externalImportNotice = c.getString(R.string.externalimport_description)
|
||||
val externalImportAuthenticatorPro = c.getString(R.string.externalimport__authenticatorpro)
|
||||
|
||||
val trashTitle = c.getString(R.string.settings__trash)
|
||||
val trashEmpty = c.getString(R.string.settings__trash_is_empty)
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: de-DE, German (Germany)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Token werden nach dem antippen enthüllt</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: es-ES, Spanish (Spain)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Los tokens se revelarán al tacto</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: fr-FR, French (France)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Les jetons sont révélés lorsque vous appuyez sur l\'écran.</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: it-IT, Italian (Italy)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">I token saranno rivelati al tocco</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: pl-PL, Polish (Poland)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -782,4 +782,10 @@
|
||||
<string name="settings__hide_tokens_description">Pokaż token po kliknięciu</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: pt-PT, Portuguese (Portugal)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Os tokens serão revelados ao tocar</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: uk-UA, Ukrainian (Ukraine)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -780,6 +780,12 @@
|
||||
<string name="social__facebook">Facebook</string>
|
||||
<string name="settings__hide_tokens_title">Сховати токени</string>
|
||||
<string name="settings__hide_tokens_description">Показати токени при натисканні</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="browser__pair_manually_cta">Підключити вручну</string>
|
||||
<string name="browser__pair_manually_hint">Код підключення</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Імпорт токенів з Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">Цей текстовий файл дозволяє імпорт токенів з Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Імпорт 2ФА токенів з додатку Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Експортуйте ваші акаунти з Authenticator Pro в незашифрований текстовий файл і завантажте його, використовуючи кнопку \"Обрати текстовий файл\". Не забудьте видалити файл після успішного імпорту.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Оберіть текстовий файл</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: en, English
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Tokens will be revealed on tap</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -211,6 +211,9 @@ internal class ServicesRepositoryImpl(
|
||||
override fun isServiceValid(link: OtpAuthLink): Boolean {
|
||||
return try {
|
||||
val otpAlgorithm = link.params[OtpAuthLink.ALGORITHM_PARAM]
|
||||
val otpDigits = link.params[OtpAuthLink.DIGITS_PARAM]?.toIntOrNull()
|
||||
val otpPeriod = link.params[OtpAuthLink.PERIOD_PARAM]?.toIntOrNull()
|
||||
|
||||
val algorithm = when {
|
||||
otpAlgorithm == null -> Service.Algorithm.SHA1
|
||||
otpAlgorithm.equals("SHA1", ignoreCase = true) -> Service.Algorithm.SHA1
|
||||
@ -221,10 +224,26 @@ internal class ServicesRepositoryImpl(
|
||||
else -> return false
|
||||
}
|
||||
|
||||
val digits = when {
|
||||
otpDigits == 6 -> 6
|
||||
otpDigits == 7 -> 7
|
||||
otpDigits == 8 -> 8
|
||||
otpDigits == null -> 6
|
||||
else -> return false
|
||||
}
|
||||
|
||||
val period = when {
|
||||
otpPeriod == 30 -> 30
|
||||
otpPeriod == 60 -> 60
|
||||
otpPeriod == 90 -> 90
|
||||
otpPeriod == null -> 30
|
||||
else -> return false
|
||||
}
|
||||
|
||||
codeGenerator.check(
|
||||
secret = link.secret,
|
||||
digits = link.params[OtpAuthLink.DIGITS_PARAM]?.toIntOrNull() ?: 6,
|
||||
period = link.params[OtpAuthLink.PERIOD_PARAM]?.toIntOrNull() ?: 30,
|
||||
digits = digits,
|
||||
period = period,
|
||||
algorithm = algorithm
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
|
@ -0,0 +1,73 @@
|
||||
package com.twofasapp.data.services.otp
|
||||
|
||||
import android.net.Uri
|
||||
import com.twofasapp.parsers.domain.OtpAuthLink
|
||||
import timber.log.Timber
|
||||
|
||||
// TODO: This object should replace ParseOtpAuthLink
|
||||
object OtpLinkParser {
|
||||
|
||||
private const val OTPAUTH = "otpauth"
|
||||
private const val TOTP = "totp"
|
||||
private const val HOTP = "hotp"
|
||||
private const val SECRET = "secret"
|
||||
private const val ISSUER = "issuer"
|
||||
|
||||
fun parseLegacy(link: String): OtpAuthLink? {
|
||||
try {
|
||||
Timber.d("Parse link: $link")
|
||||
|
||||
val decoded = Uri.decode(link).replace("#", "-") // remove hash, Uri.parse terminates on that
|
||||
val uri = Uri.parse(decoded)
|
||||
|
||||
if (isUriValid(uri).not()) {
|
||||
return null
|
||||
// throw IllegalArgumentException("Link is not supported")
|
||||
}
|
||||
|
||||
if (isAuthorityValid(uri).not()) {
|
||||
return null
|
||||
// throw IllegalArgumentException("Only TOTP and HOTP are supported")
|
||||
}
|
||||
|
||||
val type = uri.authority!!
|
||||
val label = getPath(uri)
|
||||
val secret = uri.getQueryParameter(SECRET) ?: ""
|
||||
val issuer = uri.getQueryParameter(ISSUER)
|
||||
val queryParams = mapQueryParams(uri)
|
||||
|
||||
val otpAuthLink = OtpAuthLink(
|
||||
type = type,
|
||||
label = label,
|
||||
secret = secret,
|
||||
issuer = issuer,
|
||||
params = queryParams,
|
||||
link = link,
|
||||
)
|
||||
|
||||
return otpAuthLink
|
||||
|
||||
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUriValid(uri: Uri?) = uri?.scheme?.toLowerCase() == OTPAUTH
|
||||
|
||||
private fun isAuthorityValid(uri: Uri) =
|
||||
uri.authority?.lowercase() == TOTP || uri.authority?.lowercase() == HOTP
|
||||
|
||||
private fun mapQueryParams(uri: Uri) = uri.queryParameterNames.map { it to uri.getQueryParameter(it)!! }.toMap()
|
||||
|
||||
private fun getPath(uri: Uri): String {
|
||||
if (uri.path == null) return ""
|
||||
|
||||
return if (uri.path!!.startsWith("/")) uri.path!!.drop(1) else uri.path!!
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val link: String
|
||||
)
|
||||
}
|
@ -2,6 +2,7 @@ package com.twofasapp.feature.externalimport.di
|
||||
|
||||
import com.twofasapp.di.KoinModule
|
||||
import com.twofasapp.feature.externalimport.domain.AegisImporter
|
||||
import com.twofasapp.feature.externalimport.domain.AuthenticatorProImporter
|
||||
import com.twofasapp.feature.externalimport.domain.GoogleAuthenticatorImporter
|
||||
import com.twofasapp.feature.externalimport.domain.LastPassImporter
|
||||
import com.twofasapp.feature.externalimport.domain.RaivoImporter
|
||||
@ -21,5 +22,6 @@ class ExternalImportModule : KoinModule {
|
||||
factoryOf(::AegisImporter)
|
||||
factoryOf(::RaivoImporter)
|
||||
factoryOf(::LastPassImporter)
|
||||
factoryOf(::AuthenticatorProImporter)
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.twofasapp.feature.externalimport.domain
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.twofasapp.data.services.ServicesRepository
|
||||
import com.twofasapp.data.services.otp.OtpLinkParser
|
||||
import com.twofasapp.prefs.model.ServiceDto
|
||||
import com.twofasapp.services.domain.ConvertOtpLinkToService
|
||||
import java.io.BufferedReader
|
||||
|
||||
internal class AuthenticatorProImporter(
|
||||
private val context: Context,
|
||||
private val convertOtpLinkToService: ConvertOtpLinkToService,
|
||||
private val servicesRepository: ServicesRepository,
|
||||
) : ExternalImporter {
|
||||
|
||||
override fun isSchemaSupported(content: String): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun read(content: String): ExternalImport {
|
||||
try {
|
||||
val fileUri = Uri.parse(content)
|
||||
val fileDescriptor = context.contentResolver.openAssetFileDescriptor(fileUri, "r")
|
||||
val size = fileDescriptor?.length ?: 0
|
||||
|
||||
if (size > 10 * 1024 * 1024) {
|
||||
return ExternalImport.ParsingError(RuntimeException("File too big"))
|
||||
}
|
||||
|
||||
val inputStream = context.contentResolver.openInputStream(fileUri)!!
|
||||
val text = inputStream.bufferedReader(Charsets.UTF_8).use(BufferedReader::readText)
|
||||
|
||||
fileDescriptor?.close()
|
||||
inputStream.close()
|
||||
|
||||
val totalServices = text.lines().filter { it.isNotBlank() }.size
|
||||
val servicesToImport = mutableListOf<ServiceDto>()
|
||||
|
||||
text.lines()
|
||||
.filter { it.isNotBlank() }
|
||||
.mapNotNull { OtpLinkParser.parseLegacy(it) }
|
||||
.filter { servicesRepository.isServiceValid(it) }
|
||||
.forEach { entry -> servicesToImport.add(convertOtpLinkToService.execute(entry)) }
|
||||
|
||||
return ExternalImport.Success(
|
||||
servicesToImport = servicesToImport,
|
||||
totalServicesCount = totalServices,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
return ExternalImport.ParsingError(e)
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import com.twofasapp.android.navigation.NavGraph
|
||||
import com.twofasapp.android.navigation.NavNode
|
||||
import com.twofasapp.android.navigation.withArg
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.Aegis
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.AuthenticatorPro
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.GoogleAuthenticator
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.LastPass
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.Raivo
|
||||
@ -17,6 +18,7 @@ import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.Result
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.Scan
|
||||
import com.twofasapp.feature.externalimport.navigation.ExternalImportNode.Selector
|
||||
import com.twofasapp.feature.externalimport.ui.aegis.AegisRoute
|
||||
import com.twofasapp.feature.externalimport.ui.authenticatorpro.AuthenticatorProRoute
|
||||
import com.twofasapp.feature.externalimport.ui.googleauthenticator.GoogleAuthenticatorRoute
|
||||
import com.twofasapp.feature.externalimport.ui.lastpass.LastPassRoute
|
||||
import com.twofasapp.feature.externalimport.ui.raivo.RaivoRoute
|
||||
@ -28,7 +30,14 @@ object ExternalImportGraph : NavGraph {
|
||||
override val route: String = "externalimport"
|
||||
}
|
||||
|
||||
enum class ImportType { GoogleAuthenticator, Aegis, Raivo, LastPass }
|
||||
enum class ImportType {
|
||||
GoogleAuthenticator,
|
||||
Aegis,
|
||||
Raivo,
|
||||
LastPass,
|
||||
AuthenticatorPro,
|
||||
;
|
||||
}
|
||||
|
||||
private object NavArg {
|
||||
val ImportType = navArgument("importType") { type = NavType.StringType; }
|
||||
@ -44,6 +53,7 @@ private sealed class ExternalImportNode(override val path: String) : NavNode {
|
||||
object Aegis : ExternalImportNode("aegis")
|
||||
object Raivo : ExternalImportNode("raivo")
|
||||
object LastPass : ExternalImportNode("lastpass")
|
||||
object AuthenticatorPro : ExternalImportNode("authenticatorpro")
|
||||
object Scan : ExternalImportNode("scan?startFromGallery={${NavArg.StartFromGallery.name}}")
|
||||
object Result : ExternalImportNode("result/{${NavArg.ImportType.name}}/{${NavArg.ImportContent.name}}")
|
||||
}
|
||||
@ -63,6 +73,7 @@ fun NavGraphBuilder.externalImportNavigation(
|
||||
onAegisClick = { navController.navigate(Aegis.route) },
|
||||
onRaivoClick = { navController.navigate(Raivo.route) },
|
||||
onLastPassClick = { navController.navigate(LastPass.route) },
|
||||
onAuthenticatorProClick = { navController.navigate(AuthenticatorPro.route) },
|
||||
)
|
||||
}
|
||||
|
||||
@ -106,6 +117,16 @@ fun NavGraphBuilder.externalImportNavigation(
|
||||
})
|
||||
}
|
||||
|
||||
composable(route = AuthenticatorPro.route) {
|
||||
AuthenticatorProRoute(onFilePicked = { content ->
|
||||
navController.navigate(
|
||||
Result.route
|
||||
.withArg(NavArg.ImportType, ImportType.AuthenticatorPro.name)
|
||||
.withArg(NavArg.ImportContent, content)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
composable(
|
||||
route = Scan.route,
|
||||
arguments = listOf(NavArg.StartFromGallery)
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.twofasapp.feature.externalimport.ui.authenticatorpro
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.twofasapp.core.encoding.encodeBase64ToString
|
||||
import com.twofasapp.feature.externalimport.ui.common.ImportDescription
|
||||
import com.twofasapp.feature.externalimport.ui.common.ImportFilePickerButton
|
||||
import com.twofasapp.feature.externalimport.ui.common.ImportFileScaffold
|
||||
import com.twofasapp.resources.R
|
||||
|
||||
@Composable
|
||||
internal fun AuthenticatorProRoute(
|
||||
onFilePicked: (String) -> Unit,
|
||||
) {
|
||||
|
||||
ImportFileScaffold(
|
||||
title = stringResource(id = R.string.externalimport__authenticatorpro),
|
||||
image = painterResource(id = R.drawable.ic_import_authenticatorpro),
|
||||
description = { ImportDescription(text = stringResource(id = R.string.externalimport__authenticatorpro_msg)) }
|
||||
) {
|
||||
ImportFilePickerButton(
|
||||
text = stringResource(id = R.string.externalimport__choose_txt_cta),
|
||||
fileType = "text/*",
|
||||
onFilePicked = { onFilePicked(it.toString().encodeBase64ToString()) }
|
||||
)
|
||||
}
|
||||
}
|
@ -79,6 +79,7 @@ internal fun ImportResultRoute(
|
||||
ImportType.Aegis -> R.drawable.ic_import_aegis
|
||||
ImportType.Raivo -> R.drawable.ic_import_raivo
|
||||
ImportType.LastPass -> R.drawable.ic_import_lastpass
|
||||
ImportType.AuthenticatorPro -> R.drawable.ic_import_authenticatorpro
|
||||
}
|
||||
),
|
||||
contentDescription = null,
|
||||
|
@ -7,6 +7,7 @@ import com.twofasapp.base.BaseViewModel
|
||||
import com.twofasapp.base.dispatcher.Dispatchers
|
||||
import com.twofasapp.core.encoding.decodeBase64
|
||||
import com.twofasapp.feature.externalimport.domain.AegisImporter
|
||||
import com.twofasapp.feature.externalimport.domain.AuthenticatorProImporter
|
||||
import com.twofasapp.feature.externalimport.domain.ExternalImport
|
||||
import com.twofasapp.feature.externalimport.domain.GoogleAuthenticatorImporter
|
||||
import com.twofasapp.feature.externalimport.domain.LastPassImporter
|
||||
@ -26,12 +27,13 @@ import kotlinx.coroutines.launch
|
||||
|
||||
internal class ImportResultViewModel(
|
||||
private val dispatchers: Dispatchers,
|
||||
private val addServiceCase: AddServiceCase,
|
||||
private val syncBackupDispatcher: SyncBackupWorkDispatcher,
|
||||
private val googleAuthenticatorImporter: GoogleAuthenticatorImporter,
|
||||
private val aegisImporter: AegisImporter,
|
||||
private val raivoImporter: RaivoImporter,
|
||||
private val lastPassImporter: LastPassImporter,
|
||||
private val addServiceCase: AddServiceCase,
|
||||
private val syncBackupDispatcher: SyncBackupWorkDispatcher,
|
||||
private val authenticatorProImporter: AuthenticatorProImporter,
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(ImportResultUiState())
|
||||
@ -44,6 +46,7 @@ internal class ImportResultViewModel(
|
||||
ImportType.Aegis -> aegisImporter.read(content.decodeBase64())
|
||||
ImportType.Raivo -> raivoImporter.read(content.decodeBase64())
|
||||
ImportType.LastPass -> lastPassImporter.read(content.decodeBase64())
|
||||
ImportType.AuthenticatorPro -> authenticatorProImporter.read(content.decodeBase64())
|
||||
}
|
||||
|
||||
when (result) {
|
||||
@ -99,6 +102,7 @@ internal class ImportResultViewModel(
|
||||
ImportType.Aegis -> R.string.externalimport__aegis_title
|
||||
ImportType.Raivo -> R.string.externalimport__raivo_title
|
||||
ImportType.LastPass -> R.string.externalimport__lastpass_title
|
||||
ImportType.AuthenticatorPro -> R.string.externalimport__authenticatorpro_title
|
||||
}
|
||||
|
||||
private fun getSuccessDescription(type: ImportType) = when (type) {
|
||||
@ -106,5 +110,6 @@ internal class ImportResultViewModel(
|
||||
ImportType.Aegis -> R.string.externalimport__aegis_success_msg
|
||||
ImportType.Raivo -> R.string.externalimport__raivo_success_msg
|
||||
ImportType.LastPass -> R.string.externalimport__lastpass_success_msg
|
||||
ImportType.AuthenticatorPro -> R.string.externalimport__authenticatorpro_success_msg
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,14 @@ internal fun SelectorRoute(
|
||||
onAegisClick: () -> Unit,
|
||||
onRaivoClick: () -> Unit,
|
||||
onLastPassClick: () -> Unit,
|
||||
onAuthenticatorProClick: () -> Unit,
|
||||
) {
|
||||
SelectorScreen(
|
||||
onGoogleAuthenticatorClick = onGoogleAuthenticatorClick,
|
||||
onAegisClick = onAegisClick,
|
||||
onRaivoClick = onRaivoClick,
|
||||
onLastPassClick = onLastPassClick,
|
||||
onAuthenticatorProClick = onAuthenticatorProClick,
|
||||
)
|
||||
}
|
||||
|
||||
@ -34,6 +36,7 @@ private fun SelectorScreen(
|
||||
onAegisClick: () -> Unit,
|
||||
onRaivoClick: () -> Unit,
|
||||
onLastPassClick: () -> Unit,
|
||||
onAuthenticatorProClick: () -> Unit,
|
||||
) {
|
||||
|
||||
Scaffold(
|
||||
@ -77,6 +80,14 @@ private fun SelectorScreen(
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
SettingsLink(
|
||||
title = TwLocale.strings.externalImportAuthenticatorPro,
|
||||
image = painterResource(id = R.drawable.logo_authenticatorpro),
|
||||
onClick = onAuthenticatorProClick
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
SettingsDescription(text = TwLocale.strings.externalImportNotice)
|
||||
}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
resources/src/main/res/drawable/ic_import_authenticatorpro.png
Normal file
BIN
resources/src/main/res/drawable/ic_import_authenticatorpro.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: de-DE, German (Germany)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Token werden nach dem antippen enthüllt</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: es-ES, Spanish (Spain)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Los tokens se revelarán al tacto</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: fr-FR, French (France)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Les jetons sont révélés lorsque vous appuyez sur l\'écran.</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: it-IT, Italian (Italy)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">I token saranno rivelati al tocco</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: pl-PL, Polish (Poland)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -782,4 +782,10 @@
|
||||
<string name="settings__hide_tokens_description">Pokaż token po kliknięciu</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: pt-PT, Portuguese (Portugal)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Os tokens serão revelados ao tocar</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: uk-UA, Ukrainian (Ukraine)
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -780,6 +780,12 @@
|
||||
<string name="social__facebook">Facebook</string>
|
||||
<string name="settings__hide_tokens_title">Сховати токени</string>
|
||||
<string name="settings__hide_tokens_description">Показати токени при натисканні</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="browser__pair_manually_cta">Підключити вручну</string>
|
||||
<string name="browser__pair_manually_hint">Код підключення</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Імпорт токенів з Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">Цей текстовий файл дозволяє імпорт токенів з Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Імпорт 2ФА токенів з додатку Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Експортуйте ваші акаунти з Authenticator Pro в незашифрований текстовий файл і завантажте його, використовуючи кнопку \"Обрати текстовий файл\". Не забудьте видалити файл після успішного імпорту.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Оберіть текстовий файл</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: en, English
|
||||
Exported by: rafakob
|
||||
Exported at: Sun, 02 Jul 2023 00:37:49 -0700
|
||||
Exported at: Sun, 02 Jul 2023 04:39:36 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -776,4 +776,10 @@
|
||||
<string name="settings__hide_tokens_description">Tokens will be revealed on tap</string>
|
||||
<string name="browser__pair_manually_cta">Pair manually</string>
|
||||
<string name="browser__pair_manually_hint">Pairing code</string>
|
||||
<string name="externalimport__info_authenticatorpro_title">Import tokens from Authenticator Pro</string>
|
||||
<string name="externalimport__authenticatorpro_success_msg">This text file allows importing tokens from Authenticator Pro.</string>
|
||||
<string name="externalimport__authenticatorpro_title">Importing 2FA tokens from Authenticator Pro app</string>
|
||||
<string name="externalimport__authenticatorpro_msg">Export your accounts from Authenticator Pro to an unencrypted text file and upload it using the \"Choose text file\" button. Remember to remove the file after a successful import.</string>
|
||||
<string name="externalimport__authenticatorpro">Authenticator Pro</string>
|
||||
<string name="externalimport__choose_txt_cta">Choose text file</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user