From 694c2d923f617b7b57d06d74fdc618568d18f267 Mon Sep 17 00:00:00 2001 From: David Engelmann Date: Mon, 2 Oct 2023 16:09:28 -0400 Subject: [PATCH] start working on test around the auth endpoints and tokens --- src/hrana.ml | 61 +++++++++++++++++++++++++++++++++++++- test/dune | 4 +-- test/test_auth.ml | 31 ++------------------ test/test_https_auth.ml | 62 +++++++++++++++++++++++++++++++++++++++ test/test_https_hrana.ml | 63 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 32 deletions(-) create mode 100644 test/test_https_auth.ml create mode 100644 test/test_https_hrana.ml diff --git a/src/hrana.ml b/src/hrana.ml index 4323301..c3a57cc 100644 --- a/src/hrana.ml +++ b/src/hrana.ml @@ -22,7 +22,7 @@ module Hrana = struct let parse_url_to_hrana_config (url_str : string) : config = let url = Uri.of_string url_str in - let scheme = Uri.scheme url |> Option.value ~default:"" in + let scheme_value = Uri.scheme url |> Option.value ~default:"" in let authority = Uri.host_with_default ~default:"" url in let path = Uri.path url in let initial_auth_token = Auth.get_token_from_env () in @@ -40,6 +40,12 @@ module Hrana = struct | "0" | "false" -> false | _ -> false in + let scheme = + match String.lowercase_ascii scheme_value with + | "libsql" when tls -> "wss" + | "libsql" -> "ws" + | _ -> scheme_value + in { scheme; authority; path; auth_token; tls } let validate_hrana_config (config : config) : unit = @@ -97,4 +103,57 @@ module Hrana = struct (fun body -> Lwt.return (Ok body)) let close_client client = { client with url = Uri.of_string "" } + + let get_all_api_tokens (c : client) = + let api_tokens_endpoint = Auth.create_auth_endpoint "api_tokens" "v1" in + if Uri.to_string c.url = "" then + raise (HranaError ("The client URL is empty", "CLIENT_CLOSED")); + + let uri_with_query = Uri.with_path c.url api_tokens_endpoint in + let headers = + Cohttp_client.create_headers_from_pairs + [ ("Content-Type", "application/json") ] + in + let headers = + match c.config.auth_token with + | Some token -> + Cohttp.Header.add_list headers + [ + Auth.create_bearer_auth_header (Auth.create_auth_from_token token); + ] + | None -> headers + in + + Lwt.bind + (Cohttp_client.get_request_with_headers + (Uri.to_string uri_with_query) + headers) + (fun body -> Lwt.return (Ok body)) + + let create_auth_token (c : client) (name : string) = + let api_tokens_endpoint = Auth.create_auth_endpoint "api_tokens" "v1" in + if Uri.to_string c.url = "" then + raise (HranaError ("The client URL is empty", "CLIENT_CLOSED")); + let uri_with_query = Uri.with_path c.url api_tokens_endpoint in + let uri_with_query = Uri.with_path uri_with_query name in + + let headers = + Cohttp_client.create_headers_from_pairs + [ ("Content-Type", "application/json") ] + in + let headers = + match c.config.auth_token with + | Some token -> + Cohttp.Header.add_list headers + [ + Auth.create_bearer_auth_header (Auth.create_auth_from_token token); + ] + | None -> headers + in + + Lwt.bind + (Cohttp_client.post_request_with_headers + (Uri.to_string uri_with_query) + headers) + (fun body -> Lwt.return (Ok body)) end diff --git a/test/dune b/test/dune index bce7c1a..86e82b8 100644 --- a/test/dune +++ b/test/dune @@ -1,9 +1,9 @@ (tests ; multiple test files - (names test_auth test_hrana test_path test_sqlite test_url) + (names test_auth test_hrana test_https_hrana test_https_auth test_path test_sqlite test_url) (libraries async core uri cohttp cohttp-lwt-unix cohttp-async httpaf httpaf-lwt-unix ssl sqlite3 jose lwt_ssl lwt alcotest alcotest-lwt libsql) ; multiple test files - (modules test_auth test_hrana test_path test_sqlite test_url)) + (modules test_auth test_hrana test_https_hrana test_https_auth test_path test_sqlite test_url)) diff --git a/test/test_auth.ml b/test/test_auth.ml index fdf4821..d6cb1eb 100644 --- a/test/test_auth.ml +++ b/test/test_auth.ml @@ -90,26 +90,6 @@ let test_validate_http_config_https = test_case "validate_http_config with https does not raise an exception" `Quick (fun () -> Auth.validate_http_config sample_http_config_https) -let create_test_https_config = - Auth.parse_url_to_http_config "https://ocaml-david-engelmann.turso.io" - -let call_get_api_tokens_with_client c = Auth.get_all_api_tokens c - -let call_get_api_tokens_with_https () = - let client = Auth.create_client create_test_https_config in - let api_tokens = call_get_api_tokens_with_client client in - api_tokens - -let test_get_all_api_tokens_with_https _switch () = - let open Lwt.Infix in - call_get_api_tokens_with_https () >>= fun api_tokens_result -> - (match api_tokens_result with - | Ok api_tokens -> - print_endline api_tokens; - Alcotest.(check (neg string)) "api_tokens returned" "" api_tokens - | _ -> Alcotest.fail "API tokens retrieval failed"); - Lwt.return_unit - let sync_suite = [ ("test_sample_basic_cred_defaults", `Quick, test_sample_basic_cred_defaults); @@ -150,13 +130,6 @@ let sync_suite = test_validate_http_config_https; ] -let lwt_suite = - [ - Alcotest_lwt.test_case "test_get_all_api_tokens_with_https" `Quick - test_get_all_api_tokens_with_https; - ] - let () = - Alcotest.run "Auth Test Suite" [ ("Auth", sync_suite) ]; - Lwt_main.run - (Alcotest_lwt.run "Auth Test Suite Async" [ ("Auth", lwt_suite) ]) + print_endline "Running Sync Suite"; + Alcotest.run "Auth Test Suite" [ ("Auth", sync_suite) ] diff --git a/test/test_https_auth.ml b/test/test_https_auth.ml new file mode 100644 index 0000000..9069d6c --- /dev/null +++ b/test/test_https_auth.ml @@ -0,0 +1,62 @@ +open Libsql.Auth + +let create_test_https_config = + Auth.parse_url_to_http_config "https://ocaml-david-engelmann.turso.io?tls=1" + +let call_get_api_tokens_with_client c = Auth.get_all_api_tokens c + +let call_create_auth_token_with_client c = + Auth.create_auth_token c "ocaml-create-auth-token" + +let call_get_api_tokens_with_https () = + let client = Auth.create_client create_test_https_config in + print_endline ("Url of client: " ^ Uri.to_string client.url); + print_endline ("Auth token of client: " ^ Option.get client.config.auth_token); + let api_tokens = call_get_api_tokens_with_client client in + api_tokens + +let call_create_auth_token_with_https () = + let client = Auth.create_client create_test_https_config in + let api_token = call_create_auth_token_with_client client in + api_token + +let test_get_all_api_tokens_with_https _switch () = + let open Lwt.Infix in + print_endline "Running test_get_all_api_tokens_with_https"; + call_get_api_tokens_with_https () >>= fun api_tokens_result -> + (match api_tokens_result with + | Ok api_tokens -> + print_endline ("API tokens: " ^ api_tokens); + print_endline + ("Length of API tokens: " ^ string_of_int (String.length api_tokens)); + (*Alcotest.(check (neg string)) "api_tokens returned" "" api_tokens*) + Alcotest.(check string) "api_tokens returned" "" api_tokens + | _ -> Alcotest.fail "API tokens retrieval failed"); + Lwt.return_unit + +let test_create_auth_token_with_https _switch () = + let open Lwt.Infix in + print_endline "Running test_create_auth_token_with_https"; + call_create_auth_token_with_https () >>= fun api_token_result -> + (match api_token_result with + | Ok api_token -> + print_endline ("Created API token: " ^ api_token); + print_endline + ("Length of Created API token: " + ^ string_of_int (String.length api_token)); + (*Alcotest.(check (neg string)) "api_token returned" "" api_token*) + Alcotest.(check string) "api_token returned" "" api_token + | _ -> Alcotest.fail "API token retrieval failed"); + Lwt.return_unit + +let lwt_suite = + [ + Alcotest_lwt.test_case "test_get_all_api_tokens_with_https" `Quick + test_get_all_api_tokens_with_https; + Alcotest_lwt.test_case "test_create_auth_token_with_https" `Quick + test_create_auth_token_with_https; + ] + +let () = + print_endline "Running Async Suite"; + Lwt_main.run (Alcotest_lwt.run "AuthTestSuiteAsync" [ ("Auth", lwt_suite) ]) diff --git a/test/test_https_hrana.ml b/test/test_https_hrana.ml new file mode 100644 index 0000000..5d501a6 --- /dev/null +++ b/test/test_https_hrana.ml @@ -0,0 +1,63 @@ +open Libsql.Hrana + +let create_test_https_config = + Hrana.parse_url_to_hrana_config + "libsql://ocaml-david-engelmann.turso.io?tls=1" + +let call_get_api_tokens_with_client c = Hrana.get_all_api_tokens c + +let call_create_auth_token_with_client c = + Hrana.create_auth_token c "ocaml-create-auth-token" + +let call_get_api_tokens_with_https () = + let client = Hrana.create_client create_test_https_config in + print_endline ("Url of client: " ^ Uri.to_string client.url); + print_endline ("Auth token of client: " ^ Option.get client.config.auth_token); + let api_tokens = call_get_api_tokens_with_client client in + api_tokens + +let call_create_auth_token_with_https () = + let client = Hrana.create_client create_test_https_config in + let api_token = call_create_auth_token_with_client client in + api_token + +let test_get_all_api_tokens_with_https _switch () = + let open Lwt.Infix in + print_endline "Running test_get_all_api_tokens_with_https"; + call_get_api_tokens_with_https () >>= fun api_tokens_result -> + (match api_tokens_result with + | Ok api_tokens -> + print_endline ("API tokens: " ^ api_tokens); + print_endline + ("Length of API tokens: " ^ string_of_int (String.length api_tokens)); + (*Alcotest.(check (neg string)) "api_tokens returned" "" api_tokens*) + Alcotest.(check string) "api_tokens returned" "" api_tokens + | _ -> Alcotest.fail "API tokens retrieval failed"); + Lwt.return_unit + +let test_create_auth_token_with_https _switch () = + let open Lwt.Infix in + print_endline "Running test_create_auth_token_with_https"; + call_create_auth_token_with_https () >>= fun api_token_result -> + (match api_token_result with + | Ok api_token -> + print_endline ("Created API token: " ^ api_token); + print_endline + ("Length of Created API token: " + ^ string_of_int (String.length api_token)); + (*Alcotest.(check (neg string)) "api_token returned" "" api_token*) + Alcotest.(check string) "api_token returned" "" api_token + | _ -> Alcotest.fail "API token retrieval failed"); + Lwt.return_unit + +let lwt_suite = + [ + Alcotest_lwt.test_case "test_get_all_api_tokens_with_https" `Quick + test_get_all_api_tokens_with_https; + Alcotest_lwt.test_case "test_create_auth_token_with_https" `Quick + test_create_auth_token_with_https; + ] + +let () = + print_endline "Running Async Hrana Suite"; + Lwt_main.run (Alcotest_lwt.run "HranaTestSuiteAsync" [ ("Hrana", lwt_suite) ])