Refactored to give username and password to login function as parameters, and use the clap framework to built the command line interface

Signed-off-by: Louis Vallat <louis@louis-vallat.xyz>
This commit is contained in:
Louis Vallat 2021-10-23 23:35:30 +02:00
parent 8e8dcece2d
commit 25fa9e74fa
No known key found for this signature in database
GPG Key ID: 0C87282F76E61283
4 changed files with 94 additions and 24 deletions

52
Cargo.lock generated
View File

@ -11,6 +11,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "assert-json-diff" name = "assert-json-diff"
version = "2.0.1" version = "2.0.1"
@ -83,6 +92,21 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]] [[package]]
name = "colored" name = "colored"
version = "2.0.0" version = "2.0.0"
@ -374,6 +398,7 @@ dependencies = [
name = "lychee_client" name = "lychee_client"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"dotenv", "dotenv",
"hyper", "hyper",
"hyper-tls", "hyper-tls",
@ -764,6 +789,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.80" version = "1.0.80"
@ -789,6 +820,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.12.0" version = "1.12.0"
@ -900,6 +940,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.2"
@ -912,6 +958,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "want" name = "want"
version = "0.3.0" version = "0.3.0"

View File

@ -12,6 +12,7 @@ tokio-test = "0.4.2"
hyper-tls = "0.5.0" hyper-tls = "0.5.0"
dotenv = "0.15.0" dotenv = "0.15.0"
json = "0.12.4" json = "0.12.4"
clap = "2.33.3"
[dev-dependencies] [dev-dependencies]
mockito = "0.30.0" mockito = "0.30.0"

View File

@ -1,7 +1,7 @@
use hyper_tls::HttpsConnector; use hyper_tls::HttpsConnector;
use hyper::{Body, Client, Response}; use hyper::{Body, Client, Response};
use crate::session::{login, logout}; use clap::{Arg, App, SubCommand};
use crate::albums::get_albums; use crate::session::login;
use dotenv::dotenv; use dotenv::dotenv;
mod session; mod session;
@ -16,14 +16,38 @@ pub async fn body_to_str(res: Response<Body>) -> String {
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
dotenv().ok(); let matches = App::new("Lychee CLIent")
.version("0.1.0")
.author("Louis Vallat <contact@louis-vallat.xyz>")
.about("An Lychee CLI client written in Rust.")
.subcommand(
SubCommand::with_name("login")
.about("Log into a Lychee instance")
.arg(Arg::with_name("username")
.long("username")
.short("u")
.required(true)
.value_name("USERNAME")
.help("Provide the username for the Lychee account."))
.arg(Arg::with_name("password")
.long("password")
.short("p")
.required(true)
.value_name("PASSWORD")
.help("Provide the password for the lychee account."))
)
.get_matches();
dotenv().ok();
let https = HttpsConnector::new(); let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https); let client = Client::builder().build::<_, hyper::Body>(https);
let lychee_session = login(&client).await;
let albums = get_albums(&client, &lychee_session).await; if let Some(matches) = matches.subcommand_matches("login") {
logout(&client, &lychee_session).await; let username = matches.value_of("username").unwrap();
println!("{}", albums["albums"].pretty(4)); let password = matches.value_of("password").unwrap();
let lychee_session = login(&client, username, password).await;
println!("{:?}", lychee_session);
}
Ok(()) Ok(())
} }

View File

@ -3,11 +3,8 @@ use hyper::{Body, Client, Method, Request, client::HttpConnector, header::{AUTHO
use json::object; use json::object;
use crate::body_to_str; use crate::body_to_str;
pub async fn login(client: &Client<HttpsConnector<HttpConnector>>) -> HeaderValue { pub async fn login(client: &Client<HttpsConnector<HttpConnector>>, login: &str, password: &str) -> HeaderValue {
let login_data = object! { let login_data = object! { "username": login, "password": password };
"username": std::env::var("LYCHEE_USERNAME").unwrap(),
"password": std::env::var("LYCHEE_PASSWORD").unwrap()
};
let req = Request::builder() let req = Request::builder()
.method(Method::POST) .method(Method::POST)
@ -48,8 +45,6 @@ mod session_tests {
let https = HttpsConnector::new(); let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https); let client = Client::builder().build::<_, hyper::Body>(https);
std::env::set_var("LYCHEE_ENDPOINT", mockito::server_url()); std::env::set_var("LYCHEE_ENDPOINT", mockito::server_url());
std::env::set_var("LYCHEE_USERNAME", "username");
std::env::set_var("LYCHEE_PASSWORD", "password");
std::env::set_var("LYCHEE_API_KEY", "value"); std::env::set_var("LYCHEE_API_KEY", "value");
return client; return client;
} }
@ -92,7 +87,7 @@ mod session_tests {
.with_body("true") .with_body("true")
.with_status(200) .with_status(200)
.create(); .create();
assert_eq!("demo", tokio_test::block_on(login(&client))); assert_eq!("demo", tokio_test::block_on(login(&client, "u", "p")));
m1.assert(); m1.assert();
let m2 = mock("POST", "/api/Session::login") let m2 = mock("POST", "/api/Session::login")
@ -102,7 +97,7 @@ mod session_tests {
.with_body("true") .with_body("true")
.with_status(200) .with_status(200)
.create(); .create();
assert_eq!("value", tokio_test::block_on(login(&client))); assert_eq!("value", tokio_test::block_on(login(&client, "u", "p")));
m2.assert(); m2.assert();
} }
@ -116,7 +111,7 @@ mod session_tests {
.with_body("false") .with_body("false")
.create(); .create();
tokio_test::block_on(login(&client)); tokio_test::block_on(login(&client, "u", "p"));
m.assert(); m.assert();
} }
@ -130,7 +125,7 @@ mod session_tests {
.with_body("true") .with_body("true")
.with_status(200) .with_status(200)
.create(); .create();
tokio_test::block_on(login(&client)); tokio_test::block_on(login(&client, "u", "p"));
m.assert(); m.assert();
} }
@ -143,7 +138,7 @@ mod session_tests {
.with_body("true") .with_body("true")
.match_header("authorization", "value") .match_header("authorization", "value")
.create(); .create();
tokio_test::block_on(login(&client)); tokio_test::block_on(login(&client, "u", "p"));
m1.assert(); m1.assert();
std::env::set_var("LYCHEE_API_KEY", "othervalue"); std::env::set_var("LYCHEE_API_KEY", "othervalue");
@ -153,7 +148,7 @@ mod session_tests {
.with_body("true") .with_body("true")
.match_header("authorization", "othervalue") .match_header("authorization", "othervalue")
.create(); .create();
tokio_test::block_on(login(&client)); tokio_test::block_on(login(&client, "u", "p"));
m2.assert(); m2.assert();
} }
@ -167,20 +162,18 @@ mod session_tests {
.with_body("true") .with_body("true")
.match_body(body1.dump().as_str()) .match_body(body1.dump().as_str())
.create(); .create();
tokio_test::block_on(login(&client)); tokio_test::block_on(login(&client, "username", "password"));
m1.assert(); m1.assert();
let body2 = object!{ "username": "u", "password": "p" }; let body2 = object!{ "username": "u", "password": "p" };
let client = setup(); let client = setup();
std::env::set_var("LYCHEE_USERNAME", "u");
std::env::set_var("LYCHEE_PASSWORD", "p");
let m2 = mock("POST", "/api/Session::login") let m2 = mock("POST", "/api/Session::login")
.with_header("content-type", "application/json") .with_header("content-type", "application/json")
.with_header("set-cookie", "demo") .with_header("set-cookie", "demo")
.with_body("true") .with_body("true")
.match_body(body2.dump().as_str()) .match_body(body2.dump().as_str())
.create(); .create();
tokio_test::block_on(login(&client)); tokio_test::block_on(login(&client, "u", "p"));
m2.assert(); m2.assert();
} }
} }