use redis::AsyncCommands;
use redis_universal_client::{UniversalBuilder, UniversalClient};
use testcontainers_modules::testcontainers::{
ContainerAsync, GenericImage, ImageExt, core::WaitFor, runners::AsyncRunner,
};
async fn redis_with_password(password: &str) -> (ContainerAsync<GenericImage>, String, String) {
let container = GenericImage::new("redis", "7")
.with_wait_for(WaitFor::message_on_stdout("Ready to accept connections"))
.with_cmd(["--requirepass", password])
.start()
.await
.unwrap();
let host = container.get_host().await.unwrap().to_string();
let port = container.get_host_port_ipv4(6379).await.unwrap();
let url = format!("redis://{}:{}", host, port);
(container, url, password.to_string())
}
#[tokio::test]
async fn builder_password_only_auth() {
let (_container, url, password) = redis_with_password("s3cret").await;
let client = UniversalBuilder::new(vec![url])
.password(password)
.build()
.unwrap();
let mut conn = client.get_connection().await.unwrap();
let _: () = conn.set("pw_key", "pw_value").await.unwrap();
let val: String = conn.get("pw_key").await.unwrap();
assert_eq!(val, "pw_value");
}
#[tokio::test]
async fn connection_without_password_is_rejected() {
let (_container, url, _) = redis_with_password("s3cret").await;
let client = UniversalBuilder::new(vec![url]).build().unwrap();
let conn = client.get_connection().await;
let result = match conn {
Err(e) => Err(e),
Ok(mut c) => c.set::<_, _, ()>("k", "v").await,
};
assert!(result.is_err(), "expected auth error, got success");
}
#[tokio::test]
async fn builder_username_and_password_acl() {
const ADMIN_PASS: &str = "adminpass";
const ALICE_PASS: &str = "alicepass";
let (_container, url, _) = redis_with_password(ADMIN_PASS).await;
let admin_url = url.replace("redis://", &format!("redis://:{}@", ADMIN_PASS));
let admin_client = UniversalClient::open(vec![admin_url]).unwrap();
let mut admin_conn = admin_client.get_connection().await.unwrap();
let _: () = redis::cmd("ACL")
.arg("SETUSER")
.arg("alice")
.arg("on")
.arg(format!(">{}", ALICE_PASS))
.arg("~*")
.arg("&*")
.arg("+@all")
.query_async(&mut admin_conn)
.await
.unwrap();
let client = UniversalBuilder::new(vec![url])
.username("alice")
.password(ALICE_PASS)
.build()
.unwrap();
let mut conn = client.get_connection().await.unwrap();
let _: () = conn.set("alice_key", "alice_value").await.unwrap();
let val: String = conn.get("alice_key").await.unwrap();
assert_eq!(val, "alice_value");
}