mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-02-10 00:43:09 +00:00
chore: refactor create session
This commit is contained in:
parent
7e1a4a6a79
commit
c240450fb7
@ -50,17 +50,17 @@ impl RatchetStorage {
|
||||
/// Opens an existing encrypted database file.
|
||||
pub fn new(path: &str, key: &str) -> Result<Self, StorageError> {
|
||||
let db = SqliteDb::sqlcipher(path.to_string(), key.to_string())?;
|
||||
Self::new_internal(db)
|
||||
Self::run_migration(db)
|
||||
}
|
||||
|
||||
/// Creates an in-memory storage (useful for testing).
|
||||
pub fn in_memory() -> Result<Self, StorageError> {
|
||||
let db = SqliteDb::in_memory()?;
|
||||
Self::new_internal(db)
|
||||
Self::run_migration(db)
|
||||
}
|
||||
|
||||
/// Creates a new ratchet storage with the given database.
|
||||
fn new_internal(db: SqliteDb) -> Result<Self, StorageError> {
|
||||
fn run_migration(db: SqliteDb) -> Result<Self, StorageError> {
|
||||
// Initialize schema
|
||||
db.execute_batch(RATCHET_SCHEMA)?;
|
||||
Ok(Self { db })
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Session wrapper for automatic state persistence.
|
||||
|
||||
use x25519_dalek::PublicKey;
|
||||
use storage::StorageError;
|
||||
use x25519_dalek::PublicKey;
|
||||
|
||||
use crate::{
|
||||
InstallationKeyPair,
|
||||
@ -83,10 +83,13 @@ impl<'a, D: HkdfInfo + Clone> RatchetSession<'a, D> {
|
||||
/// Initializes a new session as a sender and persists the initial state.
|
||||
pub fn create_sender_session(
|
||||
storage: &'a mut RatchetStorage,
|
||||
conversation_id: impl Into<String>,
|
||||
conversation_id: &str,
|
||||
shared_secret: SharedSecret,
|
||||
remote_pub: PublicKey,
|
||||
) -> Result<Self, StorageError> {
|
||||
if storage.exists(conversation_id)? {
|
||||
return Err(StorageError::ConversationAlreadyExists);
|
||||
}
|
||||
let state = RatchetState::<D>::init_sender(shared_secret, remote_pub);
|
||||
Self::create(storage, conversation_id, state)
|
||||
}
|
||||
@ -94,13 +97,12 @@ impl<'a, D: HkdfInfo + Clone> RatchetSession<'a, D> {
|
||||
/// Initializes a new session as a receiver and persists the initial state.
|
||||
pub fn create_receiver_session(
|
||||
storage: &'a mut RatchetStorage,
|
||||
conversation_id: impl Into<String>,
|
||||
conversation_id: &str,
|
||||
shared_secret: SharedSecret,
|
||||
dh_self: InstallationKeyPair,
|
||||
) -> Result<Self, StorageError> {
|
||||
let conversation_id = conversation_id.into();
|
||||
if storage.exists(&conversation_id)? {
|
||||
return Self::open(storage, conversation_id);
|
||||
if storage.exists(conversation_id)? {
|
||||
return Err(StorageError::ConversationAlreadyExists);
|
||||
}
|
||||
|
||||
let state = RatchetState::<D>::init_receiver(shared_secret, dh_self);
|
||||
@ -310,4 +312,76 @@ mod tests {
|
||||
assert_eq!(session.state().msg_send, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_sender_session_fails_when_conversation_exists() {
|
||||
let mut storage = create_test_storage();
|
||||
|
||||
let shared_secret = [0x42; 32];
|
||||
let bob_keypair = InstallationKeyPair::generate();
|
||||
let bob_pub = bob_keypair.public().clone();
|
||||
|
||||
// First creation succeeds
|
||||
{
|
||||
let _session: RatchetSession<DefaultDomain> = RatchetSession::create_sender_session(
|
||||
&mut storage,
|
||||
"conv1",
|
||||
shared_secret,
|
||||
bob_pub.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Second creation should fail with ConversationAlreadyExists
|
||||
{
|
||||
let result: Result<RatchetSession<DefaultDomain>, _> =
|
||||
RatchetSession::create_sender_session(
|
||||
&mut storage,
|
||||
"conv1",
|
||||
shared_secret,
|
||||
bob_pub.clone(),
|
||||
);
|
||||
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(StorageError::ConversationAlreadyExists)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_receiver_session_fails_when_conversation_exists() {
|
||||
let mut storage = create_test_storage();
|
||||
|
||||
let shared_secret = [0x42; 32];
|
||||
let bob_keypair = InstallationKeyPair::generate();
|
||||
|
||||
// First creation succeeds
|
||||
{
|
||||
let _session: RatchetSession<DefaultDomain> = RatchetSession::create_receiver_session(
|
||||
&mut storage,
|
||||
"conv1",
|
||||
shared_secret,
|
||||
bob_keypair,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Second creation should fail with ConversationAlreadyExists
|
||||
{
|
||||
let another_keypair = InstallationKeyPair::generate();
|
||||
let result: Result<RatchetSession<DefaultDomain>, _> =
|
||||
RatchetSession::create_receiver_session(
|
||||
&mut storage,
|
||||
"conv1",
|
||||
shared_secret,
|
||||
another_keypair,
|
||||
);
|
||||
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(StorageError::ConversationAlreadyExists)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,10 @@ pub enum StorageError {
|
||||
/// Transaction error.
|
||||
#[error("transaction error: {0}")]
|
||||
Transaction(String),
|
||||
|
||||
/// Database already exists.
|
||||
#[error("conversation already exists")]
|
||||
ConversationAlreadyExists,
|
||||
}
|
||||
|
||||
impl From<rusqlite::Error> for StorageError {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user