summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFxQnLr <[email protected]>2024-02-25 20:00:38 +0100
committerFxQnLr <[email protected]>2024-02-25 20:00:38 +0100
commita192e9baca9a14beaa9f87c27a63cff96aa41c94 (patch)
tree1051968707fc43405ea31fc1878c448c71f6fe34
parent465a71b6780921fb7ec19682702cbe864decd212 (diff)
downloadwebol-cli-a192e9baca9a14beaa9f87c27a63cff96aa41c94.tar
webol-cli-a192e9baca9a14beaa9f87c27a63cff96aa41c94.tar.gz
webol-cli-a192e9baca9a14beaa9f87c27a63cff96aa41c94.zip
Closes #4. Auth on Websocket. Small stuff
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--src/error.rs13
-rw-r--r--src/main.rs33
-rw-r--r--src/requests/device.rs23
-rw-r--r--src/requests/start.rs24
6 files changed, 66 insertions, 35 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c0f07f7..25f23fe 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -66,6 +66,12 @@ dependencies = [
66] 66]
67 67
68[[package]] 68[[package]]
69name = "anyhow"
70version = "1.0.80"
71source = "registry+https://github.com/rust-lang/crates.io-index"
72checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
73
74[[package]]
69name = "async-trait" 75name = "async-trait"
70version = "0.1.74" 76version = "0.1.74"
71source = "registry+https://github.com/rust-lang/crates.io-index" 77source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1725,6 +1731,7 @@ dependencies = [
1725name = "webol-cli" 1731name = "webol-cli"
1726version = "0.2.0" 1732version = "0.2.0"
1727dependencies = [ 1733dependencies = [
1734 "anyhow",
1728 "clap", 1735 "clap",
1729 "clap_complete", 1736 "clap_complete",
1730 "config", 1737 "config",
diff --git a/Cargo.toml b/Cargo.toml
index a60d788..4791c6c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,6 +10,7 @@ name = "webol"
10path = "src/main.rs" 10path = "src/main.rs"
11 11
12[dependencies] 12[dependencies]
13anyhow = "1.0"
13clap = { version = "4.5", features = ["derive"] } 14clap = { version = "4.5", features = ["derive"] }
14clap_complete = "4.5" 15clap_complete = "4.5"
15config = "0.14" 16config = "0.14"
diff --git a/src/error.rs b/src/error.rs
index 15e4308..1e6eac1 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -27,8 +27,17 @@ pub enum Error {
27 #[error("parse header: {source}")] 27 #[error("parse header: {source}")]
28 InvalidHeaderValue { 28 InvalidHeaderValue {
29 #[from] 29 #[from]
30 source: InvalidHeaderValue 30 source: InvalidHeaderValue,
31 }, 31 },
32 #[error("ws")] 32 #[error("tungstenite: {source}")]
33 Tungstenite {
34 #[from]
35 source: tokio_tungstenite::tungstenite::Error,
36 },
37 #[error("faulty websocket response")]
33 WsResponse, 38 WsResponse,
39 #[error("authorization failed")]
40 Authorization,
41 #[error("Http error status: {0}")]
42 HttpStatus(u16),
34} 43}
diff --git a/src/main.rs b/src/main.rs
index cdca6cb..d76341f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,7 +6,10 @@ use clap_complete::{generate, Generator, Shell};
6use error::Error; 6use error::Error;
7use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; 7use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
8use requests::{device, start::start}; 8use requests::{device, start::start};
9use reqwest::header::{HeaderMap, HeaderValue}; 9use reqwest::{
10 header::{HeaderMap, HeaderValue},
11 Response,
12};
10use serde::Deserialize; 13use serde::Deserialize;
11 14
12mod config; 15mod config;
@@ -66,7 +69,7 @@ enum DeviceCmd {
66} 69}
67 70
68#[tokio::main] 71#[tokio::main]
69async fn main() -> Result<(), Error> { 72async fn main() -> Result<(), anyhow::Error> {
70 let config = Config::load()?; 73 let config = Config::load()?;
71 74
72 let cli = Args::parse(); 75 let cli = Args::parse();
@@ -112,18 +115,9 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
112 115
113fn default_headers(config: &Config) -> Result<HeaderMap, Error> { 116fn default_headers(config: &Config) -> Result<HeaderMap, Error> {
114 let mut map = HeaderMap::new(); 117 let mut map = HeaderMap::new();
115 map.append( 118 map.append("Accept-Content", HeaderValue::from_str("application/json")?);
116 "Accept-Content", 119 map.append("Content-Type", HeaderValue::from_str("application/json")?);
117 HeaderValue::from_str("application/json")? 120 map.append("Authorization", HeaderValue::from_str(&config.apikey)?);
118 );
119 map.append(
120 "Content-Type",
121 HeaderValue::from_str("application/json")?
122 );
123 map.append(
124 "Authorization",
125 HeaderValue::from_str(&config.apikey)?
126 );
127 121
128 Ok(map) 122 Ok(map)
129} 123}
@@ -132,6 +126,17 @@ fn format_url(config: &Config, path: &str, protocol: &Protocols) -> String {
132 format!("{}://{}/{}", protocol, config.server, path) 126 format!("{}://{}/{}", protocol, config.server, path)
133} 127}
134 128
129async fn check_success(res: Response) -> Result<String, Error> {
130 let status = res.status();
131 if status.is_success() {
132 Ok(res.text().await?)
133 } else if status.as_u16() == 401 {
134 Err(Error::Authorization)
135 } else {
136 Err(Error::HttpStatus(status.as_u16()))
137 }
138}
139
135fn add_pb(mp: &MultiProgress, template: &str, message: String) -> ProgressBar { 140fn add_pb(mp: &MultiProgress, template: &str, message: String) -> ProgressBar {
136 let pb = mp.add(ProgressBar::new(1)); 141 let pb = mp.add(ProgressBar::new(1));
137 pb.set_style(ProgressStyle::with_template(template).unwrap()); 142 pb.set_style(ProgressStyle::with_template(template).unwrap());
diff --git a/src/requests/device.rs b/src/requests/device.rs
index a612978..7583406 100644
--- a/src/requests/device.rs
+++ b/src/requests/device.rs
@@ -1,4 +1,4 @@
1use crate::{config::Config, default_headers, error::Error, format_url, Protocols}; 1use crate::{check_success, config::Config, default_headers, error::Error, format_url, Protocols};
2 2
3pub async fn put( 3pub async fn put(
4 config: &Config, 4 config: &Config,
@@ -16,11 +16,10 @@ pub async fn put(
16 r#"{{"id": "{id}", "mac": "{mac}", "broadcast_addr": "{broadcast_addr}", "ip": "{ip}"}}"#, 16 r#"{{"id": "{id}", "mac": "{mac}", "broadcast_addr": "{broadcast_addr}", "ip": "{ip}"}}"#,
17 )) 17 ))
18 .send() 18 .send()
19 .await? 19 .await?;
20 .text()
21 .await;
22 20
23 println!("{res:?}"); 21 let body = check_success(res).await?;
22 println!("{body}");
24 Ok(()) 23 Ok(())
25} 24}
26 25
@@ -30,11 +29,10 @@ pub async fn get(config: &Config, id: String) -> Result<(), Error> {
30 .headers(default_headers(config)?) 29 .headers(default_headers(config)?)
31 .body(format!(r#"{{"id": "{id}"}}"#)) 30 .body(format!(r#"{{"id": "{id}"}}"#))
32 .send() 31 .send()
33 .await? 32 .await?;
34 .text()
35 .await;
36 33
37 println!("{res:?}"); 34 let body = check_success(res).await?;
35 println!("{body}");
38 Ok(()) 36 Ok(())
39} 37}
40 38
@@ -52,10 +50,9 @@ pub async fn post(
52 r#"{{"id": "{id}", "mac": "{mac}", "broadcast_addr": "{broadcast_addr}", "ip": "{ip}"}}"#, 50 r#"{{"id": "{id}", "mac": "{mac}", "broadcast_addr": "{broadcast_addr}", "ip": "{ip}"}}"#,
53 )) 51 ))
54 .send() 52 .send()
55 .await? 53 .await?;
56 .text()
57 .await;
58 54
59 println!("{res:?}"); 55 let body = check_success(res).await?;
56 println!("{body}");
60 Ok(()) 57 Ok(())
61} 58}
diff --git a/src/requests/start.rs b/src/requests/start.rs
index 7abbbe0..d07177e 100644
--- a/src/requests/start.rs
+++ b/src/requests/start.rs
@@ -2,7 +2,10 @@ use futures_util::{SinkExt, StreamExt};
2use indicatif::{MultiProgress, ProgressBar}; 2use indicatif::{MultiProgress, ProgressBar};
3use reqwest::StatusCode; 3use reqwest::StatusCode;
4use serde::Deserialize; 4use serde::Deserialize;
5use tokio_tungstenite::{connect_async, tungstenite::Message}; 5use tokio_tungstenite::{
6 connect_async,
7 tungstenite::{http::Request, Message},
8};
6 9
7use crate::{ 10use crate::{
8 add_pb, config::Config, default_headers, error::Error, finish_pb, format_url, ErrorResponse, 11 add_pb, config::Config, default_headers, error::Error, finish_pb, format_url, ErrorResponse,
@@ -66,17 +69,26 @@ async fn status_socket(
66 id: String, 69 id: String,
67) -> Result<bool, Error> { 70) -> Result<bool, Error> {
68 let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string()); 71 let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string());
69 let (mut ws_stream, _response) = 72
70 connect_async(format_url(config, "status", &Protocols::Websocket)) 73 let request = Request::builder()
71 .await 74 .uri(format_url(config, "status", &Protocols::Websocket))
72 .expect("Failed to connect"); 75 .header("Authorization", &config.apikey)
76 .header("sec-websocket-key", "")
77 .header("host", &config.server)
78 .header("upgrade", "websocket")
79 .header("connection", "upgrade")
80 .header("sec-websocket-version", 13)
81 .body(())
82 .unwrap();
83
84 let (mut ws_stream, _response) = connect_async(request).await?;
73 finish_pb(&ws_pb, "connected to websocket".to_string(), DONE_STYLE); 85 finish_pb(&ws_pb, "connected to websocket".to_string(), DONE_STYLE);
74 86
75 ws_stream.send(Message::Text(uuid.clone())).await.unwrap(); 87 ws_stream.send(Message::Text(uuid.clone())).await.unwrap();
76 88
77 // Get ETA 89 // Get ETA
78 let eta_msg = ws_stream.next().await.unwrap().unwrap(); 90 let eta_msg = ws_stream.next().await.unwrap().unwrap();
79 let eta = get_eta(&eta_msg.into_text().unwrap(), &uuid)? + overview.elapsed().as_secs(); 91 let eta = get_eta(&eta_msg.into_text().unwrap(), &uuid)?;
80 overview.set_message(format!("/{eta}) start {id}")); 92 overview.set_message(format!("/{eta}) start {id}"));
81 93
82 let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string()); 94 let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string());