mirror of
https://github.com/tursodatabase/libsql.git
synced 2024-12-16 06:48:48 +00:00
320 lines
9.0 KiB
Rust
320 lines
9.0 KiB
Rust
use std::time::Duration;
|
|
|
|
use insta::assert_debug_snapshot;
|
|
use libsql::Database;
|
|
use uuid::Uuid;
|
|
|
|
use crate::common::auth::{encode, key_pair};
|
|
use crate::common::http::Client;
|
|
use crate::common::net::TurmoilConnector;
|
|
|
|
use super::make_standalone_server;
|
|
|
|
#[test]
|
|
fn attach_no_auth() {
|
|
let mut sim = turmoil::Builder::new()
|
|
.simulation_duration(Duration::from_secs(1000))
|
|
.build();
|
|
|
|
sim.host("primary", make_standalone_server);
|
|
|
|
sim.client("test", async {
|
|
let client = Client::new();
|
|
|
|
client
|
|
.post(
|
|
"http://primary:9090/v1/namespaces/foo/create",
|
|
serde_json::json!({}),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
client
|
|
.post(
|
|
"http://primary:9090/v1/namespaces/bar/create",
|
|
serde_json::json!({ "allow_attach": true}),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
let foo_db =
|
|
Database::open_remote_with_connector("http://foo.primary:8080", "", TurmoilConnector)?;
|
|
let foo_conn = foo_db.connect().unwrap();
|
|
foo_conn
|
|
.execute("CREATE TABLE foo_table (x)", ())
|
|
.await
|
|
.unwrap();
|
|
foo_conn
|
|
.execute("insert into foo_table values (42)", ())
|
|
.await
|
|
.unwrap();
|
|
|
|
let bar_db =
|
|
Database::open_remote_with_connector("http://bar.primary:8080", "", TurmoilConnector)?;
|
|
let bar_conn = bar_db.connect().unwrap();
|
|
bar_conn
|
|
.execute("CREATE TABLE bar_table (x)", ())
|
|
.await
|
|
.unwrap();
|
|
bar_conn
|
|
.execute("insert into bar_table values (43)", ())
|
|
.await
|
|
.unwrap();
|
|
|
|
// fails: foo doesn't allow attach
|
|
assert_debug_snapshot!(bar_conn.execute("ATTACH foo as foo", ()).await.unwrap_err());
|
|
|
|
let txn = foo_conn.transaction().await.unwrap();
|
|
txn.execute("ATTACH DATABASE bar as bar", ()).await.unwrap();
|
|
let mut rows = txn.query("SELECT * FROM bar.bar_table", ()).await.unwrap();
|
|
// succeeds!
|
|
assert_debug_snapshot!(rows.next().await);
|
|
|
|
Ok(())
|
|
});
|
|
|
|
sim.run().unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn attach_auth() {
|
|
let mut sim = turmoil::Builder::new()
|
|
.simulation_duration(Duration::from_secs(1000))
|
|
.build();
|
|
|
|
sim.host("primary", make_standalone_server);
|
|
|
|
sim.client("test", async {
|
|
let client = Client::new();
|
|
|
|
let (enc, jwt_key) = key_pair();
|
|
|
|
assert!(client
|
|
.post(
|
|
"http://primary:9090/v1/namespaces/foo/create",
|
|
serde_json::json!({ "jwt_key": jwt_key })
|
|
)
|
|
.await
|
|
.unwrap()
|
|
.status()
|
|
.is_success());
|
|
assert!(client
|
|
.post(
|
|
"http://primary:9090/v1/namespaces/bar/create",
|
|
serde_json::json!({ "allow_attach": true, "jwt_key": jwt_key })
|
|
)
|
|
.await
|
|
.unwrap()
|
|
.status()
|
|
.is_success());
|
|
|
|
let claims = serde_json::json!({
|
|
"p": {
|
|
"rw": {
|
|
"ns": ["bar", "foo"]
|
|
}
|
|
}
|
|
});
|
|
let token = encode(&claims, &enc);
|
|
|
|
let foo_db = Database::open_remote_with_connector(
|
|
"http://foo.primary:8080",
|
|
&token,
|
|
TurmoilConnector,
|
|
)?;
|
|
let foo_conn = foo_db.connect().unwrap();
|
|
foo_conn
|
|
.execute("CREATE TABLE foo_table (x)", ())
|
|
.await
|
|
.unwrap();
|
|
foo_conn
|
|
.execute("insert into foo_table values (42)", ())
|
|
.await
|
|
.unwrap();
|
|
|
|
let bar_db = Database::open_remote_with_connector(
|
|
"http://bar.primary:8080",
|
|
&token,
|
|
TurmoilConnector,
|
|
)?;
|
|
let bar_conn = bar_db.connect().unwrap();
|
|
bar_conn
|
|
.execute("CREATE TABLE bar_table (x)", ())
|
|
.await
|
|
.unwrap();
|
|
bar_conn
|
|
.execute("insert into bar_table values (43)", ())
|
|
.await
|
|
.unwrap();
|
|
|
|
// fails: no perm
|
|
assert_debug_snapshot!(bar_conn.execute("ATTACH foo as foo", ()).await.unwrap_err());
|
|
|
|
let txn = foo_conn.transaction().await.unwrap();
|
|
// fails: no perm
|
|
assert_debug_snapshot!(txn
|
|
.execute("ATTACH DATABASE bar as bar", ())
|
|
.await
|
|
.unwrap_err());
|
|
|
|
let claims = serde_json::json!({
|
|
"p": {
|
|
"roa": {
|
|
"ns": ["bar", "foo"]
|
|
}
|
|
}
|
|
});
|
|
let token = encode(&claims, &enc);
|
|
|
|
let foo_db = Database::open_remote_with_connector(
|
|
"http://foo.primary:8080",
|
|
&token,
|
|
TurmoilConnector,
|
|
)?;
|
|
let foo_conn = foo_db.connect().unwrap();
|
|
let bar_db = Database::open_remote_with_connector(
|
|
"http://bar.primary:8080",
|
|
&token,
|
|
TurmoilConnector,
|
|
)?;
|
|
let bar_conn = bar_db.connect().unwrap();
|
|
|
|
// fails: namesapce doesn't allow attach
|
|
assert_debug_snapshot!(bar_conn.execute("ATTACH foo as foo", ()).await.unwrap_err());
|
|
|
|
let txn = foo_conn.transaction().await.unwrap();
|
|
txn.execute("ATTACH DATABASE bar as bar", ()).await.unwrap();
|
|
let mut rows = txn.query("SELECT * FROM bar.bar_table", ()).await.unwrap();
|
|
// succeeds!
|
|
assert_debug_snapshot!(rows.next().await);
|
|
|
|
// mixed claims
|
|
let claims = serde_json::json!({
|
|
"p": {
|
|
"rw": {
|
|
"ns": ["foo"]
|
|
},
|
|
"roa": {
|
|
"ns": ["bar"]
|
|
}
|
|
}
|
|
});
|
|
let token = encode(&claims, &enc);
|
|
|
|
let foo_db = Database::open_remote_with_connector(
|
|
"http://foo.primary:8080",
|
|
&token,
|
|
TurmoilConnector,
|
|
)?;
|
|
let foo_conn = foo_db.connect().unwrap();
|
|
let txn = foo_conn.transaction().await.unwrap();
|
|
txn.execute("ATTACH DATABASE bar as attached", ())
|
|
.await
|
|
.unwrap();
|
|
let mut rows = txn
|
|
.query("SELECT * FROM attached.bar_table", ())
|
|
.await
|
|
.unwrap();
|
|
// succeeds!
|
|
assert_debug_snapshot!(rows.next().await);
|
|
|
|
Ok(())
|
|
});
|
|
|
|
sim.run().unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn attach_auth_with_uuids() {
|
|
let mut sim = turmoil::Builder::new()
|
|
.simulation_duration(Duration::from_secs(1000))
|
|
.build();
|
|
|
|
sim.host("primary", make_standalone_server);
|
|
|
|
sim.client("test", async {
|
|
let client = Client::new();
|
|
|
|
let (enc, jwt_key) = key_pair();
|
|
|
|
let main_db_id = Uuid::new_v4();
|
|
let attach_db_id = Uuid::new_v4();
|
|
|
|
assert!(client
|
|
.post(
|
|
format!("http://primary:9090/v1/namespaces/{}/create", main_db_id).as_str(),
|
|
serde_json::json!({ "jwt_key": jwt_key })
|
|
)
|
|
.await
|
|
.unwrap()
|
|
.status()
|
|
.is_success());
|
|
assert!(client
|
|
.post(
|
|
format!("http://primary:9090/v1/namespaces/{}/create", attach_db_id).as_str(),
|
|
serde_json::json!({ "allow_attach": true, "jwt_key": jwt_key })
|
|
)
|
|
.await
|
|
.unwrap()
|
|
.status()
|
|
.is_success());
|
|
|
|
let claims = serde_json::json!({
|
|
"p": {
|
|
"rw": {
|
|
"ns": [main_db_id, attach_db_id]
|
|
},
|
|
"roa": {
|
|
"ns": [attach_db_id]
|
|
}
|
|
}
|
|
});
|
|
let token = encode(&claims, &enc);
|
|
|
|
let attach_conn = Database::open_remote_with_connector(
|
|
format!("http://{}.primary:8080", attach_db_id).as_str(),
|
|
&token,
|
|
TurmoilConnector,
|
|
)?
|
|
.connect()
|
|
.unwrap();
|
|
attach_conn
|
|
.execute("CREATE TABLE bar_table (x)", ())
|
|
.await
|
|
.unwrap();
|
|
attach_conn
|
|
.execute("insert into bar_table values (43)", ())
|
|
.await
|
|
.unwrap();
|
|
|
|
let main_conn = Database::open_remote_with_connector(
|
|
format!("http://{}.primary:8080", main_db_id).as_str(),
|
|
&token,
|
|
TurmoilConnector,
|
|
)?
|
|
.connect()
|
|
.unwrap();
|
|
|
|
// fails: namespace is uuid, hence needs to be wrapped in quotes
|
|
assert_debug_snapshot!(main_conn
|
|
.execute(
|
|
"ATTACH DATABASE ae308915-caca-480f-a6b4-9f9f9dc84b11 as bar",
|
|
()
|
|
)
|
|
.await
|
|
.unwrap_err());
|
|
|
|
let txn = main_conn.transaction().await.unwrap();
|
|
txn.execute(
|
|
format!("ATTACH DATABASE \"{}\" as bar", attach_db_id).as_str(),
|
|
(),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
let mut rows = txn.query("SELECT * FROM bar.bar_table", ()).await.unwrap();
|
|
assert_debug_snapshot!(rows.next().await);
|
|
Ok(())
|
|
});
|
|
|
|
sim.run().unwrap();
|
|
}
|