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