diff --git a/burrow-gtk/Cargo.toml b/burrow-gtk/Cargo.toml index 25d126c..9b489f2 100644 --- a/burrow-gtk/Cargo.toml +++ b/burrow-gtk/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" anyhow = "1.0" relm4 = { version = "0.6", features = ["libadwaita", "gnome_44"]} burrow = { version = "*", path = "../burrow/" } -tokio = { version = "1.35.0", features = ["time", "sync"] } +tokio = { version = "1.35.0", features = ["time", "sync", "net"] } gettext-rs = { version = "0.7.0", features = ["gettext-system"] } serde = { version = "1", features = ["derive"] } url = "2.5.0" diff --git a/burrow-gtk/src/auth.rs b/burrow-gtk/src/auth.rs index 110d924..f640431 100644 --- a/burrow-gtk/src/auth.rs +++ b/burrow-gtk/src/auth.rs @@ -1,8 +1,89 @@ -use super::*; -use serde::Serialize; +use reqwest::{Client, Method}; +use serde::Deserialize; +use std::process::Command; +use tokio::{ + io::AsyncWriteExt, + io::{AsyncBufReadExt, BufReader}, + net::TcpListener, +}; +use url::Url; -#[derive(Serialize)] -pub struct SlackToken { - slack_token: String, +const SLACK_CLIENT_ID: &str = "2210535565.6884042183125"; +const SLACK_CLIENT_SECRET: &str = "2793c8a5255cae38830934c664eeb62d"; +const SLACK_REDIRECT_URI: &str = "https://burrow.rs/callback/oauth2"; + +pub async fn slack_auth() { + let url = Url::parse_with_params( + "https://slack.com/openid/connect/authorize", + &[ + ("response_type", "code"), + ("scope", "openid profile"), + ("client_id", SLACK_CLIENT_ID), + ("redirect_uri", SLACK_REDIRECT_URI), + ], + ) + .unwrap(); + Command::new("xdg-open").arg(url.as_str()).spawn().unwrap(); + let listener = TcpListener::bind("127.0.0.1:1024").await.unwrap(); + + let (mut stream, _) = listener.accept().await.unwrap(); + + let buf_reader = BufReader::new(&mut stream); + + let mut lines = buf_reader.lines(); + let mut http_request = vec![]; + while let Some(line) = lines.next_line().await.unwrap() { + if !line.is_empty() { + http_request.push(line); + } else { + break; + } + } + + let response = "HTTP/1.1 200 OK\r\n\r\n"; + stream.write_all(response.as_bytes()).await.unwrap(); + + let code = http_request + .iter() + .filter_map(|field| { + if field.starts_with("GET ") { + Some( + field + .replace("GET /?code=", "") + .replace(" HTTP/1.1", "") + .to_owned(), + ) + } else { + None + } + }) + .next() + .unwrap(); + + #[derive(Debug, Clone, Deserialize)] + struct TokenRes { + ok: bool, + access_token: Option, + token_type: Option, + id_token: Option, + } + + let client = Client::builder().build().unwrap(); + let res = client + .request(Method::POST, "https://slack.com/api/openid.connect.token") + .query(&[ + ("client_id", SLACK_CLIENT_ID), + ("client_secret", SLACK_CLIENT_SECRET), + ("code", &code), + ("grant_type", "authorization_code"), + ("redirect_uri", SLACK_REDIRECT_URI), + ]) + .send() + .await + .unwrap() + .json::() + .await + .unwrap(); + + eprintln!("{:?}", res); } - diff --git a/burrow-gtk/src/components/app.rs b/burrow-gtk/src/components/app.rs index d9fdadc..62c98c0 100644 --- a/burrow-gtk/src/components/app.rs +++ b/burrow-gtk/src/components/app.rs @@ -8,7 +8,6 @@ pub struct App { daemon_client: Arc>>, settings_screen: Controller, switch_screen: AsyncController, - auth_screen: AsyncController, } #[derive(Debug)] @@ -73,16 +72,11 @@ impl AsyncComponent for App { }) .forward(sender.input_sender(), |_| AppMsg::None); - let auth_screen = auth_screen::AuthScreen::builder() - .launch(auth_screen::AuthScreenInit {}) - .forward(sender.input_sender(), |_| AppMsg::None); - let widgets = view_output!(); let view_stack = adw::ViewStack::new(); view_stack.add_titled(switch_screen.widget(), None, "Switch"); view_stack.add_titled(settings_screen.widget(), None, "Settings"); - view_stack.add_titled(auth_screen.widget(), None, "Auth Test"); let view_switcher_bar = adw::ViewSwitcherBar::builder().stack(&view_stack).build(); view_switcher_bar.set_reveal(true); @@ -116,7 +110,6 @@ impl AsyncComponent for App { daemon_client, switch_screen, settings_screen, - auth_screen, }; AsyncComponentParts { model, widgets } diff --git a/burrow-gtk/src/components/auth_screen.rs b/burrow-gtk/src/components/auth_screen.rs deleted file mode 100644 index 5c8f5d3..0000000 --- a/burrow-gtk/src/components/auth_screen.rs +++ /dev/null @@ -1,135 +0,0 @@ -use super::*; -use reqwest::{Client, Method}; -use serde::Deserialize; -use std::{ - io::{prelude::*, BufReader}, - net::TcpListener, - process::Command, -}; -use url::Url; - -const SLACK_CLIENT_ID: &str = "2210535565.6884042183125"; -const SLACK_CLIENT_SECRET: &str = "2793c8a5255cae38830934c664eeb62d"; -const SLACK_REDIRECT_URI: &str = "https://burrow.rs/callback/oauth2"; - -pub struct AuthScreen {} - -pub struct AuthScreenInit {} - -#[derive(Debug, PartialEq, Eq)] -pub enum AuthScreenMsg { - SlackAuth, -} - -#[relm4::component(pub, async)] -impl AsyncComponent for AuthScreen { - type Init = AuthScreenInit; - type Input = AuthScreenMsg; - type Output = (); - type CommandOutput = (); - - view! { - gtk::Box { - set_orientation: gtk::Orientation::Vertical, - set_valign: Align::Fill, - - gtk::Button { - set_label: "Authenticate with Slack", - connect_clicked => AuthScreenMsg::SlackAuth, - }, - } - } - - async fn init( - init: Self::Init, - root: Self::Root, - sender: AsyncComponentSender, - ) -> AsyncComponentParts { - let widgets = view_output!(); - - let model = AuthScreen {}; - - AsyncComponentParts { model, widgets } - } - - async fn update( - &mut self, - msg: Self::Input, - _: AsyncComponentSender, - _root: &Self::Root, - ) { - match msg { - AuthScreenMsg::SlackAuth => { - let url = Url::parse_with_params( - "https://slack.com/openid/connect/authorize", - &[ - ("response_type", "code"), - ("scope", "openid profile"), - ("client_id", SLACK_CLIENT_ID), - ("redirect_uri", SLACK_REDIRECT_URI), - ], - ) - .unwrap(); - Command::new("xdg-open").arg(url.as_str()).spawn().unwrap(); - let listener = TcpListener::bind("127.0.0.1:1024").unwrap(); - - let stream = listener.incoming().next().unwrap(); - let mut stream = stream.unwrap(); - - let buf_reader = BufReader::new(&mut stream); - let http_request: Vec<_> = buf_reader - .lines() - .map(|result| result.unwrap()) - .take_while(|line| !line.is_empty()) - .collect(); - - let response = "HTTP/1.1 200 OK\r\n\r\n"; - stream.write_all(response.as_bytes()).unwrap(); - - let code = http_request - .iter() - .filter_map(|field| { - if field.starts_with("GET ") { - Some( - field - .replace("GET /?code=", "") - .replace(" HTTP/1.1", "") - .to_owned(), - ) - } else { - None - } - }) - .next() - .unwrap(); - - #[derive(Debug, Clone, Deserialize)] - struct TokenRes { - ok: bool, - access_token: Option, - token_type: Option, - id_token: Option, - } - - let client = Client::builder().build().unwrap(); - let res = client - .request(Method::POST, "https://slack.com/api/openid.connect.token") - .query(&[ - ("client_id", SLACK_CLIENT_ID), - ("client_secret", SLACK_CLIENT_SECRET), - ("code", &code), - ("grant_type", "authorization_code"), - ("redirect_uri", SLACK_REDIRECT_URI), - ]) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - - eprintln!("{:?}", res); - } - }; - } -} diff --git a/burrow-gtk/src/components/mod.rs b/burrow-gtk/src/components/mod.rs index 20c213c..b134809 100644 --- a/burrow-gtk/src/components/mod.rs +++ b/burrow-gtk/src/components/mod.rs @@ -13,7 +13,6 @@ use std::sync::Arc; use tokio::sync::Mutex; mod app; -mod auth_screen; mod settings; mod settings_screen; mod switch_screen; diff --git a/burrow-gtk/src/components/settings/diag_group.rs b/burrow-gtk/src/components/settings/diag_group.rs index a15e0ea..c4c637d 100644 --- a/burrow-gtk/src/components/settings/diag_group.rs +++ b/burrow-gtk/src/components/settings/diag_group.rs @@ -35,6 +35,7 @@ impl DiagGroup { #[derive(Debug)] pub enum DiagGroupMsg { Refresh, + TestSlackAuth, } #[relm4::component(pub, async)] @@ -85,7 +86,11 @@ impl AsyncComponent for DiagGroup { gtk::Button { set_label: "Refresh", connect_clicked => DiagGroupMsg::Refresh - } + }, + gtk::Button { + set_label: "Authenticate with Slack", + connect_clicked => DiagGroupMsg::TestSlackAuth, + }, } } @@ -113,6 +118,9 @@ impl AsyncComponent for DiagGroup { // Should be impossible to panic here *self = Self::new(Arc::clone(&self.daemon_client)).await.unwrap(); } + DiagGroupMsg::TestSlackAuth => { + auth::slack_auth().await; + } } } }