Conversation
This appears to be working well! Some feedback:
Doing just a written approval here for the working, feel free to land after a code review. |
src/login/mod.rs
Outdated
|
||
rsa.private_decrypt(&encrypted_token, &mut token_bytes, Padding::PKCS1)?; | ||
let token = str::from_utf8(&token_bytes)?.trim_matches(char::from(0)); | ||
if wsl::is_wsl() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a better way to check if the current process is run on WSL without having to include another dependency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should just print this URL out despite its verbosity.. I get @threepointone's point for sure and generally agree.. but what about the case where users launch wrangler from within a Docker container? Probably not handled by this WSL crate, but wouldn't be able to open a host browser window either.
src/commands/dev/edge/mod.rs
Outdated
let mut user = user.clone(); | ||
|
||
// Check if oauth token is expired | ||
let _res = check_update_oauth_token(&mut user).expect("Failed to refresh access token"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it isn't likely that the user will be able to do anything if the expect
is reached from an Err value, we may want to consider letting the dev
caller handle this error or print something more useful here. "Failed to refresh access token"
isn't as informative as whatever might come back from the API for this call.
@ocsfrank could you dig in a bit and see what other options are available here? The end-goal is providing as much to the wrangler
user as possible for debugging.. as this stands, we just print this panic message and maybe a backtrace before suggesting they wrangler report
the issue. But, it's unlikely that we can help them, or that they can help themselves without more info.
src/commands/logout.rs
Outdated
pub fn run() -> Result<()> { | ||
let user_create = GlobalUser::new(); | ||
let mut has_auth = true; | ||
if let Ok(user) = user_create { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can any/all of these be written as if let Ok(user) = GlobalUser::new() { ... }
? Doesn't look like you need the user_create
binding anywhere. (I easily could be missing it though)
src/commands/whoami.rs
Outdated
missing_permissions: &mut Vec<String>, | ||
token_type: &str, | ||
) -> Result<String> { | ||
let token_auth_email = fetch_auth_token_email(user, missing_permissions)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly here, I think could be shortened to if let Some(token_auth_email) = fetch_auth_token_email(user, missing_permissions)? { ... }
src/commands/whoami.rs
Outdated
"an API Token".to_string() | ||
} | ||
GlobalUser::ApiTokenAuth { .. } => get_token_type(user, &mut missing_permissions, "API") | ||
.expect("Failed to get Api token type."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Api/API
Also, I think this and the following match arm should bubble up this error, or print more of the returned error's context if its available. The panic will not be very useful, and an error report via wrangler report
isn't likely to be resolved by our team.
src/login/mod.rs
Outdated
|
||
rsa.private_decrypt(&encrypted_token, &mut token_bytes, Padding::PKCS1)?; | ||
let token = str::from_utf8(&token_bytes)?.trim_matches(char::from(0)); | ||
if wsl::is_wsl() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should just print this URL out despite its verbosity.. I get @threepointone's point for sure and generally agree.. but what about the case where users launch wrangler from within a Docker container? Probably not handled by this WSL crate, but wouldn't be able to open a host browser window either.
src/login/mod.rs
Outdated
let user = GlobalUser::TokenAuth { | ||
api_token: token.to_string(), | ||
// Get authorization code and CSRF state from local HTTP server | ||
let params_response = match block_on(http_server_get_params()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason in particular to use the executor from futures
here rather than tokio
(asking because it looks like you're using tokio
elsewhere) ? Not saying it doesn't work, but I think this means we're using different runtimes for various async operations here.
if result.is_err() { | ||
log::debug!("Failed to invalidate OAuth token before login."); | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally in this file src/login/mod.rs
(besides tests), there is a lot of unwrap
and expect
usage. I think some of these are in places that will create a lot of noise from wrangler report
usage, and could be cleaned up a bit. Consider some ?
usage in place of these where returning the error (even if it's printed later on) could give the user some way of debugging an issue.
Many of them might be fine. Just adding a comment here to suggest taking another pass at error handling along this path.
src/settings/global_user.rs
Outdated
// Check if oauth token is expired | ||
if let Ok(ref mut oauth_user) = new_user { | ||
let _res = | ||
check_update_oauth_token(oauth_user).expect("Failed to refresh access token"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another case to consider more useful error handling / context-sharing with the end user.
|| ((oauth_token.is_ok() || refresh_token.is_ok() || expiration_time.is_ok()) | ||
&& (email.is_ok() || api_key.is_ok())) | ||
{ | ||
let error_info = "\nMore than one authentication method (e.g. API token and OAuth token, or OAuth token and Global API key) has been found in the configuration file. Please use only one."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably add more detail to this error:
- print the path to the config file in case they want to manually edit it
- suggest running
wrangler logout
(assuming this clears all auth info on disk?)
src/settings/global_user.rs
Outdated
} else if api_token.is_ok() { | ||
Ok(Self::ApiTokenAuth { | ||
api_token: api_token.expect("Failed to read API token"), | ||
}) | ||
} else if email.is_ok() && api_key.is_ok() { | ||
Ok(Self::GlobalKeyAuth { | ||
email: email.expect("Failed to read email"), | ||
api_key: api_key.expect("Failed to read api_key"), | ||
}) | ||
} else if oauth_token.is_ok() && refresh_token.is_ok() && expiration_time.is_ok() { | ||
Ok(Self::OAuthTokenAuth { | ||
oauth_token: oauth_token.expect("Failed to read OAuth token"), | ||
refresh_token: refresh_token.expect("Failed to read OAuth refresh token"), | ||
expiration_time: expiration_time | ||
.expect("Failed to read access token expiration time"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all of these expect
calls can just be unwrap
, since you've already attested the are Ok
in the if checks
}) | ||
} else { | ||
// Empty configuration file and no environment variables, or missing variable for global API key | ||
let error_info = "\nNo (valid) authentication method has been found."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could add more detail here too.. could running wrangler login
help? let's offer some suggestions for a user to try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! That would help, and it's being printed in the next line with the call to Self::show_config_err_info(Some(error_info.to_string()), config)
.
src/login/http.rs
Outdated
} | ||
}); | ||
|
||
// Receive authorization code and csrf state from HTTP server | ||
let params = runtime.block_on(async { | ||
let params = tokio::task::spawn(async move { | ||
match rx.recv().await { | ||
Some(values) => values, | ||
None => "error".to_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we have a history of difficult-to-debug channel errors, maybe we could be more descriptive and log this error (unless it is already being logged somewhere in the calling context).
do you know if it is possible that the rx
can receive None
at any point before it gets Some(values)
and should therefore be polled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logging is a good idea. The only case that I am aware of is when the sender side is closed for any reason, and rx
still tries to read something. In this case, it should receive None
.
src/settings/global_user.rs
Outdated
Ok(Self::ApiTokenAuth { | ||
api_token: api_token.unwrap(), | ||
api_token: api_token_value, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: these could be re-written to be a bit more concise:
} else if let Ok(api_token) = api_token {
Ok(Self::ApiTokenAuth { api_token})
// ...
the same is true for all the branches below. if the variable binding (in this case inside the if let, shadowing the outer one) is the same as the field name, you can omit the field name and just pass in the variable name in its place. Not major, but might make the code a bit nicer to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see! Will include these changes in the next commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have verified that the changes work as expected on my machine.
Still in staging, but it should be ready for review.
Please also ignore the cargo.toml, I will update it once the service goes to prod. The CI test are failing because of
oauth2
library.