@@ -109,6 +109,19 @@ impl Configuration {
109109 self . auth_keys . insert ( operation_str. to_string ( ) , api_key) ;
110110 }
111111
112+ /// Set a Personal Access Token (PAT) for authentication.
113+ /// The PAT is used in place of an application key and is sent
114+ /// via the DD-APPLICATION-KEY header.
115+ pub fn set_pat ( & mut self , pat : String ) {
116+ self . auth_keys . insert (
117+ "appKeyAuth" . to_string ( ) ,
118+ APIKey {
119+ key : pat,
120+ prefix : "" . to_owned ( ) ,
121+ } ,
122+ ) ;
123+ }
124+
112125 pub fn set_proxy_url ( & mut self , proxy_url : Option < String > ) {
113126 self . proxy_url = proxy_url;
114127 }
@@ -363,6 +376,19 @@ impl Default for Configuration {
363376 } ,
364377 ) ;
365378
379+ // DD_PAT takes precedence over DD_APP_KEY when set
380+ if let Ok ( pat) = env:: var ( "DD_PAT" ) {
381+ if !pat. is_empty ( ) {
382+ auth_keys. insert (
383+ "appKeyAuth" . to_owned ( ) ,
384+ APIKey {
385+ key : pat,
386+ prefix : "" . to_owned ( ) ,
387+ } ,
388+ ) ;
389+ }
390+ }
391+
366392 Self {
367393 user_agent : DEFAULT_USER_AGENT . clone ( ) ,
368394 unstable_operations,
@@ -1128,3 +1154,113 @@ lazy_static! {
11281154 ] )
11291155 } ;
11301156}
1157+
1158+ #[ cfg( test) ]
1159+ mod tests {
1160+ use super :: * ;
1161+ use std:: sync:: Mutex ;
1162+
1163+ // Mutex to prevent env var tests from interfering with each other
1164+ static ENV_MUTEX : Mutex < ( ) > = Mutex :: new ( ( ) ) ;
1165+
1166+ #[ test]
1167+ fn test_set_pat_overrides_app_key ( ) {
1168+ let mut config = Configuration :: new ( ) ;
1169+ config. set_pat ( "my-pat-token" . to_string ( ) ) ;
1170+
1171+ let app_key = config. auth_keys . get ( "appKeyAuth" ) . unwrap ( ) ;
1172+ assert_eq ! ( app_key. key, "my-pat-token" ) ;
1173+ }
1174+
1175+ #[ test]
1176+ fn test_set_pat_after_construction ( ) {
1177+ let mut config = Configuration :: new ( ) ;
1178+ // Set an app key first
1179+ config. set_auth_key (
1180+ "appKeyAuth" ,
1181+ APIKey {
1182+ key : "original-app-key" . to_string ( ) ,
1183+ prefix : "" . to_string ( ) ,
1184+ } ,
1185+ ) ;
1186+ // Now override with PAT
1187+ config. set_pat ( "my-pat-token" . to_string ( ) ) ;
1188+
1189+ let app_key = config. auth_keys . get ( "appKeyAuth" ) . unwrap ( ) ;
1190+ assert_eq ! ( app_key. key, "my-pat-token" ) ;
1191+ }
1192+
1193+ #[ test]
1194+ fn test_dd_pat_env_var ( ) {
1195+ let _lock = ENV_MUTEX . lock ( ) . unwrap ( ) ;
1196+ // Save and clear existing values
1197+ let old_pat = env:: var ( "DD_PAT" ) . ok ( ) ;
1198+ let old_app_key = env:: var ( "DD_APP_KEY" ) . ok ( ) ;
1199+
1200+ env:: set_var ( "DD_PAT" , "env-pat-token" ) ;
1201+ env:: remove_var ( "DD_APP_KEY" ) ;
1202+
1203+ let config = Configuration :: default ( ) ;
1204+ let app_key = config. auth_keys . get ( "appKeyAuth" ) . unwrap ( ) ;
1205+ assert_eq ! ( app_key. key, "env-pat-token" ) ;
1206+
1207+ // Restore env
1208+ match old_pat {
1209+ Some ( v) => env:: set_var ( "DD_PAT" , v) ,
1210+ None => env:: remove_var ( "DD_PAT" ) ,
1211+ }
1212+ match old_app_key {
1213+ Some ( v) => env:: set_var ( "DD_APP_KEY" , v) ,
1214+ None => env:: remove_var ( "DD_APP_KEY" ) ,
1215+ }
1216+ }
1217+
1218+ #[ test]
1219+ fn test_dd_pat_precedence_over_dd_app_key ( ) {
1220+ let _lock = ENV_MUTEX . lock ( ) . unwrap ( ) ;
1221+ // Save existing values
1222+ let old_pat = env:: var ( "DD_PAT" ) . ok ( ) ;
1223+ let old_app_key = env:: var ( "DD_APP_KEY" ) . ok ( ) ;
1224+
1225+ env:: set_var ( "DD_PAT" , "pat-wins" ) ;
1226+ env:: set_var ( "DD_APP_KEY" , "app-key-loses" ) ;
1227+
1228+ let config = Configuration :: default ( ) ;
1229+ let app_key = config. auth_keys . get ( "appKeyAuth" ) . unwrap ( ) ;
1230+ assert_eq ! ( app_key. key, "pat-wins" ) ;
1231+
1232+ // Restore env
1233+ match old_pat {
1234+ Some ( v) => env:: set_var ( "DD_PAT" , v) ,
1235+ None => env:: remove_var ( "DD_PAT" ) ,
1236+ }
1237+ match old_app_key {
1238+ Some ( v) => env:: set_var ( "DD_APP_KEY" , v) ,
1239+ None => env:: remove_var ( "DD_APP_KEY" ) ,
1240+ }
1241+ }
1242+
1243+ #[ test]
1244+ fn test_empty_dd_pat_does_not_override ( ) {
1245+ let _lock = ENV_MUTEX . lock ( ) . unwrap ( ) ;
1246+ let old_pat = env:: var ( "DD_PAT" ) . ok ( ) ;
1247+ let old_app_key = env:: var ( "DD_APP_KEY" ) . ok ( ) ;
1248+
1249+ env:: set_var ( "DD_PAT" , "" ) ;
1250+ env:: set_var ( "DD_APP_KEY" , "my-app-key" ) ;
1251+
1252+ let config = Configuration :: default ( ) ;
1253+ let app_key = config. auth_keys . get ( "appKeyAuth" ) . unwrap ( ) ;
1254+ assert_eq ! ( app_key. key, "my-app-key" ) ;
1255+
1256+ // Restore env
1257+ match old_pat {
1258+ Some ( v) => env:: set_var ( "DD_PAT" , v) ,
1259+ None => env:: remove_var ( "DD_PAT" ) ,
1260+ }
1261+ match old_app_key {
1262+ Some ( v) => env:: set_var ( "DD_APP_KEY" , v) ,
1263+ None => env:: remove_var ( "DD_APP_KEY" ) ,
1264+ }
1265+ }
1266+ }
0 commit comments