diff --git a/modules/setting/repository.go b/modules/setting/repository.go index 34eff196b..7a07fec85 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -49,7 +49,7 @@ var ( DownloadOrCloneMethods []string PrefixArchiveFiles bool DisableMigrations bool - DisableStars bool `ini:"DISABLE_STARS"` + DisableStars bool DisableForks bool DefaultBranch string AllowAdoptionOfUnadoptedRepositories bool diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index afceeefd7..48ce49447 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -964,7 +964,9 @@ func Routes() *web.Route { m.Get("/{target}", user.CheckFollowing) }) - m.Get("/starred", user.GetStarredRepos) + if !setting.Repository.DisableStars { + m.Get("/starred", user.GetStarredRepos) + } m.Get("/subscriptions", user.GetWatchedRepos) }, context_service.UserAssignmentAPI()) @@ -1039,14 +1041,16 @@ func Routes() *web.Route { Post(bind(api.CreateRepoOption{}), repo.Create) // (repo scope) - m.Group("/starred", func() { - m.Get("", user.GetMyStarredRepos) - m.Group("/{username}/{reponame}", func() { - m.Get("", user.IsStarring) - m.Put("", user.Star) - m.Delete("", user.Unstar) - }, repoAssignment()) - }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) + if !setting.Repository.DisableStars { + m.Group("/starred", func() { + m.Get("", user.GetMyStarredRepos) + m.Group("/{username}/{reponame}", func() { + m.Get("", user.IsStarring) + m.Put("", user.Star) + m.Delete("", user.Unstar) + }, repoAssignment()) + }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) + } m.Get("/times", repo.ListMyTrackedTimes) m.Get("/stopwatches", repo.GetStopwatches) m.Get("/subscriptions", user.GetMyWatchedRepos) @@ -1208,7 +1212,9 @@ func Routes() *web.Route { m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup) m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown) m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw) - m.Get("/stargazers", repo.ListStargazers) + if !setting.Repository.DisableStars { + m.Get("/stargazers", repo.ListStargazers) + } m.Get("/subscribers", repo.ListSubscribers) m.Group("/subscription", func() { m.Get("", user.IsWatching) diff --git a/routers/web/web.go b/routers/web/web.go index 6f4a7543e..12fdaea16 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1129,8 +1129,10 @@ func registerRoutes(m *web.Route) { m.Post("/unwatch", repo.ActionWatch(false)) m.Post("/accept_transfer", repo.ActionTransfer(true)) m.Post("/reject_transfer", repo.ActionTransfer(false)) - m.Post("/star", repo.ActionStar(true)) - m.Post("/unstar", repo.ActionStar(false)) + if !setting.Repository.DisableStars { + m.Post("/star", repo.ActionStar(true)) + m.Post("/unstar", repo.ActionStar(false)) + } }, reqSignIn, context.RepoAssignment, context.UnitTypes()) // Grouping for those endpoints not requiring authentication (but should respect ignSignIn) @@ -1359,7 +1361,9 @@ func registerRoutes(m *web.Route) { m.Get("/open.svg", badges.GetOpenPullsBadge) m.Get("/closed.svg", badges.GetClosedPullsBadge) }) - m.Get("/stars.svg", badges.GetStarsBadge) + if !setting.Repository.DisableStars { + m.Get("/stars.svg", badges.GetStarsBadge) + } m.Get("/release.svg", badges.GetLatestReleaseBadge) }) } @@ -1590,7 +1594,9 @@ func registerRoutes(m *web.Route) { m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit) m.Group("/{username}/{reponame}", func() { - m.Get("/stars", repo.Stars) + if !setting.Repository.DisableStars { + m.Get("/stars", repo.Stars) + } m.Get("/watchers", repo.Watchers) m.Get("/search", reqRepoCodeReader, repo.Search) }, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes()) diff --git a/tests/integration/api_user_star_test.go b/tests/integration/api_user_star_test.go index 50423c80e..aafe9cfb8 100644 --- a/tests/integration/api_user_star_test.go +++ b/tests/integration/api_user_star_test.go @@ -9,7 +9,10 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/routers" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" @@ -25,12 +28,26 @@ func TestAPIStar(t *testing.T) { token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser) tokenWithUserScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteRepository) + assertDisabledStarsNotFound := func(t *testing.T, req *RequestWrapper) { + t.Helper() + + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Repository.DisableStars, true)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + + MakeRequest(t, req, http.StatusNotFound) + } + t.Run("Star", func(t *testing.T) { defer tests.PrintCurrentTest(t)() req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)). AddTokenAuth(tokenWithUserScope) MakeRequest(t, req, http.StatusNoContent) + + t.Run("disabled stars", func(t *testing.T) { + assertDisabledStarsNotFound(t, req) + }) }) t.Run("GetStarredRepos", func(t *testing.T) { @@ -46,6 +63,10 @@ func TestAPIStar(t *testing.T) { DecodeJSON(t, resp, &repos) assert.Len(t, repos, 1) assert.Equal(t, repo, repos[0].FullName) + + t.Run("disabled stars", func(t *testing.T) { + assertDisabledStarsNotFound(t, req) + }) }) t.Run("GetMyStarredRepos", func(t *testing.T) { @@ -61,6 +82,10 @@ func TestAPIStar(t *testing.T) { DecodeJSON(t, resp, &repos) assert.Len(t, repos, 1) assert.Equal(t, repo, repos[0].FullName) + + t.Run("disabled stars", func(t *testing.T) { + assertDisabledStarsNotFound(t, req) + }) }) t.Run("IsStarring", func(t *testing.T) { @@ -73,6 +98,10 @@ func TestAPIStar(t *testing.T) { req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s", repo+"notexisting")). AddTokenAuth(tokenWithUserScope) MakeRequest(t, req, http.StatusNotFound) + + t.Run("disabled stars", func(t *testing.T) { + assertDisabledStarsNotFound(t, req) + }) }) t.Run("Unstar", func(t *testing.T) { @@ -81,5 +110,9 @@ func TestAPIStar(t *testing.T) { req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s", repo)). AddTokenAuth(tokenWithUserScope) MakeRequest(t, req, http.StatusNoContent) + + t.Run("disabled stars", func(t *testing.T) { + assertDisabledStarsNotFound(t, req) + }) }) } diff --git a/tests/integration/repo_badges_test.go b/tests/integration/repo_badges_test.go index 18d04930f..b7020bbad 100644 --- a/tests/integration/repo_badges_test.go +++ b/tests/integration/repo_badges_test.go @@ -16,7 +16,9 @@ import ( unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/routers" files_service "code.gitea.io/gitea/services/repository/files" "code.gitea.io/gitea/tests" @@ -107,6 +109,14 @@ func TestBadges(t *testing.T) { resp := MakeRequest(t, req, http.StatusSeeOther) assertBadge(t, resp, "stars-0-blue") + + t.Run("disabled stars", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Repository.DisableStars, true)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + + MakeRequest(t, req, http.StatusNotFound) + }) }) t.Run("Issues", func(t *testing.T) { diff --git a/tests/integration/repo_starwatch_test.go b/tests/integration/repo_starwatch_test.go index 4b4f96772..d1ba2dbf0 100644 --- a/tests/integration/repo_starwatch_test.go +++ b/tests/integration/repo_starwatch_test.go @@ -9,6 +9,9 @@ import ( "strings" "testing" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/routers" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" @@ -80,3 +83,26 @@ func TestRepoStarUnstarUI(t *testing.T) { func TestRepoWatchUnwatchUI(t *testing.T) { testRepoStarringOrWatching(t, "watch", "watchers") } + +func TestDisabledStars(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.Repository.DisableStars, true)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + + t.Run("repo star, unstar", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "POST", "/user2/repo1/action/star") + MakeRequest(t, req, http.StatusNotFound) + + req = NewRequest(t, "POST", "/user2/repo1/action/unstar") + MakeRequest(t, req, http.StatusNotFound) + }) + + t.Run("repo stargazers", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", "/user2/repo1/stars") + MakeRequest(t, req, http.StatusNotFound) + }) +}