creddy/src-tauri/src/state.rs

169 lines
5.6 KiB
Rust
Raw Normal View History

2022-12-19 16:20:46 -08:00
use std::collections::{HashMap, HashSet};
use std::time::Duration;
2023-05-02 15:24:35 -07:00
use tokio::{
sync::oneshot::Sender,
sync::RwLock,
time::sleep,
};
2023-04-28 14:33:04 -07:00
use sqlx::SqlitePool;
2022-12-03 21:47:09 -08:00
use tauri::async_runtime as runtime;
2022-12-19 16:20:46 -08:00
use tauri::Manager;
use crate::app::APP;
use crate::credentials::{
Session,
BaseCredentials,
SessionCredentials,
};
use crate::{config, config::AppConfig};
use crate::ipc::{self, Approval};
2022-12-20 16:11:49 -08:00
use crate::clientinfo::Client;
2022-11-28 16:16:33 -08:00
use crate::errors::*;
2023-04-28 14:33:04 -07:00
use crate::server::Server;
#[derive(Debug)]
pub struct AppState {
pub config: RwLock<AppConfig>,
2022-12-03 21:47:09 -08:00
pub session: RwLock<Session>,
pub request_count: RwLock<u64>,
pub open_requests: RwLock<HashMap<u64, Sender<ipc::Approval>>>,
2022-12-20 16:11:49 -08:00
pub bans: RwLock<std::collections::HashSet<Option<Client>>>,
2023-04-28 14:33:04 -07:00
server: RwLock<Server>,
pool: sqlx::SqlitePool,
}
impl AppState {
2023-04-29 10:01:45 -07:00
pub fn new(config: AppConfig, session: Session, server: Server, pool: SqlitePool) -> AppState {
AppState {
config: RwLock::new(config),
session: RwLock::new(session),
request_count: RwLock::new(0),
open_requests: RwLock::new(HashMap::new()),
bans: RwLock::new(HashSet::new()),
server: RwLock::new(server),
pool,
}
2022-12-02 22:59:13 -08:00
}
2023-04-28 14:33:04 -07:00
pub async fn new_creds(&self, base_creds: BaseCredentials, passphrase: &str) -> Result<(), UnlockError> {
let locked = base_creds.encrypt(passphrase);
2023-04-25 22:10:14 -07:00
// do this first so that if it fails we don't save bad credentials
self.new_session(base_creds).await?;
locked.save(&self.pool).await?;
2022-12-19 15:26:44 -08:00
2022-12-02 22:59:13 -08:00
Ok(())
}
2023-04-27 14:24:08 -07:00
pub async fn update_config(&self, new_config: AppConfig) -> Result<(), SetupError> {
2023-05-02 15:24:35 -07:00
let mut live_config = self.config.write().await;
if new_config.start_on_login != live_config.start_on_login {
config::set_auto_launch(new_config.start_on_login)?;
}
if new_config.listen_addr != live_config.listen_addr
|| new_config.listen_port != live_config.listen_port
2023-04-28 14:33:04 -07:00
{
2023-05-02 15:24:35 -07:00
let mut sv = self.server.write().await;
sv.rebind(new_config.listen_addr, new_config.listen_port).await?;
2023-04-28 14:33:04 -07:00
}
2023-04-27 14:24:08 -07:00
2023-04-28 14:33:04 -07:00
new_config.save(&self.pool).await?;
2023-04-27 14:24:08 -07:00
*live_config = new_config;
2023-04-26 15:49:08 -07:00
Ok(())
}
2023-05-02 15:24:35 -07:00
pub async fn register_request(&self, chan: Sender<ipc::Approval>) -> u64 {
let count = {
2023-05-02 15:24:35 -07:00
let mut c = self.request_count.write().await;
*c += 1;
c
};
2023-05-02 15:24:35 -07:00
let mut open_requests = self.open_requests.write().await;
2022-12-03 21:47:09 -08:00
open_requests.insert(*count, chan); // `count` is the request id
2022-11-28 16:16:33 -08:00
*count
}
2023-05-02 15:24:35 -07:00
pub async fn unregister_request(&self, id: u64) {
let mut open_requests = self.open_requests.write().await;
2022-12-20 16:11:49 -08:00
open_requests.remove(&id);
}
2023-05-02 15:24:35 -07:00
pub async fn req_count(&self) -> usize {
let open_requests = self.open_requests.read().await;
2022-12-21 16:04:12 -08:00
open_requests.len()
}
2023-05-02 11:33:18 -07:00
pub async fn send_response(&self, response: ipc::RequestResponse) -> Result<(), SendResponseError> {
if let Approval::Approved = response.approval {
let mut session = self.session.write().await;
session.renew_if_expired().await?;
}
2023-05-02 11:33:18 -07:00
2023-05-02 15:24:35 -07:00
let mut open_requests = self.open_requests.write().await;
2022-11-28 16:16:33 -08:00
let chan = open_requests
.remove(&response.id)
.ok_or(SendResponseError::NotFound)
?;
2022-11-28 16:16:33 -08:00
chan.send(response.approval)
.map_err(|_e| SendResponseError::Abandoned)
}
2023-05-02 15:24:35 -07:00
pub async fn add_ban(&self, client: Option<Client>) {
let mut bans = self.bans.write().await;
2022-12-20 16:11:49 -08:00
bans.insert(client.clone());
2022-12-19 16:20:46 -08:00
runtime::spawn(async move {
sleep(Duration::from_secs(5)).await;
let app = APP.get().unwrap();
2022-12-19 16:20:46 -08:00
let state = app.state::<AppState>();
2023-05-02 15:24:35 -07:00
let mut bans = state.bans.write().await;
2022-12-20 16:11:49 -08:00
bans.remove(&client);
2022-12-19 16:20:46 -08:00
});
}
2023-05-02 15:24:35 -07:00
pub async fn is_banned(&self, client: &Option<Client>) -> bool {
self.bans.read().await.contains(&client)
2022-12-19 16:20:46 -08:00
}
pub async fn unlock(&self, passphrase: &str) -> Result<(), UnlockError> {
let base_creds = match *self.session.read().await {
2023-05-02 15:24:35 -07:00
Session::Empty => {return Err(UnlockError::NoCredentials);},
Session::Unlocked{..} => {return Err(UnlockError::NotLocked);},
Session::Locked(ref locked) => locked.decrypt(passphrase)?,
};
// Read lock is dropped here, so this doesn't deadlock
self.new_session(base_creds).await?;
2022-12-19 15:26:44 -08:00
2022-12-03 21:47:09 -08:00
Ok(())
2022-11-29 16:13:09 -08:00
}
pub async fn serialize_base_creds(&self) -> Result<String, GetCredentialsError> {
let session = self.session.read().await;
match *session {
Session::Unlocked{ref base, ..} => Ok(serde_json::to_string(base).unwrap()),
Session::Locked(_) => Err(GetCredentialsError::Locked),
Session::Empty => Err(GetCredentialsError::Empty),
}
}
2023-05-02 15:24:35 -07:00
pub async fn serialize_session_creds(&self) -> Result<String, GetCredentialsError> {
let session = self.session.read().await;
2022-12-03 21:47:09 -08:00
match *session {
Session::Unlocked{ref session, ..} => Ok(serde_json::to_string(session).unwrap()),
2022-12-03 21:47:09 -08:00
Session::Locked(_) => Err(GetCredentialsError::Locked),
Session::Empty => Err(GetCredentialsError::Empty),
}
2022-11-28 16:16:33 -08:00
}
2022-12-19 15:26:44 -08:00
async fn new_session(&self, base: BaseCredentials) -> Result<(), GetSessionError> {
let session = SessionCredentials::from_base(&base).await?;
let mut app_session = self.session.write().await;
*app_session = Session::Unlocked {base, session};
Ok(())
2023-05-02 11:33:18 -07:00
}
}