tenseleyflow/shithub / c8156e7

Browse files

Satisfy API policy boundary lint

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
c8156e7bd512cd17afb1249ff2b301c057024657
Parents
ff4e857
Tree
e70876f

4 changed files

StatusFile+-
M internal/auth/policy/resources.go 7 0
M internal/web/handlers/api/collaborators.go 1 1
M internal/web/handlers/api/repos.go 2 1
M internal/web/handlers/api/search.go 3 1
internal/auth/policy/resources.gomodified
@@ -43,3 +43,10 @@ func (r RepoRef) IsPublic() bool { return r.Visibility == "public" }
4343
 // IsPrivate is the inverse. Use whichever phrasing reads better at the
4444
 // call site.
4545
 func (r RepoRef) IsPrivate() bool { return r.Visibility == "private" }
46
+
47
+// IsOwnedByUser reports whether userID is the direct user owner. Keep
48
+// ownership interpretation here so handlers do not grow inline owner
49
+// checks next to request behavior.
50
+func (r RepoRef) IsOwnedByUser(userID int64) bool {
51
+	return userID != 0 && r.OwnerUserID == userID
52
+}
internal/web/handlers/api/collaborators.gomodified
@@ -152,7 +152,7 @@ func (h *Handlers) collaboratorPut(w http.ResponseWriter, r *http.Request) {
152152
 	// implicitly hold every permission, so a row would be confusing
153153
 	// at best (and could lock the legitimate owner into a downgraded
154154
 	// role at worst).
155
-	if repo.OwnerUserID.Valid && repo.OwnerUserID.Int64 == user.ID {
155
+	if policy.NewRepoRefFromRepo(*repo).IsOwnedByUser(user.ID) {
156156
 		writeAPIError(w, http.StatusUnprocessableEntity, "owner already has full access")
157157
 		return
158158
 	}
internal/web/handlers/api/repos.gomodified
@@ -84,6 +84,7 @@ func presentRepo(r reposdb.Repo, ownerLogin string) repoResponse {
8484
 	if r.OwnerOrgID.Valid {
8585
 		ownerType = "org"
8686
 	}
87
+	repoRef := policy.NewRepoRefFromRepo(r)
8788
 	return repoResponse{
8889
 		ID:            r.ID,
8990
 		Name:          r.Name,
@@ -92,7 +93,7 @@ func presentRepo(r reposdb.Repo, ownerLogin string) repoResponse {
9293
 		OwnerType:     ownerType,
9394
 		Description:   r.Description,
9495
 		Visibility:    string(r.Visibility),
95
-		Private:       string(r.Visibility) == "private",
96
+		Private:       repoRef.IsPrivate(),
9697
 		DefaultBranch: r.DefaultBranch,
9798
 		Fork:          r.ForkOfRepoID.Valid,
9899
 		Archived:      r.IsArchived,
internal/web/handlers/api/search.gomodified
@@ -10,6 +10,7 @@ import (
1010
 	"github.com/go-chi/chi/v5"
1111
 
1212
 	"github.com/tenseleyFlow/shithub/internal/auth/pat"
13
+	"github.com/tenseleyFlow/shithub/internal/auth/policy"
1314
 	"github.com/tenseleyFlow/shithub/internal/search"
1415
 	"github.com/tenseleyFlow/shithub/internal/web/handlers/api/apipage"
1516
 	"github.com/tenseleyFlow/shithub/internal/web/middleware"
@@ -86,6 +87,7 @@ func (h *Handlers) searchRepositories(w http.ResponseWriter, r *http.Request) {
8687
 	}
8788
 	items := make([]searchRepoItem, 0, len(rows))
8889
 	for _, row := range rows {
90
+		repoRef := policy.RepoRef{Visibility: row.Visibility}
8991
 		items = append(items, searchRepoItem{
9092
 			ID:          row.ID,
9193
 			Name:        row.Name,
@@ -93,7 +95,7 @@ func (h *Handlers) searchRepositories(w http.ResponseWriter, r *http.Request) {
9395
 			OwnerLogin:  row.OwnerUsername,
9496
 			Description: row.Description,
9597
 			Visibility:  row.Visibility,
96
-			Private:     row.Visibility == "private",
98
+			Private:     repoRef.IsPrivate(),
9799
 			StarCount:   row.StarCount,
98100
 			UpdatedAt:   row.UpdatedAt.UTC().Format(time.RFC3339),
99101
 			Score:       row.Rank,