From f28e8d2b65943f1f1fae5ec1848de42b0964368a Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Sat, 15 Nov 2025 03:15:29 +0900 Subject: [PATCH] appview: use less `OwnerSlashRepo()` in handlers Change-Id: yurolxtlpsmzploooutrlmxlmwszowlo Signed-off-by: Seongmin Lee --- appview/issues/issues.go | 13 +++++++--- appview/middleware/middleware.go | 4 +-- appview/pages/repoinfo/repoinfo.go | 4 +-- appview/pulls/pulls.go | 40 ++++++++++++++++++------------ appview/repo/archive.go | 4 +-- appview/repo/artifact.go | 11 ++++++-- appview/repo/blob.go | 10 +++++--- appview/repo/branches.go | 2 +- appview/repo/compare.go | 4 +-- appview/repo/feed.go | 40 +++++++++++++++++------------- appview/repo/index.go | 4 +-- appview/repo/log.go | 4 +-- appview/repo/repo.go | 10 ++++---- appview/repo/settings.go | 4 +-- appview/repo/tags.go | 2 +- appview/repo/tree.go | 8 +++--- appview/reporesolver/resolver.go | 40 +++++++++++------------------- 17 files changed, 112 insertions(+), 92 deletions(-) diff --git a/appview/issues/issues.go b/appview/issues/issues.go index 89254819..53cfb109 100644 --- a/appview/issues/issues.go +++ b/appview/issues/issues.go @@ -312,7 +312,8 @@ func (rp *Issues) CloseIssue(w http.ResponseWriter, r *http.Request) { // notify about the issue closure rp.notifier.NewIssueState(r.Context(), syntax.DID(user.Did), issue) - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) return } else { l.Error("user is not permitted to close issue") @@ -362,7 +363,8 @@ func (rp *Issues) ReopenIssue(w http.ResponseWriter, r *http.Request) { // notify about the issue reopen rp.notifier.NewIssueState(r.Context(), syntax.DID(user.Did), issue) - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) return } else { l.Error("user is not the owner of the repo") @@ -466,7 +468,8 @@ func (rp *Issues) NewIssueComment(w http.ResponseWriter, r *http.Request) { } rp.notifier.NewIssueComment(r.Context(), &comment, mentions) - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d#comment-%d", f.OwnerSlashRepo(), issue.IssueId, commentId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d#comment-%d", ownerSlashRepo, issue.IssueId, commentId)) } func (rp *Issues) IssueComment(w http.ResponseWriter, r *http.Request) { @@ -988,7 +991,9 @@ func (rp *Issues) NewIssue(w http.ResponseWriter, r *http.Request) { } } rp.notifier.NewIssue(r.Context(), issue, mentions) - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId)) + + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) return } } diff --git a/appview/middleware/middleware.go b/appview/middleware/middleware.go index 8ec71059..f4866abd 100644 --- a/appview/middleware/middleware.go +++ b/appview/middleware/middleware.go @@ -164,7 +164,7 @@ func (mw Middleware) RepoPermissionMiddleware(requiredPerm string) middlewareFun ok, err := mw.enforcer.E.Enforce(actor.Did, f.Knot, f.DidSlashRepo(), requiredPerm) if err != nil || !ok { // we need a logged in user - log.Printf("%s does not have perms of a %s in repo %s", actor.Did, requiredPerm, f.OwnerSlashRepo()) + log.Printf("%s does not have perms of a %s in repo %s", actor.Did, requiredPerm, f.DidSlashRepo()) http.Error(w, "Forbiden", http.StatusUnauthorized) return } @@ -327,7 +327,7 @@ func (mw Middleware) GoImport() middlewareFunc { return } - fullName := f.OwnerHandle() + "/" + f.Name + fullName := reporesolver.GetBaseRepoPath(r, &f.Repo) if r.Header.Get("User-Agent") == "Go-http-client/1.1" { if r.URL.Query().Get("go-get") == "1" { diff --git a/appview/pages/repoinfo/repoinfo.go b/appview/pages/repoinfo/repoinfo.go index d9aaba6b..9b5472d4 100644 --- a/appview/pages/repoinfo/repoinfo.go +++ b/appview/pages/repoinfo/repoinfo.go @@ -21,7 +21,7 @@ func (r RepoInfo) FullName() string { return path.Join(r.owner(), r.Name) } -func (r RepoInfo) OwnerWithoutAt() string { +func (r RepoInfo) ownerWithoutAt() string { if r.OwnerHandle != "" { return r.OwnerHandle } else { @@ -30,7 +30,7 @@ func (r RepoInfo) OwnerWithoutAt() string { } func (r RepoInfo) FullNameWithoutAt() string { - return path.Join(r.OwnerWithoutAt(), r.Name) + return path.Join(r.ownerWithoutAt(), r.Name) } func (r RepoInfo) GetTabs() [][]string { diff --git a/appview/pulls/pulls.go b/appview/pulls/pulls.go index da384e8d..0ee5a671 100644 --- a/appview/pulls/pulls.go +++ b/appview/pulls/pulls.go @@ -268,7 +268,7 @@ func (s *Pulls) mergeCheck(r *http.Request, f *reporesolver.ResolvedRepo, pull * r.Context(), &xrpcc, &tangled.RepoMergeCheck_Input{ - Did: f.OwnerDid(), + Did: f.Did, Name: f.Name, Branch: pull.TargetBranch, Patch: patch, @@ -382,7 +382,7 @@ func (s *Pulls) resubmitCheck(r *http.Request, f *reporesolver.ResolvedRepo, pul } else { // pulls within the same repo knot = f.Knot - ownerDid = f.OwnerDid() + ownerDid = f.Did repoName = f.Name } @@ -802,7 +802,8 @@ func (s *Pulls) PullComment(w http.ResponseWriter, r *http.Request) { } s.notifier.NewPullComment(r.Context(), comment, mentions) - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", f.OwnerSlashRepo(), pull.PullId, commentId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", ownerSlashRepo, pull.PullId, commentId)) return } } @@ -826,7 +827,7 @@ func (s *Pulls) NewPull(w http.ResponseWriter, r *http.Request) { Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { @@ -991,7 +992,7 @@ func (s *Pulls) handleBranchBasedPull( Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, targetBranch, sourceBranch) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { @@ -1273,7 +1274,8 @@ func (s *Pulls) createPullRequest( s.notifier.NewPull(r.Context(), pull) - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pullId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pullId)) } func (s *Pulls) createStackedPullRequest( @@ -1374,7 +1376,8 @@ func (s *Pulls) createStackedPullRequest( return } - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", f.OwnerSlashRepo())) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", ownerSlashRepo)) } func (s *Pulls) ValidatePatch(w http.ResponseWriter, r *http.Request) { @@ -1433,7 +1436,7 @@ func (s *Pulls) CompareBranchesFragment(w http.ResponseWriter, r *http.Request) Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { @@ -1554,7 +1557,7 @@ func (s *Pulls) CompareForksBranchesFragment(w http.ResponseWriter, r *http.Requ Host: targetHost, } - targetRepo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + targetRepo := fmt.Sprintf("%s/%s", f.Did, f.Name) targetXrpcBytes, err := tangled.RepoBranches(r.Context(), targetXrpcc, "", 0, targetRepo) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { @@ -1685,7 +1688,7 @@ func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) { Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, pull.TargetBranch, pull.PullSource.Branch) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { @@ -1922,7 +1925,8 @@ func (s *Pulls) resubmitPullHelper( return } - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) } func (s *Pulls) resubmitStackedPullHelper( @@ -2115,7 +2119,8 @@ func (s *Pulls) resubmitStackedPullHelper( return } - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) } func (s *Pulls) MergePull(w http.ResponseWriter, r *http.Request) { @@ -2168,7 +2173,7 @@ func (s *Pulls) MergePull(w http.ResponseWriter, r *http.Request) { authorName := ident.Handle.String() mergeInput := &tangled.RepoMerge_Input{ - Did: f.OwnerDid(), + Did: f.Did, Name: f.Name, Branch: pull.TargetBranch, Patch: patch, @@ -2233,7 +2238,8 @@ func (s *Pulls) MergePull(w http.ResponseWriter, r *http.Request) { s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) } - s.pages.HxLocation(w, fmt.Sprintf("/@%s/%s/pulls/%d", f.OwnerHandle(), f.Name, pull.PullId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) } func (s *Pulls) ClosePull(w http.ResponseWriter, r *http.Request) { @@ -2305,7 +2311,8 @@ func (s *Pulls) ClosePull(w http.ResponseWriter, r *http.Request) { s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) } - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) } func (s *Pulls) ReopenPull(w http.ResponseWriter, r *http.Request) { @@ -2378,7 +2385,8 @@ func (s *Pulls) ReopenPull(w http.ResponseWriter, r *http.Request) { s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) } - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) } func newStack(f *reporesolver.ResolvedRepo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) { diff --git a/appview/repo/archive.go b/appview/repo/archive.go index 3d3ee729..eac24201 100644 --- a/appview/repo/archive.go +++ b/appview/repo/archive.go @@ -31,8 +31,8 @@ func (rp *Repo) DownloadArchive(w http.ResponseWriter, r *http.Request) { xrpcc := &indigoxrpc.Client{ Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) - archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, repo) + didSlashRepo := f.DidSlashRepo() + archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, didSlashRepo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.archive", "err", xrpcerr) rp.pages.Error503(w) diff --git a/appview/repo/artifact.go b/appview/repo/artifact.go index 469d63e1..c6f0a100 100644 --- a/appview/repo/artifact.go +++ b/appview/repo/artifact.go @@ -174,7 +174,14 @@ func (rp *Repo) DownloadArtifact(w http.ResponseWriter, r *http.Request) { artifact := artifacts[0] - ownerPds := f.OwnerId.PDSEndpoint() + ownerId, err := rp.idResolver.ResolveIdent(r.Context(), f.Did) + if err != nil { + log.Println("failed to resolve repo owner did", f.Did, err) + http.Error(w, "repository owner not found", http.StatusNotFound) + return + } + + ownerPds := ownerId.PDSEndpoint() url, _ := url.Parse(fmt.Sprintf("%s/xrpc/com.atproto.sync.getBlob", ownerPds)) q := url.Query() q.Set("cid", artifact.BlobCid.String()) @@ -305,7 +312,7 @@ func (rp *Repo) resolveTag(ctx context.Context, f *reporesolver.ResolvedRepo, ta Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoTags(ctx, xrpcc, "", 0, repo) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { diff --git a/appview/repo/blob.go b/appview/repo/blob.go index 481753bb..14720666 100644 --- a/appview/repo/blob.go +++ b/appview/repo/blob.go @@ -54,7 +54,7 @@ func (rp *Repo) Blob(w http.ResponseWriter, r *http.Request) { xrpcc := &indigoxrpc.Client{ Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Repo.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Repo.Name) resp, err := tangled.RepoBlob(r.Context(), xrpcc, filePath, false, ref, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.blob", "err", xrpcerr) @@ -62,9 +62,11 @@ func (rp *Repo) Blob(w http.ResponseWriter, r *http.Request) { return } + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) + // Use XRPC response directly instead of converting to internal types var breadcrumbs [][]string - breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", f.OwnerSlashRepo(), url.PathEscape(ref))}) + breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", ownerSlashRepo, url.PathEscape(ref))}) if filePath != "" { for idx, elem := range strings.Split(filePath, "/") { breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], url.PathEscape(elem))}) @@ -105,7 +107,7 @@ func (rp *Repo) RepoBlobRaw(w http.ResponseWriter, r *http.Request) { if !rp.config.Core.Dev { scheme = "https" } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Repo.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Repo.Name) baseURL := &url.URL{ Scheme: scheme, Host: f.Knot, @@ -256,7 +258,7 @@ func generateBlobURL(config *config.Config, f *reporesolver.ResolvedRepo, ref, f scheme = "https" } - repoName := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repoName := fmt.Sprintf("%s/%s", f.Did, f.Name) baseURL := &url.URL{ Scheme: scheme, Host: f.Knot, diff --git a/appview/repo/branches.go b/appview/repo/branches.go index ffd9baab..74c09cae 100644 --- a/appview/repo/branches.go +++ b/appview/repo/branches.go @@ -29,7 +29,7 @@ func (rp *Repo) Branches(w http.ResponseWriter, r *http.Request) { xrpcc := &indigoxrpc.Client{ Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.branches", "err", xrpcerr) diff --git a/appview/repo/compare.go b/appview/repo/compare.go index b0b85d3e..ca3b73da 100644 --- a/appview/repo/compare.go +++ b/appview/repo/compare.go @@ -36,7 +36,7 @@ func (rp *Repo) CompareNew(w http.ResponseWriter, r *http.Request) { Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.branches", "err", xrpcerr) @@ -151,7 +151,7 @@ func (rp *Repo) Compare(w http.ResponseWriter, r *http.Request) { Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { diff --git a/appview/repo/feed.go b/appview/repo/feed.go index 7d23faa0..90de0f14 100644 --- a/appview/repo/feed.go +++ b/appview/repo/feed.go @@ -11,16 +11,16 @@ import ( "tangled.org/core/appview/db" "tangled.org/core/appview/models" "tangled.org/core/appview/pagination" - "tangled.org/core/appview/reporesolver" + "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax" "github.com/gorilla/feeds" ) -func (rp *Repo) getRepoFeed(ctx context.Context, f *reporesolver.ResolvedRepo) (*feeds.Feed, error) { +func (rp *Repo) getRepoFeed(ctx context.Context, repo *models.Repo, ownerSlashRepo string) (*feeds.Feed, error) { const feedLimitPerType = 100 - pulls, err := db.GetPullsWithLimit(rp.db, feedLimitPerType, db.FilterEq("repo_at", f.RepoAt())) + pulls, err := db.GetPullsWithLimit(rp.db, feedLimitPerType, db.FilterEq("repo_at", repo.RepoAt())) if err != nil { return nil, err } @@ -28,21 +28,21 @@ func (rp *Repo) getRepoFeed(ctx context.Context, f *reporesolver.ResolvedRepo) ( issues, err := db.GetIssuesPaginated( rp.db, pagination.Page{Limit: feedLimitPerType}, - db.FilterEq("repo_at", f.RepoAt()), + db.FilterEq("repo_at", repo.RepoAt()), ) if err != nil { return nil, err } feed := &feeds.Feed{ - Title: fmt.Sprintf("activity feed for %s", f.OwnerSlashRepo()), - Link: &feeds.Link{Href: fmt.Sprintf("%s/%s", rp.config.Core.AppviewHost, f.OwnerSlashRepo()), Type: "text/html", Rel: "alternate"}, + Title: fmt.Sprintf("activity feed for @%s", ownerSlashRepo), + Link: &feeds.Link{Href: fmt.Sprintf("%s/%s", rp.config.Core.AppviewHost, ownerSlashRepo), Type: "text/html", Rel: "alternate"}, Items: make([]*feeds.Item, 0), Updated: time.UnixMilli(0), } for _, pull := range pulls { - items, err := rp.createPullItems(ctx, pull, f) + items, err := rp.createPullItems(ctx, pull, repo, ownerSlashRepo) if err != nil { return nil, err } @@ -50,7 +50,7 @@ func (rp *Repo) getRepoFeed(ctx context.Context, f *reporesolver.ResolvedRepo) ( } for _, issue := range issues { - item, err := rp.createIssueItem(ctx, issue, f) + item, err := rp.createIssueItem(ctx, issue, repo, ownerSlashRepo) if err != nil { return nil, err } @@ -71,7 +71,7 @@ func (rp *Repo) getRepoFeed(ctx context.Context, f *reporesolver.ResolvedRepo) ( return feed, nil } -func (rp *Repo) createPullItems(ctx context.Context, pull *models.Pull, f *reporesolver.ResolvedRepo) ([]*feeds.Item, error) { +func (rp *Repo) createPullItems(ctx context.Context, pull *models.Pull, repo *models.Repo, ownerSlashRepo string) ([]*feeds.Item, error) { owner, err := rp.idResolver.ResolveIdent(ctx, pull.OwnerDid) if err != nil { return nil, err @@ -80,12 +80,12 @@ func (rp *Repo) createPullItems(ctx context.Context, pull *models.Pull, f *repor var items []*feeds.Item state := rp.getPullState(pull) - description := rp.buildPullDescription(owner.Handle, state, pull, f.OwnerSlashRepo()) + description := rp.buildPullDescription(owner.Handle, state, pull, ownerSlashRepo) mainItem := &feeds.Item{ Title: fmt.Sprintf("[PR #%d] %s", pull.PullId, pull.Title), Description: description, - Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/pulls/%d", rp.config.Core.AppviewHost, f.OwnerSlashRepo(), pull.PullId)}, + Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/pulls/%d", rp.config.Core.AppviewHost, ownerSlashRepo, pull.PullId)}, Created: pull.Created, Author: &feeds.Author{Name: fmt.Sprintf("@%s", owner.Handle)}, } @@ -98,8 +98,8 @@ func (rp *Repo) createPullItems(ctx context.Context, pull *models.Pull, f *repor roundItem := &feeds.Item{ Title: fmt.Sprintf("[PR #%d] %s (round #%d)", pull.PullId, pull.Title, round.RoundNumber), - Description: fmt.Sprintf("@%s submitted changes (at round #%d) on PR #%d in %s", owner.Handle, round.RoundNumber, pull.PullId, f.OwnerSlashRepo()), - Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/pulls/%d/round/%d/", rp.config.Core.AppviewHost, f.OwnerSlashRepo(), pull.PullId, round.RoundNumber)}, + Description: fmt.Sprintf("@%s submitted changes (at round #%d) on PR #%d in @%s", owner.Handle, round.RoundNumber, pull.PullId, ownerSlashRepo), + Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/pulls/%d/round/%d/", rp.config.Core.AppviewHost, ownerSlashRepo, pull.PullId, round.RoundNumber)}, Created: round.Created, Author: &feeds.Author{Name: fmt.Sprintf("@%s", owner.Handle)}, } @@ -109,7 +109,7 @@ func (rp *Repo) createPullItems(ctx context.Context, pull *models.Pull, f *repor return items, nil } -func (rp *Repo) createIssueItem(ctx context.Context, issue models.Issue, f *reporesolver.ResolvedRepo) (*feeds.Item, error) { +func (rp *Repo) createIssueItem(ctx context.Context, issue models.Issue, repo *models.Repo, ownerSlashRepo string) (*feeds.Item, error) { owner, err := rp.idResolver.ResolveIdent(ctx, issue.Did) if err != nil { return nil, err @@ -122,8 +122,8 @@ func (rp *Repo) createIssueItem(ctx context.Context, issue models.Issue, f *repo return &feeds.Item{ Title: fmt.Sprintf("[Issue #%d] %s", issue.IssueId, issue.Title), - Description: fmt.Sprintf("@%s %s issue #%d in %s", owner.Handle, state, issue.IssueId, f.OwnerSlashRepo()), - Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/issues/%d", rp.config.Core.AppviewHost, f.OwnerSlashRepo(), issue.IssueId)}, + Description: fmt.Sprintf("@%s %s issue #%d in @%s", owner.Handle, state, issue.IssueId, ownerSlashRepo), + Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/issues/%d", rp.config.Core.AppviewHost, ownerSlashRepo, issue.IssueId)}, Created: issue.Created, Author: &feeds.Author{Name: fmt.Sprintf("@%s", owner.Handle)}, }, nil @@ -152,8 +152,14 @@ func (rp *Repo) AtomFeed(w http.ResponseWriter, r *http.Request) { log.Println("failed to fully resolve repo:", err) return } + repoOwnerId, ok := r.Context().Value("resolvedId").(identity.Identity) + if !ok || repoOwnerId.Handle.IsInvalidHandle() { + log.Println("failed to get resolved repo owner id") + return + } + ownerSlashRepo := repoOwnerId.Handle.String() + "/" + f.Name - feed, err := rp.getRepoFeed(r.Context(), f) + feed, err := rp.getRepoFeed(r.Context(), &f.Repo, ownerSlashRepo) if err != nil { log.Println("failed to get repo feed:", err) rp.pages.Error500(w) diff --git a/appview/repo/index.go b/appview/repo/index.go index 6815e5c7..209d76a9 100644 --- a/appview/repo/index.go +++ b/appview/repo/index.go @@ -179,7 +179,7 @@ func (rp *Repo) getLanguageInfo( if err != nil || langs == nil { // non-fatal, fetch langs from ks via XRPC - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, repo) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { @@ -256,7 +256,7 @@ func (rp *Repo) getLanguageInfo( // buildIndexResponse creates a RepoIndexResponse by combining multiple xrpc calls in parallel func (rp *Repo) buildIndexResponse(ctx context.Context, xrpcc *indigoxrpc.Client, f *reporesolver.ResolvedRepo, ref string) (*types.RepoIndexResponse, error) { - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) // first get branches to determine the ref if not specified branchesBytes, err := tangled.RepoBranches(ctx, xrpcc, "", 0, repo) diff --git a/appview/repo/log.go b/appview/repo/log.go index 89b22405..e340d3f5 100644 --- a/appview/repo/log.go +++ b/appview/repo/log.go @@ -57,7 +57,7 @@ func (rp *Repo) Log(w http.ResponseWriter, r *http.Request) { cursor = strconv.Itoa(offset) } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.log", "err", xrpcerr) @@ -174,7 +174,7 @@ func (rp *Repo) Commit(w http.ResponseWriter, r *http.Request) { Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.diff", "err", xrpcerr) diff --git a/appview/repo/repo.go b/appview/repo/repo.go index 4ba4cf5c..cd7dbd15 100644 --- a/appview/repo/repo.go +++ b/appview/repo/repo.go @@ -864,7 +864,7 @@ func (rp *Repo) DeleteRepo(w http.ResponseWriter, r *http.Request) { r.Context(), client, &tangled.RepoDelete_Input{ - Did: f.OwnerDid(), + Did: f.Did, Name: f.Name, Rkey: f.Rkey, }, @@ -902,14 +902,14 @@ func (rp *Repo) DeleteRepo(w http.ResponseWriter, r *http.Request) { l.Info("removed collaborators") // remove repo RBAC - err = rp.enforcer.RemoveRepo(f.OwnerDid(), f.Knot, f.DidSlashRepo()) + err = rp.enforcer.RemoveRepo(f.Did, f.Knot, f.DidSlashRepo()) if err != nil { rp.pages.Notice(w, noticeId, "Failed to update RBAC rules") return } // remove repo from db - err = db.RemoveRepo(tx, f.OwnerDid(), f.Name) + err = db.RemoveRepo(tx, f.Did, f.Name) if err != nil { rp.pages.Notice(w, noticeId, "Failed to update appview") return @@ -930,7 +930,7 @@ func (rp *Repo) DeleteRepo(w http.ResponseWriter, r *http.Request) { return } - rp.pages.HxRedirect(w, fmt.Sprintf("/%s", f.OwnerDid())) + rp.pages.HxRedirect(w, fmt.Sprintf("/%s", f.Did)) } func (rp *Repo) SyncRepoFork(w http.ResponseWriter, r *http.Request) { @@ -1058,7 +1058,7 @@ func (rp *Repo) ForkRepo(w http.ResponseWriter, r *http.Request) { uri = "http" } - forkSourceUrl := fmt.Sprintf("%s://%s/%s/%s", uri, f.Knot, f.OwnerDid(), f.Repo.Name) + forkSourceUrl := fmt.Sprintf("%s://%s/%s/%s", uri, f.Knot, f.Did, f.Repo.Name) l = l.With("cloneUrl", forkSourceUrl) sourceAt := f.RepoAt().String() diff --git a/appview/repo/settings.go b/appview/repo/settings.go index 1b54b342..bf4ebc0a 100644 --- a/appview/repo/settings.go +++ b/appview/repo/settings.go @@ -194,7 +194,7 @@ func (rp *Repo) generalSettings(w http.ResponseWriter, r *http.Request) { Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.branches", "err", xrpcerr) @@ -292,7 +292,7 @@ func (rp *Repo) pipelineSettings(w http.ResponseWriter, r *http.Request) { user := rp.oauth.GetUser(r) // all spindles that the repo owner is a member of - spindles, err := rp.enforcer.GetSpindlesForUser(f.OwnerDid()) + spindles, err := rp.enforcer.GetSpindlesForUser(f.Did) if err != nil { l.Error("failed to fetch spindles", "err", err) return diff --git a/appview/repo/tags.go b/appview/repo/tags.go index 320ac93f..2737f881 100644 --- a/appview/repo/tags.go +++ b/appview/repo/tags.go @@ -31,7 +31,7 @@ func (rp *Repo) Tags(w http.ResponseWriter, r *http.Request) { xrpcc := &indigoxrpc.Client{ Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.tags", "err", xrpcerr) diff --git a/appview/repo/tree.go b/appview/repo/tree.go index 82f68352..17a7bb9a 100644 --- a/appview/repo/tree.go +++ b/appview/repo/tree.go @@ -9,6 +9,7 @@ import ( "tangled.org/core/api/tangled" "tangled.org/core/appview/pages" + "tangled.org/core/appview/reporesolver" xrpcclient "tangled.org/core/appview/xrpcclient" "tangled.org/core/types" @@ -39,7 +40,7 @@ func (rp *Repo) Tree(w http.ResponseWriter, r *http.Request) { xrpcc := &indigoxrpc.Client{ Host: host, } - repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name) + repo := fmt.Sprintf("%s/%s", f.Did, f.Name) xrpcResp, err := tangled.RepoTree(r.Context(), xrpcc, treePath, ref, repo) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { l.Error("failed to call XRPC repo.tree", "err", xrpcerr) @@ -79,16 +80,17 @@ func (rp *Repo) Tree(w http.ResponseWriter, r *http.Request) { result.ReadmeFileName = xrpcResp.Readme.Filename result.Readme = xrpcResp.Readme.Contents } + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo) // redirects tree paths trying to access a blob; in this case the result.Files is unpopulated, // so we can safely redirect to the "parent" (which is the same file). if len(result.Files) == 0 && result.Parent == treePath { - redirectTo := fmt.Sprintf("/%s/blob/%s/%s", f.OwnerSlashRepo(), url.PathEscape(ref), result.Parent) + redirectTo := fmt.Sprintf("/%s/blob/%s/%s", ownerSlashRepo, url.PathEscape(ref), result.Parent) http.Redirect(w, r, redirectTo, http.StatusFound) return } user := rp.oauth.GetUser(r) var breadcrumbs [][]string - breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", f.OwnerSlashRepo(), url.PathEscape(ref))}) + breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", ownerSlashRepo, url.PathEscape(ref))}) if treePath != "" { for idx, elem := range strings.Split(treePath, "/") { breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], url.PathEscape(elem))}) diff --git a/appview/reporesolver/resolver.go b/appview/reporesolver/resolver.go index 974bd20c..05b4b165 100644 --- a/appview/reporesolver/resolver.go +++ b/appview/reporesolver/resolver.go @@ -12,7 +12,6 @@ import ( "strings" "github.com/bluesky-social/indigo/atproto/identity" - securejoin "github.com/cyphar/filepath-securejoin" "github.com/go-chi/chi/v5" "tangled.org/core/appview/config" "tangled.org/core/appview/db" @@ -44,6 +43,18 @@ func New(config *config.Config, enforcer *rbac.Enforcer, resolver *idresolver.Re return &RepoResolver{config: config, enforcer: enforcer, idResolver: resolver, execer: execer} } +// NOTE: this... should not even be here. the entire package will be removed in future refactor +func GetBaseRepoPath(r *http.Request, repo *models.Repo) string { + var ( + user = chi.URLParam(r, "user") + name = chi.URLParam(r, "repo") + ) + if user == "" || name == "" { + return repo.DidSlashRepo() + } + return path.Join(user, name) +} + func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { repo, ok := r.Context().Value("repo").(*models.Repo) if !ok { @@ -69,27 +80,6 @@ func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { }, nil } -func (f *ResolvedRepo) OwnerDid() string { - return f.OwnerId.DID.String() -} - -func (f *ResolvedRepo) OwnerHandle() string { - return f.OwnerId.Handle.String() -} - -func (f *ResolvedRepo) OwnerSlashRepo() string { - handle := f.OwnerId.Handle - - var p string - if handle != "" && !handle.IsInvalidHandle() { - p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.Name) - } else { - p, _ = securejoin.SecureJoin(f.OwnerDid(), f.Name) - } - - return p -} - func (f *ResolvedRepo) Collaborators(ctx context.Context) ([]pages.Collaborator, error) { repoCollaborators, err := f.rr.enforcer.E.GetImplicitUsersForResourceByDomain(f.DidSlashRepo(), f.Knot) if err != nil { @@ -168,10 +158,10 @@ func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo { knot := f.Knot repoInfo := repoinfo.RepoInfo{ - OwnerDid: f.OwnerDid(), - OwnerHandle: f.OwnerHandle(), + OwnerDid: f.OwnerId.DID.String(), + OwnerHandle: f.OwnerId.Handle.String(), Name: f.Name, - Rkey: f.Repo.Rkey, + Rkey: f.Rkey, RepoAt: repoAt, Description: f.Description, Website: f.Website, -- 2.43.0