Merge remote-tracking branch 'origin/nrobi144/desktop-phase1'
* origin/nrobi144/desktop-phase1: Fixes FilledFilter test moves keystore to commons to avoid unnecessary dependencies on Quartz Fixes missing tagsAll
This commit is contained in:
@@ -104,6 +104,9 @@ kotlin {
|
|||||||
// Desktop-specific Compose
|
// Desktop-specific Compose
|
||||||
implementation(compose.desktop.currentOs)
|
implementation(compose.desktop.currentOs)
|
||||||
implementation(compose.uiTooling)
|
implementation(compose.uiTooling)
|
||||||
|
|
||||||
|
// Secure key storage via OS keychain (macOS/Windows/Linux)
|
||||||
|
implementation(libs.java.keyring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +115,10 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
// Android-specific Compose tooling
|
// Android-specific Compose tooling
|
||||||
implementation(libs.androidx.ui.tooling.preview)
|
implementation(libs.androidx.ui.tooling.preview)
|
||||||
|
|
||||||
|
// Secure key storage via Android Keystore
|
||||||
|
implementation(libs.androidx.security.crypto.ktx)
|
||||||
|
implementation(libs.androidx.datastore.preferences)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip01Core.crypto
|
package com.vitorpamplona.amethyst.commons.keystorage
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.security.keystore.KeyGenParameterSpec
|
import android.security.keystore.KeyGenParameterSpec
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip01Core.crypto
|
package com.vitorpamplona.amethyst.commons.keystorage
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
+10
-1
@@ -276,6 +276,7 @@ class FilterBuilder {
|
|||||||
private var authors: List<String>? = null
|
private var authors: List<String>? = null
|
||||||
private var kinds: List<Int>? = null
|
private var kinds: List<Int>? = null
|
||||||
private var tags: MutableMap<String, List<String>>? = null
|
private var tags: MutableMap<String, List<String>>? = null
|
||||||
|
private var tagsAll: MutableMap<String, List<String>>? = null
|
||||||
private var since: Long? = null
|
private var since: Long? = null
|
||||||
private var until: Long? = null
|
private var until: Long? = null
|
||||||
private var limit: Int? = null
|
private var limit: Int? = null
|
||||||
@@ -313,6 +314,14 @@ class FilterBuilder {
|
|||||||
tags!![name] = values
|
tags!![name] = values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun tagAll(
|
||||||
|
name: String,
|
||||||
|
values: List<String>,
|
||||||
|
) {
|
||||||
|
if (tagsAll == null) tagsAll = mutableMapOf()
|
||||||
|
tagsAll!![name] = values
|
||||||
|
}
|
||||||
|
|
||||||
fun pTag(vararg pubKeys: String) {
|
fun pTag(vararg pubKeys: String) {
|
||||||
tag("p", pubKeys.toList())
|
tag("p", pubKeys.toList())
|
||||||
}
|
}
|
||||||
@@ -337,7 +346,7 @@ class FilterBuilder {
|
|||||||
this.search = search
|
this.search = search
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): Filter = Filter(ids, authors, kinds, tags, since, until, limit, search)
|
fun build(): Filter = Filter(ids, authors, kinds, tags, tagsAll, since, until, limit, search)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip01Core.crypto
|
package com.vitorpamplona.amethyst.commons.keystorage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Secure storage for private keys using platform-specific secure storage mechanisms.
|
* Secure storage for private keys using platform-specific secure storage mechanisms.
|
||||||
+9
-9
@@ -418,7 +418,7 @@ class FilterBuildersTest {
|
|||||||
fun testGlobalFeedScenario() {
|
fun testGlobalFeedScenario() {
|
||||||
val filter = FilterBuilders.textNotesGlobal(limit = 50)
|
val filter = FilterBuilders.textNotesGlobal(limit = 50)
|
||||||
|
|
||||||
assertTrue(filter.isFilledFilter())
|
assertTrue(!filter.isEmpty())
|
||||||
assertEquals(listOf(1), filter.kinds)
|
assertEquals(listOf(1), filter.kinds)
|
||||||
assertEquals(50, filter.limit)
|
assertEquals(50, filter.limit)
|
||||||
}
|
}
|
||||||
@@ -428,7 +428,7 @@ class FilterBuildersTest {
|
|||||||
val followedUsers = listOf(testPubKey, testPubKey2)
|
val followedUsers = listOf(testPubKey, testPubKey2)
|
||||||
val filter = FilterBuilders.textNotesFromAuthors(followedUsers, limit = 50)
|
val filter = FilterBuilders.textNotesFromAuthors(followedUsers, limit = 50)
|
||||||
|
|
||||||
assertTrue(filter.isFilledFilter())
|
assertTrue(!filter.isEmpty())
|
||||||
assertEquals(listOf(1), filter.kinds)
|
assertEquals(listOf(1), filter.kinds)
|
||||||
assertEquals(followedUsers, filter.authors)
|
assertEquals(followedUsers, filter.authors)
|
||||||
assertEquals(50, filter.limit)
|
assertEquals(50, filter.limit)
|
||||||
@@ -440,9 +440,9 @@ class FilterBuildersTest {
|
|||||||
val postsFilter = FilterBuilders.textNotesFromAuthors(listOf(testPubKey), limit = 50)
|
val postsFilter = FilterBuilders.textNotesFromAuthors(listOf(testPubKey), limit = 50)
|
||||||
val contactListFilter = FilterBuilders.contactList(testPubKey)
|
val contactListFilter = FilterBuilders.contactList(testPubKey)
|
||||||
|
|
||||||
assertTrue(metadataFilter.isFilledFilter())
|
assertTrue(!metadataFilter.isEmpty())
|
||||||
assertTrue(postsFilter.isFilledFilter())
|
assertTrue(!postsFilter.isEmpty())
|
||||||
assertTrue(contactListFilter.isFilledFilter())
|
assertTrue(!contactListFilter.isEmpty())
|
||||||
|
|
||||||
assertEquals(listOf(0), metadataFilter.kinds)
|
assertEquals(listOf(0), metadataFilter.kinds)
|
||||||
assertEquals(listOf(1), postsFilter.kinds)
|
assertEquals(listOf(1), postsFilter.kinds)
|
||||||
@@ -453,7 +453,7 @@ class FilterBuildersTest {
|
|||||||
fun testNotificationsScenario() {
|
fun testNotificationsScenario() {
|
||||||
val filter = FilterBuilders.notificationsForUser(testPubKey, limit = 100)
|
val filter = FilterBuilders.notificationsForUser(testPubKey, limit = 100)
|
||||||
|
|
||||||
assertTrue(filter.isFilledFilter())
|
assertTrue(!filter.isEmpty())
|
||||||
assertEquals(listOf(1, 7, 6, 16, 9735), filter.kinds)
|
assertEquals(listOf(1, 7, 6, 16, 9735), filter.kinds)
|
||||||
assertNotNull(filter.tags)
|
assertNotNull(filter.tags)
|
||||||
assertEquals(listOf(testPubKey), filter.tags!!["p"])
|
assertEquals(listOf(testPubKey), filter.tags!!["p"])
|
||||||
@@ -470,7 +470,7 @@ class FilterBuildersTest {
|
|||||||
limit(100)
|
limit(100)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(filter.isFilledFilter())
|
assertTrue(!filter.isEmpty())
|
||||||
assertEquals(listOf(1), filter.kinds)
|
assertEquals(listOf(1), filter.kinds)
|
||||||
assertNotNull(filter.tags)
|
assertNotNull(filter.tags)
|
||||||
assertEquals(listOf(testEventId), filter.tags!!["e"])
|
assertEquals(listOf(testEventId), filter.tags!!["e"])
|
||||||
@@ -485,7 +485,7 @@ class FilterBuildersTest {
|
|||||||
limit(50)
|
limit(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(filter.isFilledFilter())
|
assertTrue(!filter.isEmpty())
|
||||||
assertEquals(listOf(7), filter.kinds)
|
assertEquals(listOf(7), filter.kinds)
|
||||||
assertNotNull(filter.tags)
|
assertNotNull(filter.tags)
|
||||||
assertEquals(listOf(testEventId), filter.tags!!["e"])
|
assertEquals(listOf(testEventId), filter.tags!!["e"])
|
||||||
@@ -500,7 +500,7 @@ class FilterBuildersTest {
|
|||||||
limit(50)
|
limit(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(filter.isFilledFilter())
|
assertTrue(!filter.isEmpty())
|
||||||
assertEquals(listOf(1), filter.kinds)
|
assertEquals(listOf(1), filter.kinds)
|
||||||
assertNotNull(filter.tags)
|
assertNotNull(filter.tags)
|
||||||
assertEquals(listOf("bitcoin"), filter.tags!!["t"])
|
assertEquals(listOf("bitcoin"), filter.tags!!["t"])
|
||||||
|
|||||||
+2
-2
@@ -21,11 +21,11 @@
|
|||||||
package com.vitorpamplona.amethyst.commons.account
|
package com.vitorpamplona.amethyst.commons.account
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.vitorpamplona.amethyst.commons.keystorage.SecureKeyStorage
|
||||||
|
import com.vitorpamplona.amethyst.commons.keystorage.SecureStorageException
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
||||||
import com.vitorpamplona.quartz.nip01Core.crypto.SecureKeyStorage
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.crypto.SecureStorageException
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||||
import com.vitorpamplona.quartz.nip19Bech32.decodePrivateKeyAsHexOrNull
|
import com.vitorpamplona.quartz.nip19Bech32.decodePrivateKeyAsHexOrNull
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip01Core.crypto
|
package com.vitorpamplona.amethyst.commons.keystorage
|
||||||
|
|
||||||
import com.github.javakeyring.BackendNotSupportedException
|
import com.github.javakeyring.BackendNotSupportedException
|
||||||
import com.github.javakeyring.Keyring
|
import com.github.javakeyring.Keyring
|
||||||
@@ -166,9 +166,6 @@ kotlin {
|
|||||||
// LibSodium for ChaCha encryption (NIP-44)
|
// LibSodium for ChaCha encryption (NIP-44)
|
||||||
implementation (libs.lazysodium.java)
|
implementation (libs.lazysodium.java)
|
||||||
implementation (libs.jna)
|
implementation (libs.jna)
|
||||||
|
|
||||||
// Secure key storage via OS keychain (macOS/Windows/Linux)
|
|
||||||
implementation(libs.java.keyring)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,10 +188,6 @@ kotlin {
|
|||||||
// LibSodium for ChaCha encryption (NIP-44)
|
// LibSodium for ChaCha encryption (NIP-44)
|
||||||
implementation ("com.goterl:lazysodium-android:5.2.0@aar")
|
implementation ("com.goterl:lazysodium-android:5.2.0@aar")
|
||||||
implementation ("net.java.dev.jna:jna:5.18.1@aar")
|
implementation ("net.java.dev.jna:jna:5.18.1@aar")
|
||||||
|
|
||||||
// Secure key storage via Android Keystore
|
|
||||||
implementation(libs.androidx.security.crypto.ktx)
|
|
||||||
implementation(libs.androidx.datastore.preferences)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user