feat: add check active account before init client

This commit is contained in:
2024-02-05 13:36:10 +07:00
parent 2a58326cd1
commit 08fa7de01d
9 changed files with 85 additions and 76 deletions

1
src-tauri/Cargo.lock generated
View File

@@ -2859,6 +2859,7 @@ dependencies = [
"native_db", "native_db",
"native_model", "native_model",
"nostr-sdk", "nostr-sdk",
"once_cell",
"serde", "serde",
"serde_json", "serde_json",
"tauri", "tauri",

View File

@@ -40,6 +40,7 @@ webpage = { version = "2.0", features = ["serde"] }
keyring = "2" keyring = "2"
native_db = "0.5.3" native_db = "0.5.3"
native_model = "0.4.6" native_model = "0.4.6"
once_cell = "1.19.0"
[features] [features]
# by default Tauri runs in production mode # by default Tauri runs in production mode

View File

View File

@@ -1,59 +0,0 @@
-- create accounts table
CREATE TABLE
accounts (
id INTEGER NOT NULL PRIMARY KEY,
pubkey TEXT NOT NULL UNIQUE,
is_active INTEGER NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- create ndk cache users table
CREATE TABLE
ndk_users (
pubkey TEXT NOT NULL PRIMARY KEY,
profile TEXT,
createdAt NUMBER
);
-- create ndk cache events table
CREATE TABLE
ndk_events (
id TEXT NOT NULL PRIMARY KEY,
pubkey TEXT,
content TEXT,
kind NUMBER,
createdAt NUMBER,
relay TEXT,
event TEXT
);
-- create ndk cache eventtags table
CREATE TABLE
ndk_eventtags (
id TEXT NOT NULL PRIMARY KEY,
eventId TEXT,
tag TEXT,
value TEXT,
tagValue TEXT
);
-- create settings table
CREATE TABLE
settings (
id INTEGER NOT NULL PRIMARY KEY,
key TEXT NOT NULL,
value TEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- create columns table
CREATE TABLE
columns (
id INTEGER NOT NULL PRIMARY KEY,
account_id INTEGER NOT NULL,
kind INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (account_id) REFERENCES accounts (id)
);

29
src-tauri/src/db.rs Normal file
View File

@@ -0,0 +1,29 @@
use once_cell::sync::Lazy;
pub(crate) mod api {
use native_db::{native_db, InnerKeyValue};
use native_model::{native_model, Model};
use serde::{Deserialize, Serialize};
pub mod v1 {
use super::*;
#[derive(Serialize, Deserialize, Debug)]
#[native_model(id = 1, version = 2)]
#[native_db]
pub struct Account {
#[primary_key]
pub pubkey: String,
#[secondary_key]
status: String,
}
}
}
pub static DATABASE_BUILDER: Lazy<native_db::DatabaseBuilder> = Lazy::new(|| {
let mut builder = native_db::DatabaseBuilder::new();
builder
.define::<api::v1::Account>()
.expect("failed to define model Account v1");
builder
});

View File

@@ -4,15 +4,20 @@
)] )]
pub mod commands; pub mod commands;
pub mod db;
pub mod nostr; pub mod nostr;
use crate::db::api::v1::AccountKey;
use crate::db::DATABASE_BUILDER;
use db::api::v1::Account;
use keyring::Entry;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use std::sync::Arc; use std::sync::Arc;
use tauri::Manager; use tauri::Manager;
use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_autostart::MacosLauncher;
pub struct AppState { pub struct Nostr {
pub nostr: Arc<Client>, pub client: Arc<Client>,
} }
fn main() { fn main() {
@@ -21,6 +26,16 @@ fn main() {
.setup(|app| { .setup(|app| {
let handle = app.handle().clone(); let handle = app.handle().clone();
let config_dir = app.path().app_config_dir().unwrap(); let config_dir = app.path().app_config_dir().unwrap();
let db = DATABASE_BUILDER
.create(config_dir.join("app.db"))
.expect("failed to create app database");
// run db migrate
let rw = db
.rw_transaction()
.expect("failed to create rw migration transaction");
rw.migrate::<Account>().expect("failed to migrate Account");
rw.commit().expect("failed to commit migration");
tauri::async_runtime::spawn(async move { tauri::async_runtime::spawn(async move {
// Create database connection // Create database connection
@@ -31,8 +46,30 @@ fn main() {
// Create nostr connection // Create nostr connection
let client = ClientBuilder::default().database(nostr_db).build(); let client = ClientBuilder::default().database(nostr_db).build();
// get stored account
let r = db.r_transaction().expect("failed to create ro transaction");
let accounts: Vec<Account> = r
.scan()
.secondary(AccountKey::status)
.expect("failed to scan accounts")
.start_with("active")
.collect();
if let Some(account) = accounts.into_iter().nth(0) {
let entry = Entry::new("Lume", &account.pubkey).expect("failed to load secret");
if let Ok(key) = entry.get_password() {
let secret_key = SecretKey::from_bech32(key).unwrap();
let keys = Keys::new(secret_key);
let signer = ClientSigner::Keys(keys);
// update client's signer
client.set_signer(Some(signer)).await;
}
}
// Add some bootstrap relays // Add some bootstrap relays
// #TODO: Add option to user config bootstrap relay // #TODO: Pull bootstrap relays from user's settings
client client
.add_relay("wss://nostr.mutinywallet.com") .add_relay("wss://nostr.mutinywallet.com")
.await .await
@@ -46,8 +83,8 @@ fn main() {
client.connect().await; client.connect().await;
// Init global state // Init global state
handle.manage(AppState { handle.manage(Nostr {
nostr: client.into(), client: client.into(),
}) })
}); });

View File

@@ -1,11 +1,11 @@
use crate::AppState; use crate::Nostr;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use std::time::Duration; use std::time::Duration;
use tauri::State; use tauri::State;
#[tauri::command(async)] #[tauri::command(async)]
pub async fn get_event(id: String, app_state: State<'_, AppState>) -> Result<String, ()> { pub async fn get_event(id: String, nostr: State<'_, Nostr>) -> Result<String, ()> {
let client = &app_state.nostr; let client = &nostr.client;
let event_id = EventId::from_bech32(id).unwrap(); let event_id = EventId::from_bech32(id).unwrap();
let filter = Filter::new().id(event_id); let filter = Filter::new().id(event_id);

View File

@@ -1,4 +1,4 @@
use crate::AppState; use crate::Nostr;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use tauri::State; use tauri::State;
@@ -29,8 +29,8 @@ pub fn get_public_key(secret_key: SecretKey) -> Result<String, ()> {
} }
#[tauri::command] #[tauri::command]
pub async fn update_signer(key: String, app_state: State<'_, AppState>) -> Result<(), ()> { pub async fn update_signer(key: String, nostr: State<'_, Nostr>) -> Result<(), ()> {
let client = &app_state.nostr; let client = &nostr.client;
let secret_key = SecretKey::from_bech32(key).unwrap(); let secret_key = SecretKey::from_bech32(key).unwrap();
let keys = Keys::new(secret_key); let keys = Keys::new(secret_key);
let signer = ClientSigner::Keys(keys); let signer = ClientSigner::Keys(keys);
@@ -41,8 +41,8 @@ pub async fn update_signer(key: String, app_state: State<'_, AppState>) -> Resul
} }
#[tauri::command] #[tauri::command]
pub async fn verify_signer(app_state: State<'_, AppState>) -> Result<bool, ()> { pub async fn verify_signer(nostr: State<'_, Nostr>) -> Result<bool, ()> {
let client = &app_state.nostr; let client = &nostr.client;
let status = client.signer().await.is_ok(); let status = client.signer().await.is_ok();
Ok(status) Ok(status)

View File

@@ -1,11 +1,11 @@
use crate::AppState; use crate::Nostr;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use std::time::Duration; use std::time::Duration;
use tauri::State; use tauri::State;
#[tauri::command(async)] #[tauri::command(async)]
pub async fn get_metadata(npub: String, app_state: State<'_, AppState>) -> Result<Metadata, ()> { pub async fn get_metadata(npub: String, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
let client = &app_state.nostr; let client = &nostr.client;
let public_key = XOnlyPublicKey::from_bech32(npub).unwrap(); let public_key = XOnlyPublicKey::from_bech32(npub).unwrap();