Skip to content

Commit c417675

Browse files
authored
Merge pull request #13 from cryptosense/project-name
Allow the user to provide a project name
2 parents 8b4eda2 + 2a2f522 commit c417675

3 files changed

Lines changed: 97 additions & 4 deletions

File tree

cs_api_cli/cs_api_cli.ml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,30 @@ let get_file path =
1616
| _ ->
1717
Lwt_result.fail ("Could not read file " ^ path ^ " for unknown reasons"))
1818

19+
let resolve_project_name ~api ~verify ~project_id ~project_name =
20+
(* The user can provide an ID or a name. If a name is provided, look for the
21+
corresponding ID. Otherwise, just return the given ID. *)
22+
let open Lwt_result.Infix in
23+
match (project_id, project_name) with
24+
| (None, None)
25+
| (Some _, Some _) ->
26+
Lwt_result.fail "Exactly one of project ID or name must be provided."
27+
| (Some id, None) -> Lwt_result.return id
28+
| (None, Some name) -> (
29+
Cs_api_core.build_list_projects_request ~api
30+
|> Cs_api_io.send_request ~verify
31+
>>= Cs_api_io.get_response
32+
>>= fun body ->
33+
let projects = Cs_api_core.parse_list_projects_response ~body in
34+
match CCList.Assoc.get ~eq:String.equal name projects with
35+
| None -> Lwt_result.fail (Printf.sprintf "Project name not found: %s" name)
36+
| Some id -> Lwt_result.return id)
37+
1938
let upload_trace
2039
~trace_file
2140
~trace_name
2241
~project_id
42+
~project_name
2343
~api_endpoint
2444
~api_key
2545
~no_check_certificate =
@@ -28,6 +48,8 @@ let upload_trace
2848
let api = Api.make ~api_endpoint ~api_key in
2949
(let open Lwt_result.Infix in
3050
get_file trace_file >>= fun file ->
51+
resolve_project_name ~api ~verify ~project_id ~project_name
52+
>>= fun project_id ->
3153
Cs_api_core.build_s3_signed_post_request ~api
3254
|> Cs_api_io.send_request ~verify
3355
>>= Cs_api_io.get_response
@@ -73,8 +95,18 @@ let trace_name =
7395
& info ["n"; "trace-name"] ~docv:"TRACENAME" ~doc)
7496

7597
let project_id =
76-
let doc = "ID of the project to which the trace should be added" in
77-
Cmdliner.Arg.(required & opt (some int) None & info ["p"; "project-id"] ~doc)
98+
let doc =
99+
"ID of the project to which the trace should be added. Mutually exclusive \
100+
with --project-name."
101+
in
102+
Cmdliner.Arg.(value & opt (some int) None & info ["p"; "project-id"] ~doc)
103+
104+
let project_name =
105+
let doc =
106+
"Name of the project to which the trace should be added. Mutually \
107+
exclusive with --project-id."
108+
in
109+
Cmdliner.Arg.(value & opt (some string) None & info ["project-name"] ~doc)
78110

79111
let api_endpoint =
80112
let doc = "Base URL of the API server." in
@@ -104,11 +136,12 @@ let upload_trace_main
104136
trace_file
105137
trace_name
106138
project_id
139+
project_name
107140
api_endpoint
108141
api_key
109142
no_check_certificate =
110-
upload_trace ~trace_file ~trace_name ~project_id ~api_endpoint ~api_key
111-
~no_check_certificate
143+
upload_trace ~trace_file ~trace_name ~project_id ~project_name ~api_endpoint
144+
~api_key ~no_check_certificate
112145
|> Lwt_main.run
113146

114147
let upload_trace_term =
@@ -117,6 +150,7 @@ let upload_trace_term =
117150
$ trace_file
118151
$ trace_name
119152
$ project_id
153+
$ project_name
120154
$ api_endpoint
121155
$ api_key
122156
$ no_check_certificate)

cs_api_core/cs_api_core.ml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ module Graphql = struct
22
let to_global_id ~type_ ~id =
33
Printf.sprintf "%s:%d" type_ id |> Base64.encode |> Result.get_ok
44

5+
let of_global_id ~type_ global_id =
6+
global_id
7+
|> Base64.decode
8+
|> Result.get_ok
9+
|> CCString.chop_prefix ~pre:(Printf.sprintf "%s:" type_)
10+
|> CCOption.get_exn_or
11+
(Printf.sprintf "Invalid global ID prefix for type %s" type_)
12+
|> int_of_string
13+
514
let create_trace =
615
{|
716
mutation CreateTrace($projectId: ID!, $name: String!, $key: String!, $size: Int!) {
@@ -19,8 +28,54 @@ module Graphql = struct
1928
}
2029
}
2130
|}
31+
32+
let list_projects =
33+
{|
34+
query ListProjects {
35+
viewer {
36+
organization {
37+
projects {
38+
edges {
39+
node {
40+
id
41+
name
42+
}
43+
}
44+
}
45+
}
46+
}
47+
}
48+
|}
2249
end
2350

51+
let build_list_projects_request ~api =
52+
let {Api.endpoint; key} = api in
53+
{ Api.Request.url = endpoint ^ "/api/v2"
54+
; header = [("API-KEY", key); ("Content-Type", "application/json")]
55+
; method_ = Post
56+
; data =
57+
Raw
58+
(Yojson.Safe.to_string
59+
(`Assoc [("query", `String Graphql.list_projects)])) }
60+
61+
let parse_list_projects_response ~body =
62+
let open Yojson.Basic.Util in
63+
let json = Yojson.Basic.from_string body in
64+
json
65+
|> member "data"
66+
|> member "viewer"
67+
|> member "organization"
68+
|> member "projects"
69+
|> member "edges"
70+
|> to_list
71+
|> CCList.map (fun edge ->
72+
let node = edge |> member "node" in
73+
( node |> member "name" |> to_string
74+
, node
75+
|> member "id"
76+
|> to_string
77+
|> Graphql.of_global_id ~type_:"Project" ))
78+
2479
let parse_s3_signature_request ~body =
2580
let open CCOption.Infix in
2681
let open Yojson.Basic.Util in

cs_api_core/cs_api_core.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ val parse_s3_response : body:string -> string
1313
val build_s3_signed_post_request : api:Api.t -> Api.Request.t
1414
(** Request building functions **)
1515

16+
val build_list_projects_request : api:Api.t -> Api.Request.t
17+
18+
val parse_list_projects_response : body:string -> (string * int) list
19+
1620
val build_file_upload_request :
1721
s3_url:string
1822
-> s3_signature:Api.S3Signature.t

0 commit comments

Comments
 (0)