@@ -185,7 +185,7 @@ func (h *Handlers) repoHome(w http.ResponseWriter, r *http.Request) { |
| 185 | owner := chi.URLParam(r, "owner") | 185 | owner := chi.URLParam(r, "owner") |
| 186 | name := chi.URLParam(r, "repo") | 186 | name := chi.URLParam(r, "repo") |
| 187 | | 187 | |
| 188 | - row, err := h.lookupRepoForViewer(r.Context(), owner, name, middleware.CurrentUserFromContext(r.Context()).ID) | 188 | + row, err := h.lookupRepoForViewer(r.Context(), owner, name, middleware.CurrentUserFromContext(r.Context())) |
| 189 | if err != nil { | 189 | if err != nil { |
| 190 | // Maybe the (owner, name) is a stale name; look up the redirect | 190 | // Maybe the (owner, name) is a stale name; look up the redirect |
| 191 | // table and 301 to the canonical URL so old bookmarks keep | 191 | // table and 301 to the canonical URL so old bookmarks keep |
@@ -239,7 +239,7 @@ func (h *Handlers) repoHome(w http.ResponseWriter, r *http.Request) { |
| 239 | // - AND the viewer is allowed to see it (public OR viewer is owner). | 239 | // - AND the viewer is allowed to see it (public OR viewer is owner). |
| 240 | // | 240 | // |
| 241 | // Anything else returns ErrNoRows so the caller can 404 uniformly. | 241 | // Anything else returns ErrNoRows so the caller can 404 uniformly. |
| 242 | -func (h *Handlers) lookupRepoForViewer(ctx context.Context, ownerName, repoName string, viewerID int64) (reposdb.Repo, error) { | 242 | +func (h *Handlers) lookupRepoForViewer(ctx context.Context, ownerName, repoName string, viewer middleware.CurrentUser) (reposdb.Repo, error) { |
| 243 | owner, err := h.uq.GetUserByUsername(ctx, h.d.Pool, ownerName) | 243 | owner, err := h.uq.GetUserByUsername(ctx, h.d.Pool, ownerName) |
| 244 | if err != nil { | 244 | if err != nil { |
| 245 | return reposdb.Repo{}, err | 245 | return reposdb.Repo{}, err |
@@ -255,11 +255,17 @@ func (h *Handlers) lookupRepoForViewer(ctx context.Context, ownerName, repoName |
| 255 | // when the decision denies, return ErrNoRows so the caller can 404. | 255 | // when the decision denies, return ErrNoRows so the caller can 404. |
| 256 | repoRef := policy.NewRepoRefFromRepo(row) | 256 | repoRef := policy.NewRepoRefFromRepo(row) |
| 257 | var actor policy.Actor | 257 | var actor policy.Actor |
| 258 | - if viewerID == 0 { | 258 | + if viewer.IsAnonymous() { |
| 259 | actor = policy.AnonymousActor() | 259 | actor = policy.AnonymousActor() |
| 260 | } else { | 260 | } else { |
| 261 | - actor = policy.UserActor(viewerID, "", false, false) | 261 | + actor = policy.UserActor(viewer.ID, viewer.Username, viewer.IsSuspended, false) |
| 262 | } | 262 | } |
| | 263 | + // ActionRepoRead deny on a private repo with a non-collab viewer is |
| | 264 | + // indistinguishable from "doesn't exist" — Maybe404 returns 404 in |
| | 265 | + // that shape, so the caller's pgx.ErrNoRows fallthrough is the |
| | 266 | + // right shape regardless of whether the row was missing or just |
| | 267 | + // invisible. Honest 403s (e.g. ActionRepoWrite on archived) are |
| | 268 | + // gated through `loadRepoAndAuthorize`, not this read-only helper. |
| 263 | if !policy.Can(ctx, policy.Deps{Pool: h.d.Pool}, actor, policy.ActionRepoRead, repoRef).Allow { | 269 | if !policy.Can(ctx, policy.Deps{Pool: h.d.Pool}, actor, policy.ActionRepoRead, repoRef).Allow { |
| 264 | return reposdb.Repo{}, pgx.ErrNoRows | 270 | return reposdb.Repo{}, pgx.ErrNoRows |
| 265 | } | 271 | } |