mirror of https://github.com/astral-sh/uv
Show organization name after authenticating (#15823)
## Summary Shows the name of the logged-in organization on success, rather than repeating the URL.
This commit is contained in:
parent
663053b0d1
commit
ac52201626
|
|
@ -10,7 +10,9 @@ pub use credentials::{Credentials, Username};
|
|||
pub use index::{AuthPolicy, Index, Indexes};
|
||||
pub use keyring::KeyringProvider;
|
||||
pub use middleware::AuthMiddleware;
|
||||
pub use pyx::{DEFAULT_TOLERANCE_SECS, PyxOAuthTokens, PyxTokenStore, PyxTokens, TokenStoreError};
|
||||
pub use pyx::{
|
||||
DEFAULT_TOLERANCE_SECS, PyxJwt, PyxOAuthTokens, PyxTokenStore, PyxTokens, TokenStoreError,
|
||||
};
|
||||
pub use realm::Realm;
|
||||
pub use service::{Service, ServiceParseError};
|
||||
pub use store::{AuthBackend, AuthScheme, TextCredentialStore, TomlCredentialError};
|
||||
|
|
|
|||
|
|
@ -368,9 +368,9 @@ impl PyxTokenStore {
|
|||
tolerance_secs: u64,
|
||||
) -> Result<PyxTokens, TokenStoreError> {
|
||||
// Decode the access token.
|
||||
let jwt = Jwt::decode(match &tokens {
|
||||
PyxTokens::OAuth(PyxOAuthTokens { access_token, .. }) => access_token.as_str(),
|
||||
PyxTokens::ApiKey(PyxApiKeyTokens { access_token, .. }) => access_token.as_str(),
|
||||
let jwt = PyxJwt::decode(match &tokens {
|
||||
PyxTokens::OAuth(PyxOAuthTokens { access_token, .. }) => access_token,
|
||||
PyxTokens::ApiKey(PyxApiKeyTokens { access_token, .. }) => access_token,
|
||||
})?;
|
||||
|
||||
// If the access token is expired, refresh it.
|
||||
|
|
@ -503,14 +503,20 @@ impl TokenStoreError {
|
|||
|
||||
/// The payload of the JWT.
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct Jwt {
|
||||
exp: Option<i64>,
|
||||
pub struct PyxJwt {
|
||||
/// The expiration time of the JWT, as a Unix timestamp.
|
||||
pub exp: Option<i64>,
|
||||
/// The issuer of the JWT.
|
||||
pub iss: Option<String>,
|
||||
/// The name of the organization, if any.
|
||||
#[serde(rename = "urn:pyx:org_name")]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
impl Jwt {
|
||||
impl PyxJwt {
|
||||
/// Decode the JWT from the access token.
|
||||
fn decode(access_token: &str) -> Result<Self, JwtError> {
|
||||
let mut token_segments = access_token.splitn(3, '.');
|
||||
pub fn decode(access_token: &AccessToken) -> Result<Self, JwtError> {
|
||||
let mut token_segments = access_token.as_str().splitn(3, '.');
|
||||
|
||||
let _header = token_segments.next().ok_or(JwtError::MissingHeader)?;
|
||||
let payload = token_segments.next().ok_or(JwtError::MissingPayload)?;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ use url::Url;
|
|||
use uuid::Uuid;
|
||||
|
||||
use uv_auth::{
|
||||
AccessToken, AuthBackend, Credentials, PyxOAuthTokens, PyxTokenStore, PyxTokens, Service,
|
||||
TextCredentialStore,
|
||||
AccessToken, AuthBackend, Credentials, PyxJwt, PyxOAuthTokens, PyxTokenStore, PyxTokens,
|
||||
Service, TextCredentialStore,
|
||||
};
|
||||
use uv_client::{AuthIntegration, BaseClient, BaseClientBuilder};
|
||||
use uv_distribution_types::IndexUrl;
|
||||
|
|
@ -45,12 +45,19 @@ pub(crate) async fn login(
|
|||
.auth_integration(AuthIntegration::NoAuthMiddleware)
|
||||
.build();
|
||||
|
||||
pyx_login_with_browser(&pyx_store, &client, &printer).await?;
|
||||
writeln!(
|
||||
printer.stderr(),
|
||||
"Logged in to {}",
|
||||
pyx_store.api().bold().cyan()
|
||||
)?;
|
||||
let access_token = pyx_login_with_browser(&pyx_store, &client, &printer).await?;
|
||||
let jwt = PyxJwt::decode(&access_token)?;
|
||||
|
||||
if let Some(name) = jwt.name.as_deref() {
|
||||
writeln!(printer.stderr(), "Logged in to {}", name.bold().cyan())?;
|
||||
} else {
|
||||
writeln!(
|
||||
printer.stderr(),
|
||||
"Logged in to {}",
|
||||
pyx_store.api().bold().cyan()
|
||||
)?;
|
||||
}
|
||||
|
||||
return Ok(ExitStatus::Success);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue