diff options
Diffstat (limited to 'teleterm/src/oauth.rs')
-rw-r--r-- | teleterm/src/oauth.rs | 118 |
1 files changed, 81 insertions, 37 deletions
diff --git a/teleterm/src/oauth.rs b/teleterm/src/oauth.rs index d76a1b7..c4ec4bb 100644 --- a/teleterm/src/oauth.rs +++ b/teleterm/src/oauth.rs @@ -1,40 +1,39 @@ use crate::prelude::*; use oauth2::TokenResponse as _; -mod recurse_center; -pub use recurse_center::RecurseCenter; - // this needs to be fixed because we listen for it in a hardcoded place pub const CLI_REDIRECT_URL: &str = "http://localhost:44141/oauth"; -pub trait Oauth { - fn client(&self) -> &oauth2::basic::BasicClient; - fn user_id(&self) -> &str; - fn name(&self) -> &str; +pub struct Oauth { + client: oauth2::basic::BasicClient, + user_id: String, +} - fn server_token_file( - &self, - must_exist: bool, - ) -> Option<std::path::PathBuf> { - let name = format!("server-oauth-{}-{}", self.name(), self.user_id()); - crate::dirs::Dirs::new().data_file(&name, must_exist) +impl Oauth { + pub fn new(config: Config, user_id: String) -> Self { + let client = config.into_basic_client(); + Self { client, user_id } } - fn generate_authorize_url(&self) -> String { + pub fn generate_authorize_url(&self) -> String { let (auth_url, _) = self - .client() + .client .authorize_url(oauth2::CsrfToken::new_random) .url(); auth_url.to_string() } - fn get_access_token_from_auth_code( + pub fn user_id(&self) -> &str { + &self.user_id + } + + pub fn get_access_token_from_auth_code( &self, code: &str, ) -> Box<dyn futures::Future<Item = String, Error = Error> + Send> { let token_cache_file = self.server_token_file(false).unwrap(); let fut = self - .client() + .client .exchange_code(oauth2::AuthorizationCode::new(code.to_string())) .request_future(oauth2::reqwest::future_http_client) .map_err(|e| { @@ -48,32 +47,61 @@ pub trait Oauth { Box::new(fut) } - fn get_access_token_from_refresh_token( - &self, - token: &str, + pub fn get_access_token_from_refresh_token( + self, ) -> Box<dyn futures::Future<Item = String, Error = Error> + Send> { let token_cache_file = self.server_token_file(false).unwrap(); - let fut = self - .client() - .exchange_refresh_token(&oauth2::RefreshToken::new( - token.to_string(), - )) - .request_future(oauth2::reqwest::future_http_client) - .map_err(|e| { - let msg = stringify_oauth2_http_error(&e); - Error::ExchangeRefreshToken { msg } - }) - .and_then(|token| { - cache_refresh_token(token_cache_file, &token) - .map(move |_| token.access_token().secret().to_string()) - }); + let fut = load_refresh_token(&token_cache_file).and_then( + move |refresh_token| { + // XXX + let refresh_token = refresh_token.unwrap(); + self.client + .exchange_refresh_token(&oauth2::RefreshToken::new( + refresh_token, + )) + .request_future(oauth2::reqwest::future_http_client) + .map_err(|e| { + let msg = stringify_oauth2_http_error(&e); + Error::ExchangeRefreshToken { msg } + }) + .and_then(move |token| { + cache_refresh_token(token_cache_file, &token).map( + move |_| { + token.access_token().secret().to_string() + }, + ) + }) + }, + ); Box::new(fut) } - fn get_username_from_access_token( + pub fn server_token_file( &self, - token: &str, - ) -> Box<dyn futures::Future<Item = String, Error = Error> + Send>; + must_exist: bool, + ) -> Option<std::path::PathBuf> { + let name = format!("server-oauth-{}", self.user_id); + crate::dirs::Dirs::new().data_file(&name, must_exist) + } +} + +fn load_refresh_token( + token_cache_file: &std::path::Path, +) -> Box<dyn futures::Future<Item = Option<String>, Error = Error> + Send> { + let token_cache_file = token_cache_file.to_path_buf(); + Box::new( + tokio::fs::File::open(token_cache_file.clone()) + .with_context(move || crate::error::OpenFile { + filename: token_cache_file.to_string_lossy().to_string(), + }) + .and_then(|file| { + tokio::io::lines(std::io::BufReader::new(file)) + .into_future() + .map_err(|(e, _)| e) + .context(crate::error::ReadFile) + }) + .map(|(refresh_token, _)| refresh_token), + ) } fn cache_refresh_token( @@ -107,6 +135,22 @@ pub struct Config { } impl Config { + pub fn new( + client_id: String, + client_secret: String, + auth_url: url::Url, + token_url: url::Url, + redirect_url: url::Url, + ) -> Self { + Self { + client_id, + client_secret, + auth_url, + token_url, + redirect_url, + } + } + pub fn set_redirect_url(&mut self, url: url::Url) { self.redirect_url = url; } |