Disabling Stars should disable the routes too

Similarly to how `[repository].DISABLE_FORKS` works, lets make
`[repository].DISABLE_STARS` disable the routes too, not just hide the
functionality from the UI.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
This commit is contained in:
Gergely Nagy 2024-02-26 09:22:51 +01:00
parent 3d3196eb3c
commit 0b4a9c4ec2
No known key found for this signature in database
6 changed files with 96 additions and 15 deletions

View file

@ -49,7 +49,7 @@ var (
DownloadOrCloneMethods []string DownloadOrCloneMethods []string
PrefixArchiveFiles bool PrefixArchiveFiles bool
DisableMigrations bool DisableMigrations bool
DisableStars bool `ini:"DISABLE_STARS"` DisableStars bool
DisableForks bool DisableForks bool
DefaultBranch string DefaultBranch string
AllowAdoptionOfUnadoptedRepositories bool AllowAdoptionOfUnadoptedRepositories bool

View file

@ -964,7 +964,9 @@ func Routes() *web.Route {
m.Get("/{target}", user.CheckFollowing) m.Get("/{target}", user.CheckFollowing)
}) })
m.Get("/starred", user.GetStarredRepos) if !setting.Repository.DisableStars {
m.Get("/starred", user.GetStarredRepos)
}
m.Get("/subscriptions", user.GetWatchedRepos) m.Get("/subscriptions", user.GetWatchedRepos)
}, context_service.UserAssignmentAPI()) }, context_service.UserAssignmentAPI())
@ -1039,14 +1041,16 @@ func Routes() *web.Route {
Post(bind(api.CreateRepoOption{}), repo.Create) Post(bind(api.CreateRepoOption{}), repo.Create)
// (repo scope) // (repo scope)
m.Group("/starred", func() { if !setting.Repository.DisableStars {
m.Get("", user.GetMyStarredRepos) m.Group("/starred", func() {
m.Group("/{username}/{reponame}", func() { m.Get("", user.GetMyStarredRepos)
m.Get("", user.IsStarring) m.Group("/{username}/{reponame}", func() {
m.Put("", user.Star) m.Get("", user.IsStarring)
m.Delete("", user.Unstar) m.Put("", user.Star)
}, repoAssignment()) m.Delete("", user.Unstar)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) }, repoAssignment())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
}
m.Get("/times", repo.ListMyTrackedTimes) m.Get("/times", repo.ListMyTrackedTimes)
m.Get("/stopwatches", repo.GetStopwatches) m.Get("/stopwatches", repo.GetStopwatches)
m.Get("/subscriptions", user.GetMyWatchedRepos) m.Get("/subscriptions", user.GetMyWatchedRepos)
@ -1208,7 +1212,9 @@ func Routes() *web.Route {
m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup) m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup)
m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown) m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown)
m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw) 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.Get("/subscribers", repo.ListSubscribers)
m.Group("/subscription", func() { m.Group("/subscription", func() {
m.Get("", user.IsWatching) m.Get("", user.IsWatching)

View file

@ -1129,8 +1129,10 @@ func registerRoutes(m *web.Route) {
m.Post("/unwatch", repo.ActionWatch(false)) m.Post("/unwatch", repo.ActionWatch(false))
m.Post("/accept_transfer", repo.ActionTransfer(true)) m.Post("/accept_transfer", repo.ActionTransfer(true))
m.Post("/reject_transfer", repo.ActionTransfer(false)) m.Post("/reject_transfer", repo.ActionTransfer(false))
m.Post("/star", repo.ActionStar(true)) if !setting.Repository.DisableStars {
m.Post("/unstar", repo.ActionStar(false)) m.Post("/star", repo.ActionStar(true))
m.Post("/unstar", repo.ActionStar(false))
}
}, reqSignIn, context.RepoAssignment, context.UnitTypes()) }, reqSignIn, context.RepoAssignment, context.UnitTypes())
// Grouping for those endpoints not requiring authentication (but should respect ignSignIn) // 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("/open.svg", badges.GetOpenPullsBadge)
m.Get("/closed.svg", badges.GetClosedPullsBadge) 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) m.Get("/release.svg", badges.GetLatestReleaseBadge)
}) })
} }
@ -1582,7 +1586,9 @@ func registerRoutes(m *web.Route) {
m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit) m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit)
m.Group("/{username}/{reponame}", func() { 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("/watchers", repo.Watchers)
m.Get("/search", reqRepoCodeReader, repo.Search) m.Get("/search", reqRepoCodeReader, repo.Search)
}, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes()) }, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes())

View file

@ -9,7 +9,10 @@ import (
"testing" "testing"
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -25,12 +28,26 @@ func TestAPIStar(t *testing.T) {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
tokenWithUserScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteRepository) 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) { t.Run("Star", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)). req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
AddTokenAuth(tokenWithUserScope) AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNoContent) MakeRequest(t, req, http.StatusNoContent)
t.Run("disabled stars", func(t *testing.T) {
assertDisabledStarsNotFound(t, req)
})
}) })
t.Run("GetStarredRepos", func(t *testing.T) { t.Run("GetStarredRepos", func(t *testing.T) {
@ -46,6 +63,10 @@ func TestAPIStar(t *testing.T) {
DecodeJSON(t, resp, &repos) DecodeJSON(t, resp, &repos)
assert.Len(t, repos, 1) assert.Len(t, repos, 1)
assert.Equal(t, repo, repos[0].FullName) 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) { t.Run("GetMyStarredRepos", func(t *testing.T) {
@ -61,6 +82,10 @@ func TestAPIStar(t *testing.T) {
DecodeJSON(t, resp, &repos) DecodeJSON(t, resp, &repos)
assert.Len(t, repos, 1) assert.Len(t, repos, 1)
assert.Equal(t, repo, repos[0].FullName) 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) { 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")). req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s", repo+"notexisting")).
AddTokenAuth(tokenWithUserScope) AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
t.Run("disabled stars", func(t *testing.T) {
assertDisabledStarsNotFound(t, req)
})
}) })
t.Run("Unstar", func(t *testing.T) { 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)). req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
AddTokenAuth(tokenWithUserScope) AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNoContent) MakeRequest(t, req, http.StatusNoContent)
t.Run("disabled stars", func(t *testing.T) {
assertDisabledStarsNotFound(t, req)
})
}) })
} }

View file

@ -16,7 +16,9 @@ import (
unit_model "code.gitea.io/gitea/models/unit" unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
@ -107,6 +109,14 @@ func TestBadges(t *testing.T) {
resp := MakeRequest(t, req, http.StatusSeeOther) resp := MakeRequest(t, req, http.StatusSeeOther)
assertBadge(t, resp, "stars-0-blue") 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) { t.Run("Issues", func(t *testing.T) {

View file

@ -9,6 +9,9 @@ import (
"strings" "strings"
"testing" "testing"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -80,3 +83,26 @@ func TestRepoStarUnstarUI(t *testing.T) {
func TestRepoWatchUnwatchUI(t *testing.T) { func TestRepoWatchUnwatchUI(t *testing.T) {
testRepoStarringOrWatching(t, "watch", "watchers") 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)
})
}