[FEAT] Repository flags
This implements "repository flags", a way for instance administrators to
assign custom flags to repositories. The idea is that custom templates
can look at these flags, and display banners based on them, Forgejo does
not provide anything built on top of it, just the foundation. The
feature is optional, and disabled by default. To enable it, set
`[repository].ENABLE_FLAGS = true`.
On the UI side, instance administrators will see a new "Manage flags"
tab on repositories, and a list of enabled tags (if any) on the
repository home page. The "Manage flags" page allows them to remove
existing flags, or add any new ones that are listed in
`[repository].SETTABLE_FLAGS`.
The model does not enforce that only the `SETTABLE_FLAGS` are present.
If the setting is changed, old flags may remain present in the database,
and anything that uses them, will still work. The repository flag
management page will allow an instance administrator to remove them, but
not set them, once removed.
Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit ba735ce2228f8dd7ca105e94b9baa1be058ebe37)
(cherry picked from commit f09f6e029b4fb2714b86cd32dc19255078ecc0ee)
(cherry picked from commit 2f8b0414892f6099f519bda63a9e0fbc8ba6cfc7)
(cherry picked from commit d3186ee5f41fac896c7d2341402fcd39dd250bf1)
2024-01-04 14:28:19 +01:00
|
|
|
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
package integration
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2024-01-05 13:45:10 +01:00
|
|
|
"slices"
|
[FEAT] Repository flags
This implements "repository flags", a way for instance administrators to
assign custom flags to repositories. The idea is that custom templates
can look at these flags, and display banners based on them, Forgejo does
not provide anything built on top of it, just the foundation. The
feature is optional, and disabled by default. To enable it, set
`[repository].ENABLE_FLAGS = true`.
On the UI side, instance administrators will see a new "Manage flags"
tab on repositories, and a list of enabled tags (if any) on the
repository home page. The "Manage flags" page allows them to remove
existing flags, or add any new ones that are listed in
`[repository].SETTABLE_FLAGS`.
The model does not enforce that only the `SETTABLE_FLAGS` are present.
If the setting is changed, old flags may remain present in the database,
and anything that uses them, will still work. The repository flag
management page will allow an instance administrator to remove them, but
not set them, once removed.
Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit ba735ce2228f8dd7ca105e94b9baa1be058ebe37)
(cherry picked from commit f09f6e029b4fb2714b86cd32dc19255078ecc0ee)
(cherry picked from commit 2f8b0414892f6099f519bda63a9e0fbc8ba6cfc7)
(cherry picked from commit d3186ee5f41fac896c7d2341402fcd39dd250bf1)
2024-01-04 14:28:19 +01:00
|
|
|
"testing"
|
|
|
|
|
2024-01-05 13:45:10 +01:00
|
|
|
auth_model "code.gitea.io/gitea/models/auth"
|
[FEAT] Repository flags
This implements "repository flags", a way for instance administrators to
assign custom flags to repositories. The idea is that custom templates
can look at these flags, and display banners based on them, Forgejo does
not provide anything built on top of it, just the foundation. The
feature is optional, and disabled by default. To enable it, set
`[repository].ENABLE_FLAGS = true`.
On the UI side, instance administrators will see a new "Manage flags"
tab on repositories, and a list of enabled tags (if any) on the
repository home page. The "Manage flags" page allows them to remove
existing flags, or add any new ones that are listed in
`[repository].SETTABLE_FLAGS`.
The model does not enforce that only the `SETTABLE_FLAGS` are present.
If the setting is changed, old flags may remain present in the database,
and anything that uses them, will still work. The repository flag
management page will allow an instance administrator to remove them, but
not set them, once removed.
Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit ba735ce2228f8dd7ca105e94b9baa1be058ebe37)
(cherry picked from commit f09f6e029b4fb2714b86cd32dc19255078ecc0ee)
(cherry picked from commit 2f8b0414892f6099f519bda63a9e0fbc8ba6cfc7)
(cherry picked from commit d3186ee5f41fac896c7d2341402fcd39dd250bf1)
2024-01-04 14:28:19 +01:00
|
|
|
"code.gitea.io/gitea/models/db"
|
|
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
|
|
"code.gitea.io/gitea/models/unittest"
|
|
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
|
|
"code.gitea.io/gitea/modules/setting"
|
2024-01-05 13:45:10 +01:00
|
|
|
api "code.gitea.io/gitea/modules/structs"
|
[FEAT] Repository flags
This implements "repository flags", a way for instance administrators to
assign custom flags to repositories. The idea is that custom templates
can look at these flags, and display banners based on them, Forgejo does
not provide anything built on top of it, just the foundation. The
feature is optional, and disabled by default. To enable it, set
`[repository].ENABLE_FLAGS = true`.
On the UI side, instance administrators will see a new "Manage flags"
tab on repositories, and a list of enabled tags (if any) on the
repository home page. The "Manage flags" page allows them to remove
existing flags, or add any new ones that are listed in
`[repository].SETTABLE_FLAGS`.
The model does not enforce that only the `SETTABLE_FLAGS` are present.
If the setting is changed, old flags may remain present in the database,
and anything that uses them, will still work. The repository flag
management page will allow an instance administrator to remove them, but
not set them, once removed.
Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit ba735ce2228f8dd7ca105e94b9baa1be058ebe37)
(cherry picked from commit f09f6e029b4fb2714b86cd32dc19255078ecc0ee)
(cherry picked from commit 2f8b0414892f6099f519bda63a9e0fbc8ba6cfc7)
(cherry picked from commit d3186ee5f41fac896c7d2341402fcd39dd250bf1)
2024-01-04 14:28:19 +01:00
|
|
|
"code.gitea.io/gitea/modules/test"
|
|
|
|
"code.gitea.io/gitea/routers"
|
|
|
|
"code.gitea.io/gitea/tests"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestRepositoryFlagsUIDisabled(t *testing.T) {
|
|
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
defer test.MockVariableValue(&setting.Repository.EnableFlags, false)()
|
|
|
|
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
|
|
|
|
|
|
|
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
|
|
|
|
session := loginUser(t, admin.Name)
|
|
|
|
|
|
|
|
// With the repo flags feature disabled, the /flags route is 404
|
|
|
|
req := NewRequest(t, "GET", "/user2/repo1/flags")
|
|
|
|
session.MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
|
|
|
|
// With the repo flags feature disabled, the "Modify flags" tab does not
|
|
|
|
// appear for instance admins
|
|
|
|
req = NewRequest(t, "GET", "/user2/repo1")
|
|
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
doc := NewHTMLParser(t, resp.Body)
|
|
|
|
flagsLinkCount := doc.Find(fmt.Sprintf(`a[href="%s/flags"]`, "/user2/repo1")).Length()
|
|
|
|
assert.Equal(t, 0, flagsLinkCount)
|
|
|
|
}
|
|
|
|
|
2024-01-05 13:45:10 +01:00
|
|
|
func TestRepositoryFlagsAPI(t *testing.T) {
|
|
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
defer test.MockVariableValue(&setting.Repository.EnableFlags, true)()
|
|
|
|
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
|
|
|
|
|
|
|
// *************
|
|
|
|
// ** Helpers **
|
|
|
|
// *************
|
|
|
|
|
|
|
|
adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true}).Name
|
|
|
|
normalUserBean := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
|
|
assert.False(t, normalUserBean.IsAdmin)
|
|
|
|
normalUser := normalUserBean.Name
|
|
|
|
|
|
|
|
assertAccess := func(t *testing.T, user, method, uri string, expectedStatus int) {
|
|
|
|
session := loginUser(t, user)
|
|
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadAdmin)
|
|
|
|
|
|
|
|
req := NewRequestf(t, method, "/api/v1/repos/user2/repo1/flags%s", uri).AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, expectedStatus)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***********
|
|
|
|
// ** Tests **
|
|
|
|
// ***********
|
|
|
|
|
|
|
|
t.Run("API access", func(t *testing.T) {
|
|
|
|
t.Run("as admin", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertAccess(t, adminUser, "GET", "", http.StatusOK)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("as normal user", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertAccess(t, normalUser, "GET", "", http.StatusForbidden)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("token scopes", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
// Trying to access the API with a token that lacks permissions, will
|
|
|
|
// fail, even if the token owner is an instance admin.
|
|
|
|
session := loginUser(t, adminUser)
|
|
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
|
|
|
|
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/flags").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusForbidden)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("setting.Repository.EnableFlags is respected", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer test.MockVariableValue(&setting.Repository.EnableFlags, false)()
|
|
|
|
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
|
|
|
|
|
|
|
t.Run("as admin", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertAccess(t, adminUser, "GET", "", http.StatusNotFound)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("as normal user", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertAccess(t, normalUser, "GET", "", http.StatusNotFound)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("API functionality", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
|
|
|
defer func() {
|
|
|
|
repo.ReplaceAllFlags(db.DefaultContext, []string{})
|
|
|
|
}()
|
|
|
|
|
|
|
|
baseURLFmtStr := "/api/v1/repos/user5/repo4/flags%s"
|
|
|
|
|
|
|
|
session := loginUser(t, adminUser)
|
|
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteAdmin)
|
|
|
|
|
|
|
|
// Listing flags
|
|
|
|
req := NewRequestf(t, "GET", baseURLFmtStr, "").AddTokenAuth(token)
|
|
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
var flags []string
|
|
|
|
DecodeJSON(t, resp, &flags)
|
|
|
|
assert.Empty(t, flags)
|
|
|
|
|
|
|
|
// Replacing all tags works, twice in a row
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
req = NewRequestWithJSON(t, "PUT", fmt.Sprintf(baseURLFmtStr, ""), &api.ReplaceFlagsOption{
|
|
|
|
Flags: []string{"flag-1", "flag-2", "flag-3"},
|
|
|
|
}).AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The list now includes all three flags
|
|
|
|
req = NewRequestf(t, "GET", baseURLFmtStr, "").AddTokenAuth(token)
|
|
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
DecodeJSON(t, resp, &flags)
|
|
|
|
assert.Len(t, flags, 3)
|
|
|
|
for _, flag := range []string{"flag-1", "flag-2", "flag-3"} {
|
|
|
|
assert.True(t, slices.Contains(flags, flag))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check a flag that is on the repo
|
|
|
|
req = NewRequestf(t, "GET", baseURLFmtStr, "/flag-1").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
|
|
|
|
// Check a flag that isn't on the repo
|
|
|
|
req = NewRequestf(t, "GET", baseURLFmtStr, "/no-such-flag").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
|
|
|
|
// We can add the same flag twice
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
req = NewRequestf(t, "PUT", baseURLFmtStr, "/brand-new-flag").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The new flag is there
|
|
|
|
req = NewRequestf(t, "GET", baseURLFmtStr, "/brand-new-flag").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
|
|
|
|
// We can delete a flag, twice
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
req = NewRequestf(t, "DELETE", baseURLFmtStr, "/flag-3").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can delete a flag that wasn't there
|
|
|
|
req = NewRequestf(t, "DELETE", baseURLFmtStr, "/no-such-flag").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
|
|
|
|
// We can delete all of the flags in one go, too
|
|
|
|
req = NewRequestf(t, "DELETE", baseURLFmtStr, "").AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
|
|
|
|
// ..once all flags are deleted, none are listed, either
|
|
|
|
req = NewRequestf(t, "GET", baseURLFmtStr, "").AddTokenAuth(token)
|
|
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
DecodeJSON(t, resp, &flags)
|
|
|
|
assert.Empty(t, flags)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
[FEAT] Repository flags
This implements "repository flags", a way for instance administrators to
assign custom flags to repositories. The idea is that custom templates
can look at these flags, and display banners based on them, Forgejo does
not provide anything built on top of it, just the foundation. The
feature is optional, and disabled by default. To enable it, set
`[repository].ENABLE_FLAGS = true`.
On the UI side, instance administrators will see a new "Manage flags"
tab on repositories, and a list of enabled tags (if any) on the
repository home page. The "Manage flags" page allows them to remove
existing flags, or add any new ones that are listed in
`[repository].SETTABLE_FLAGS`.
The model does not enforce that only the `SETTABLE_FLAGS` are present.
If the setting is changed, old flags may remain present in the database,
and anything that uses them, will still work. The repository flag
management page will allow an instance administrator to remove them, but
not set them, once removed.
Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit ba735ce2228f8dd7ca105e94b9baa1be058ebe37)
(cherry picked from commit f09f6e029b4fb2714b86cd32dc19255078ecc0ee)
(cherry picked from commit 2f8b0414892f6099f519bda63a9e0fbc8ba6cfc7)
(cherry picked from commit d3186ee5f41fac896c7d2341402fcd39dd250bf1)
2024-01-04 14:28:19 +01:00
|
|
|
func TestRepositoryFlagsUI(t *testing.T) {
|
|
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
defer test.MockVariableValue(&setting.Repository.EnableFlags, true)()
|
|
|
|
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
|
|
|
|
|
|
|
// *******************
|
|
|
|
// ** Preparations **
|
|
|
|
// *******************
|
|
|
|
flaggedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
|
|
unflaggedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
|
|
|
|
|
|
|
// **************
|
|
|
|
// ** Helpers **
|
|
|
|
// **************
|
|
|
|
|
|
|
|
adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true}).Name
|
|
|
|
flaggedOwner := "user2"
|
|
|
|
flaggedRepoURLStr := "/user2/repo1"
|
|
|
|
unflaggedOwner := "user5"
|
|
|
|
unflaggedRepoURLStr := "/user5/repo4"
|
|
|
|
otherUser := "user4"
|
|
|
|
|
|
|
|
ensureFlags := func(repo *repo_model.Repository, flags []string) func() {
|
|
|
|
repo.ReplaceAllFlags(db.DefaultContext, flags)
|
|
|
|
|
|
|
|
return func() {
|
|
|
|
repo.ReplaceAllFlags(db.DefaultContext, flags)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests:
|
|
|
|
// - Presence of the link
|
|
|
|
// - Number of flags listed in the admin-only message box
|
|
|
|
// - Whether there's a link to /user/repo/flags
|
|
|
|
// - Whether /user/repo/flags is OK or Forbidden
|
|
|
|
assertFlagAccessAndCount := func(t *testing.T, user, repoURL string, hasAccess bool, expectedFlagCount int) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
var expectedLinkCount int
|
|
|
|
var expectedStatus int
|
|
|
|
if hasAccess {
|
|
|
|
expectedLinkCount = 1
|
|
|
|
expectedStatus = http.StatusOK
|
|
|
|
} else {
|
|
|
|
expectedLinkCount = 0
|
|
|
|
if user != "" {
|
|
|
|
expectedStatus = http.StatusForbidden
|
|
|
|
} else {
|
|
|
|
expectedStatus = http.StatusSeeOther
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var resp *httptest.ResponseRecorder
|
|
|
|
var session *TestSession
|
|
|
|
req := NewRequest(t, "GET", repoURL)
|
|
|
|
if user != "" {
|
|
|
|
session = loginUser(t, user)
|
|
|
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
} else {
|
|
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
}
|
|
|
|
doc := NewHTMLParser(t, resp.Body)
|
|
|
|
|
|
|
|
flagsLinkCount := doc.Find(fmt.Sprintf(`a[href="%s/flags"]`, repoURL)).Length()
|
|
|
|
assert.Equal(t, expectedLinkCount, flagsLinkCount)
|
|
|
|
|
|
|
|
flagCount := doc.Find(".ui.info.message .ui.label").Length()
|
|
|
|
assert.Equal(t, expectedFlagCount, flagCount)
|
|
|
|
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("%s/flags", repoURL))
|
|
|
|
if user != "" {
|
|
|
|
session.MakeRequest(t, req, expectedStatus)
|
|
|
|
} else {
|
|
|
|
MakeRequest(t, req, expectedStatus)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensures that given a repo owner and a repo:
|
|
|
|
// - An instance admin has access to flags, and sees the list on the repo home
|
|
|
|
// - A repo admin does not have access to either, and does not see the list
|
|
|
|
// - A passer by has no access to either, and does not see the list
|
|
|
|
runTests := func(t *testing.T, ownerUser, repoURL string, expectedFlagCount int) {
|
|
|
|
t.Run("as instance admin", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertFlagAccessAndCount(t, adminUser, repoURL, true, expectedFlagCount)
|
|
|
|
})
|
|
|
|
t.Run("as owner", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertFlagAccessAndCount(t, ownerUser, repoURL, false, 0)
|
|
|
|
})
|
|
|
|
t.Run("as other user", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertFlagAccessAndCount(t, otherUser, repoURL, false, 0)
|
|
|
|
})
|
|
|
|
t.Run("as non-logged in user", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
assertFlagAccessAndCount(t, "", repoURL, false, 0)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// **************************
|
|
|
|
// ** The tests themselves **
|
|
|
|
// **************************
|
|
|
|
t.Run("unflagged repo", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer ensureFlags(unflaggedRepo, []string{})()
|
|
|
|
|
|
|
|
runTests(t, unflaggedOwner, unflaggedRepoURLStr, 0)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("flagged repo", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer ensureFlags(flaggedRepo, []string{"test-flag"})()
|
|
|
|
|
|
|
|
runTests(t, flaggedOwner, flaggedRepoURLStr, 1)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("modifying flags", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
|
|
|
|
session := loginUser(t, adminUser)
|
|
|
|
flaggedRepoManageURL := fmt.Sprintf("%s/flags", flaggedRepoURLStr)
|
|
|
|
unflaggedRepoManageURL := fmt.Sprintf("%s/flags", unflaggedRepoURLStr)
|
|
|
|
|
|
|
|
assertUIFlagStates := func(t *testing.T, url string, flagStates map[string]bool) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
req := NewRequest(t, "GET", url)
|
|
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
|
|
|
|
doc := NewHTMLParser(t, resp.Body)
|
|
|
|
flagBoxes := doc.Find(`input[name="flags"]`)
|
|
|
|
assert.Equal(t, len(flagStates), flagBoxes.Length())
|
|
|
|
|
|
|
|
for name, state := range flagStates {
|
|
|
|
_, checked := doc.Find(fmt.Sprintf(`input[value="%s"]`, name)).Attr("checked")
|
|
|
|
assert.Equal(t, state, checked)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("flag presence on the UI", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer ensureFlags(flaggedRepo, []string{"test-flag"})()
|
|
|
|
|
|
|
|
assertUIFlagStates(t, flaggedRepoManageURL, map[string]bool{"test-flag": true})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("setting.Repository.SettableFlags is respected", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer test.MockVariableValue(&setting.Repository.SettableFlags, []string{"featured", "no-license"})()
|
|
|
|
defer ensureFlags(flaggedRepo, []string{"test-flag"})()
|
|
|
|
|
|
|
|
assertUIFlagStates(t, flaggedRepoManageURL, map[string]bool{
|
|
|
|
"test-flag": true,
|
|
|
|
"featured": false,
|
|
|
|
"no-license": false,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("removing flags", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer ensureFlags(flaggedRepo, []string{"test-flag"})()
|
|
|
|
|
|
|
|
flagged := flaggedRepo.IsFlagged(db.DefaultContext)
|
|
|
|
assert.True(t, flagged)
|
|
|
|
|
|
|
|
req := NewRequestWithValues(t, "POST", flaggedRepoManageURL, map[string]string{
|
|
|
|
"_csrf": GetCSRF(t, session, flaggedRepoManageURL),
|
|
|
|
})
|
|
|
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
|
|
|
|
|
|
|
flagged = flaggedRepo.IsFlagged(db.DefaultContext)
|
|
|
|
assert.False(t, flagged)
|
|
|
|
|
|
|
|
assertUIFlagStates(t, flaggedRepoManageURL, map[string]bool{})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("adding flags", func(t *testing.T) {
|
|
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
defer ensureFlags(unflaggedRepo, []string{})()
|
|
|
|
|
|
|
|
flagged := unflaggedRepo.IsFlagged(db.DefaultContext)
|
|
|
|
assert.False(t, flagged)
|
|
|
|
|
|
|
|
req := NewRequestWithValues(t, "POST", unflaggedRepoManageURL, map[string]string{
|
|
|
|
"_csrf": GetCSRF(t, session, unflaggedRepoManageURL),
|
|
|
|
"flags": "test-flag",
|
|
|
|
})
|
|
|
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
|
|
|
|
|
|
|
assertUIFlagStates(t, unflaggedRepoManageURL, map[string]bool{"test-flag": true})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|