[Fix] Stability
This commit is contained in:
parent
84a56678e0
commit
cf9607b15e
5 changed files with 55 additions and 54 deletions
|
|
@ -31,4 +31,3 @@ uuid = { version = "1.24.0", features = ["v4", "v7"] }
|
|||
thiserror = "2.0.19"
|
||||
serde = { version = "1.0.229", features = ["derive"] }
|
||||
serde_json = "1.0.151"
|
||||
zeroize = "1.9"
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@ pub async fn register_complete_iota(id: IotaId, public_key: PublicKeyBundle) ->
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn change_iota_key(id: IotaId, key: PublicKeyBundle) -> Result<()> {
|
||||
sqlx::query("UPDATE iotas SET public_key = ? WHERE id = ?")
|
||||
.bind(key.try_as_bytes()?)
|
||||
.bind(id.0)
|
||||
.execute(&pool().await?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
pub async fn delete_iota(id: IotaId) -> Result<()> {
|
||||
sqlx::query("DELETE FROM iotas WHERE id = ?")
|
||||
.bind(id.0)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::error::{IdentityError, Result};
|
||||
use mtp::crypto::{Keyring, PublicKeyBundle};
|
||||
use mtp::files::{
|
||||
FileError, load_keyring, load_public_key_bundle, save_keyring, save_public_key_bundle,
|
||||
FileError, load_keyring_raw, load_public_key_bundle, save_keyring_raw,
|
||||
save_public_key_bundle,
|
||||
};
|
||||
use std::{
|
||||
fs,
|
||||
|
|
@ -22,25 +23,20 @@ pub struct OmegaIdentity {
|
|||
static PUBLIC_BUNDLE_TEMP_COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
impl OmegaIdentity {
|
||||
pub fn load_or_create(passphrase: &[u8]) -> Result<Self> {
|
||||
Self::load_or_create_at(
|
||||
Path::new(KEYRING_PATH),
|
||||
Path::new(PUBLIC_KEY_PATH),
|
||||
passphrase,
|
||||
)
|
||||
pub fn load_or_create() -> Result<Self> {
|
||||
Self::load_or_create_at(Path::new(KEYRING_PATH), Path::new(PUBLIC_KEY_PATH))
|
||||
}
|
||||
|
||||
pub(crate) fn load_or_create_at(
|
||||
keyring_path: impl AsRef<Path>,
|
||||
public_key_path: impl AsRef<Path>,
|
||||
passphrase: &[u8],
|
||||
) -> Result<Self> {
|
||||
let keyring_path = keyring_path.as_ref();
|
||||
let public_key_path = public_key_path.as_ref();
|
||||
let keyring = match load_keyring(keyring_path, passphrase) {
|
||||
let keyring = match load_keyring_raw(keyring_path) {
|
||||
Ok(keyring) => keyring,
|
||||
Err(FileError::Io(error)) if error.kind() == std::io::ErrorKind::NotFound => {
|
||||
return Self::create_at(keyring_path, public_key_path, passphrase);
|
||||
return Self::create_at(keyring_path, public_key_path);
|
||||
}
|
||||
Err(error) => {
|
||||
return Err(IdentityError::Storage {
|
||||
|
|
@ -72,9 +68,9 @@ impl OmegaIdentity {
|
|||
Ok(identity)
|
||||
}
|
||||
|
||||
fn create_at(keyring_path: &Path, public_key_path: &Path, passphrase: &[u8]) -> Result<Self> {
|
||||
fn create_at(keyring_path: &Path, public_key_path: &Path) -> Result<Self> {
|
||||
let keyring = Keyring::generate();
|
||||
save_keyring(&keyring, keyring_path, passphrase).map_err(|error| {
|
||||
save_keyring_raw(&keyring, keyring_path).map_err(|error| {
|
||||
IdentityError::Storage {
|
||||
path: keyring_path.to_path_buf(),
|
||||
source: error,
|
||||
|
|
@ -188,9 +184,7 @@ mod tests {
|
|||
let directory = test_directory();
|
||||
let keyring_path = directory.join("omega.mk");
|
||||
let public_key_path = directory.join("omega.mpkb");
|
||||
let passphrase = b"test-passphrase";
|
||||
|
||||
let first = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase)
|
||||
let first = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("create identity");
|
||||
let first_bundle = first.public_key_bundle().try_as_bytes().expect("bundle");
|
||||
|
||||
|
|
@ -199,8 +193,7 @@ mod tests {
|
|||
assert_eq!(&keyring_bytes[..4], b"MTMK");
|
||||
assert_eq!(&bundle_bytes[..4], b"MPKB");
|
||||
|
||||
let restarted =
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase)
|
||||
let restarted = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("reload identity");
|
||||
assert_eq!(
|
||||
restarted
|
||||
|
|
@ -227,8 +220,7 @@ mod tests {
|
|||
let public_key_path = directory.join("omega.mpkb");
|
||||
fs::write(&keyring_path, b"not-a-keyring").expect("write invalid keyring");
|
||||
|
||||
let result =
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, b"test-passphrase");
|
||||
let result = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path);
|
||||
assert!(result.is_err());
|
||||
assert!(!public_key_path.exists());
|
||||
|
||||
|
|
@ -240,15 +232,12 @@ mod tests {
|
|||
let directory = test_directory();
|
||||
let keyring_path = directory.join("omega.mk");
|
||||
let public_key_path = directory.join("omega.mpkb");
|
||||
let passphrase = b"test-passphrase";
|
||||
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase)
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("create identity");
|
||||
let original_keyring = fs::read(&keyring_path).expect("read keyring");
|
||||
fs::remove_file(&public_key_path).expect("remove bundle");
|
||||
|
||||
let repaired =
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase)
|
||||
let repaired = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("repair bundle");
|
||||
|
||||
assert_eq!(
|
||||
|
|
@ -271,16 +260,14 @@ mod tests {
|
|||
let directory = test_directory();
|
||||
let keyring_path = directory.join("omega.mk");
|
||||
let public_key_path = directory.join("omega.mpkb");
|
||||
let passphrase = b"test-passphrase";
|
||||
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase)
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("create identity");
|
||||
let other_keyring = Keyring::generate();
|
||||
save_public_key_bundle(&other_keyring.public_key_bundle(), &public_key_path)
|
||||
.expect("save mismatched bundle");
|
||||
|
||||
assert!(matches!(
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase),
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path),
|
||||
Err(crate::OmegaError::Identity(
|
||||
IdentityError::PublicBundleMismatch { .. }
|
||||
))
|
||||
|
|
@ -290,24 +277,28 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_passphrase_does_not_replace_existing_keyring() {
|
||||
fn existing_raw_keyring_is_reloaded_without_a_passphrase() {
|
||||
let directory = test_directory();
|
||||
let keyring_path = directory.join("omega.mk");
|
||||
let public_key_path = directory.join("omega.mpkb");
|
||||
let passphrase = b"test-passphrase";
|
||||
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, passphrase)
|
||||
let first = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("create identity");
|
||||
let original_keyring = fs::read(&keyring_path).expect("read keyring");
|
||||
|
||||
assert!(
|
||||
OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path, b"wrong-passphrase")
|
||||
.is_err()
|
||||
);
|
||||
let reloaded = OmegaIdentity::load_or_create_at(&keyring_path, &public_key_path)
|
||||
.expect("reload identity");
|
||||
assert_eq!(
|
||||
fs::read(&keyring_path).expect("read keyring"),
|
||||
original_keyring
|
||||
);
|
||||
assert_eq!(
|
||||
reloaded
|
||||
.public_key_bundle()
|
||||
.try_as_bytes()
|
||||
.expect("bundle"),
|
||||
first.public_key_bundle().try_as_bytes().expect("bundle")
|
||||
);
|
||||
|
||||
fs::remove_dir_all(directory).expect("remove test directory");
|
||||
}
|
||||
|
|
|
|||
16
src/main.rs
16
src/main.rs
|
|
@ -25,7 +25,6 @@ use std::env;
|
|||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use tokio::time::interval;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
|
@ -38,18 +37,6 @@ async fn main() {
|
|||
log_in!("Incoming messages");
|
||||
log_out!("Outgoing messages");
|
||||
|
||||
let identity_secret = match env::var("OMEGA_IDENTITY_SECRET") {
|
||||
Ok(secret) if !secret.is_empty() => secret,
|
||||
Ok(_) => {
|
||||
log!("[FATAL] OMEGA_IDENTITY_SECRET must not be empty");
|
||||
return;
|
||||
}
|
||||
Err(error) => {
|
||||
log!("[FATAL] Unable to load OMEGA_IDENTITY_SECRET: {}", error);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let identity_secret = Zeroizing::new(identity_secret);
|
||||
let config = match OmegaConfig::from_env() {
|
||||
Ok(config) => config,
|
||||
Err(error) => {
|
||||
|
|
@ -61,14 +48,13 @@ async fn main() {
|
|||
log!("[FATAL] Omega rate-limit configuration was initialized more than once");
|
||||
return;
|
||||
}
|
||||
let identity = match identity::OmegaIdentity::load_or_create(identity_secret.as_bytes()) {
|
||||
let identity = match identity::OmegaIdentity::load_or_create() {
|
||||
Ok(identity) => identity,
|
||||
Err(error) => {
|
||||
log!("[FATAL] Omega identity initialization failed: {}", error);
|
||||
return;
|
||||
}
|
||||
};
|
||||
drop(identity_secret);
|
||||
let state = OmegaState::new(identity, config);
|
||||
|
||||
log!("Started");
|
||||
|
|
|
|||
|
|
@ -764,8 +764,9 @@ pub async fn start(port: u16, state: Arc<OmegaState>) -> Result<(), Box<dyn std:
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{DispatchClass, OmikronConnection};
|
||||
use super::{DispatchClass, OmikronConnection, parse_bind_address};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue};
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
#[test]
|
||||
fn relay_dispatch_is_not_on_the_ordered_state_lane() {
|
||||
|
|
@ -776,6 +777,14 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_configured_bind_address() {
|
||||
assert_eq!(
|
||||
parse_bind_address(Some("10.200.2.0")),
|
||||
Ok(IpAddr::V4(Ipv4Addr::new(10, 200, 2, 0)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn presence_lifecycle_dispatch_is_ordered() {
|
||||
let value = CommunicationValue::new(CommunicationType::UserConnected);
|
||||
|
|
@ -806,4 +815,12 @@ mod tests {
|
|||
&CommunicationValue::new(CommunicationType::GetUserData).with_id(1)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn defaults_bind_address_to_all_interfaces() {
|
||||
assert_eq!(
|
||||
parse_bind_address(None),
|
||||
Ok(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue