Something went wrong. Try again.
forked from tangled.org/core
Something went wrong. Try again.
7.0 kB · 336 lines
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337package knotclient
import ( "bytes" "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "time"
"tangled.sh/tangled.sh/core/types")
type SignerTransport struct { Secret string}
func (s SignerTransport) RoundTrip(req *http.Request) (*http.Response, error) { timestamp := time.Now().Format(time.RFC3339) mac := hmac.New(sha256.New, []byte(s.Secret)) message := req.Method + req.URL.Path + timestamp mac.Write([]byte(message)) signature := hex.EncodeToString(mac.Sum(nil)) req.Header.Set("X-Signature", signature) req.Header.Set("X-Timestamp", timestamp) return http.DefaultTransport.RoundTrip(req)}
type SignedClient struct { Secret string Url *url.URL client *http.Client}
func NewSignedClient(domain, secret string, dev bool) (*SignedClient, error) { client := &http.Client{ Timeout: 5 * time.Second, Transport: SignerTransport{ Secret: secret, }, }
scheme := "https" if dev { scheme = "http" } url, err := url.Parse(fmt.Sprintf("%s://%s", scheme, domain)) if err != nil { return nil, err }
signedClient := &SignedClient{ Secret: secret, client: client, Url: url, }
return signedClient, nil}
func (s *SignedClient) newRequest(method, endpoint string, body []byte) (*http.Request, error) { return http.NewRequest(method, s.Url.JoinPath(endpoint).String(), bytes.NewReader(body))}
func (s *SignedClient) Init(did string) (*http.Response, error) { const ( Method = "POST" Endpoint = "/init" )
body, _ := json.Marshal(map[string]any{ "did": did, })
req, err := s.newRequest(Method, Endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) NewRepo(did, repoName, defaultBranch string) (*http.Response, error) { const ( Method = "PUT" Endpoint = "/repo/new" )
body, _ := json.Marshal(map[string]any{ "did": did, "name": repoName, "default_branch": defaultBranch, })
req, err := s.newRequest(Method, Endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) RepoLanguages(ownerDid, repoName, ref string) (*types.RepoLanguageResponse, error) { const ( Method = "GET" ) endpoint := fmt.Sprintf("/%s/%s/languages/%s", ownerDid, repoName, url.PathEscape(ref))
req, err := s.newRequest(Method, endpoint, nil) if err != nil { return nil, err }
resp, err := s.client.Do(req) if err != nil { return nil, err }
var result types.RepoLanguageResponse if resp.StatusCode != http.StatusOK { log.Println("failed to calculate languages", resp.Status) return &types.RepoLanguageResponse{}, nil }
body, err := io.ReadAll(resp.Body) if err != nil { return nil, err }
err = json.Unmarshal(body, &result) if err != nil { return nil, err }
return &result, nil}
func (s *SignedClient) RepoForkAheadBehind(ownerDid, source, name, branch, hiddenRef string) (*http.Response, error) { const ( Method = "GET" ) endpoint := fmt.Sprintf("/repo/fork/sync/%s", url.PathEscape(branch))
body, _ := json.Marshal(map[string]any{ "did": ownerDid, "source": source, "name": name, "hiddenref": hiddenRef, })
req, err := s.newRequest(Method, endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) SyncRepoFork(ownerDid, source, name, branch string) (*http.Response, error) { const ( Method = "POST" ) endpoint := fmt.Sprintf("/repo/fork/sync/%s", url.PathEscape(branch))
body, _ := json.Marshal(map[string]any{ "did": ownerDid, "source": source, "name": name, })
req, err := s.newRequest(Method, endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) ForkRepo(ownerDid, source, name string) (*http.Response, error) { const ( Method = "POST" Endpoint = "/repo/fork" )
body, _ := json.Marshal(map[string]any{ "did": ownerDid, "source": source, "name": name, })
req, err := s.newRequest(Method, Endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) RemoveRepo(did, repoName string) (*http.Response, error) { const ( Method = "DELETE" Endpoint = "/repo" )
body, _ := json.Marshal(map[string]any{ "did": did, "name": repoName, })
req, err := s.newRequest(Method, Endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) AddMember(did string) (*http.Response, error) { const ( Method = "PUT" Endpoint = "/member/add" )
body, _ := json.Marshal(map[string]any{ "did": did, })
req, err := s.newRequest(Method, Endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) SetDefaultBranch(ownerDid, repoName, branch string) (*http.Response, error) { const ( Method = "PUT" ) endpoint := fmt.Sprintf("/%s/%s/branches/default", ownerDid, repoName)
body, _ := json.Marshal(map[string]any{ "branch": branch, })
req, err := s.newRequest(Method, endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) AddCollaborator(ownerDid, repoName, memberDid string) (*http.Response, error) { const ( Method = "POST" ) endpoint := fmt.Sprintf("/%s/%s/collaborator/add", ownerDid, repoName)
body, _ := json.Marshal(map[string]any{ "did": memberDid, })
req, err := s.newRequest(Method, endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) Merge( patch []byte, ownerDid, targetRepo, branch, commitMessage, commitBody, authorName, authorEmail string,) (*http.Response, error) { const ( Method = "POST" ) endpoint := fmt.Sprintf("/%s/%s/merge", ownerDid, targetRepo)
mr := types.MergeRequest{ Branch: branch, CommitMessage: commitMessage, CommitBody: commitBody, AuthorName: authorName, AuthorEmail: authorEmail, Patch: string(patch), }
body, _ := json.Marshal(mr)
req, err := s.newRequest(Method, endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) MergeCheck(patch []byte, ownerDid, targetRepo, branch string) (*http.Response, error) { const ( Method = "POST" ) endpoint := fmt.Sprintf("/%s/%s/merge/check", ownerDid, targetRepo)
body, _ := json.Marshal(map[string]any{ "patch": string(patch), "branch": branch, })
req, err := s.newRequest(Method, endpoint, body) if err != nil { return nil, err }
return s.client.Do(req)}
func (s *SignedClient) NewHiddenRef(ownerDid, targetRepo, forkBranch, remoteBranch string) (*http.Response, error) { const ( Method = "POST" ) endpoint := fmt.Sprintf("/%s/%s/hidden-ref/%s/%s", ownerDid, targetRepo, url.PathEscape(forkBranch), url.PathEscape(remoteBranch))
req, err := s.newRequest(Method, endpoint, nil) if err != nil { return nil, err }
return s.client.Do(req)}