|
@@ -4,20 +4,20 @@ use chrono::{DateTime, Utc};
|
|
use dashmap::DashMap;
|
|
use dashmap::DashMap;
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
use tauri_plugin_store::StoreBuilder;
|
|
use tauri_plugin_store::StoreBuilder;
|
|
-use tokio_util::sync::CancellationToken;
|
|
|
|
use tokio::sync::RwLock;
|
|
use tokio::sync::RwLock;
|
|
|
|
+use tokio_util::sync::CancellationToken;
|
|
|
|
|
|
use crate::error::AppError;
|
|
use crate::error::AppError;
|
|
|
|
|
|
/// Describes one registered app instance
|
|
/// Describes one registered app instance
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Registration {
|
|
pub struct Registration {
|
|
- pub registered_at: DateTime<Utc>,
|
|
|
|
|
|
+ pub registered_at: DateTime<Utc>,
|
|
|
|
|
|
- /// base16 (lowercase) encoded shared secret that the client
|
|
|
|
- /// and agent established during registration that is used
|
|
|
|
- /// to encrypt traffic between them
|
|
|
|
- pub shared_secret_b16: String
|
|
|
|
|
|
+ /// base16 (lowercase) encoded shared secret that the client
|
|
|
|
+ /// and agent established during registration that is used
|
|
|
|
+ /// to encrypt traffic between them
|
|
|
|
+ pub shared_secret_b16: String,
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Default)]
|
|
#[derive(Default)]
|
|
@@ -30,28 +30,26 @@ pub struct AppState {
|
|
|
|
|
|
/// Registrations against the agent, the key is the auth
|
|
/// Registrations against the agent, the key is the auth
|
|
/// token associated to the registration
|
|
/// token associated to the registration
|
|
- registrations: DashMap<String, Registration>
|
|
|
|
|
|
+ registrations: DashMap<String, Registration>,
|
|
}
|
|
}
|
|
|
|
|
|
impl AppState {
|
|
impl AppState {
|
|
-
|
|
|
|
pub fn new(app_handle: tauri::AppHandle) -> Self {
|
|
pub fn new(app_handle: tauri::AppHandle) -> Self {
|
|
- let mut store = StoreBuilder::new("app_data.bin")
|
|
|
|
- .build(app_handle);
|
|
|
|
|
|
+ let store = StoreBuilder::new(&app_handle, "app_data.bin").build();
|
|
|
|
|
|
let _ = store.load();
|
|
let _ = store.load();
|
|
|
|
|
|
// Try loading and parsing registrations from the store, if that failed,
|
|
// Try loading and parsing registrations from the store, if that failed,
|
|
// load the default list
|
|
// load the default list
|
|
- let registrations = store.get("registrations")
|
|
|
|
- .and_then(|val| serde_json::from_value(val.clone()).ok())
|
|
|
|
- .unwrap_or_else(|| DashMap::new());
|
|
|
|
-
|
|
|
|
|
|
+ let registrations = store
|
|
|
|
+ .get("registrations")
|
|
|
|
+ .and_then(|val| serde_json::from_value(val.clone()).ok())
|
|
|
|
+ .unwrap_or_else(|| DashMap::new());
|
|
|
|
|
|
Self {
|
|
Self {
|
|
active_registration_code: RwLock::new(None),
|
|
active_registration_code: RwLock::new(None),
|
|
cancellation_tokens: DashMap::new(),
|
|
cancellation_tokens: DashMap::new(),
|
|
- registrations
|
|
|
|
|
|
+ registrations,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -60,39 +58,41 @@ impl AppState {
|
|
/// reference, you shouldn't do it for registrations as `update_registrations`
|
|
/// reference, you shouldn't do it for registrations as `update_registrations`
|
|
/// performs save operation that needs to be done and should be used instead
|
|
/// performs save operation that needs to be done and should be used instead
|
|
pub fn get_registrations(&self) -> &DashMap<String, Registration> {
|
|
pub fn get_registrations(&self) -> &DashMap<String, Registration> {
|
|
- &self.registrations
|
|
|
|
|
|
+ &self.registrations
|
|
}
|
|
}
|
|
|
|
|
|
/// Provides you an opportunity to update the registrations list
|
|
/// Provides you an opportunity to update the registrations list
|
|
/// and also persists the data to the disk
|
|
/// and also persists the data to the disk
|
|
- pub fn update_registrations(
|
|
|
|
|
|
+ pub fn update_registrations(
|
|
&self,
|
|
&self,
|
|
app_handle: tauri::AppHandle,
|
|
app_handle: tauri::AppHandle,
|
|
- update_func: impl FnOnce(&DashMap<String, Registration>)
|
|
|
|
|
|
+ update_func: impl FnOnce(&DashMap<String, Registration>),
|
|
) -> Result<(), AppError> {
|
|
) -> Result<(), AppError> {
|
|
update_func(&self.registrations);
|
|
update_func(&self.registrations);
|
|
|
|
|
|
- let mut store = StoreBuilder::new("app_data.bin")
|
|
|
|
- .build(app_handle);
|
|
|
|
|
|
+ let store = StoreBuilder::new(&app_handle, "app_data.bin").build();
|
|
|
|
|
|
- let _ = store.load();
|
|
|
|
|
|
+ let _ = store.load()?;
|
|
|
|
|
|
- store.delete("registrations")
|
|
|
|
- .map_err(|_| AppError::RegistrationClearError)?;
|
|
|
|
|
|
+ let _ = store
|
|
|
|
+ .delete("registrations")
|
|
|
|
+ .then_some(())
|
|
|
|
+ .ok_or(AppError::RegistrationClearError)?;
|
|
|
|
|
|
- store.insert("registrations".into(), serde_json::to_value(self.registrations.clone()).unwrap())
|
|
|
|
- .map_err(|_| AppError::RegistrationInsertError)?;
|
|
|
|
|
|
+ let _ = store.set(
|
|
|
|
+ "registrations",
|
|
|
|
+ serde_json::to_value(self.registrations.clone()).unwrap(),
|
|
|
|
+ );
|
|
|
|
|
|
- store.save()
|
|
|
|
- .map_err(|_| AppError::RegistrationSaveError)?;
|
|
|
|
|
|
+ store.save().map_err(|_| AppError::RegistrationSaveError)?;
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn validate_registration(&self, registration: &str) -> bool {
|
|
pub async fn validate_registration(&self, registration: &str) -> bool {
|
|
match *self.active_registration_code.read().await {
|
|
match *self.active_registration_code.read().await {
|
|
- Some(ref code) => code == registration,
|
|
|
|
- None => false
|
|
|
|
|
|
+ Some(ref code) => code == registration,
|
|
|
|
+ None => false,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -105,50 +105,40 @@ impl AppState {
|
|
}
|
|
}
|
|
|
|
|
|
pub fn validate_access(&self, auth_key: &str) -> bool {
|
|
pub fn validate_access(&self, auth_key: &str) -> bool {
|
|
- self.registrations.get(auth_key).is_some()
|
|
|
|
|
|
+ self.registrations.get(auth_key).is_some()
|
|
}
|
|
}
|
|
|
|
|
|
pub fn validate_access_and_get_data<T>(
|
|
pub fn validate_access_and_get_data<T>(
|
|
- &self,
|
|
|
|
- auth_key: &str,
|
|
|
|
- nonce: &str,
|
|
|
|
- data: &Bytes
|
|
|
|
|
|
+ &self,
|
|
|
|
+ auth_key: &str,
|
|
|
|
+ nonce: &str,
|
|
|
|
+ data: &Bytes,
|
|
) -> Option<T>
|
|
) -> Option<T>
|
|
where
|
|
where
|
|
- T : DeserializeOwned
|
|
|
|
|
|
+ T: DeserializeOwned,
|
|
{
|
|
{
|
|
- if let Some(registration) = self.registrations.get(auth_key) {
|
|
|
|
- let key: [u8; 32] = base16::decode(®istration.shared_secret_b16)
|
|
|
|
- .ok()?
|
|
|
|
- [0..32]
|
|
|
|
- .try_into()
|
|
|
|
- .ok()?;
|
|
|
|
-
|
|
|
|
- let nonce: [u8; 12] = base16::decode(nonce)
|
|
|
|
- .ok()?
|
|
|
|
- [0..12]
|
|
|
|
- .try_into()
|
|
|
|
- .ok()?;
|
|
|
|
-
|
|
|
|
- let cipher = Aes256Gcm::new(&key.into());
|
|
|
|
-
|
|
|
|
- let data = data
|
|
|
|
- .iter()
|
|
|
|
- .cloned()
|
|
|
|
- .collect::<Vec<u8>>();
|
|
|
|
-
|
|
|
|
- let plain_data = cipher.decrypt(&nonce.into(), data.as_slice())
|
|
|
|
- .ok()?;
|
|
|
|
-
|
|
|
|
- serde_json::from_reader(plain_data.as_slice())
|
|
|
|
- .ok()
|
|
|
|
- } else {
|
|
|
|
- None
|
|
|
|
- }
|
|
|
|
|
|
+ if let Some(registration) = self.registrations.get(auth_key) {
|
|
|
|
+ let key: [u8; 32] = base16::decode(®istration.shared_secret_b16).ok()?[0..32]
|
|
|
|
+ .try_into()
|
|
|
|
+ .ok()?;
|
|
|
|
+
|
|
|
|
+ let nonce: [u8; 12] = base16::decode(nonce).ok()?[0..12].try_into().ok()?;
|
|
|
|
+
|
|
|
|
+ let cipher = Aes256Gcm::new(&key.into());
|
|
|
|
+
|
|
|
|
+ let data = data.iter().cloned().collect::<Vec<u8>>();
|
|
|
|
+
|
|
|
|
+ let plain_data = cipher.decrypt(&nonce.into(), data.as_slice()).ok()?;
|
|
|
|
+
|
|
|
|
+ serde_json::from_reader(plain_data.as_slice()).ok()
|
|
|
|
+ } else {
|
|
|
|
+ None
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
pub fn get_registration_info(&self, auth_key: &str) -> Option<Registration> {
|
|
pub fn get_registration_info(&self, auth_key: &str) -> Option<Registration> {
|
|
- self.registrations.get(auth_key)
|
|
|
|
- .map(|reference| reference.value().clone())
|
|
|
|
|
|
+ self.registrations
|
|
|
|
+ .get(auth_key)
|
|
|
|
+ .map(|reference| reference.value().clone())
|
|
}
|
|
}
|
|
}
|
|
}
|