Added a structure to hold all of our recurrent and needed data that can be passed to all functions

Signed-off-by: Louis Vallat <louis@louis-vallat.xyz>
This commit is contained in:
Louis Vallat 2021-10-24 00:01:36 +02:00
parent 25fa9e74fa
commit 028adbff93
No known key found for this signature in database
GPG Key ID: 0C87282F76E61283
2 changed files with 34 additions and 38 deletions

View File

@ -1,5 +1,5 @@
use hyper_tls::HttpsConnector; use hyper_tls::HttpsConnector;
use hyper::{Body, Client, Response}; use hyper::{Body, Client, Response, client::HttpConnector};
use clap::{Arg, App, SubCommand}; use clap::{Arg, App, SubCommand};
use crate::session::login; use crate::session::login;
@ -7,6 +7,12 @@ use dotenv::dotenv;
mod session; mod session;
mod albums; mod albums;
pub struct LycheeClient {
client: Client<HttpsConnector<HttpConnector>>,
endpoint: String,
api_key: String
}
pub async fn body_to_str(res: Response<Body>) -> String { pub async fn body_to_str(res: Response<Body>) -> String {
let body = hyper::body::to_bytes(res).await.unwrap(); let body = hyper::body::to_bytes(res).await.unwrap();
let body_str = std::str::from_utf8(&body).unwrap().clone(); let body_str = std::str::from_utf8(&body).unwrap().clone();
@ -39,8 +45,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.get_matches(); .get_matches();
dotenv().ok(); dotenv().ok();
let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https); let client = LycheeClient {
client: Client::builder().build::<_, hyper::Body>(HttpsConnector::new()),
endpoint: std::env::var("LYCHEE_ENDPOINT").unwrap(),
api_key: std::env::var("LYCHEE_API_KEY").unwrap()
};
if let Some(matches) = matches.subcommand_matches("login") { if let Some(matches) = matches.subcommand_matches("login") {
let username = matches.value_of("username").unwrap(); let username = matches.value_of("username").unwrap();

View File

@ -1,52 +1,51 @@
use hyper_tls::HttpsConnector; use hyper::{Body, Method, Request, header::{AUTHORIZATION, CONTENT_TYPE, COOKIE, HeaderValue, SET_COOKIE}};
use hyper::{Body, Client, Method, Request, client::HttpConnector, header::{AUTHORIZATION, CONTENT_TYPE, COOKIE, HeaderValue, SET_COOKIE}};
use json::object; use json::object;
use crate::body_to_str; use crate::{LycheeClient, body_to_str};
pub async fn login(client: &Client<HttpsConnector<HttpConnector>>, login: &str, password: &str) -> HeaderValue { pub async fn login(client: &LycheeClient, login: &str, password: &str) -> HeaderValue {
let login_data = object! { "username": login, "password": password }; let login_data = object! { "username": login, "password": password };
let req = Request::builder() let req = Request::builder()
.method(Method::POST) .method(Method::POST)
.uri(std::env::var("LYCHEE_ENDPOINT").unwrap() + "/api/Session::login") .uri(client.endpoint.clone() + "/api/Session::login")
.header(AUTHORIZATION, std::env::var("LYCHEE_API_KEY").unwrap()) .header(AUTHORIZATION, client.api_key.clone())
.header(CONTENT_TYPE, "application/json") .header(CONTENT_TYPE, "application/json")
.body(Body::from(login_data.dump())) .body(Body::from(login_data.dump()))
.expect("error"); .expect("error");
let res = client.request(req).await.unwrap(); let res = client.client.request(req).await.unwrap();
let lychee_session = res.headers().get(SET_COOKIE.as_str()).unwrap().clone(); let lychee_session = res.headers().get(SET_COOKIE.as_str()).unwrap().clone();
assert_eq!(res.headers().get(CONTENT_TYPE.as_str()).unwrap(), "application/json");
assert!(json::parse(body_to_str(res).await.as_str()).unwrap().as_bool().unwrap()); assert!(json::parse(body_to_str(res).await.as_str()).unwrap().as_bool().unwrap());
return lychee_session; return lychee_session;
} }
pub async fn logout(client: &Client<HttpsConnector<HttpConnector>>, lychee_session: &HeaderValue) { pub async fn logout(client: &LycheeClient, lychee_session: &HeaderValue) {
let req = Request::builder() let req = Request::builder()
.method(Method::POST) .method(Method::POST)
.uri(std::env::var("LYCHEE_ENDPOINT").unwrap() + "/api/Session::logout") .uri(client.endpoint.clone() + "/api/Session::logout")
.header(COOKIE.as_str(), lychee_session) .header(COOKIE.as_str(), lychee_session)
.header(AUTHORIZATION, std::env::var("LYCHEE_API_KEY").unwrap()) .header(AUTHORIZATION, client.api_key.clone())
.body(Body::empty()) .body(Body::empty())
.expect("error"); .expect("error");
let res = client.request(req).await.unwrap(); let res = client.client.request(req).await.unwrap();
assert!(json::parse(body_to_str(res).await.as_str()).unwrap().as_bool().unwrap()); assert!(json::parse(body_to_str(res).await.as_str()).unwrap().as_bool().unwrap());
} }
#[cfg(test)] #[cfg(test)]
mod session_tests { mod session_tests {
use hyper_tls::HttpsConnector; use hyper_tls::HttpsConnector;
use hyper::{Client, client::HttpConnector, header::HeaderValue}; use hyper::{Client, header::HeaderValue};
use json::object; use json::object;
use mockito::mock; use mockito::mock;
use crate::session::{login, logout}; use crate::{LycheeClient, session::{login, logout}};
fn setup() -> Client<HttpsConnector<HttpConnector>> { fn setup() -> LycheeClient {
let https = HttpsConnector::new(); let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https); return LycheeClient {
std::env::set_var("LYCHEE_ENDPOINT", mockito::server_url()); client: Client::builder().build::<_, hyper::Body>(https),
std::env::set_var("LYCHEE_API_KEY", "value"); endpoint: mockito::server_url(),
return client; api_key: "value".to_string()
};
} }
#[test] #[test]
@ -115,23 +114,9 @@ mod session_tests {
m.assert(); m.assert();
} }
#[test]
#[should_panic]
fn login_html_returned() {
let client = setup();
let m = mock("POST", "/api/Session::login")
.with_header("content-type", "text/html")
.with_header("set-cookie", "demo")
.with_body("true")
.with_status(200)
.create();
tokio_test::block_on(login(&client, "u", "p"));
m.assert();
}
#[test] #[test]
fn login_check_api_key() { fn login_check_api_key() {
let client = setup(); let mut client = setup();
let m1 = mock("POST", "/api/Session::login") let m1 = 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")
@ -141,7 +126,7 @@ mod session_tests {
tokio_test::block_on(login(&client, "u", "p")); tokio_test::block_on(login(&client, "u", "p"));
m1.assert(); m1.assert();
std::env::set_var("LYCHEE_API_KEY", "othervalue"); client.api_key = "othervalue".to_string();
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")