diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt index 1da97b10..52bacfa2 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt @@ -319,8 +319,12 @@ class SignerProvider : ContentProvider() { // SignerType, kind); fall back to a kind=null "all kinds" // grant. V3 grants do NOT satisfy V2 requests and vice versa. var permission = if (isV3) { + // V3 grants are kind-scoped; fall back to the explicit + // "all kinds" (kind IS NULL) grant only, never to any + // other kind — otherwise e.g. a kind-A reject would + // leak to a kind-B request. permDao.getPermission(packageName, type.toString(), v3Kind!!) - ?: permDao.getPermission(packageName, type.toString()) + ?: permDao.getPermissionAllKinds(packageName, type.toString()) } else { // Classify the content to determine EncryptedDataKind-based permission type val classifyContent = if (isEncrypt) content else (result ?: content) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt index 8de614b2..922dc21a 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt @@ -78,6 +78,18 @@ interface ApplicationDao { type: String, ): ApplicationPermissionsEntity? + /** + * Match an "all kinds" grant — the row whose `kind` column is `NULL`. + * Distinct from [getPermission] (no kind), which matches any row of the + * given type regardless of kind: V3's kind-scoped permission model needs + * the explicit `IS NULL` to avoid kind-A rejects leaking to kind-B requests. + */ + @Query("SELECT * FROM applicationPermission WHERE pkKey = :key AND type = :type AND kind IS NULL AND relay = '' LIMIT 1") + fun getPermissionAllKinds( + key: String, + type: String, + ): ApplicationPermissionsEntity? + @Query("SELECT * FROM applicationPermission WHERE pkKey = :key AND type = :type AND kind = :kind AND relay = :relay LIMIT 1") fun getPermissionForRelay( key: String, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/CachingApplicationDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/CachingApplicationDao.kt index 777fd9b6..e6de66cc 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/CachingApplicationDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/CachingApplicationDao.kt @@ -21,7 +21,7 @@ import androidx.paging.PagingSource class CachingApplicationDao( private val delegate: ApplicationDao, ) : ApplicationDao { - private enum class Method { SIGN_POLICY, PERM, PERM_KIND, PERM_RELAY, PERM_WILDCARD } + private enum class Method { SIGN_POLICY, PERM, PERM_KIND, PERM_ALL_KINDS, PERM_RELAY, PERM_WILDCARD } private data class Key( val method: Method, @@ -81,6 +81,14 @@ class CachingApplicationDao( return result } + override fun getPermissionAllKinds(key: String, type: String): ApplicationPermissionsEntity? { + val k = Key(Method.PERM_ALL_KINDS, key, type, null, null) + lookup(k)?.let { return it.permission } + val result = delegate.getPermissionAllKinds(key, type) + store(k, Value(null, result)) + return result + } + override fun getPermissionForRelay(key: String, type: String, kind: Int, relay: String): ApplicationPermissionsEntity? { val k = Key(Method.PERM_RELAY, key, type, kind, relay) lookup(k)?.let { return it.permission }