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 index::{AuthPolicy, Index, Indexes};
|
||||||
pub use keyring::KeyringProvider;
|
pub use keyring::KeyringProvider;
|
||||||
pub use middleware::AuthMiddleware;
|
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 realm::Realm;
|
||||||
pub use service::{Service, ServiceParseError};
|
pub use service::{Service, ServiceParseError};
|
||||||
pub use store::{AuthBackend, AuthScheme, TextCredentialStore, TomlCredentialError};
|
pub use store::{AuthBackend, AuthScheme, TextCredentialStore, TomlCredentialError};
|
||||||
|
|
|
||||||
|
|
@ -368,9 +368,9 @@ impl PyxTokenStore {
|
||||||
tolerance_secs: u64,
|
tolerance_secs: u64,
|
||||||
) -> Result<PyxTokens, TokenStoreError> {
|
) -> Result<PyxTokens, TokenStoreError> {
|
||||||
// Decode the access token.
|
// Decode the access token.
|
||||||
let jwt = Jwt::decode(match &tokens {
|
let jwt = PyxJwt::decode(match &tokens {
|
||||||
PyxTokens::OAuth(PyxOAuthTokens { access_token, .. }) => access_token.as_str(),
|
PyxTokens::OAuth(PyxOAuthTokens { access_token, .. }) => access_token,
|
||||||
PyxTokens::ApiKey(PyxApiKeyTokens { access_token, .. }) => access_token.as_str(),
|
PyxTokens::ApiKey(PyxApiKeyTokens { access_token, .. }) => access_token,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// If the access token is expired, refresh it.
|
// If the access token is expired, refresh it.
|
||||||
|
|
@ -503,14 +503,20 @@ impl TokenStoreError {
|
||||||
|
|
||||||
/// The payload of the JWT.
|
/// The payload of the JWT.
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
struct Jwt {
|
pub struct PyxJwt {
|
||||||
exp: Option<i64>,
|
/// 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.
|
/// Decode the JWT from the access token.
|
||||||
fn decode(access_token: &str) -> Result<Self, JwtError> {
|
pub fn decode(access_token: &AccessToken) -> Result<Self, JwtError> {
|
||||||
let mut token_segments = access_token.splitn(3, '.');
|
let mut token_segments = access_token.as_str().splitn(3, '.');
|
||||||
|
|
||||||
let _header = token_segments.next().ok_or(JwtError::MissingHeader)?;
|
let _header = token_segments.next().ok_or(JwtError::MissingHeader)?;
|
||||||
let payload = token_segments.next().ok_or(JwtError::MissingPayload)?;
|
let payload = token_segments.next().ok_or(JwtError::MissingPayload)?;
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use uv_auth::{
|
use uv_auth::{
|
||||||
AccessToken, AuthBackend, Credentials, PyxOAuthTokens, PyxTokenStore, PyxTokens, Service,
|
AccessToken, AuthBackend, Credentials, PyxJwt, PyxOAuthTokens, PyxTokenStore, PyxTokens,
|
||||||
TextCredentialStore,
|
Service, TextCredentialStore,
|
||||||
};
|
};
|
||||||
use uv_client::{AuthIntegration, BaseClient, BaseClientBuilder};
|
use uv_client::{AuthIntegration, BaseClient, BaseClientBuilder};
|
||||||
use uv_distribution_types::IndexUrl;
|
use uv_distribution_types::IndexUrl;
|
||||||
|
|
@ -45,12 +45,19 @@ pub(crate) async fn login(
|
||||||
.auth_integration(AuthIntegration::NoAuthMiddleware)
|
.auth_integration(AuthIntegration::NoAuthMiddleware)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
pyx_login_with_browser(&pyx_store, &client, &printer).await?;
|
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!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"Logged in to {}",
|
"Logged in to {}",
|
||||||
pyx_store.api().bold().cyan()
|
pyx_store.api().bold().cyan()
|
||||||
)?;
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue