Skip to content

Commit 752d21a

Browse files
committed
fix: require auth for pubky approval
1 parent f3481b5 commit 752d21a

3 files changed

Lines changed: 112 additions & 8 deletions

File tree

app/src/main/java/to/bitkit/ui/screens/profile/PubkyAuthApprovalSheet.kt

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import kotlinx.collections.immutable.persistentListOf
3232
import to.bitkit.R
3333
import to.bitkit.models.PubkyAuthPermission
3434
import to.bitkit.models.PubkyProfile
35+
import to.bitkit.ui.appViewModel
36+
import to.bitkit.ui.components.AuthCheckView
3537
import to.bitkit.ui.components.BiometricsView
3638
import to.bitkit.ui.components.BodyM
3739
import to.bitkit.ui.components.BodySSB
@@ -61,8 +63,10 @@ fun PubkyAuthApprovalSheet(
6163
) {
6264
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
6365
var showBiometrics by remember { mutableStateOf(false) }
66+
var showAuthCheck by remember { mutableStateOf(false) }
6467
var pendingAuthUrl by remember { mutableStateOf<String?>(null) }
6568

69+
val app = appViewModel ?: return
6670
val settings = settingsViewModel ?: return
6771
val isPinEnabled by settings.isPinEnabled.collectAsStateWithLifecycle()
6872
val isBiometricEnabled by settings.isBiometricEnabled.collectAsStateWithLifecycle()
@@ -73,12 +77,29 @@ fun PubkyAuthApprovalSheet(
7377
LaunchedEffect(Unit) {
7478
viewModel.effects.collect {
7579
when (it) {
76-
is PubkyAuthApprovalEffect.RequestBiometric -> {
77-
if (isPinEnabled && isBiometricEnabled && isBiometrySupported) {
78-
pendingAuthUrl = it.authUrl
79-
showBiometrics = true
80-
} else {
81-
viewModel.confirmAuthorize(it.authUrl)
80+
is PubkyAuthApprovalEffect.RequestLocalAuth -> {
81+
pendingAuthUrl = it.authUrl
82+
when (
83+
resolvePubkyApprovalLocalAuthMode(
84+
isPinEnabled = isPinEnabled,
85+
isBiometricEnabled = isBiometricEnabled,
86+
isBiometrySupported = isBiometrySupported,
87+
)
88+
) {
89+
PubkyApprovalLocalAuthMode.AuthCheck -> {
90+
showBiometrics = false
91+
showAuthCheck = true
92+
}
93+
94+
PubkyApprovalLocalAuthMode.Biometrics -> {
95+
showAuthCheck = false
96+
showBiometrics = true
97+
}
98+
99+
PubkyApprovalLocalAuthMode.None -> {
100+
pendingAuthUrl = null
101+
viewModel.confirmAuthorize(it.authUrl)
102+
}
82103
}
83104
}
84105
PubkyAuthApprovalEffect.Dismiss -> onDismiss()
@@ -94,6 +115,22 @@ fun PubkyAuthApprovalSheet(
94115
onDismiss = { viewModel.dismiss() },
95116
)
96117

118+
if (showAuthCheck) {
119+
AuthCheckView(
120+
appViewModel = app,
121+
settingsViewModel = settings,
122+
onSuccess = {
123+
showAuthCheck = false
124+
pendingAuthUrl?.let { viewModel.confirmAuthorize(it) }
125+
pendingAuthUrl = null
126+
},
127+
onBack = {
128+
showAuthCheck = false
129+
pendingAuthUrl = null
130+
},
131+
)
132+
}
133+
97134
if (showBiometrics) {
98135
BiometricsView(
99136
onSuccess = {
@@ -110,6 +147,22 @@ fun PubkyAuthApprovalSheet(
110147
}
111148
}
112149

150+
internal enum class PubkyApprovalLocalAuthMode {
151+
None,
152+
Biometrics,
153+
AuthCheck,
154+
}
155+
156+
internal fun resolvePubkyApprovalLocalAuthMode(
157+
isPinEnabled: Boolean,
158+
isBiometricEnabled: Boolean,
159+
isBiometrySupported: Boolean,
160+
): PubkyApprovalLocalAuthMode = when {
161+
isPinEnabled -> PubkyApprovalLocalAuthMode.AuthCheck
162+
isBiometricEnabled && isBiometrySupported -> PubkyApprovalLocalAuthMode.Biometrics
163+
else -> PubkyApprovalLocalAuthMode.None
164+
}
165+
113166
@Composable
114167
private fun Content(
115168
uiState: PubkyAuthApprovalUiState,

app/src/main/java/to/bitkit/ui/screens/profile/PubkyAuthApprovalViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class PubkyAuthApprovalViewModel @Inject constructor(
6363

6464
fun requestAuthorize(authUrl: String) {
6565
viewModelScope.launch {
66-
_effects.emit(PubkyAuthApprovalEffect.RequestBiometric(authUrl))
66+
_effects.emit(PubkyAuthApprovalEffect.RequestLocalAuth(authUrl))
6767
}
6868
}
6969

@@ -112,6 +112,6 @@ sealed interface ApprovalState {
112112
}
113113

114114
sealed interface PubkyAuthApprovalEffect {
115-
data class RequestBiometric(val authUrl: String) : PubkyAuthApprovalEffect
115+
data class RequestLocalAuth(val authUrl: String) : PubkyAuthApprovalEffect
116116
data object Dismiss : PubkyAuthApprovalEffect
117117
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package to.bitkit.ui.screens.profile
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertEquals
5+
6+
class PubkyAuthApprovalSheetTest {
7+
8+
@Test
9+
fun `resolve auth mode uses auth check when pin is enabled`() {
10+
val result = resolvePubkyApprovalLocalAuthMode(
11+
isPinEnabled = true,
12+
isBiometricEnabled = true,
13+
isBiometrySupported = true,
14+
)
15+
16+
assertEquals(PubkyApprovalLocalAuthMode.AuthCheck, result)
17+
}
18+
19+
@Test
20+
fun `resolve auth mode uses biometrics when only biometrics are available`() {
21+
val result = resolvePubkyApprovalLocalAuthMode(
22+
isPinEnabled = false,
23+
isBiometricEnabled = true,
24+
isBiometrySupported = true,
25+
)
26+
27+
assertEquals(PubkyApprovalLocalAuthMode.Biometrics, result)
28+
}
29+
30+
@Test
31+
fun `resolve auth mode returns none when no local auth is available`() {
32+
val result = resolvePubkyApprovalLocalAuthMode(
33+
isPinEnabled = false,
34+
isBiometricEnabled = false,
35+
isBiometrySupported = false,
36+
)
37+
38+
assertEquals(PubkyApprovalLocalAuthMode.None, result)
39+
}
40+
41+
@Test
42+
fun `resolve auth mode returns none when biometrics are unsupported and pin is disabled`() {
43+
val result = resolvePubkyApprovalLocalAuthMode(
44+
isPinEnabled = false,
45+
isBiometricEnabled = true,
46+
isBiometrySupported = false,
47+
)
48+
49+
assertEquals(PubkyApprovalLocalAuthMode.None, result)
50+
}
51+
}

0 commit comments

Comments
 (0)