@@ -4,7 +4,7 @@ use std::io::Read;
44
55use anyhow:: { Context , Result , bail} ;
66use serde:: { Deserialize , Serialize } ;
7- use url :: Url ;
7+ use tracing :: debug ;
88
99use uv_auth:: { AuthBackend , Credentials , PyxTokenStore } ;
1010use uv_client:: BaseClientBuilder ;
@@ -16,7 +16,7 @@ use crate::{commands::ExitStatus, printer::Printer, settings::NetworkSettings};
1616/// Request format for the Bazel credential helper protocol.
1717#[ derive( Debug , Deserialize ) ]
1818struct BazelCredentialRequest {
19- uri : String ,
19+ uri : DisplaySafeUrl ,
2020}
2121
2222impl BazelCredentialRequest {
@@ -42,21 +42,16 @@ struct BazelCredentialResponse {
4242
4343impl TryFrom < Credentials > for BazelCredentialResponse {
4444 fn try_from ( creds : Credentials ) -> Result < Self > {
45- let mut headers = HashMap :: new ( ) ;
46- // Only include the Authorization header if credentials are authenticated
47- // (i.e., not just a username without password)
48- if creds. is_authenticated ( ) {
49- let header_value = creds. to_header_value ( ) ;
50-
51- // Convert HeaderValue to String
52- let header_str = header_value
53- . to_str ( )
54- . context ( "Failed to convert header value to string" ) ?
55- . to_string ( ) ;
56-
57- headers. insert ( "Authorization" . to_string ( ) , vec ! [ header_str] ) ;
58- }
59- Ok ( Self { headers } )
45+ let header_str = creds
46+ . to_header_value ( )
47+ . to_str ( )
48+ // TODO: this is infallible in practice
49+ . context ( "Failed to convert header value to string" ) ?
50+ . to_owned ( ) ;
51+
52+ Ok ( Self {
53+ headers : HashMap :: from ( [ ( "Authorization" . to_owned ( ) , vec ! [ header_str] ) ] ) ,
54+ } )
6055 }
6156
6257 type Error = anyhow:: Error ;
@@ -71,16 +66,22 @@ async fn credentials_for_url(
7166
7267 // Use only the username from the URL, if present - discarding the password
7368 let url_credentials = Credentials :: from_url ( url) ;
74- let url_username = url_credentials. as_ref ( ) . and_then ( |c| c. username ( ) ) ;
75- let username = url_username. map ( ToString :: to_string) ;
69+ let username = url_credentials. as_ref ( ) . and_then ( |c| c. username ( ) ) ;
70+ if url_credentials
71+ . as_ref ( )
72+ . map ( |c| c. password ( ) . is_some ( ) )
73+ . unwrap_or ( false )
74+ {
75+ debug ! ( "URL '{url}' contain a password; ignoring" ) ;
76+ }
7677
7778 if pyx_store. is_known_domain ( url) {
7879 if username. is_some ( ) {
7980 bail ! (
8081 "Cannot specify a username for URLs under {}" ,
8182 url. host( )
8283 . map( |host| host. to_string( ) )
83- . unwrap_or( "this host" . to_owned ( ) )
84+ . unwrap_or( url . to_string ( ) )
8485 ) ;
8586 }
8687 let client = BaseClientBuilder :: new (
@@ -97,15 +98,13 @@ async fn credentials_for_url(
9798 . access_token ( client. for_host ( pyx_store. api ( ) ) . raw_client ( ) , 0 )
9899 . await
99100 . context ( "Authentication failure" ) ?;
100- let token = maybe_token. ok_or_else ( || anyhow :: anyhow! ( "No access token found" ) ) ?;
101+ let token = maybe_token. context ( "No access token found" ) ?;
101102 return Ok ( Some ( Credentials :: bearer ( token. into_bytes ( ) ) ) ) ;
102103 }
103104 let backend = AuthBackend :: from_settings ( preview) ?;
104105 let credentials = match & backend {
105- AuthBackend :: System ( provider) => provider. fetch ( url, username. as_deref ( ) ) . await ,
106- AuthBackend :: TextStore ( store, _lock) => {
107- store. get_credentials ( url, username. as_deref ( ) ) . cloned ( )
108- }
106+ AuthBackend :: System ( provider) => provider. fetch ( url, username) . await ,
107+ AuthBackend :: TextStore ( store, _lock) => store. get_credentials ( url, username) . cloned ( ) ,
109108 } ;
110109 Ok ( credentials)
111110}
@@ -131,17 +130,14 @@ pub(crate) async fn helper(
131130
132131 // TODO: make this logic generic over the protocol by providing `request.uri` from a
133132 // trait - that should help with adding new protocols
134- let url = Url :: parse ( & request. uri ) . context ( "Invalid URI in credential request" ) ?;
135- let safe_url = DisplaySafeUrl :: from_url ( url) ;
136-
137- let credentials = credentials_for_url ( & safe_url, preview, network_settings) . await ?;
133+ let credentials = credentials_for_url ( & request. uri , preview, network_settings) . await ?;
138134
139135 let response = serde_json:: to_string (
140136 & credentials
141137 . map ( BazelCredentialResponse :: try_from)
142138 . unwrap_or_else ( || Ok ( BazelCredentialResponse :: default ( ) ) ) ?,
143139 )
144140 . context ( "Failed to serialize response as JSON" ) ?;
145- writeln ! ( printer. stdout ( ) , "{response}" ) ?;
141+ writeln ! ( printer. stdout_important ( ) , "{response}" ) ?;
146142 Ok ( ExitStatus :: Success )
147143}
0 commit comments