use eidetica::{
Database,
auth::{
crypto::{format_public_key, generate_keypair},
settings::AuthSettings,
types::{AuthKey, Permission},
},
crdt::Doc,
user::types::{DatabasePreferences, SyncSettings},
};
use super::helpers::{login_user, setup_instance};
#[test]
fn test_add_database() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", "shared_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key.clone(),
sync_settings: SyncSettings {
sync_enabled: true,
sync_on_commit: false,
interval_seconds: Some(60),
properties: Default::default(),
},
};
user.add_database(prefs)?;
let tracked_dbs = user.list_database_prefs()?;
assert_eq!(tracked_dbs.len(), 1);
assert_eq!(tracked_dbs[0].database_id, db_id);
assert_eq!(tracked_dbs[0].key_id, user_key);
assert!(tracked_dbs[0].sync_settings.sync_enabled);
Ok(())
}
#[test]
fn test_add_database_no_sigkey_error() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
instance
.backend()
.store_private_key("alice_key", alice_key.clone())?;
let mut db_settings = Doc::new();
db_settings.set_string("name", "private_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id,
key_id: user_key,
sync_settings: Default::default(),
};
let result = user.add_database(prefs);
assert!(result.is_err());
Ok(())
}
#[test]
fn test_list_databases() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
assert_eq!(user.list_database_prefs()?.len(), 0);
for i in 0..3 {
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", format!("db_{}", i));
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
format!("alice_{}", i),
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, format!("alice_{}", i))?;
let prefs = DatabasePreferences {
database_id: db.root_id().clone(),
key_id: user_key.clone(),
sync_settings: Default::default(),
};
user.add_database(prefs)?;
}
let tracked = user.list_database_prefs()?;
assert_eq!(tracked.len(), 3);
Ok(())
}
#[test]
fn test_get_database_preferences() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key.clone(),
sync_settings: SyncSettings {
sync_enabled: true,
sync_on_commit: true,
interval_seconds: Some(30),
properties: Default::default(),
},
};
user.add_database(prefs)?;
let retrieved = user.database_prefs(&db_id)?;
assert_eq!(retrieved.database_id, db_id);
assert_eq!(retrieved.key_id, user_key);
assert!(retrieved.sync_settings.sync_enabled);
assert!(retrieved.sync_settings.sync_on_commit);
assert_eq!(retrieved.sync_settings.interval_seconds, Some(30));
Ok(())
}
#[test]
fn test_update_database_preferences() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let initial_prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key.clone(),
sync_settings: SyncSettings {
sync_enabled: false,
sync_on_commit: false,
interval_seconds: None,
properties: Default::default(),
},
};
user.add_database(initial_prefs)?;
let updated_prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key.clone(),
sync_settings: SyncSettings {
sync_enabled: true,
sync_on_commit: true,
interval_seconds: Some(60),
properties: Default::default(),
},
};
user.add_database(updated_prefs)?;
let retrieved = user.database_prefs(&db_id)?;
assert!(retrieved.sync_settings.sync_enabled);
assert!(retrieved.sync_settings.sync_on_commit);
assert_eq!(retrieved.sync_settings.interval_seconds, Some(60));
Ok(())
}
#[test]
fn test_remove_database() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key,
sync_settings: Default::default(),
};
user.add_database(prefs)?;
assert_eq!(user.list_database_prefs()?.len(), 1);
user.remove_database(&db_id)?;
assert_eq!(user.list_database_prefs()?.len(), 0);
let result = user.database_prefs(&db_id);
assert!(result.is_err());
Ok(())
}
#[test]
fn test_load_tracked_database() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key,
sync_settings: Default::default(),
};
user.add_database(prefs)?;
let loaded_db = user.open_database(&db_id)?;
assert_eq!(loaded_db.root_id(), &db_id);
assert_eq!(loaded_db.get_name()?, "test_db");
Ok(())
}
#[test]
fn test_update_preferences_valid_key_change() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let key1 = user.get_default_key()?;
let key2 = user.add_private_key(Some("Second Key"))?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
instance
.backend()
.store_private_key("alice_key", alice_key.clone())?;
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: key1.clone(),
sync_settings: Default::default(),
};
user.add_database(prefs)?;
let updated_prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: key2.clone(),
sync_settings: SyncSettings {
sync_enabled: true,
sync_on_commit: true,
interval_seconds: Some(120),
properties: Default::default(),
},
};
user.add_database(updated_prefs)?;
let retrieved = user.database_prefs(&db_id)?;
assert_eq!(retrieved.key_id, key2);
assert!(retrieved.sync_settings.sync_enabled);
assert!(retrieved.sync_settings.sync_on_commit);
assert_eq!(retrieved.sync_settings.interval_seconds, Some(120));
Ok(())
}
#[test]
fn test_update_preferences_nonexistent_key_fails() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let user_key = user.get_default_key()?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
instance
.backend()
.store_private_key("alice_key", alice_key.clone())?;
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: user_key,
sync_settings: Default::default(),
};
user.add_database(prefs)?;
let fake_key_id = "Ed25519:fake_nonexistent_key_12345".to_string();
let invalid_prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: fake_key_id,
sync_settings: Default::default(),
};
let result = user.add_database(invalid_prefs);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("Key not found"));
Ok(())
}
#[test]
fn test_update_preferences_no_access_fails() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let key1 = user.get_default_key()?;
let key2 = user.add_private_key(Some("Second Key"))?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
instance
.backend()
.store_private_key("alice_key", alice_key.clone())?;
let mut db_settings = Doc::new();
db_settings.set_string("name", "private_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(
db_settings,
&instance,
alice_key.clone(),
"alice".to_string(),
)?;
let db_id = db.root_id().clone();
let key1_pubkey = user.get_public_key(&key1)?;
let tx = db.new_transaction()?;
let settings_store = tx.get_settings()?;
settings_store.update_auth_settings(|auth| {
auth.add_key(
"user_key1",
AuthKey::active(&key1_pubkey, Permission::Write(5))?,
)
})?;
tx.commit()?;
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: key1,
sync_settings: Default::default(),
};
user.add_database(prefs)?;
let invalid_prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: key2,
sync_settings: Default::default(),
};
let result = user.add_database(invalid_prefs);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No SigKey found"));
Ok(())
}
#[test]
fn test_update_preferences_auto_creates_mapping() -> eidetica::Result<()> {
let instance = setup_instance();
instance.create_user("test_user", None)?;
let mut user = login_user(&instance, "test_user", None);
let key1 = user.get_default_key()?;
let key2 = user.add_private_key(Some("Second Key"))?;
let (alice_key, alice_pubkey) = generate_keypair();
let alice_pubkey_str = format_public_key(&alice_pubkey);
let mut db_settings = Doc::new();
db_settings.set_string("name", "test_db");
let mut auth_settings = AuthSettings::new();
auth_settings.add_key(
"alice",
AuthKey::active(&alice_pubkey_str, Permission::Admin(1))?,
)?;
auth_settings.add_key("*", AuthKey::active("*", Permission::Write(10))?)?;
db_settings.set_doc("auth", auth_settings.as_doc().clone());
let db = Database::create(db_settings, &instance, alice_key, "alice".to_string())?;
let db_id = db.root_id().clone();
let prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: key1.clone(),
sync_settings: Default::default(),
};
user.add_database(prefs)?;
let updated_prefs = DatabasePreferences {
database_id: db_id.clone(),
key_id: key2.clone(),
sync_settings: SyncSettings {
sync_enabled: true,
sync_on_commit: false,
interval_seconds: Some(90),
properties: Default::default(),
},
};
user.add_database(updated_prefs)?;
let retrieved = user.database_prefs(&db_id)?;
assert_eq!(retrieved.key_id, key2);
assert!(retrieved.sync_settings.sync_enabled);
assert_eq!(retrieved.sync_settings.interval_seconds, Some(90));
let mapping = user.key_mapping(&key2, &db_id)?;
assert_eq!(mapping, Some("*".to_string()));
Ok(())
}