Support for ping requests when using bunker

This commit is contained in:
greenart7c3
2025-11-10 09:24:29 -03:00
parent f9d8606724
commit 5cc834f206
9 changed files with 236 additions and 3 deletions
+1 -1
View File
@@ -54,7 +54,7 @@
<provider
android:name=".SignerProvider"
android:authorities="${applicationId}.SIGN_MESSAGE;${applicationId}.SIGN_EVENT;${applicationId}.NIP04_ENCRYPT;${applicationId}.NIP04_DECRYPT;${applicationId}.NIP44_ENCRYPT;${applicationId}.NIP44_DECRYPT;${applicationId}.GET_PUBLIC_KEY;${applicationId}.DECRYPT_ZAP_EVENT"
android:authorities="${applicationId}.PING;${applicationId}.SIGN_MESSAGE;${applicationId}.SIGN_EVENT;${applicationId}.NIP04_ENCRYPT;${applicationId}.NIP04_DECRYPT;${applicationId}.NIP44_ENCRYPT;${applicationId}.NIP44_DECRYPT;${applicationId}.GET_PUBLIC_KEY;${applicationId}.DECRYPT_ZAP_EVENT"
android:enabled="true"
android:exported="true"
tools:ignore="ExportedContentProvider" />
@@ -456,7 +456,77 @@ class SignerProvider : ContentProvider() {
cursor.addRow(arrayOf<Any>(result, result))
return cursor
}
"content://$appId.PING" -> {
val npub = if (projection != null && projection.isNotEmpty()) IntentUtils.parsePubKey(projection[0]) else null
val account = if (npub != null) {
LocalPreferences.loadFromEncryptedStorageSync(context!!, npub)
} else {
LocalPreferences.allSavedAccounts(context!!).firstNotNullOfOrNull { accountInfo ->
val localDatabase = Amber.instance.getDatabase(accountInfo.npub)
val hasAccount = localDatabase.dao().getByKeySync(packageName) != null
if (hasAccount) {
LocalPreferences.loadFromEncryptedStorageSync(context!!, accountInfo.npub)
} else {
null
}
}
}
if (account == null) {
return null
}
val database = Amber.instance.getDatabase(account.npub)
val historyDatabase = Amber.instance.getHistoryDatabase(account.npub)
val permission =
database
.dao()
.getPermission(
packageName,
"PING",
)
val signPolicy = database.dao().getSignPolicy(packageName)
val isRemembered = IntentUtils.isRemembered(signPolicy, permission) ?: return null
if (!isRemembered) {
scope.launch {
historyDatabase.dao().addHistory(
HistoryEntity(
0,
packageName,
uri.toString().replace("content://$appId.", ""),
null,
TimeUtils.now(),
false,
),
account.npub,
)
}
val cursor =
MatrixCursor(arrayOf("rejected")).also {
it.addRow(arrayOf("true"))
}
return cursor
}
scope.launch {
historyDatabase.dao().addHistory(
HistoryEntity(
0,
packageName,
uri.toString().replace("content://$appId.", ""),
null,
TimeUtils.now(),
true,
),
account.npub,
)
}
val cursor = MatrixCursor(arrayOf("signature", "result"))
cursor.addRow(arrayOf<Any>("pong", "pong"))
return cursor
}
else -> null
}
} catch (e: Exception) {
@@ -10,5 +10,6 @@ enum class SignerType {
NIP44_DECRYPT,
GET_PUBLIC_KEY,
DECRYPT_ZAP_EVENT,
PING,
INVALID,
}
@@ -203,6 +203,7 @@ object BunkerRequestUtils {
"nip44_encrypt" -> SignerType.NIP44_ENCRYPT
"nip44_decrypt" -> SignerType.NIP44_DECRYPT
"decrypt_zap_event" -> SignerType.DECRYPT_ZAP_EVENT
"ping" -> SignerType.PING
else -> SignerType.INVALID
}
}
@@ -216,6 +217,7 @@ object BunkerRequestUtils {
AmberEvent.toEvent(amberEvent).toJson()
}
"nip04_encrypt", "nip04_decrypt", "nip44_encrypt", "nip44_decrypt", "decrypt_zap_event" -> bunkerRequest.params.getOrElse(1) { "" }
"ping" -> "pong"
else -> ""
}
}
@@ -402,7 +402,7 @@ class EventNotificationConsumer(private val applicationContext: Context) {
return
}
val data = BunkerRequestUtils.getDataFromBunker(bunkerRequest)
val projection = if (type == SignerType.GET_PUBLIC_KEY) {
val projection = if (type == SignerType.GET_PUBLIC_KEY || type == SignerType.PING) {
arrayOf(acc.npub)
} else {
arrayOf(data, pubKey, acc.npub)
@@ -0,0 +1,101 @@
package com.greenart7c3.nostrsigner.ui.components
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.models.Account
import com.greenart7c3.nostrsigner.ui.RememberType
@Composable
fun BunkerPingScreen(
account: Account,
modifier: Modifier,
shouldRunOnAccept: Boolean?,
appName: String,
onAccept: (RememberType) -> Unit,
onReject: (RememberType) -> Unit,
) {
var rememberType by remember {
mutableStateOf(RememberType.NEVER)
}
Column(
modifier,
) {
ProfilePicture(account)
val message = stringResource(R.string.ping)
Text(
buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(appName)
}
append(" ${stringResource(R.string.requests)} $message")
},
fontSize = 18.sp,
)
Spacer(Modifier.size(4.dp))
Card(
modifier = Modifier
.fillMaxWidth(),
) {
Column(Modifier.padding(6.dp)) {
Text(
stringResource(R.string.response),
fontWeight = FontWeight.Bold,
)
Text(
"pong",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
)
}
}
Spacer(modifier = Modifier.weight(1f))
RememberMyChoice(
shouldRunOnAccept,
null,
true,
onAccept,
onReject,
) {
rememberType = it
}
AcceptRejectButtons(
onAccept = {
onAccept(rememberType)
},
onReject = {
onReject(rememberType)
},
)
}
}
@@ -46,6 +46,7 @@ import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequestNip04Decrypt
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequestNip04Encrypt
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequestNip44Decrypt
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequestNip44Encrypt
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequestPing
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequestSign
import com.vitorpamplona.quartz.nip55AndroidSigner.signString
import com.vitorpamplona.quartz.utils.Hex
@@ -83,6 +84,62 @@ fun BunkerSingleEventHomeScreen(
val type = BunkerRequestUtils.getTypeFromBunker(bunkerRequest.request)
when (bunkerRequest.request) {
is BunkerRequestPing -> {
val permission =
applicationEntity?.permissions?.firstOrNull {
it.pkKey == key && it.type == type.toString()
}
val acceptUntil = permission?.acceptUntil ?: 0
val rejectUntil = permission?.rejectUntil ?: 0
val acceptOrReject = if (rejectUntil == 0L && acceptUntil == 0L) {
null
} else if (rejectUntil > TimeUtils.now() && rejectUntil > 0) {
false
} else if (acceptUntil > TimeUtils.now() && acceptUntil > 0) {
true
} else {
null
}
BunkerPingScreen(
modifier = modifier,
account = account,
appName = appName,
shouldRunOnAccept = acceptOrReject,
onAccept = {
val result = "pong"
BunkerRequestUtils.sendResult(
context = context,
account = account,
key = key,
response = result,
bunkerRequest = bunkerRequest,
kind = null,
onLoading = onLoading,
permissions = null,
appName = appName,
signPolicy = null,
shouldCloseApplication = null,
rememberType = it,
)
},
onReject = {
BunkerRequestUtils.sendRejection(
key = key,
account = account,
bunkerRequest = bunkerRequest,
appName = appName,
rememberType = it,
signerType = type,
kind = null,
onLoading = onLoading,
)
},
)
}
is BunkerRequestConnect -> {
var showExistingAppDialog by remember { mutableStateOf(false) }
var localPermissions by remember { mutableStateOf<List<Permission>?>(null) }
+2
View File
@@ -594,4 +594,6 @@
<string name="read_from_encrypted_content">Read %1$s from %2$s encrypted content</string>
<string name="read_this_list_of_tags_from_encrypted_content">Read this list of tags from %1$s encrypted content</string>
<string name="read_this_text_from_encrypted_content">Read this text from %1$s encrypted content</string>
<string name="ping">Ping</string>
<string name="response">Response</string>
</resources>
+1 -1
View File
@@ -20,7 +20,7 @@
<provider
android:name=".SignerProvider"
android:authorities="${applicationId}.SIGN_MESSAGE;${applicationId}.SIGN_EVENT;${applicationId}.NIP04_ENCRYPT;${applicationId}.NIP04_DECRYPT;${applicationId}.NIP44_ENCRYPT;${applicationId}.NIP44_DECRYPT;${applicationId}.GET_PUBLIC_KEY;${applicationId}.DECRYPT_ZAP_EVENT"
android:authorities="${applicationId}.PING;${applicationId}.SIGN_MESSAGE;${applicationId}.SIGN_EVENT;${applicationId}.NIP04_ENCRYPT;${applicationId}.NIP04_DECRYPT;${applicationId}.NIP44_ENCRYPT;${applicationId}.NIP44_DECRYPT;${applicationId}.GET_PUBLIC_KEY;${applicationId}.DECRYPT_ZAP_EVENT"
android:enabled="true"
android:exported="true" />