update
This commit is contained in:
@@ -18,7 +18,7 @@ use nostr_sdk::prelude::*;
|
|||||||
use person::Directory;
|
use person::Directory;
|
||||||
use settings::AppSettings;
|
use settings::AppSettings;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use state::{Announcement, CLIENT_NAME, NostrRegistry, UniversalSigner};
|
use state::{Announcement, NostrRegistry, UniversalSigner, credentials};
|
||||||
use ui::Avatar;
|
use ui::Avatar;
|
||||||
|
|
||||||
const IDENTIFIER: &str = "coop:device";
|
const IDENTIFIER: &str = "coop:device";
|
||||||
@@ -840,10 +840,10 @@ fn authorization_code(public_key: &PublicKey) -> SharedString {
|
|||||||
|
|
||||||
/// Get or create new app keys (async, returns a task)
|
/// Get or create new app keys (async, returns a task)
|
||||||
fn get_or_init_app_keys(cx: &App) -> Task<Result<Keys, Error>> {
|
fn get_or_init_app_keys(cx: &App) -> Task<Result<Keys, Error>> {
|
||||||
let read = cx.read_credentials(CLIENT_NAME);
|
let read = credentials::read_app_keys(cx);
|
||||||
|
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
if let Ok(Some((_, secret))) = read.await
|
if let Ok(Some(secret)) = read.await
|
||||||
&& let Ok(keys) = SecretKey::from_slice(&secret).map(Keys::new)
|
&& let Ok(keys) = SecretKey::from_slice(&secret).map(Keys::new)
|
||||||
{
|
{
|
||||||
return Ok(keys);
|
return Ok(keys);
|
||||||
@@ -851,14 +851,13 @@ fn get_or_init_app_keys(cx: &App) -> Task<Result<Keys, Error>> {
|
|||||||
|
|
||||||
// No stored keys found or invalid — generate new ones
|
// No stored keys found or invalid — generate new ones
|
||||||
let keys = Keys::generate();
|
let keys = Keys::generate();
|
||||||
let user = keys.public_key().to_hex();
|
|
||||||
let secret = keys.secret_key().to_secret_bytes();
|
let secret = keys.secret_key().to_secret_bytes();
|
||||||
|
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
let write = cx.write_credentials(CLIENT_NAME, &user, &secret);
|
let write = credentials::write_app_keys(cx, &secret);
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
if let Err(e) = write.await {
|
if let Err(e) = write.await {
|
||||||
log::error!("Keyring not available or panic: {e}")
|
log::error!("Failed to persist app keys: {e}")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use common::web_store;
|
use common::web_store;
|
||||||
use gpui::{App, Task};
|
use gpui::{App, AppContext as _, Task};
|
||||||
|
|
||||||
use crate::USER_KEYRING;
|
use crate::USER_KEYRING;
|
||||||
|
|
||||||
|
/// The storage key for the NIP-4e app keys
|
||||||
|
const APP_KEYS_KEY: &str = "coop/nip4e/app-keys";
|
||||||
|
|
||||||
/// Read the stored credential as `(username, secret)`
|
/// Read the stored credential as `(username, secret)`
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub(crate) fn read(cx: &App) -> Task<Result<Option<(String, Vec<u8>)>>> {
|
pub(crate) fn read(cx: &App) -> Task<Result<Option<(String, Vec<u8>)>>> {
|
||||||
@@ -49,3 +52,54 @@ pub(crate) fn delete(cx: &App) -> Task<Result<()>> {
|
|||||||
Task::ready(web_store::remove(USER_KEYRING))
|
Task::ready(web_store::remove(USER_KEYRING))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read named bytes from the platform keyring,
|
||||||
|
/// falling back to browser storage on web where no keyring exists
|
||||||
|
fn read_named(cx: &App, key: &str) -> Task<Result<Option<Vec<u8>>>> {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
let key = key.to_owned();
|
||||||
|
let read = cx.read_credentials(&key);
|
||||||
|
cx.background_spawn(async move { Ok(read.await?.map(|(_, secret)| secret)) })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
let _ = cx;
|
||||||
|
let stored = web_store::get(key).map(|content| content.map(|s| s.into_bytes()));
|
||||||
|
Task::ready(stored)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write named bytes to the platform keyring,
|
||||||
|
/// falling back to browser storage on web where no keyring exists
|
||||||
|
fn write_named(cx: &App, key: &str, secret: &[u8]) -> Task<Result<()>> {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
let key = key.to_owned();
|
||||||
|
let secret = secret.to_vec();
|
||||||
|
let write = cx.write_credentials(&key, "", &secret);
|
||||||
|
cx.background_spawn(write)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
let _ = cx;
|
||||||
|
let content = match std::str::from_utf8(secret) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(e) => return Task::ready(Err(anyhow::anyhow!("secret is not UTF-8: {e}"))),
|
||||||
|
};
|
||||||
|
|
||||||
|
Task::ready(web_store::set(key, content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load the NIP-4e app keys from storage, as raw secret bytes
|
||||||
|
pub fn read_app_keys(cx: &App) -> Task<Result<Option<Vec<u8>>>> {
|
||||||
|
read_named(cx, APP_KEYS_KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Persist the NIP-4e app keys, as raw secret bytes
|
||||||
|
pub fn write_app_keys(cx: &App, secret: &[u8]) -> Task<Result<()>> {
|
||||||
|
write_named(cx, APP_KEYS_KEY, secret)
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use nostr_sdk::prelude::*;
|
|||||||
|
|
||||||
mod blossom;
|
mod blossom;
|
||||||
mod constants;
|
mod constants;
|
||||||
mod credentials;
|
pub mod credentials;
|
||||||
mod file;
|
mod file;
|
||||||
mod nip05;
|
mod nip05;
|
||||||
mod nip4e;
|
mod nip4e;
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ impl Render for DragPanelPreview {
|
|||||||
.cursor_grab()
|
.cursor_grab()
|
||||||
.p_1()
|
.p_1()
|
||||||
.whitespace_nowrap()
|
.whitespace_nowrap()
|
||||||
|
.font_family(cx.theme().font_family.clone())
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.rounded(cx.theme().radius_lg)
|
.rounded(cx.theme().radius_lg)
|
||||||
|
|||||||
Reference in New Issue
Block a user