Skip to content

Commit

Permalink
Fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
augustuswm committed Oct 6, 2023
1 parent 87b190f commit 3b19b7b
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 74 deletions.
56 changes: 33 additions & 23 deletions rfd-api/src/endpoints/login/oauth/device_token.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use chrono::{DateTime, Utc};
use dropshot::{endpoint, HttpError, HttpResponseOk, Method, Path, RequestContext, TypedBody};
use http::{header, Request, Response, StatusCode, HeaderValue};
use http::{header, HeaderValue, Request, Response, StatusCode};
use hyper::{body::to_bytes, Body};
use oauth2::{basic::BasicTokenType, EmptyExtraTokenFields, StandardTokenResponse, TokenResponse};
use schemars::JsonSchema;
Expand Down Expand Up @@ -155,30 +155,33 @@ pub async fn exchange_device_token(
// We unfortunately can not trust our providers to follow specs and therefore need to do
// our own inspection of the response to determine what to do
if !parts.status.is_success() {

// If the server returned a non-success status then we are going to trust the server and
// report their error back to the client
tracing::debug!(provider = ?path.provider, "Received error response from OAuth provider");

Ok(Response::from_parts(parts, body))
} else {

// The server gave us back a non-error response but it still may not be a success.
// GitHub for instance does not use a status code for indicating the success or failure
// of a call. So instead we try to deserialize the body into an access token, with the
// understanding that it may fail and we will need to try and treat the response as
// an error instead.

let bytes = to_bytes(body).await?;
let parsed: Result<StandardTokenResponse<EmptyExtraTokenFields, BasicTokenType>, serde_json::Error> = serde_json::from_slice(&bytes);
let parsed: Result<
StandardTokenResponse<EmptyExtraTokenFields, BasicTokenType>,
serde_json::Error,
> = serde_json::from_slice(&bytes);

match parsed {
Ok(parsed) => {
let info = provider
.get_user_info(provider.client(), parsed.access_token().secret())
.await
.map_err(LoginError::UserInfo)
.tap_err(|err| tracing::error!(?err, "Failed to look up user information"))?;
.get_user_info(provider.client(), parsed.access_token().secret())
.await
.map_err(LoginError::UserInfo)
.tap_err(|err| {
tracing::error!(?err, "Failed to look up user information")
})?;

tracing::debug!("Verified and validated OAuth user");

Expand Down Expand Up @@ -223,45 +226,52 @@ pub async fn exchange_device_token(
.unwrap()
.into(),
)?)
},
}
Err(_) => {

// Do not log the error here as we want to ensure we do not leak token information
tracing::debug!("Failed to parse a success response from the remote token endpoint");
tracing::debug!(
"Failed to parse a success response from the remote token endpoint"
);

// Try to deserialize the body again, but this time as an error
let mut error_response = match serde_json::from_slice::<ProxyTokenError>(&bytes) {
let mut error_response = match serde_json::from_slice::<ProxyTokenError>(&bytes)
{
Ok(error) => {

// We found an error in the message body. This is not ideal, but we at
// least can understand what the server was trying to tell us
tracing::debug!(?error, provider = ?path.provider, "Parsed error response from OAuth provider");
Response::from_parts(parts, Body::from(bytes))
}
Err(_) => {

// We still do not know what the remote server is doing... and need to
// cancel the request ourselves
tracing::warn!("Remote OAuth provide returned a response that we do not undestand");

Response::new(Body::from(serde_json::to_string(&ProxyTokenError {
error: "access_denied".to_string(),
error_description: Some(format!("{} returned a malformed response", path.provider)),
error_uri: None,
}).unwrap()))
tracing::warn!(
"Remote OAuth provide returned a response that we do not undestand"
);

Response::new(Body::from(
serde_json::to_string(&ProxyTokenError {
error: "access_denied".to_string(),
error_description: Some(format!(
"{} returned a malformed response",
path.provider
)),
error_uri: None,
})
.unwrap(),
))
}
};

*error_response.status_mut() = StatusCode::BAD_REQUEST;
error_response.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("application/json")
HeaderValue::from_static("application/json"),
);

Ok(error_response)
}
}

}
} else {
tracing::info!(provider = ?path.provider, "Found an OAuth provider, but it is not configured properly");
Expand Down
14 changes: 7 additions & 7 deletions rfd-api/src/endpoints/login/oauth/github.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use std::fmt;

use http::{HeaderMap, header::USER_AGENT, HeaderValue};
use http::{header::USER_AGENT, HeaderMap, HeaderValue};
use hyper::body::Bytes;
use reqwest::Client;
use serde::Deserialize;

use crate::endpoints::login::{ExternalUserId, UserInfo, UserInfoError};

use super::{ClientType, ExtractUserInfo, OAuthProvider, OAuthProviderName, OAuthPublicCredentials, OAuthPrivateCredentials};
use super::{
ClientType, ExtractUserInfo, OAuthPrivateCredentials, OAuthProvider, OAuthProviderName,
OAuthPublicCredentials,
};

pub struct GitHubOAuthProvider {
// public: GitHubPublicProvider,
Expand All @@ -34,10 +37,7 @@ impl GitHubOAuthProvider {
) -> Self {
let mut headers = HeaderMap::new();
headers.insert(USER_AGENT, HeaderValue::from_static("rfd-api"));
let client = Client::builder()
.default_headers(headers)
.build()
.unwrap();
let client = Client::builder().default_headers(headers).build().unwrap();

Self {
device_public: OAuthPublicCredentials {
Expand Down Expand Up @@ -87,7 +87,7 @@ impl ExtractUserInfo for GitHubOAuthProvider {
Ok(UserInfo {
external_id: ExternalUserId::GitHub(user.id.to_string()),
verified_emails,
github_username: Some(user.login)
github_username: Some(user.login),
})
}
}
Expand Down
11 changes: 4 additions & 7 deletions rfd-api/src/endpoints/login/oauth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use async_trait::async_trait;
use dropshot::Method;
use http::header;
use hyper::{
body::Bytes,
Body
};
use hyper::{body::Bytes, Body};
use oauth2::{basic::BasicClient, url::ParseError, AuthUrl, ClientId, ClientSecret, TokenUrl};
use rfd_model::OAuthClient;
use schemars::JsonSchema;
Expand Down Expand Up @@ -104,14 +101,14 @@ where
&self,
client: &reqwest::Client,
token: &str,
) -> Result<UserInfo, UserInfoError>
{
) -> Result<UserInfo, UserInfoError> {
tracing::trace!("Requesting user information from OAuth provider");

let mut responses = vec![];

for endpoint in self.user_info_endpoints() {
let request = client.request(Method::GET, endpoint)
let request = client
.request(Method::GET, endpoint)
.header(header::AUTHORIZATION, format!("Bearer {}", token))
.body(Body::empty())
.build()?;
Expand Down
13 changes: 11 additions & 2 deletions rfd-api/src/mapper/github_username.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ impl MapperRule for GitHubUsernameMapper {
_ctx: &ApiContext,
user: &UserInfo,
) -> Result<ApiPermissions, StoreError> {
if user.github_username.as_ref().map(|u| u == &self.github_username).unwrap_or(false)
if user
.github_username
.as_ref()
.map(|u| u == &self.github_username)
.unwrap_or(false)
{
Ok(self.permissions.clone())
} else {
Expand All @@ -38,7 +42,12 @@ impl MapperRule for GitHubUsernameMapper {
ctx: &ApiContext,
user: &UserInfo,
) -> Result<BTreeSet<Uuid>, StoreError> {
if user.github_username.as_ref().map(|u| u == &self.github_username).unwrap_or(false) {
if user
.github_username
.as_ref()
.map(|u| u == &self.github_username)
.unwrap_or(false)
{
let groups = ctx
.get_groups()
.await?
Expand Down
5 changes: 4 additions & 1 deletion rfd-api/src/mapper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use uuid::Uuid;

use crate::{context::ApiContext, endpoints::login::UserInfo, ApiPermissions};

use self::{email_address::EmailAddressMapper, email_domain::EmailDomainMapper, github_username::GitHubUsernameMapper};
use self::{
email_address::EmailAddressMapper, email_domain::EmailDomainMapper,
github_username::GitHubUsernameMapper,
};

pub mod email_address;
pub mod email_domain;
Expand Down
9 changes: 5 additions & 4 deletions rfd-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use anyhow::{anyhow, Result};
use clap::{Arg, ArgAction, Command, CommandFactory, FromArgMatches};
use generated::cli::*;
use printer::{RfdTabPrinter, Printer, RfdJsonPrinter};
use printer::{Printer, RfdJsonPrinter, RfdTabPrinter};
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use rfd_sdk::Client;
use std::time::Duration;
Expand Down Expand Up @@ -168,7 +168,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
}

let mut cmd = root.cmd("rfd");
cmd = cmd.bin_name("rfd")
cmd = cmd
.bin_name("rfd")
.arg(
Arg::new("debug")
.long("debug")
Expand All @@ -185,7 +186,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
.global(true)
.value_parser(["json", "tab"])
.default_value("json")
.action(ArgAction::Set)
.action(ArgAction::Set),
);

cmd = cmd.subcommand(cmd::config::ConfigCmd::command());
Expand All @@ -203,7 +204,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let printer = match format.as_str() {
"json" => Printer::Json(RfdJsonPrinter),
"tab" => Printer::Tab(RfdTabPrinter),
other => panic!("Unknown format {}", other)
other => panic!("Unknown format {}", other),
};

let mut node = &root;
Expand Down
7 changes: 5 additions & 2 deletions rfd-cli/src/printer/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::generated::cli::CliOutput;

pub struct RfdJsonPrinter;

fn print_cli_output<T>(response: &Result<T, progenitor_client::Error<types::Error>>) where T: Serialize {
fn print_cli_output<T>(response: &Result<T, progenitor_client::Error<types::Error>>)
where
T: Serialize,
{
match response {
Ok(res) => println!("{}", serde_json::to_string(&res).unwrap()),
Err(err) => eprintln!("{}", err),
Expand Down Expand Up @@ -225,4 +228,4 @@ impl CliOutput for RfdJsonPrinter {
) {
print_cli_output(&response)
}
}
}
2 changes: 1 addition & 1 deletion rfd-cli/src/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,4 @@ impl CliOutput for Printer {
Printer::Tab(printer) => printer.output_get_self(response),
}
}
}
}
52 changes: 32 additions & 20 deletions rfd-cli/src/printer/tab.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use itertools::{Itertools, EitherOrBoth};
use rfd_sdk::types::{Error, ListRfd, ApiUserForApiPermission, AccessGroupForApiPermission};
use itertools::{EitherOrBoth, Itertools};
use rfd_sdk::types::{AccessGroupForApiPermission, ApiUserForApiPermission, Error, ListRfd};
use std::{fs::File, io::Write, process::Command};
use tabwriter::TabWriter;

Expand Down Expand Up @@ -118,7 +118,7 @@ impl CliOutput for RfdTabPrinter {
) {
match response {
Ok(user) => print_user(&user),
Err(err) => print_error(err)
Err(err) => print_error(err),
}
}

Expand All @@ -128,7 +128,7 @@ impl CliOutput for RfdTabPrinter {
) {
match response {
Ok(user) => print_user(&user),
Err(err) => print_error(err)
Err(err) => print_error(err),
}
}

Expand All @@ -141,7 +141,7 @@ impl CliOutput for RfdTabPrinter {
) {
match response {
Ok(groups) => print_groups(&groups),
Err(err) => print_error(err)
Err(err) => print_error(err),
}
}
}
Expand Down Expand Up @@ -239,9 +239,17 @@ fn print_user(user: &ApiUserForApiPermission) {
&mut tw,
"{}{}\t{}\t{}",
TEXT_COLOR,
if i == 0 { user.id.to_string() } else { String::new() },
if i == 0 {
user.id.to_string()
} else {
String::new()
},
inner,
if i == 0 { user.created_at.to_string() } else { String::new() },
if i == 0 {
user.created_at.to_string()
} else {
String::new()
},
);
}

Expand All @@ -254,27 +262,31 @@ fn print_user(user: &ApiUserForApiPermission) {
fn print_groups(groups: &Vec<AccessGroupForApiPermission>) {
let mut tw = TabWriter::new(vec![]).ansi(true);

writeln!(
&mut tw,
"{}Id\tName\tPermissions\tCreated At",
HEADER_COLOR
);
writeln!(
&mut tw,
"{}--\t----\t-----------\t----------",
HEADER_COLOR
);
writeln!(&mut tw, "{}Id\tName\tPermissions\tCreated At", HEADER_COLOR);
writeln!(&mut tw, "{}--\t----\t-----------\t----------", HEADER_COLOR);

for group in groups {
for (i, permission) in group.permissions.iter().enumerate() {
writeln!(
&mut tw,
"{}{}\t{}\t{}\t{}",
TEXT_COLOR,
if i == 0 { group.id.to_string() } else { String::new() },
if i == 0 { group.name.to_string() } else { String::new() },
if i == 0 {
group.id.to_string()
} else {
String::new()
},
if i == 0 {
group.name.to_string()
} else {
String::new()
},
permission,
if i == 0 { group.created_at.to_string() } else { String::new() },
if i == 0 {
group.created_at.to_string()
} else {
String::new()
},
);
}
}
Expand Down
Loading

0 comments on commit 3b19b7b

Please sign in to comment.