Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature flags to the config for Wiki and Issues #7032

Closed
wants to merge 10 commits into from
4 changes: 4 additions & 0 deletions custom/conf/app.ini.sample
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ ACCESS_CONTROL_ALLOW_ORIGIN =
USE_COMPAT_SSH_URI = false
; Close issues as long as a commit on any branch marks it as fixed
DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
; Set this to false to completely disable the wiki function
ENABLE_WIKI = true
; Set this to false to completely disable the issue function
ENABLE_ISSUES = true

[repository.editor]
; List of file extensions for which lines should be wrapped in the CodeMirror editor
Expand Down
7 changes: 7 additions & 0 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,9 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
var units = make([]RepoUnit, 0, len(DefaultRepoUnits))
for _, tp := range DefaultRepoUnits {
if tp == UnitTypeIssues {
if !setting.Repository.EnableIssues {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be possible to do these changes without changing how unit rights are saved to DB? so that if you later enable enable issues back you would not have to go through all repo teams to enable issues back

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really think this is will happen.

Example: We have a company wiki, and an issue tracker. All we do need gitea for is for managing git repositories.
Enabling wiki and issue functions will - very probably - not happen in this use case.

I also don't see a different use case, where you would want to globally disable the Wiki / Issue functions, do you?

DefaultRepoUnits also does not contain UnitTypeIssues (as by @lunny's request #7032 (comment)). So that even removing that line will not change the behavior.

I can provide a small bash+curl script to enable the wiki and/or issues via the API for inclusion in the documentation, so a user could easily work around this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is what if I already have existing repository and now I disable issues globally, units for existing repositories will be added so there is not really much point in skiping this for new repos as you will have to check anyway later not only if unit is enabled but also new setting. And if for whaterver reason I later want to enable it back it would be better that user would not have to run scripts to fix db to have working instance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it seems this PR is doing two things at the same time

  • Disabling the possibility to enable issues/wiki (including default value)
  • Disabling any issue/wiki view, even if it was enabled.

Of course in the second case, it would be confusing to still have the settings for enabling it, but there is really no point of affecting the defaults (as @lafriks point out). If only the first case is wanted, there should not be necessary with any changes in routers, as the wiki/issues is anyhow disabled. For a fresh installation I don't think it matter, but the question is how it shall behave for an existing installation if issues/wikis are globally disabled. Either issues/wikis are disabled for existing repos even if they was enabled before the ini setting was changed. Other alternative is to only allow disable issues/wiki for a repo but not enable it. This would correspond to how FORCE_PRIVATE option is working.

continue
}
units = append(units, RepoUnit{
RepoID: repo.ID,
Type: tp,
Expand All @@ -1287,6 +1290,10 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
EnableDependencies: setting.Service.DefaultEnableDependencies,
},
})
} else if tp == UnitTypeWiki {
if !setting.Repository.EnableWiki {
continue
}
} else if tp == UnitTypePullRequests {
units = append(units, RepoUnit{
RepoID: repo.ID,
Expand Down
11 changes: 11 additions & 0 deletions modules/setting/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ var (
Issue struct {
LockReasons []string
} `ini:"repository.issue"`

// global feature flags
EnableWiki bool
EnableIssues bool
}{
AnsiCharset: "",
ForcePrivate: false,
Expand Down Expand Up @@ -121,6 +125,9 @@ var (
}{
LockReasons: strings.Split("Too heated,Off-topic,Spam,Resolved", ","),
},

EnableWiki: true,
EnableIssues: true,
}
RepoRootPath string
ScriptType = "bash"
Expand All @@ -147,6 +154,10 @@ func newRepository() {
}
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")

// feature flags
Repository.EnableIssues = sec.Key("ENABLE_ISSUES").MustBool(true)
Repository.EnableWiki = sec.Key("ENABLE_WIKI").MustBool(true)

if err = Cfg.Section("repository").MapTo(&Repository); err != nil {
log.Fatal("Failed to map Repository settings: %v", err)
} else if err = Cfg.Section("repository.editor").MapTo(&Repository.Editor); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ issues.review.review = Review
issues.review.reviewers = Reviewers
issues.review.show_outdated = Show outdated
issues.review.hide_outdated = Hide outdated
issues.disabled = Issues are disabled for this installation.

pulls.desc = Enable merge requests and code reviews.
pulls.new = New Pull Request
Expand Down Expand Up @@ -1044,6 +1045,7 @@ wiki.page_already_exists = A wiki page with the same name already exists.
wiki.reserved_page = The wiki page name '%s' is reserved.
wiki.pages = Pages
wiki.last_updated = Last updated %s
wiki.disabled = The wiki function has been disabled for this installation.

activity = Activity
activity.period.filter_label = Period:
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ func mustAllowPulls(ctx *context.APIContext) {
}

func mustEnableIssuesOrPulls(ctx *context.APIContext) {
if !ctx.Repo.CanRead(models.UnitTypeIssues) &&
if (!setting.Repository.EnableIssues || !ctx.Repo.CanRead(models.UnitTypeIssues)) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So even the repository created some issues, this will still hide them when setting.Repository.EnableIssues changed to true?

!(ctx.Repo.Repository.CanEnablePulls() && ctx.Repo.CanRead(models.UnitTypePullRequests)) {
if ctx.Repo.Repository.CanEnablePulls() && log.IsTrace() {
if ctx.IsSigned {
Expand Down
3 changes: 2 additions & 1 deletion routers/repo/activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
)

const (
Expand Down Expand Up @@ -46,7 +47,7 @@ func Activity(ctx *context.Context) {
var err error
if ctx.Data["Activity"], err = models.GetActivityStats(ctx.Repo.Repository, timeFrom,
ctx.Repo.CanRead(models.UnitTypeReleases),
ctx.Repo.CanRead(models.UnitTypeIssues),
setting.Repository.EnableIssues && ctx.Repo.CanRead(models.UnitTypeIssues),
ctx.Repo.CanRead(models.UnitTypePullRequests),
ctx.Repo.CanRead(models.UnitTypeCode)); err != nil {
ctx.ServerError("GetActivityStats", err)
Expand Down
9 changes: 5 additions & 4 deletions routers/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ func MustAllowUserComment(ctx *context.Context) {

// MustEnableIssues check if repository enable internal issues
func MustEnableIssues(ctx *context.Context) {
if !ctx.Repo.CanRead(models.UnitTypeIssues) &&
!ctx.Repo.CanRead(models.UnitTypeExternalTracker) {
if !setting.Repository.EnableIssues ||
(!ctx.Repo.CanRead(models.UnitTypeIssues) &&
!ctx.Repo.CanRead(models.UnitTypeExternalTracker)) {
ctx.NotFound("MustEnableIssues", nil)
return
}
Expand Down Expand Up @@ -987,7 +988,7 @@ func GetActionIssue(ctx *context.Context) *models.Issue {

func checkIssueRights(ctx *context.Context, issue *models.Issue) {
if issue.IsPull && !ctx.Repo.CanRead(models.UnitTypePullRequests) ||
!issue.IsPull && !ctx.Repo.CanRead(models.UnitTypeIssues) {
!issue.IsPull && (!setting.Repository.EnableIssues || !ctx.Repo.CanRead(models.UnitTypeIssues)) {
ctx.NotFound("IssueOrPullRequestUnitNotAllowed", nil)
}
}
Expand All @@ -1012,7 +1013,7 @@ func getActionIssues(ctx *context.Context) []*models.Issue {
return nil
}
// Check access rights for all issues
issueUnitEnabled := ctx.Repo.CanRead(models.UnitTypeIssues)
issueUnitEnabled := setting.Repository.EnableIssues && ctx.Repo.CanRead(models.UnitTypeIssues)
prUnitEnabled := ctx.Repo.CanRead(models.UnitTypePullRequests)
for _, issue := range issues {
if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled {
Expand Down
2 changes: 2 additions & 0 deletions routers/repo/issue_label_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -133,6 +134,7 @@ func TestUpdateIssueLabel_Clear(t *testing.T) {
}

func TestUpdateIssueLabel_Toggle(t *testing.T) {
setting.Repository.EnableIssues = true
for _, testCase := range []struct {
Action string
IssueIDs []int64
Expand Down
4 changes: 2 additions & 2 deletions routers/repo/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
})
}

if form.EnableWiki {
if form.EnableWiki && setting.Repository.EnableWiki {
if form.EnableExternalWiki {
if !validation.IsValidExternalURL(form.ExternalWikiURL) {
ctx.Flash.Error(ctx.Tr("repo.settings.external_wiki_url_error"))
Expand All @@ -242,7 +242,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
}
}

if form.EnableIssues {
if form.EnableIssues && setting.Repository.EnableIssues {
if form.EnableExternalTracker {
if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
Expand Down
5 changes: 5 additions & 0 deletions routers/repo/wiki.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)

Expand All @@ -32,6 +33,10 @@ const (

// MustEnableWiki check if wiki is enabled, if external then redirect
func MustEnableWiki(ctx *context.Context) {
if !setting.Repository.EnableWiki {
ctx.NotFound("MustEnableWiki", nil)
return
}
if !ctx.Repo.CanRead(models.UnitTypeWiki) &&
!ctx.Repo.CanRead(models.UnitTypeExternalWiki) {
if log.IsTrace() {
Expand Down
8 changes: 6 additions & 2 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ func RegisterRoutes(m *macaron.Macaron) {
}

m.Use(user.GetNotificationCount)
m.Use(func(ctx *context.Context) {
ctx.Data["GlobalEnableWiki"] = setting.Repository.EnableWiki
ctx.Data["GlobalEnableIssues"] = setting.Repository.EnableIssues
})

// FIXME: not all routes need go through same middlewares.
// Especially some AJAX requests, we can reduce middleware number to improve performance.
Expand Down Expand Up @@ -677,7 +681,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:username/:reponame", func() {
m.Group("/issues", func() {
m.Combo("/new").Get(context.RepoRef(), repo.NewIssue).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost, repo.MustEnableIssues)
}, context.RepoMustNotBeArchived(), reqRepoIssueReader)
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
// So they can apply their own enable/disable logic on routers.
Expand Down Expand Up @@ -707,7 +711,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/milestone", reqRepoIssuesOrPullsWriter, repo.UpdateIssueMilestone)
m.Post("/assignee", reqRepoIssuesOrPullsWriter, repo.UpdateIssueAssignee)
m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus)
}, context.RepoMustNotBeArchived())
}, context.RepoMustNotBeArchived(), repo.MustEnableIssues)
m.Group("/comments/:id", func() {
m.Post("", repo.UpdateCommentContent)
m.Post("/delete", repo.DeleteComment)
Expand Down
2 changes: 1 addition & 1 deletion routers/user/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func Issues(ctx *context.Context) {
ctx.ServerError("GetUserRepoPermission", fmt.Errorf("[%d]%v", repoID, err))
return
}
if !perm.CanRead(models.UnitTypeIssues) {
if !setting.Repository.EnableIssues || !perm.CanRead(models.UnitTypeIssues) {
if log.IsTrace() {
log.Trace("Permission Denied: User %-v cannot read %-v of repo %-v\n"+
"User in repo has Permissions: %-+v",
Expand Down
4 changes: 3 additions & 1 deletion templates/base/head_navbar.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

{{if .IsSigned}}
<a class="item {{if .PageIsDashboard}}active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "dashboard"}}</a>
<a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
{{if .GlobalEnableIssues}}
<a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
{{end}}
<a class="item {{if .PageIsPulls}}active{{end}}" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a>
<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "explore"}}</a>
{{else if .IsLandingPageHome}}
Expand Down
6 changes: 3 additions & 3 deletions templates/repo/header.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@
</a>
{{end}}

{{if .Permission.CanRead $.UnitTypeIssues}}
{{if and .GlobalEnableIssues (.Permission.CanRead $.UnitTypeIssues)}}
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">
<i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} <span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}</span>
</a>
{{end}}

{{if .Permission.CanRead $.UnitTypeExternalTracker}}
{{if and .GlobalEnableIssues (.Permission.CanRead $.UnitTypeExternalTracker)}}
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer">
<i class="octicon octicon-link-external"></i> {{.i18n.Tr "repo.issues"}} </span>
</a>
Expand All @@ -79,7 +79,7 @@
</a>
{{end}}

{{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}}
{{if and .GlobalEnableWiki (or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki))}}
<a class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki" {{if (.Permission.CanRead $.UnitTypeExternalWiki)}} target="_blank" rel="noopener noreferrer" {{end}}>
<i class="octicon octicon-book"></i> {{.i18n.Tr "repo.wiki"}}
</a>
Expand Down
Loading