@@ -318,6 +318,22 @@ impl RestCatalog {
318
318
319
319
Ok ( file_io)
320
320
}
321
+
322
+ /// Invalidate the current token without generating a new one. On the next request, the client
323
+ /// will attempt to generate a new token.
324
+ pub async fn invalidate_token ( & self ) -> Result < ( ) > {
325
+ self . context ( ) . await ?. client . invalidate_token ( ) . await
326
+ }
327
+
328
+ /// Invalidate the current token and set a new one. Generates a new token before invalidating
329
+ /// the current token, meaning the old token will be used until this function acquires the lock
330
+ /// and overwrites the token.
331
+ ///
332
+ /// If credential is invalid, or the request fails, this method will return an error and leave
333
+ /// the current token unchanged.
334
+ pub async fn regenerate_token ( & self ) -> Result < ( ) > {
335
+ self . context ( ) . await ?. client . regenerate_token ( ) . await
336
+ }
321
337
}
322
338
323
339
/// All requests and expected responses are derived from the REST catalog API spec:
@@ -860,21 +876,27 @@ mod tests {
860
876
}
861
877
862
878
async fn create_oauth_mock ( server : & mut ServerGuard ) -> Mock {
863
- create_oauth_mock_with_path ( server, "/v1/oauth/tokens" ) . await
879
+ create_oauth_mock_with_path ( server, "/v1/oauth/tokens" , "ey000000000000" , 200 ) . await
864
880
}
865
881
866
- async fn create_oauth_mock_with_path ( server : & mut ServerGuard , path : & str ) -> Mock {
867
- server
868
- . mock ( "POST" , path)
869
- . with_status ( 200 )
870
- . with_body (
871
- r#"{
872
- "access_token": "ey000000000000",
882
+ async fn create_oauth_mock_with_path (
883
+ server : & mut ServerGuard ,
884
+ path : & str ,
885
+ token : & str ,
886
+ status : usize ,
887
+ ) -> Mock {
888
+ let body = format ! (
889
+ r#"{{
890
+ "access_token": "{token}",
873
891
"token_type": "Bearer",
874
892
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
875
893
"expires_in": 86400
876
- }"# ,
877
- )
894
+ }}"#
895
+ ) ;
896
+ server
897
+ . mock ( "POST" , path)
898
+ . with_status ( status)
899
+ . with_body ( body)
878
900
. expect ( 1 )
879
901
. create_async ( )
880
902
. await
@@ -949,6 +971,129 @@ mod tests {
949
971
assert_eq ! ( token, Some ( "ey000000000000" . to_string( ) ) ) ;
950
972
}
951
973
974
+ #[ tokio:: test]
975
+ async fn test_invalidate_token ( ) {
976
+ let mut server = Server :: new_async ( ) . await ;
977
+ let oauth_mock = create_oauth_mock ( & mut server) . await ;
978
+ let config_mock = create_config_mock ( & mut server) . await ;
979
+
980
+ let mut props = HashMap :: new ( ) ;
981
+ props. insert ( "credential" . to_string ( ) , "client1:secret1" . to_string ( ) ) ;
982
+
983
+ let catalog = RestCatalog :: new (
984
+ RestCatalogConfig :: builder ( )
985
+ . uri ( server. url ( ) )
986
+ . props ( props)
987
+ . build ( ) ,
988
+ ) ;
989
+
990
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
991
+ oauth_mock. assert_async ( ) . await ;
992
+ config_mock. assert_async ( ) . await ;
993
+ assert_eq ! ( token, Some ( "ey000000000000" . to_string( ) ) ) ;
994
+
995
+ let oauth_mock =
996
+ create_oauth_mock_with_path ( & mut server, "/v1/oauth/tokens" , "ey000000000001" , 200 )
997
+ . await ;
998
+ catalog. invalidate_token ( ) . await . unwrap ( ) ;
999
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1000
+ oauth_mock. assert_async ( ) . await ;
1001
+ assert_eq ! ( token, Some ( "ey000000000001" . to_string( ) ) ) ;
1002
+ }
1003
+
1004
+ #[ tokio:: test]
1005
+ async fn test_invalidate_token_failing_request ( ) {
1006
+ let mut server = Server :: new_async ( ) . await ;
1007
+ let oauth_mock = create_oauth_mock ( & mut server) . await ;
1008
+ let config_mock = create_config_mock ( & mut server) . await ;
1009
+
1010
+ let mut props = HashMap :: new ( ) ;
1011
+ props. insert ( "credential" . to_string ( ) , "client1:secret1" . to_string ( ) ) ;
1012
+
1013
+ let catalog = RestCatalog :: new (
1014
+ RestCatalogConfig :: builder ( )
1015
+ . uri ( server. url ( ) )
1016
+ . props ( props)
1017
+ . build ( ) ,
1018
+ ) ;
1019
+
1020
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1021
+ oauth_mock. assert_async ( ) . await ;
1022
+ config_mock. assert_async ( ) . await ;
1023
+ assert_eq ! ( token, Some ( "ey000000000000" . to_string( ) ) ) ;
1024
+
1025
+ let oauth_mock =
1026
+ create_oauth_mock_with_path ( & mut server, "/v1/oauth/tokens" , "ey000000000001" , 500 )
1027
+ . await ;
1028
+ catalog. invalidate_token ( ) . await . unwrap ( ) ;
1029
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1030
+ oauth_mock. assert_async ( ) . await ;
1031
+ assert_eq ! ( token, None ) ;
1032
+ }
1033
+
1034
+ #[ tokio:: test]
1035
+ async fn test_regenerate_token ( ) {
1036
+ let mut server = Server :: new_async ( ) . await ;
1037
+ let oauth_mock = create_oauth_mock ( & mut server) . await ;
1038
+ let config_mock = create_config_mock ( & mut server) . await ;
1039
+
1040
+ let mut props = HashMap :: new ( ) ;
1041
+ props. insert ( "credential" . to_string ( ) , "client1:secret1" . to_string ( ) ) ;
1042
+
1043
+ let catalog = RestCatalog :: new (
1044
+ RestCatalogConfig :: builder ( )
1045
+ . uri ( server. url ( ) )
1046
+ . props ( props)
1047
+ . build ( ) ,
1048
+ ) ;
1049
+
1050
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1051
+ oauth_mock. assert_async ( ) . await ;
1052
+ config_mock. assert_async ( ) . await ;
1053
+ assert_eq ! ( token, Some ( "ey000000000000" . to_string( ) ) ) ;
1054
+
1055
+ let oauth_mock =
1056
+ create_oauth_mock_with_path ( & mut server, "/v1/oauth/tokens" , "ey000000000001" , 200 )
1057
+ . await ;
1058
+ catalog. regenerate_token ( ) . await . unwrap ( ) ;
1059
+ oauth_mock. assert_async ( ) . await ;
1060
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1061
+ assert_eq ! ( token, Some ( "ey000000000001" . to_string( ) ) ) ;
1062
+ }
1063
+
1064
+ #[ tokio:: test]
1065
+ async fn test_regenerate_token_failing_request ( ) {
1066
+ let mut server = Server :: new_async ( ) . await ;
1067
+ let oauth_mock = create_oauth_mock ( & mut server) . await ;
1068
+ let config_mock = create_config_mock ( & mut server) . await ;
1069
+
1070
+ let mut props = HashMap :: new ( ) ;
1071
+ props. insert ( "credential" . to_string ( ) , "client1:secret1" . to_string ( ) ) ;
1072
+
1073
+ let catalog = RestCatalog :: new (
1074
+ RestCatalogConfig :: builder ( )
1075
+ . uri ( server. url ( ) )
1076
+ . props ( props)
1077
+ . build ( ) ,
1078
+ ) ;
1079
+
1080
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1081
+ oauth_mock. assert_async ( ) . await ;
1082
+ config_mock. assert_async ( ) . await ;
1083
+ assert_eq ! ( token, Some ( "ey000000000000" . to_string( ) ) ) ;
1084
+
1085
+ let oauth_mock =
1086
+ create_oauth_mock_with_path ( & mut server, "/v1/oauth/tokens" , "ey000000000001" , 500 )
1087
+ . await ;
1088
+ let invalidate_result = catalog. regenerate_token ( ) . await ;
1089
+ assert ! ( invalidate_result. is_err( ) ) ;
1090
+ oauth_mock. assert_async ( ) . await ;
1091
+ let token = catalog. context ( ) . await . unwrap ( ) . client . token ( ) . await ;
1092
+
1093
+ // original token is left intact
1094
+ assert_eq ! ( token, Some ( "ey000000000000" . to_string( ) ) ) ;
1095
+ }
1096
+
952
1097
#[ tokio:: test]
953
1098
async fn test_http_headers ( ) {
954
1099
let server = Server :: new_async ( ) . await ;
@@ -1026,7 +1171,9 @@ mod tests {
1026
1171
1027
1172
let mut auth_server = Server :: new_async ( ) . await ;
1028
1173
let auth_server_path = "/some/path" ;
1029
- let oauth_mock = create_oauth_mock_with_path ( & mut auth_server, auth_server_path) . await ;
1174
+ let oauth_mock =
1175
+ create_oauth_mock_with_path ( & mut auth_server, auth_server_path, "ey000000000000" , 200 )
1176
+ . await ;
1030
1177
1031
1178
let mut props = HashMap :: new ( ) ;
1032
1179
props. insert ( "credential" . to_string ( ) , "client1:secret1" . to_string ( ) ) ;
0 commit comments