creddy/src-tauri/src/state.rs

117 lines
3.3 KiB
Rust
Raw Normal View History

2022-11-28 16:16:33 -08:00
use std::collections::HashMap;
use std::sync::RwLock;
use serde::{Serialize, Deserialize};
use tokio::sync::oneshot::Sender;
2022-12-02 22:59:13 -08:00
use sqlx::{SqlitePool, sqlite::SqlitePoolOptions, sqlite::SqliteConnectOptions};
use crate::ipc;
2022-11-28 16:16:33 -08:00
use crate::errors::*;
#[derive(Serialize, Deserialize)]
2022-11-28 16:16:33 -08:00
#[serde(rename_all = "PascalCase")]
#[serde(untagged)]
pub enum Credentials {
LongLived {
2022-11-28 16:16:33 -08:00
access_key_id: String,
secret_access_key: String,
},
ShortLived {
2022-11-28 16:16:33 -08:00
access_key_id: String,
secret_access_key: String,
token: String,
expiration: String,
},
}
#[derive(Serialize, Deserialize)]
2022-11-28 16:16:33 -08:00
pub enum SessionStatus {
Unlocked,
Locked,
Empty,
}
pub struct AppState {
2022-11-28 16:16:33 -08:00
status: RwLock<SessionStatus>,
credentials: RwLock<Option<Credentials>>,
request_count: RwLock<u64>,
2022-11-28 16:16:33 -08:00
open_requests: RwLock<HashMap<u64, Sender<ipc::Approval>>>,
2022-12-02 22:59:13 -08:00
pool: SqlitePool,
}
impl AppState {
2022-12-02 22:59:13 -08:00
pub fn new(status: SessionStatus, creds: Option<Credentials>) -> Result<Self, sqlx::error::Error> {
let conn_opts = SqliteConnectOptions::new()
.filename("creddy.db")
.create_if_missing(true);
let pool_opts = SqlitePoolOptions::new();
let pool: SqlitePool = tauri::async_runtime::block_on(pool_opts.connect_with(conn_opts))?;
tauri::async_runtime::block_on(sqlx::migrate!().run(&pool))?;
let state = AppState {
2022-11-28 16:16:33 -08:00
status: RwLock::new(status),
credentials: RwLock::new(creds),
request_count: RwLock::new(0),
open_requests: RwLock::new(HashMap::new()),
2022-12-02 22:59:13 -08:00
pool,
};
Ok(state)
}
async fn _load_from_db(&self) -> Result<(), sqlx::error::Error> {
let row: (i32,) = sqlx::query_as("SELECT COUNT(*) FROM credentials")
.fetch_one(&self.pool)
.await?;
let mut status = self.status.write().unwrap();
if row.0 > 0 {
*status = SessionStatus::Locked;
}
else {
*status = SessionStatus::Empty;
}
2022-12-02 22:59:13 -08:00
Ok(())
}
2022-11-28 16:16:33 -08:00
pub fn register_request(&self, chan: Sender<ipc::Approval>) -> u64 {
let count = {
2022-11-29 16:13:09 -08:00
let mut c = self.request_count.write().unwrap();
*c += 1;
c
};
2022-11-29 16:13:09 -08:00
let mut open_requests = self.open_requests.write().unwrap();
2022-11-28 16:16:33 -08:00
open_requests.insert(*count, chan);
*count
}
2022-11-28 16:16:33 -08:00
pub fn send_response(&self, response: ipc::RequestResponse) -> Result<(), SendResponseError> {
let mut open_requests = self.open_requests.write().unwrap();
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)
}
2022-11-29 16:13:09 -08:00
pub fn set_creds(&self, new_creds: Credentials) {
let mut current_creds = self.credentials.write().unwrap();
*current_creds = Some(new_creds);
let mut status = self.status.write().unwrap();
*status = SessionStatus::Unlocked;
}
2022-11-28 16:16:33 -08:00
pub fn get_creds_serialized(&self) -> String {
2022-11-29 16:13:09 -08:00
let creds_option = self.credentials.read().unwrap();
2022-11-28 16:16:33 -08:00
// fix this at some point
2022-11-29 16:13:09 -08:00
let creds = creds_option.as_ref().unwrap();
serde_json::to_string(creds).unwrap()
2022-11-28 16:16:33 -08:00
}
}