Skip to content

Commit

Permalink
refactor: implement a new pkg/api desing
Browse files Browse the repository at this point in the history
Signed-off-by: Kairo Araujo <[email protected]>
  • Loading branch information
kairoaraujo committed Nov 20, 2024
1 parent 4e6f88d commit 2554623
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 31 deletions.
2 changes: 1 addition & 1 deletion cmd/archivistactl/cmd/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func storeAttestationByPath(ctx context.Context, baseUrl, path string) (string,
}

defer file.Close()
resp, err := api.UploadWithReader(ctx, baseUrl, file)
resp, err := api.StoreWithReader(ctx, baseUrl, file)
if err != nil {
return "", err
}
Expand Down
45 changes: 40 additions & 5 deletions pkg/api/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,40 @@ import (
"github.com/in-toto/go-witness/dsse"
)

func Download(ctx context.Context, baseUrl string, gitoid string) (dsse.Envelope, error) {
func DownloadReadCloser(ctx context.Context, baseURL string, gitoid string) (io.ReadCloser, error) {
return DownloadReadCloserWithHTTPClient(ctx, &http.Client{}, baseURL, gitoid)
}

func DownloadReadCloserWithHTTPClient(ctx context.Context, client *http.Client, baseURL string, gitoid string) (io.ReadCloser, error) {
downloadURL, err := url.JoinPath(baseURL, "download", gitoid)
if err != nil {
return nil, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadURL, nil)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
// NOTE: attempt to read body on error and
// only close if an error occurs
defer resp.Body.Close()
errMsg, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, errors.New(string(errMsg))
}
return resp.Body, nil
}

func Download(ctx context.Context, baseURL string, gitoid string) (dsse.Envelope, error) {
buf := &bytes.Buffer{}
if err := DownloadWithWriter(ctx, baseUrl, gitoid, buf); err != nil {
if err := DownloadWithWriter(ctx, baseURL, gitoid, buf); err != nil {
return dsse.Envelope{}, err
}

Expand All @@ -41,13 +72,17 @@ func Download(ctx context.Context, baseUrl string, gitoid string) (dsse.Envelope
return env, nil
}

func DownloadWithWriter(ctx context.Context, baseUrl, gitoid string, dst io.Writer) error {
downloadUrl, err := url.JoinPath(baseUrl, "download", gitoid)
func DownloadWithWriter(ctx context.Context, baseURL string, gitoid string, dst io.Writer) error {
return DownloadWithWriterWithHTTPClient(ctx, &http.Client{}, baseURL, gitoid, dst)
}

func DownloadWithWriterWithHTTPClient(ctx context.Context, client *http.Client, baseURL string, gitoid string, dst io.Writer) error {
downloadUrl, err := url.JoinPath(baseURL, "download", gitoid)
if err != nil {
return err
}

req, err := http.NewRequestWithContext(ctx, "GET", downloadUrl, nil)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadUrl, nil)
if err != nil {
return err
}
Expand Down
73 changes: 59 additions & 14 deletions pkg/api/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,69 @@ import (
"net/url"
)

type graphQLError struct {
Message string `json:"message"`
}
const RetrieveSubjectsQuery = `query($gitoid: String!) {
subjects(
where: {
hasStatementWith:{
hasDsseWith:{
gitoidSha256: $gitoid
}
}
}
) {
edges {
node{
name
subjectDigests{
algorithm
value
}
}
}
}
}`

type graphQLResponse[T any] struct {
Data T `json:"data,omitempty"`
Errors []graphQLError `json:"errors,omitempty"`
}
const SearchQuery = `query($algo: String!, $digest: String!) {
dsses(
where: {
hasStatementWith: {
hasSubjectsWith: {
hasSubjectDigestsWith: {
value: $digest,
algorithm: $algo
}
}
}
}
) {
edges {
node {
gitoidSha256
statement {
attestationCollections {
name
attestations {
type
}
}
}
}
}
}
}`

type graphQLRequestBody[TVars any] struct {
Query string `json:"query"`
Variables TVars `json:"variables,omitempty"`
func GraphQlQuery[TRes any, TVars any](ctx context.Context, baseUrl, query string, vars TVars) (TRes, error) {
return GraphQlQueryWithHeaders[TRes, TVars](ctx, baseUrl, query, vars, nil)
}

func GraphQlQuery[TRes any, TVars any](ctx context.Context, baseUrl, query string, vars TVars) (TRes, error) {
func GraphQlQueryWithHeaders[TRes any, TVars any](ctx context.Context, baseUrl, query string, vars TVars, headers map[string]string) (TRes, error) {
var response TRes
queryUrl, err := url.JoinPath(baseUrl, "query")
if err != nil {
return response, err
}

requestBody := graphQLRequestBody[TVars]{
requestBody := GraphQLRequestBodyGeneric[TVars]{
Query: query,
Variables: vars,
}
Expand All @@ -56,11 +97,15 @@ func GraphQlQuery[TRes any, TVars any](ctx context.Context, baseUrl, query strin
return response, err
}

req, err := http.NewRequestWithContext(ctx, "POST", queryUrl, bytes.NewReader(reqBody))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, queryUrl, bytes.NewReader(reqBody))
if err != nil {
return response, err
}

for k, v := range headers {
req.Header.Set(k, v)
}

req.Header.Set("Content-Type", "application/json")
hc := &http.Client{}
res, err := hc.Do(req)
Expand All @@ -79,7 +124,7 @@ func GraphQlQuery[TRes any, TVars any](ctx context.Context, baseUrl, query strin
}

dec := json.NewDecoder(res.Body)
gqlRes := graphQLResponse[TRes]{}
gqlRes := GraphQLResponseGeneric[TRes]{}
if err := dec.Decode(&gqlRes); err != nil {
return response, err
}
Expand Down
76 changes: 76 additions & 0 deletions pkg/api/structs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package api

type GraphQLError struct {
Message string `json:"message"`
}

type GraphQLResponseGeneric[T any] struct {
Data T `json:"data,omitempty"`
Errors []GraphQLError `json:"errors,omitempty"`
}

type GraphQLRequestBodyGeneric[TVars any] struct {
Query string `json:"query"`
Variables TVars `json:"variables,omitempty"`
}

type RetrieveSubjectVars struct {
Gitoid string `json:"gitoid"`
}

type SearchVars struct {
Algorithm string `json:"algo"`
Digest string `json:"digest"`
}

type RetrieveSubjectResults struct {
Subjects Subjects `json:"subjects"`
}

type Subjects struct {
Edges []SubjectEdge `json:"edges"`
}

type SubjectEdge struct {
Node SubjectNode `json:"node"`
}

type SubjectNode struct {
Name string `json:"name"`
SubjectDigests []SubjectDigest `json:"subjectDigests"`
}

type SubjectDigest struct {
Algorithm string `json:"algorithm"`
Value string `json:"value"`
}

type SearchResults struct {
Dsses DSSES `json:"dsses"`
}

type DSSES struct {
Edges []SearchEdge `json:"edges"`
}

type SearchEdge struct {
Node SearchNode `json:"node"`
}

type SearchNode struct {
GitoidSha256 string `json:"gitoidSha256"`
Statement Statement `json:"statement"`
}

type Statement struct {
AttestationCollection AttestationCollection `json:"attestationCollections"`
}

type AttestationCollection struct {
Name string `json:"name"`
Attestations []Attestation `json:"attestations"`
}

type Attestation struct {
Type string `json:"type"`
}
21 changes: 10 additions & 11 deletions pkg/api/upload.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 The Witness Contributors
// Copyright 2023 The Archivista Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,28 +33,27 @@ type UploadResponse struct {
// Deprecated: Use UploadResponse instead. It will be removed in version >= v0.6.0
type StoreResponse = UploadResponse

// Deprecated: Use Upload instead. It will be removed in version >= v0.6.0
func Store(ctx context.Context, baseUrl string, envelope dsse.Envelope) (StoreResponse, error) {
return Upload(ctx, baseUrl, envelope)
// Deprecated: Use Store instead. It will be removed in version >= v0.6.0
func Upload(ctx context.Context, baseURL string, envelope dsse.Envelope) (UploadResponse, error) {
return Store(ctx, baseURL, envelope)
}

func Upload(ctx context.Context, baseUrl string, envelope dsse.Envelope) (StoreResponse, error) {
func Store(ctx context.Context, baseURL string, envelope dsse.Envelope) (StoreResponse, error) {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
if err := enc.Encode(envelope); err != nil {
return StoreResponse{}, err
}

return UploadWithReader(ctx, baseUrl, buf)
return StoreWithReader(ctx, baseURL, buf)
}

// Deprecated: Use UploadWithReader instead. It will be removed in version >= v0.6.0
func StoreWithReader(ctx context.Context, baseUrl string, r io.Reader) (StoreResponse, error) {
return UploadWithReader(ctx, baseUrl, r)
func StoreWithReader(ctx context.Context, baseURL string, r io.Reader) (StoreResponse, error) {
return StoreWithReaderWithHTTPClient(ctx, &http.Client{}, baseURL, r)
}

func UploadWithReader(ctx context.Context, baseUrl string, r io.Reader) (StoreResponse, error) {
uploadPath, err := url.JoinPath(baseUrl, "upload")
func StoreWithReaderWithHTTPClient(ctx context.Context, client *http.Client, baseURL string, r io.Reader) (StoreResponse, error) {
uploadPath, err := url.JoinPath(baseURL, "upload")
if err != nil {
return UploadResponse{}, err
}
Expand Down

0 comments on commit 2554623

Please sign in to comment.