okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
c9cb3a0
main
1// A refresh moves a stored token, so it is checked against a local token endpoint rather than a scripted model turn. 2import gleam/string 3import gleeunit/should 4 5const stale = 6"{\"type\":\"oauth\",\"access\":\"old\",\"refresh\":\"r1\",\"expires\":0,\"email\":\"a@example.com\"}" 7 8const other = 9"{\"type\":\"oauth\",\"access\":\"keep\",\"refresh\":\"r2\",\"expires\":0,\"email\":\"b@example.com\"}" 10 11const fresh = "99999999999999" 12 13fn accounts ( items : List ( String )) -> String { 14"[" <> string . join ( items , "," ) <> "]" 15} 16 17pub fn a_stale_account_is_refreshed_saved_and_the_others_left_alone_test () -> Nil { 18let #( result , stored , form ) = 19refresh ( accounts ([ stale , other ]), #( 20200 , 21"{\"access_token\":\"new\",\"expires_in\":3600}" , 22)) 23result |> should . equal ( Ok ( "new" )) 24string . contains ( stored , "\"access\":\"new\"" ) |> should . be_true 25string . contains ( stored , "\"refresh\":\"r1\"" ) |> should . be_true 26string . contains ( stored , "\"access\":\"keep\"" ) |> should . be_true 27string . contains ( form , "grant_type=refresh_token" ) |> should . be_true 28string . contains ( form , "refresh_token=r1" ) |> should . be_true 29} 30 31pub fn a_rotated_refresh_token_replaces_the_old_one_test () -> Nil { 32let #( _ , stored , _ ) = 33refresh ( accounts ([ stale ]), #( 34200 , 35"{\"access_token\":\"new\",\"refresh_token\":\"r9\",\"expires_in\":3600}" , 36)) 37string . contains ( stored , "\"refresh\":\"r9\"" ) |> should . be_true 38string . contains ( stored , "r1" ) |> should . be_false 39} 40 41pub fn a_rejected_refresh_keeps_the_stored_account_test () -> Nil { 42let #( result , stored , _ ) = 43refresh ( accounts ([ stale ]), #( 400 , "{\"error\":\"invalid_grant\"}" )) 44result |> should . equal ( Error ( "Google Colab token refresh failed (400)" )) 45string . contains ( stored , "\"access\":\"old\"" ) |> should . be_true 46} 47 48pub fn an_account_without_a_refresh_token_is_invalid_test () -> Nil { 49let #( result , _ , _ ) = 50refresh ( 51accounts ([ "{\"type\":\"oauth\",\"access\":\"old\",\"expires\":0}" ]), 52#( 200 , "{}" ), 53) 54result |> should . equal ( Error ( "invalid" )) 55} 56 57pub fn colab_uses_the_selected_account_and_names_its_email_test () -> Nil { 58let selected = 59"{\"type\":\"oauth\",\"access\":\"second\",\"refresh\":\"r2\",\"expires\":" 60<> fresh 61<> ",\"email\":\"b@example.com\",\"selected\":true}" 62let first = 63"{\"type\":\"oauth\",\"access\":\"first\",\"refresh\":\"r1\",\"expires\":" 64<> fresh 65<> ",\"email\":\"a@example.com\"}" 66signed_in ( accounts ([ first , selected ])) 67|> should . equal ( Ok (#( "second" , "b@example.com" ))) 68signed_in ( accounts ([ first , first ])) 69|> should . equal ( Ok (#( "first" , "a@example.com" ))) 70} 71 72pub fn colab_with_no_account_says_to_sign_in_test () -> Nil { 73signed_in ( "[]" ) 74|> should . equal ( Error ( 75"Google Colab is not authenticated; run /login and add a Google Colab account" , 76)) 77} 78 79@external ( erlang , "albedo_google_oauth_test_support" , "refresh" ) 80fn refresh ( 81accounts : String , 82answer : #( Int , String ), 83) -> #( Result ( String , String ), String , String ) 84 85@external ( erlang , "albedo_google_oauth_test_support" , "signed_in" ) 86fn signed_in ( accounts : String ) -> Result (#( String , String ), String )