half working apple keychain support???
This commit is contained in:
parent
a19937058b
commit
46cb4b3462
11 changed files with 356 additions and 83 deletions
114
Cargo.lock
generated
114
Cargo.lock
generated
|
@ -171,7 +171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289"
|
||||
dependencies = [
|
||||
"android-properties",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cc",
|
||||
"cesu8",
|
||||
"jni",
|
||||
|
@ -579,7 +579,7 @@ version = "0.69.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
|
@ -677,9 +677,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -824,7 +824,7 @@ version = "0.12.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"log",
|
||||
"polling 3.7.0",
|
||||
"rustix 0.38.34",
|
||||
|
@ -974,7 +974,7 @@ dependencies = [
|
|||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
|
@ -989,7 +989,7 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7"
|
|||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics-types",
|
||||
"libc",
|
||||
"objc",
|
||||
|
@ -1072,10 +1072,20 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
name = "core-foundation"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
|
@ -1084,7 +1094,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
|
@ -1097,7 +1107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -1876,10 +1886,10 @@ version = "0.31.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cfg_aliases",
|
||||
"cgl",
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"dispatch",
|
||||
"glutin_egl_sys",
|
||||
"glutin_glx_sys",
|
||||
|
@ -1941,7 +1951,7 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"gpu-alloc-types",
|
||||
]
|
||||
|
||||
|
@ -1951,7 +1961,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1973,7 +1983,7 @@ version = "0.2.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"gpu-descriptor-types",
|
||||
"hashbrown",
|
||||
]
|
||||
|
@ -1984,7 +1994,7 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2013,7 +2023,7 @@ version = "0.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"com",
|
||||
"libc",
|
||||
"libloading 0.8.3",
|
||||
|
@ -2090,6 +2100,7 @@ dependencies = [
|
|||
"puffin",
|
||||
"puffin_http",
|
||||
"rand",
|
||||
"security-framework",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
|
@ -2481,7 +2492,7 @@ version = "0.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
@ -2492,7 +2503,7 @@ version = "0.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -2603,7 +2614,7 @@ version = "0.27.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"block",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
|
@ -2662,7 +2673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"codespan-reporting",
|
||||
"hexf-parse",
|
||||
"indexmap",
|
||||
|
@ -2681,7 +2692,7 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"jni-sys",
|
||||
"log",
|
||||
"ndk-sys",
|
||||
|
@ -3663,7 +3674,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -3715,7 +3726,7 @@ version = "0.38.34"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.13",
|
||||
|
@ -3859,6 +3870,29 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d0283c0a4a22a0f1b0e4edca251aa20b92fc96eaa09b84bec052f9415e9d71"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation 0.10.0",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
|
@ -4036,7 +4070,7 @@ version = "0.18.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"calloop",
|
||||
"calloop-wayland-source",
|
||||
"cursor-icon",
|
||||
|
@ -4110,7 +4144,7 @@ version = "0.3.0+sdk-1.3.268.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4860,7 +4894,7 @@ version = "0.31.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"rustix 0.38.34",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
|
@ -4872,7 +4906,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cursor-icon",
|
||||
"wayland-backend",
|
||||
]
|
||||
|
@ -4894,7 +4928,7 @@ version = "0.31.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-scanner",
|
||||
|
@ -4906,7 +4940,7 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
|
@ -4919,7 +4953,7 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
|
@ -4975,7 +5009,7 @@ version = "0.8.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b"
|
||||
dependencies = [
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"home",
|
||||
"jni",
|
||||
"log",
|
||||
|
@ -5033,7 +5067,7 @@ checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-vec",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cfg_aliases",
|
||||
"codespan-reporting",
|
||||
"indexmap",
|
||||
|
@ -5060,7 +5094,7 @@ dependencies = [
|
|||
"android_system_properties",
|
||||
"arrayvec",
|
||||
"ash",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cfg_aliases",
|
||||
"core-graphics-types",
|
||||
"glow",
|
||||
|
@ -5098,7 +5132,7 @@ version = "0.19.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"js-sys",
|
||||
"web-sys",
|
||||
]
|
||||
|
@ -5418,11 +5452,11 @@ dependencies = [
|
|||
"ahash",
|
||||
"android-activity",
|
||||
"atomic-waker",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"bytemuck",
|
||||
"calloop",
|
||||
"cfg_aliases",
|
||||
"core-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics",
|
||||
"cursor-icon",
|
||||
"icrate",
|
||||
|
@ -5540,7 +5574,7 @@ version = "0.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"dlib",
|
||||
"log",
|
||||
"once_cell",
|
||||
|
|
|
@ -28,3 +28,6 @@ rand = "0.8.5"
|
|||
nostr = { version = "0.32.1", features = ["std", "nip59"] }
|
||||
serde = "1.0.204"
|
||||
serde_json = "1.0.121"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
security-framework = "3.0.0"
|
||||
|
|
|
@ -37,10 +37,16 @@ impl AccountManager {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
fn get_platform_keystorage() -> KeyStorageType {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
KeyStorageType::Linux
|
||||
return KeyStorageType::Linux;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
return KeyStorageType::MacOS;
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
RelayNotConnected,
|
||||
SerdeJson(serde_json::Error),
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
fn from(value: serde_json::Error) -> Self {
|
||||
Self::SerdeJson(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![cfg(target_os = "linux")]
|
||||
use super::{Error, KeyStorage};
|
||||
use nostr::Keys;
|
||||
|
||||
|
|
122
src/keystorage/macos.rs
Normal file
122
src/keystorage/macos.rs
Normal file
|
@ -0,0 +1,122 @@
|
|||
#![cfg(target_os = "macos")]
|
||||
|
||||
use nostr::{Keys, PublicKey, SecretKey};
|
||||
use tracing::error;
|
||||
|
||||
use super::{Result, Error, KeyStorage};
|
||||
|
||||
use security_framework::item::{ItemClass, ItemSearchOptions, Limit, SearchResult};
|
||||
use security_framework::passwords::{delete_generic_password, set_generic_password};
|
||||
|
||||
pub struct MacOSKeyStorage {
|
||||
service_name: &'static str,
|
||||
}
|
||||
|
||||
impl MacOSKeyStorage {
|
||||
pub fn new(service_name: &'static str) -> Self {
|
||||
Self {
|
||||
service_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_key(&self, key: &Keys) -> Result<()> {
|
||||
match set_generic_password(self.service_name, &key.public_key().to_hex(), key.secret_key().unwrap().as_secret_bytes()) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err(Error::Addition(key.public_key().to_hex())),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pubkey_strings(&self) -> Vec<String> {
|
||||
let search_results = ItemSearchOptions::new()
|
||||
.class(ItemClass::generic_password())
|
||||
.service(self.service_name)
|
||||
.load_attributes(true)
|
||||
.limit(Limit::All)
|
||||
.search();
|
||||
|
||||
let mut accounts = Vec::new();
|
||||
|
||||
if let Ok(search_results) = search_results {
|
||||
for result in search_results {
|
||||
if let Some(map) = result.simplify_dict() {
|
||||
if let Some(val) = map.get("acct") {
|
||||
accounts.push(val.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
accounts
|
||||
}
|
||||
|
||||
fn get_pubkeys(&self) -> Vec<PublicKey> {
|
||||
self.get_pubkey_strings()
|
||||
.iter_mut()
|
||||
.filter_map(|pubkey_str| PublicKey::from_hex(pubkey_str.as_str()).ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_privkey_bytes_for(&self, account: &str) -> Option<Vec<u8>> {
|
||||
let search_result = ItemSearchOptions::new()
|
||||
.class(ItemClass::generic_password())
|
||||
.service(self.service_name)
|
||||
.load_data(true)
|
||||
.account(account)
|
||||
.search();
|
||||
|
||||
if let Ok(results) = search_result {
|
||||
if let Some(SearchResult::Data(vec)) = results.first() {
|
||||
return Some(vec.clone());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn get_secret_key_for_pubkey(&self, pubkey: &PublicKey) -> Option<SecretKey> {
|
||||
if let Some(bytes) = self.get_privkey_bytes_for(pubkey.to_hex().as_str()) {
|
||||
SecretKey::from_slice(bytes.as_slice()).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_all_keypairs(&self) -> Vec<Keys> {
|
||||
let mut keypairs: Vec<Keys> = Vec::new();
|
||||
for pubkey in self.get_pubkeys() {
|
||||
let maybe_secret = self.get_secret_key_for_pubkey(&pubkey);
|
||||
if let Some(secret) = maybe_secret {
|
||||
keypairs.push(Keys::new(secret));
|
||||
}
|
||||
}
|
||||
|
||||
keypairs
|
||||
}
|
||||
|
||||
fn delete_key(&self, pubkey: &PublicKey) -> Result<()> {
|
||||
match delete_generic_password(self.service_name, pubkey.to_hex().as_str()) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => {
|
||||
error!("delete key error {}", e);
|
||||
Err(Error::Removal(pubkey.to_hex()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyStorage for MacOSKeyStorage {
|
||||
fn get_keys(&self) -> Result<Vec<Keys>> {
|
||||
let mmt = self.get_all_keypairs();
|
||||
Ok(mmt)
|
||||
}
|
||||
|
||||
fn add_key(&self, key: &Keys) -> Result<()> {
|
||||
self.add_key(key)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_key(&self, key: &Keys) -> Result<()> {
|
||||
self.delete_key(&key.public_key())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,12 +1,27 @@
|
|||
use nostr::Keys;
|
||||
|
||||
mod linux;
|
||||
mod macos;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use linux::LinuxKeyStorage;
|
||||
#[cfg(target_os = "macos")]
|
||||
use macos::MacOSKeyStorage;
|
||||
|
||||
// for macos keychain service name
|
||||
#[cfg(debug_assertions)]
|
||||
const SERVICE_NAME: &'static str = "com.chakanysystems.hoot-dev";
|
||||
#[cfg(not(debug_assertions))]
|
||||
const SERVICE_NAME: &'static str = "com.chakanysystems.hoot";
|
||||
|
||||
pub enum Error {
|
||||
IOError(std::io::Error),
|
||||
Addition(String),
|
||||
Removal(String),
|
||||
}
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Error::IOError(value)
|
||||
|
@ -17,6 +32,8 @@ impl std::fmt::Debug for Error {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::IOError(err) => write!(f, "IOError: {:?}", err),
|
||||
Error::Addition(key) => write!(f, "Could not add key {}", key),
|
||||
Error::Removal(key) => write!(f, "Could not remove key {}", key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +42,8 @@ impl std::fmt::Display for Error {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::IOError(err) => write!(f, "IO error: {}", err),
|
||||
Error::Addition(key) => write!(f, "Could not add key {}", key),
|
||||
Error::Removal(key) => write!(f, "Could not remove key {}", key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,36 +52,44 @@ pub enum KeyStorageType {
|
|||
None,
|
||||
#[cfg(target_os = "linux")]
|
||||
Linux,
|
||||
#[cfg(target_os = "macos")]
|
||||
MacOS,
|
||||
}
|
||||
|
||||
pub trait KeyStorage {
|
||||
fn get_keys(&self) -> Result<Vec<Keys>, Error>;
|
||||
fn add_key(&self, key: &Keys) -> Result<(), Error>;
|
||||
fn remove_key(&self, key: &Keys) -> Result<(), Error>;
|
||||
fn get_keys(&self) -> Result<Vec<Keys>>;
|
||||
fn add_key(&self, key: &Keys) -> Result<()>;
|
||||
fn remove_key(&self, key: &Keys) -> Result<()>;
|
||||
}
|
||||
|
||||
impl KeyStorage for KeyStorageType {
|
||||
fn add_key(&self, key: &Keys) -> Result<(), Error> {
|
||||
fn add_key(&self, key: &Keys) -> Result<()> {
|
||||
match self {
|
||||
Self::None => Ok(()),
|
||||
#[cfg(target_os = "linux")]
|
||||
Self::Linux => LinuxKeyStorage::new().add_key(key),
|
||||
#[cfg(target_os = "macos")]
|
||||
Self::MacOS => MacOSKeyStorage::new(SERVICE_NAME).add_key(key),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_keys(&self) -> Result<Vec<Keys>, Error> {
|
||||
fn get_keys(&self) -> Result<Vec<Keys>> {
|
||||
match self {
|
||||
Self::None => Ok(Vec::new()),
|
||||
#[cfg(target_os = "linux")]
|
||||
Self::Linux => LinuxKeyStorage::new().get_keys(),
|
||||
#[cfg(target_os = "macos")]
|
||||
Self::MacOS => MacOSKeyStorage::new(SERVICE_NAME).get_keys(),
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_key(&self, key: &Keys) -> Result<(), Error> {
|
||||
fn remove_key(&self, key: &Keys) -> Result<()> {
|
||||
match self {
|
||||
Self::None => Ok(()),
|
||||
#[cfg(target_os = "linux")]
|
||||
Self::Linux => LinuxKeyStorage::new().remove_key(key),
|
||||
#[cfg(target_os = "macos")]
|
||||
Self::MacOS => MacOSKeyStorage::new(SERVICE_NAME).remove_key(key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -104,10 +104,25 @@ fn update_app(app: &mut Hoot, ctx: &egui::Context) {
|
|||
Ok(..) => {}
|
||||
Err(v) => error!("something went wrong trying to load keys: {}", v),
|
||||
}
|
||||
app.relays
|
||||
let _ = app.relays
|
||||
.add_url("wss://relay.damus.io".to_string(), wake_up.clone());
|
||||
app.relays
|
||||
let _ = app.relays
|
||||
.add_url("wss://relay-dev.hoot.sh".to_string(), wake_up);
|
||||
|
||||
if app.account_manager.loaded_keys.len() > 0 {
|
||||
let mut pks: Vec<nostr::PublicKey> = Vec::new();
|
||||
|
||||
for keys in app.account_manager.loaded_keys.clone() {
|
||||
pks.push(keys.public_key());
|
||||
}
|
||||
|
||||
let mut gw_sub = relay::Subscription::default();
|
||||
gw_sub.filter(nostr::Filter::new().authors(pks));
|
||||
|
||||
// TODO: fix error handling
|
||||
let _ = app.relays.add_subscription(gw_sub);
|
||||
}
|
||||
|
||||
app.status = HootStatus::Ready;
|
||||
info!("Hoot Ready");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use tracing::{error, info, debug};
|
||||
use ewebsock::{WsEvent, WsMessage};
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
|
||||
mod pool;
|
||||
|
@ -52,22 +51,22 @@ impl Relay {
|
|||
if self.status != RelayStatus::Connected {
|
||||
return Err(Error::RelayNotConnected);
|
||||
}
|
||||
debug!("sending message to {}: {:?}", self.url, message);
|
||||
|
||||
self.writer.send(message);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn try_recv(&mut self) -> Option<String> {
|
||||
pub fn try_recv(&mut self) -> Option<WsEvent> {
|
||||
if let Some(event) = self.reader.try_recv() {
|
||||
use WsEvent::*;
|
||||
match event {
|
||||
Message(message) => {
|
||||
return self.handle_message(message);
|
||||
Message(_) => {
|
||||
}
|
||||
Opened => {
|
||||
self.status = RelayStatus::Connected;
|
||||
}
|
||||
Error(error) => {
|
||||
Error(ref error) => {
|
||||
error!("error in websocket connection to {}: {}", self.url, error);
|
||||
}
|
||||
Closed => {
|
||||
|
@ -75,34 +74,13 @@ impl Relay {
|
|||
self.status = RelayStatus::Disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
return Some(event);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_message(&mut self, message: WsMessage) -> Option<String> {
|
||||
use WsMessage::*;
|
||||
match message {
|
||||
Text(txt) => {
|
||||
return Some(txt);
|
||||
}
|
||||
Binary(..) => {
|
||||
error!("recived binary messsage, your move semisol");
|
||||
}
|
||||
Ping(d) => {
|
||||
let pong_msg = WsMessage::Pong(d);
|
||||
match self.send(pong_msg) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("error when sending websocket message {:?}", e),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// who cares
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn ping(&mut self) {
|
||||
let ping_msg = WsMessage::Ping(Vec::new());
|
||||
|
|
|
@ -1,21 +1,46 @@
|
|||
use crate::error::Result;
|
||||
use crate::relay::Subscription;
|
||||
use crate::relay::message::ClientMessage;
|
||||
use crate::relay::{Relay, RelayStatus};
|
||||
use ewebsock::{WsEvent, WsMessage};
|
||||
use std::collections::HashMap;
|
||||
use tracing::error;
|
||||
|
||||
pub struct RelayPool {
|
||||
pub relays: HashMap<String, Relay>,
|
||||
pub subscriptions: HashMap<String, Subscription>,
|
||||
}
|
||||
|
||||
impl RelayPool {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
relays: HashMap::new(),
|
||||
subscriptions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_url(&mut self, url: String, wake_up: impl Fn() + Send + Sync + 'static) {
|
||||
pub fn add_subscription(&mut self, sub: Subscription) -> Result<()> {
|
||||
{
|
||||
let cloned_sub = sub.clone();
|
||||
self.subscriptions.insert(cloned_sub.id.clone(), cloned_sub);
|
||||
}
|
||||
|
||||
let client_message = ClientMessage::Req {
|
||||
subscription_id: sub.id,
|
||||
filters: sub.filters,
|
||||
};
|
||||
|
||||
let payload = serde_json::to_string(&client_message)?;
|
||||
self.send(ewebsock::WsMessage::Text(payload))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_url(&mut self, url: String, wake_up: impl Fn() + Send + Sync + 'static) -> Result<()> {
|
||||
let relay = Relay::new_with_wakeup(url.clone(), wake_up);
|
||||
self.relays.insert(url, relay);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_url(&mut self, url: &str) -> Option<Relay> {
|
||||
|
@ -24,13 +49,66 @@ impl RelayPool {
|
|||
|
||||
pub fn try_recv(&mut self) -> Option<String> {
|
||||
for relay in self.relays.values_mut() {
|
||||
if let Some(message) = relay.try_recv() {
|
||||
return Some(message);
|
||||
if let Some(event) = relay.try_recv() {
|
||||
use WsEvent::*;
|
||||
match event {
|
||||
Message(message) => {
|
||||
return self.handle_message(message);
|
||||
}
|
||||
Opened => {
|
||||
for sub in self.subscriptions.clone() {
|
||||
let client_message = ClientMessage::Req {
|
||||
subscription_id: sub.1.id,
|
||||
filters: sub.1.filters,
|
||||
};
|
||||
|
||||
let payload = match serde_json::to_string(&client_message) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
error!("could not turn subscription into json: {}", e);
|
||||
continue;
|
||||
},
|
||||
};
|
||||
|
||||
match relay.send(ewebsock::WsMessage::Text(payload)) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!("could not send subscription to {}: {:?}", relay.url, e),
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// we only want to know when the connection opens
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_message(&mut self, message: WsMessage) -> Option<String> {
|
||||
use WsMessage::*;
|
||||
match message {
|
||||
Text(txt) => {
|
||||
return Some(txt);
|
||||
}
|
||||
Binary(..) => {
|
||||
error!("recived binary messsage, your move semisol");
|
||||
}
|
||||
Ping(d) => {
|
||||
let pong_msg = WsMessage::Pong(d);
|
||||
match self.send(pong_msg) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("error when sending websocket message {:?}", e),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// who cares
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn send(&mut self, message: ewebsock::WsMessage) -> Result<()> {
|
||||
for relay in self.relays.values_mut() {
|
||||
if relay.status == RelayStatus::Connected {
|
||||
|
|
|
@ -23,7 +23,9 @@ impl Subscription {
|
|||
Self { id, filters }
|
||||
}
|
||||
|
||||
pub fn filter(&mut self, filter: Filter) {
|
||||
self.filters.push(filter)
|
||||
pub fn filter(&mut self, filter: Filter) -> &mut Self {
|
||||
self.filters.push(filter);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue