Skip to content

Commit d0f4e92

Browse files
HeCorrwxiaoguang
andauthored
Reject star-related requests if stars are disabled (#33208)
This PR fixes #33205. If stars are disabled: * The `.../repo/stars` page returns a 403 Forbidden error * Star-related API endpoints return a 403 Forbidden error saying `Stars are disabled.` * Same for action endpoints --------- Co-authored-by: wxiaoguang <[email protected]>
1 parent a4676db commit d0f4e92

File tree

6 files changed

+113
-5
lines changed

6 files changed

+113
-5
lines changed

routers/api/v1/api.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,16 @@ func reqWebhooksEnabled() func(ctx *context.APIContext) {
580580
}
581581
}
582582

583+
// reqStarsEnabled requires Starring to be enabled in the config.
584+
func reqStarsEnabled() func(ctx *context.APIContext) {
585+
return func(ctx *context.APIContext) {
586+
if setting.Repository.DisableStars {
587+
ctx.Error(http.StatusForbidden, "", "stars disabled by administrator")
588+
return
589+
}
590+
}
591+
}
592+
583593
func orgAssignment(args ...bool) func(ctx *context.APIContext) {
584594
var (
585595
assignOrg bool
@@ -995,7 +1005,7 @@ func Routes() *web.Router {
9951005
m.Get("/{target}", user.CheckFollowing)
9961006
})
9971007

998-
m.Get("/starred", user.GetStarredRepos)
1008+
m.Get("/starred", reqStarsEnabled(), user.GetStarredRepos)
9991009

10001010
m.Get("/subscriptions", user.GetWatchedRepos)
10011011
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
@@ -1086,7 +1096,7 @@ func Routes() *web.Router {
10861096
m.Put("", user.Star)
10871097
m.Delete("", user.Unstar)
10881098
}, repoAssignment(), checkTokenPublicOnly())
1089-
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
1099+
}, reqStarsEnabled(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
10901100
m.Get("/times", repo.ListMyTrackedTimes)
10911101
m.Get("/stopwatches", repo.GetStopwatches)
10921102
m.Get("/subscriptions", user.GetMyWatchedRepos)
@@ -1248,7 +1258,7 @@ func Routes() *web.Router {
12481258
m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup)
12491259
m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown)
12501260
m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw)
1251-
m.Get("/stargazers", repo.ListStargazers)
1261+
m.Get("/stargazers", reqStarsEnabled(), repo.ListStargazers)
12521262
m.Get("/subscribers", repo.ListSubscribers)
12531263
m.Group("/subscription", func() {
12541264
m.Get("", user.IsWatching)

routers/api/v1/repo/star.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ func ListStargazers(ctx *context.APIContext) {
4444
// "$ref": "#/responses/UserList"
4545
// "404":
4646
// "$ref": "#/responses/notFound"
47+
// "403":
48+
// "$ref": "#/responses/forbidden"
4749

4850
stargazers, err := repo_model.GetStargazers(ctx, ctx.Repo.Repository, utils.GetListOptions(ctx))
4951
if err != nil {

routers/api/v1/user/star.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ func GetStarredRepos(ctx *context.APIContext) {
6666
// "$ref": "#/responses/RepositoryList"
6767
// "404":
6868
// "$ref": "#/responses/notFound"
69+
// "403":
70+
// "$ref": "#/responses/forbidden"
6971

7072
private := ctx.ContextUser.ID == ctx.Doer.ID
7173
repos, err := getStarredRepos(ctx, ctx.ContextUser, private)
@@ -97,6 +99,8 @@ func GetMyStarredRepos(ctx *context.APIContext) {
9799
// responses:
98100
// "200":
99101
// "$ref": "#/responses/RepositoryList"
102+
// "403":
103+
// "$ref": "#/responses/forbidden"
100104

101105
repos, err := getStarredRepos(ctx, ctx.Doer, true)
102106
if err != nil {
@@ -128,6 +132,8 @@ func IsStarring(ctx *context.APIContext) {
128132
// "$ref": "#/responses/empty"
129133
// "404":
130134
// "$ref": "#/responses/notFound"
135+
// "403":
136+
// "$ref": "#/responses/forbidden"
131137

132138
if repo_model.IsStaring(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) {
133139
ctx.Status(http.StatusNoContent)
@@ -193,6 +199,8 @@ func Unstar(ctx *context.APIContext) {
193199
// "$ref": "#/responses/empty"
194200
// "404":
195201
// "$ref": "#/responses/notFound"
202+
// "403":
203+
// "$ref": "#/responses/forbidden"
196204

197205
err := repo_model.StarRepo(ctx, ctx.Doer, ctx.Repo.Repository, false)
198206
if err != nil {

routers/web/web.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,13 @@ func registerRoutes(m *web.Router) {
347347
}
348348
}
349349

350+
starsEnabled := func(ctx *context.Context) {
351+
if setting.Repository.DisableStars {
352+
ctx.Error(http.StatusForbidden)
353+
return
354+
}
355+
}
356+
350357
lfsServerEnabled := func(ctx *context.Context) {
351358
if !setting.LFS.StartServer {
352359
ctx.Error(http.StatusNotFound)
@@ -1593,10 +1600,12 @@ func registerRoutes(m *web.Router) {
15931600
// end "/{username}/{reponame}": repo code
15941601

15951602
m.Group("/{username}/{reponame}", func() {
1596-
m.Get("/stars", repo.Stars)
1603+
m.Get("/stars", starsEnabled, repo.Stars)
15971604
m.Get("/watchers", repo.Watchers)
15981605
m.Get("/search", reqUnitCodeReader, repo.Search)
1599-
m.Post("/action/{action}", reqSignIn, repo.Action)
1606+
m.Post("/action/{action:star|unstar}", reqSignIn, starsEnabled, repo.Action)
1607+
m.Post("/action/{action:watch|unwatch}", reqSignIn, repo.Action)
1608+
m.Post("/action/{action:accept_transfer|reject_transfer}", reqSignIn, repo.Action)
16001609
}, optSignIn, context.RepoAssignment)
16011610

16021611
common.AddOwnerRepoGitLFSRoutes(m, optSignInIgnoreCsrf, lfsServerEnabled) // "/{username}/{reponame}/{lfs-paths}": git-lfs support

templates/swagger/v1_json.tmpl

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/api_user_star_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import (
1111
auth_model "code.gitea.io/gitea/models/auth"
1212
"code.gitea.io/gitea/models/unittest"
1313
user_model "code.gitea.io/gitea/models/user"
14+
"code.gitea.io/gitea/modules/setting"
1415
api "code.gitea.io/gitea/modules/structs"
16+
"code.gitea.io/gitea/modules/test"
1517
"code.gitea.io/gitea/tests"
1618

1719
"github.com/stretchr/testify/assert"
@@ -91,3 +93,65 @@ func TestAPIStar(t *testing.T) {
9193
MakeRequest(t, req, http.StatusNoContent)
9294
})
9395
}
96+
97+
func TestAPIStarDisabled(t *testing.T) {
98+
defer tests.PrepareTestEnv(t)()
99+
100+
user := "user1"
101+
repo := "user2/repo1"
102+
103+
session := loginUser(t, user)
104+
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
105+
tokenWithUserScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteRepository)
106+
107+
defer test.MockVariableValue(&setting.Repository.DisableStars, true)()
108+
109+
t.Run("Star", func(t *testing.T) {
110+
defer tests.PrintCurrentTest(t)()
111+
112+
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
113+
AddTokenAuth(tokenWithUserScope)
114+
MakeRequest(t, req, http.StatusForbidden)
115+
116+
user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
117+
req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
118+
AddTokenAuth(getUserToken(t, user34.Name, auth_model.AccessTokenScopeWriteRepository))
119+
MakeRequest(t, req, http.StatusForbidden)
120+
})
121+
122+
t.Run("GetStarredRepos", func(t *testing.T) {
123+
defer tests.PrintCurrentTest(t)()
124+
125+
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s/starred", user)).
126+
AddTokenAuth(token)
127+
MakeRequest(t, req, http.StatusForbidden)
128+
})
129+
130+
t.Run("GetMyStarredRepos", func(t *testing.T) {
131+
defer tests.PrintCurrentTest(t)()
132+
133+
req := NewRequest(t, "GET", "/api/v1/user/starred").
134+
AddTokenAuth(tokenWithUserScope)
135+
MakeRequest(t, req, http.StatusForbidden)
136+
})
137+
138+
t.Run("IsStarring", func(t *testing.T) {
139+
defer tests.PrintCurrentTest(t)()
140+
141+
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
142+
AddTokenAuth(tokenWithUserScope)
143+
MakeRequest(t, req, http.StatusForbidden)
144+
145+
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s", repo+"notexisting")).
146+
AddTokenAuth(tokenWithUserScope)
147+
MakeRequest(t, req, http.StatusForbidden)
148+
})
149+
150+
t.Run("Unstar", func(t *testing.T) {
151+
defer tests.PrintCurrentTest(t)()
152+
153+
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
154+
AddTokenAuth(tokenWithUserScope)
155+
MakeRequest(t, req, http.StatusForbidden)
156+
})
157+
}

0 commit comments

Comments
 (0)