From ca4b9c8ba21e24162639f4d53f9ea755972c3e5f Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Sun, 11 May 2025 22:53:18 +0300 Subject: [PATCH] appview: knotclient: init knot server client package Lets us use it without an import cycle. --- appview/{state => knotclient}/signer.go | 2 +- appview/oauth/handler/handler.go | 37 +++++++++++++++++++++++++ appview/state/artifact.go | 3 +- appview/state/pull.go | 29 +++++++++---------- appview/state/repo.go | 21 +++++++------- appview/state/repo_util.go | 3 +- appview/state/router.go | 1 + appview/state/state.go | 7 +++-- 8 files changed, 73 insertions(+), 30 deletions(-) rename appview/{state => knotclient}/signer.go (99%) diff --git a/appview/state/signer.go b/appview/knotclient/signer.go similarity index 99% rename from appview/state/signer.go rename to appview/knotclient/signer.go index d3936a22..807d9fac 100644 --- a/appview/state/signer.go +++ b/appview/knotclient/signer.go @@ -1,4 +1,4 @@ -package state +package knotclient import ( "bytes" diff --git a/appview/oauth/handler/handler.go b/appview/oauth/handler/handler.go index e24d00a8..bf768b34 100644 --- a/appview/oauth/handler/handler.go +++ b/appview/oauth/handler/handler.go @@ -14,10 +14,12 @@ import ( "github.com/lestrrat-go/jwx/v2/jwk" "tangled.sh/tangled.sh/core/appview" "tangled.sh/tangled.sh/core/appview/db" + "tangled.sh/tangled.sh/core/appview/knotclient" "tangled.sh/tangled.sh/core/appview/middleware" "tangled.sh/tangled.sh/core/appview/oauth" "tangled.sh/tangled.sh/core/appview/oauth/client" "tangled.sh/tangled.sh/core/appview/pages" + "tangled.sh/tangled.sh/core/rbac" ) const ( @@ -31,6 +33,7 @@ type OAuthHandler struct { Db *db.DB Store *sessions.CookieStore OAuth *oauth.OAuth + Enforcer *rbac.Enforcer } func (o *OAuthHandler) Router() http.Handler { @@ -243,6 +246,7 @@ func (o *OAuthHandler) callback(w http.ResponseWriter, r *http.Request) { } log.Println("session saved successfully") + go o.addToDefaultKnot(oauthRequest.Did) http.Redirect(w, r, "/", http.StatusFound) } @@ -270,3 +274,36 @@ func pubKeyFromJwk(jwks string) (jwk.Key, error) { } return pubKey, nil } + +func (o *OAuthHandler) addToDefaultKnot(did string) { + defaultKnot := "knot1.tangled.sh" + + log.Printf("adding %s to default knot", did) + err := o.Enforcer.AddMember(defaultKnot, did) + if err != nil { + log.Println("failed to add user to knot1.tangled.sh: ", err) + return + } + err = o.Enforcer.E.SavePolicy() + if err != nil { + log.Println("failed to add user to knot1.tangled.sh: ", err) + return + } + + secret, err := db.GetRegistrationKey(o.Db, defaultKnot) + if err != nil { + log.Println("failed to get registration key for knot1.tangled.sh") + return + } + signedClient, err := knotclient.NewSignedClient(defaultKnot, secret, o.Config.Core.Dev) + resp, err := signedClient.AddMember(did) + if err != nil { + log.Println("failed to add user to knot1.tangled.sh: ", err) + return + } + + if resp.StatusCode != http.StatusNoContent { + log.Println("failed to add user to knot1.tangled.sh: ", resp.StatusCode) + return + } +} diff --git a/appview/state/artifact.go b/appview/state/artifact.go index 8cb629c6..0ffe5dc8 100644 --- a/appview/state/artifact.go +++ b/appview/state/artifact.go @@ -16,6 +16,7 @@ import ( "tangled.sh/tangled.sh/core/api/tangled" "tangled.sh/tangled.sh/core/appview" "tangled.sh/tangled.sh/core/appview/db" + "tangled.sh/tangled.sh/core/appview/knotclient" "tangled.sh/tangled.sh/core/appview/pages" "tangled.sh/tangled.sh/core/types" ) @@ -263,7 +264,7 @@ func (s *State) resolveTag(f *FullyResolvedRepo, tagParam string) (*types.TagRef return nil, err } - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { return nil, err } diff --git a/appview/state/pull.go b/appview/state/pull.go index 1fc229da..4286e66b 100644 --- a/appview/state/pull.go +++ b/appview/state/pull.go @@ -14,6 +14,7 @@ import ( "tangled.sh/tangled.sh/core/api/tangled" "tangled.sh/tangled.sh/core/appview" "tangled.sh/tangled.sh/core/appview/db" + "tangled.sh/tangled.sh/core/appview/knotclient" "tangled.sh/tangled.sh/core/appview/oauth" "tangled.sh/tangled.sh/core/appview/pages" "tangled.sh/tangled.sh/core/patchutil" @@ -143,7 +144,7 @@ func (s *State) mergeCheck(f *FullyResolvedRepo, pull *db.Pull) types.MergeCheck } } - ksClient, err := NewSignedClient(f.Knot, secret, s.config.Core.Dev) + ksClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev) if err != nil { log.Printf("failed to setup signed client for %s; ignoring: %v", f.Knot, err) return types.MergeCheckResponse{ @@ -215,7 +216,7 @@ func (s *State) resubmitCheck(f *FullyResolvedRepo, pull *db.Pull) pages.Resubmi repoName = f.RepoName } - us, err := NewUnsignedClient(knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(knot, s.config.Core.Dev) if err != nil { log.Printf("failed to setup client for %s; ignoring: %v", knot, err) return pages.Unknown @@ -582,7 +583,7 @@ func (s *State) NewPull(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client for %s", f.Knot) s.pages.Error503(w) @@ -651,7 +652,7 @@ func (s *State) NewPull(w http.ResponseWriter, r *http.Request) { return } - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client to %s: %v", f.Knot, err) s.pages.Notice(w, "pull", "Failed to create a pull request. Try again later.") @@ -703,7 +704,7 @@ func (s *State) handleBranchBasedPull(w http.ResponseWriter, r *http.Request, f } // Generate a patch using /compare - ksClient, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + ksClient, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create signed client for %s: %s", f.Knot, err) s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") @@ -755,14 +756,14 @@ func (s *State) handleForkBasedPull(w http.ResponseWriter, r *http.Request, f *F return } - sc, err := NewSignedClient(fork.Knot, secret, s.config.Core.Dev) + sc, err := knotclient.NewSignedClient(fork.Knot, secret, s.config.Core.Dev) if err != nil { log.Println("failed to create signed client:", err) s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - us, err := NewUnsignedClient(fork.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(fork.Knot, s.config.Core.Dev) if err != nil { log.Println("failed to create unsigned client:", err) s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") @@ -964,7 +965,7 @@ func (s *State) CompareBranchesFragment(w http.ResponseWriter, r *http.Request) return } - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client for %s", f.Knot) s.pages.Error503(w) @@ -1034,7 +1035,7 @@ func (s *State) CompareForksBranchesFragment(w http.ResponseWriter, r *http.Requ return } - sourceBranchesClient, err := NewUnsignedClient(repo.Knot, s.config.Core.Dev) + sourceBranchesClient, err := knotclient.NewUnsignedClient(repo.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client for %s", repo.Knot) s.pages.Error503(w) @@ -1061,7 +1062,7 @@ func (s *State) CompareForksBranchesFragment(w http.ResponseWriter, r *http.Requ return } - targetBranchesClient, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + targetBranchesClient, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client for target knot %s", f.Knot) s.pages.Error503(w) @@ -1247,7 +1248,7 @@ func (s *State) resubmitBranch(w http.ResponseWriter, r *http.Request) { return } - ksClient, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + ksClient, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create client for %s: %s", f.Knot, err) s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") @@ -1367,7 +1368,7 @@ func (s *State) resubmitFork(w http.ResponseWriter, r *http.Request) { } // extract patch by performing compare - ksClient, err := NewUnsignedClient(forkRepo.Knot, s.config.Core.Dev) + ksClient, err := knotclient.NewUnsignedClient(forkRepo.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create client for %s: %s", forkRepo.Knot, err) s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") @@ -1382,7 +1383,7 @@ func (s *State) resubmitFork(w http.ResponseWriter, r *http.Request) { } // update the hidden tracking branch to latest - signedClient, err := NewSignedClient(forkRepo.Knot, secret, s.config.Core.Dev) + signedClient, err := knotclient.NewSignedClient(forkRepo.Knot, secret, s.config.Core.Dev) if err != nil { log.Printf("failed to create signed client for %s: %s", forkRepo.Knot, err) s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") @@ -1533,7 +1534,7 @@ func (s *State) MergePull(w http.ResponseWriter, r *http.Request) { log.Printf("failed to get primary email: %s", err) } - ksClient, err := NewSignedClient(f.Knot, secret, s.config.Core.Dev) + ksClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev) if err != nil { log.Printf("failed to create signed client for %s: %s", f.Knot, err) s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.") diff --git a/appview/state/repo.go b/appview/state/repo.go index 9c0fa296..2a1d9407 100644 --- a/appview/state/repo.go +++ b/appview/state/repo.go @@ -19,6 +19,7 @@ import ( "tangled.sh/tangled.sh/core/api/tangled" "tangled.sh/tangled.sh/core/appview" "tangled.sh/tangled.sh/core/appview/db" + "tangled.sh/tangled.sh/core/appview/knotclient" "tangled.sh/tangled.sh/core/appview/oauth" "tangled.sh/tangled.sh/core/appview/pages" "tangled.sh/tangled.sh/core/appview/pages/markup" @@ -45,7 +46,7 @@ func (s *State) RepoIndex(w http.ResponseWriter, r *http.Request) { return } - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client for %s", f.Knot) s.pages.Error503(w) @@ -150,7 +151,7 @@ func (s *State) RepoLog(w http.ResponseWriter, r *http.Request) { ref := chi.URLParam(r, "ref") - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Println("failed to create unsigned client", err) return @@ -416,7 +417,7 @@ func (s *State) RepoTags(w http.ResponseWriter, r *http.Request) { return } - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Println("failed to create unsigned client", err) return @@ -474,7 +475,7 @@ func (s *State) RepoBranches(w http.ResponseWriter, r *http.Request) { return } - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Println("failed to create unsigned client", err) return @@ -657,7 +658,7 @@ func (s *State) AddCollaborator(w http.ResponseWriter, r *http.Request) { return } - ksClient, err := NewSignedClient(f.Knot, secret, s.config.Core.Dev) + ksClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev) if err != nil { log.Println("failed to create client to ", f.Knot) return @@ -752,7 +753,7 @@ func (s *State) DeleteRepo(w http.ResponseWriter, r *http.Request) { return } - ksClient, err := NewSignedClient(f.Knot, secret, s.config.Core.Dev) + ksClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev) if err != nil { log.Println("failed to create client to ", f.Knot) return @@ -847,7 +848,7 @@ func (s *State) SetDefaultBranch(w http.ResponseWriter, r *http.Request) { return } - ksClient, err := NewSignedClient(f.Knot, secret, s.config.Core.Dev) + ksClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev) if err != nil { log.Println("failed to create client to ", f.Knot) return @@ -893,7 +894,7 @@ func (s *State) RepoSettings(w http.ResponseWriter, r *http.Request) { var branchNames []string var defaultBranch string - us, err := NewUnsignedClient(f.Knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) if err != nil { log.Println("failed to create unsigned client", err) } else { @@ -1060,7 +1061,7 @@ func (f *FullyResolvedRepo) RepoInfo(s *State, u *oauth.User) repoinfo.RepoInfo knot := f.Knot var disableFork bool - us, err := NewUnsignedClient(knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(knot, s.config.Core.Dev) if err != nil { log.Printf("failed to create unsigned client for %s: %v", knot, err) } else { @@ -1862,7 +1863,7 @@ func (s *State) ForkRepo(w http.ResponseWriter, r *http.Request) { return } - client, err := NewSignedClient(knot, secret, s.config.Core.Dev) + client, err := knotclient.NewSignedClient(knot, secret, s.config.Core.Dev) if err != nil { s.pages.Notice(w, "repo", "Failed to reach knot server.") return diff --git a/appview/state/repo_util.go b/appview/state/repo_util.go index df8d8679..7b4f6a39 100644 --- a/appview/state/repo_util.go +++ b/appview/state/repo_util.go @@ -13,6 +13,7 @@ import ( "github.com/go-chi/chi/v5" "github.com/go-git/go-git/v5/plumbing/object" "tangled.sh/tangled.sh/core/appview/db" + "tangled.sh/tangled.sh/core/appview/knotclient" "tangled.sh/tangled.sh/core/appview/oauth" "tangled.sh/tangled.sh/core/appview/pages/repoinfo" ) @@ -45,7 +46,7 @@ func (s *State) fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) { ref := chi.URLParam(r, "ref") if ref == "" { - us, err := NewUnsignedClient(knot, s.config.Core.Dev) + us, err := knotclient.NewUnsignedClient(knot, s.config.Core.Dev) if err != nil { return nil, err } diff --git a/appview/state/router.go b/appview/state/router.go index 8401cbeb..20769b88 100644 --- a/appview/state/router.go +++ b/appview/state/router.go @@ -264,6 +264,7 @@ func (s *State) OAuthRouter() http.Handler { Db: s.db, Store: sessions.NewCookieStore([]byte(s.config.Core.CookieSecret)), OAuth: s.oauth, + Enforcer: s.enforcer, } return oauth.Router() diff --git a/appview/state/state.go b/appview/state/state.go index aa43e62d..61c5d0f2 100644 --- a/appview/state/state.go +++ b/appview/state/state.go @@ -20,6 +20,7 @@ import ( "tangled.sh/tangled.sh/core/api/tangled" "tangled.sh/tangled.sh/core/appview" "tangled.sh/tangled.sh/core/appview/db" + "tangled.sh/tangled.sh/core/appview/knotclient" "tangled.sh/tangled.sh/core/appview/oauth" "tangled.sh/tangled.sh/core/appview/pages" "tangled.sh/tangled.sh/core/jetstream" @@ -309,7 +310,7 @@ func (s *State) InitKnotServer(w http.ResponseWriter, r *http.Request) { return } - client, err := NewSignedClient(domain, secret, s.config.Core.Dev) + client, err := knotclient.NewSignedClient(domain, secret, s.config.Core.Dev) if err != nil { log.Println("failed to create client to ", domain) } @@ -551,7 +552,7 @@ func (s *State) AddMember(w http.ResponseWriter, r *http.Request) { return } - ksClient, err := NewSignedClient(domain, secret, s.config.Core.Dev) + ksClient, err := knotclient.NewSignedClient(domain, secret, s.config.Core.Dev) if err != nil { log.Println("failed to create client to ", domain) return @@ -672,7 +673,7 @@ func (s *State) NewRepo(w http.ResponseWriter, r *http.Request) { return } - client, err := NewSignedClient(domain, secret, s.config.Core.Dev) + client, err := knotclient.NewSignedClient(domain, secret, s.config.Core.Dev) if err != nil { s.pages.Notice(w, "repo", "Failed to connect to knot server.") return -- 2.51.2