; It also enables them to access other resources available to the user on the operating system that is running the Gitea instance and perform arbitrary actions in the name of the Gitea OS user.
; WARNING: This maybe harmful to you website or your operating system.
DISABLE_GIT_HOOKS = true
+; Set to true to disable webhooks feature.
+DISABLE_WEBHOOKS = false
; Set to false to allow pushes to gitea repositories despite having an incomplete environment - NOT RECOMMENDED
ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = true
;Comma separated list of character classes required to pass minimum complexity.
It also enables them to access other resources available to the user on the operating system that is running the
Gitea instance and perform arbitrary actions in the name of the Gitea OS user.
This maybe harmful to you website or your operating system.
+- `DISABLE_WEBHOOKS`: **false**: Set to `true` to disable webhooks feature.
- `ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET`: **true**: Set to `false` to allow local users to push to gitea-repositories without setting up the Gitea environment. This is not recommended and if you want local users to push to gitea repositories you should set the environment appropriately.
- `IMPORT_LOCAL_PATHS`: **false**: Set to `false` to prevent all users (including admin) from importing local path on server.
- `INTERNAL_TOKEN`: **\<random at every install if no uri set\>**: Secret used to validate communication within Gitea binary.
MinPasswordLength int
ImportLocalPaths bool
DisableGitHooks bool
+ DisableWebhooks bool
OnlyAllowPushIfGiteaEnvironmentSet bool
PasswordComplexity []string
PasswordHashAlgo string
MinPasswordLength = sec.Key("MIN_PASSWORD_LENGTH").MustInt(6)
ImportLocalPaths = sec.Key("IMPORT_LOCAL_PATHS").MustBool(false)
DisableGitHooks = sec.Key("DISABLE_GIT_HOOKS").MustBool(true)
+ DisableWebhooks = sec.Key("DISABLE_WEBHOOKS").MustBool(false)
OnlyAllowPushIfGiteaEnvironmentSet = sec.Key("ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET").MustBool(true)
PasswordHashAlgo = sec.Key("PASSWORD_HASH_ALGO").MustString("argon2")
CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true)
"DisableGitHooks": func() bool {
return setting.DisableGitHooks
},
+ "DisableWebhooks": func() bool {
+ return setting.DisableWebhooks
+ },
"DisableImportLocal": func() bool {
return !setting.ImportLocalPaths
},
}
}
+// reqWebhooksEnabled requires webhooks to be enabled by admin.
+func reqWebhooksEnabled() func(ctx *context.APIContext) {
+ return func(ctx *context.APIContext) {
+ if setting.DisableWebhooks {
+ ctx.Error(http.StatusForbidden, "", "webhooks disabled by administrator")
+ return
+ }
+ }
+}
+
func orgAssignment(args ...bool) func(ctx *context.APIContext) {
var (
assignOrg bool
m.Combo("/notifications").
Get(reqToken(), notify.ListRepoNotifications).
Put(reqToken(), notify.ReadRepoNotifications)
+ m.Group("/hooks/git", func() {
+ m.Combo("").Get(repo.ListGitHooks)
+ m.Group("/{id}", func() {
+ m.Combo("").Get(repo.GetGitHook).
+ Patch(bind(api.EditGitHookOption{}), repo.EditGitHook).
+ Delete(repo.DeleteGitHook)
+ })
+ }, reqToken(), reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true))
m.Group("/hooks", func() {
m.Combo("").Get(repo.ListHooks).
Post(bind(api.CreateHookOption{}), repo.CreateHook)
Delete(repo.DeleteHook)
m.Post("/tests", context.RepoRefForAPI, repo.TestHook)
})
- m.Group("/git", func() {
- m.Combo("").Get(repo.ListGitHooks)
- m.Group("/{id}", func() {
- m.Combo("").Get(repo.GetGitHook).
- Patch(bind(api.EditGitHookOption{}), repo.EditGitHook).
- Delete(repo.DeleteGitHook)
- })
- }, reqGitHook(), context.ReferencesGitRepo(true))
- }, reqToken(), reqAdmin())
+ }, reqToken(), reqAdmin(), reqWebhooksEnabled())
m.Group("/collaborators", func() {
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
m.Combo("/{collaborator}").Get(reqAnyRepoReader(), repo.IsCollaborator).
m.Combo("/{id}").Get(org.GetHook).
Patch(bind(api.EditHookOption{}), org.EditHook).
Delete(org.DeleteHook)
- }, reqToken(), reqOrgOwnership())
+ }, reqToken(), reqOrgOwnership(), reqWebhooksEnabled())
}, orgAssignment(true))
m.Group("/teams/{teamid}", func() {
m.Combo("").Get(org.GetTeam).
}
}
+ // webhooksEnabled requires webhooks to be enabled by admin.
+ webhooksEnabled := func(ctx *context.Context) {
+ if setting.DisableWebhooks {
+ ctx.Error(403)
+ return
+ }
+ }
+
// FIXME: not all routes need go through same middleware.
// Especially some AJAX requests, we can reduce middleware number to improve performance.
// Routers.
m.Post("/matrix/{id}", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
m.Post("/msteams/{id}", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
m.Post("/feishu/{id}", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
- })
+ }, webhooksEnabled)
m.Group("/{configType:default-hooks|system-hooks}", func() {
m.Get("/{type}/new", repo.WebhooksNew)
m.Post("/matrix/{id}", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
m.Post("/msteams/{id}", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
m.Post("/feishu/{id}", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
- })
+ }, webhooksEnabled)
m.Group("/labels", func() {
m.Get("", org.RetrieveLabels, org.Labels)
Post(bindIgnErr(auth.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo.SettingsProtectedBranchPost)
}, repo.MustBeNotEmpty)
+ m.Group("/hooks/git", func() {
+ m.Get("", repo.GitHooks)
+ m.Combo("/{name}").Get(repo.GitHooksEdit).
+ Post(repo.GitHooksEditPost)
+ }, context.GitHookService())
+
m.Group("/hooks", func() {
m.Get("", repo.Webhooks)
m.Post("/delete", repo.DeleteWebhook)
m.Post("/matrix/{id}", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
m.Post("/msteams/{id}", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
m.Post("/feishu/{id}", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
-
- m.Group("/git", func() {
- m.Get("", repo.GitHooks)
- m.Combo("/{name}").Get(repo.GitHooksEdit).
- Post(repo.GitHooksEditPost)
- }, context.GitHookService())
- })
+ }, webhooksEnabled)
m.Group("/keys", func() {
m.Combo("").Get(repo.DeployKeys).
}
}()
+ if setting.DisableWebhooks {
+ return fmt.Errorf("Webhook task skipped (webhooks disabled): [%d]", t.ID)
+ }
+
resp, err := webhookHTTPClient.Do(req)
if err != nil {
t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err)
}
func prepareWebhook(w *models.Webhook, repo *models.Repository, event models.HookEventType, p api.Payloader) error {
+ // Skip sending if webhooks are disabled.
+ if setting.DisableWebhooks {
+ return nil
+ }
+
for _, e := range w.EventCheckers() {
if event == e.Type {
if !e.Has() {
<a class="{{if .PageIsAdminRepositories}}active{{end}} item" href="{{AppSubUrl}}/admin/repos">
{{.i18n.Tr "admin.repositories"}}
</a>
- <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
- {{.i18n.Tr "admin.hooks"}}
- </a>
+ {{if not DisableWebhooks}}
+ <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
+ {{.i18n.Tr "admin.hooks"}}
+ </a>
+ {{end}}
<a class="{{if .PageIsAdminAuthentications}}active{{end}} item" href="{{AppSubUrl}}/admin/auths">
{{.i18n.Tr "admin.authentication"}}
</a>
<a class="{{if .PageIsSettingsOptions}}active{{end}} item" href="{{.OrgLink}}/settings">
{{.i18n.Tr "org.settings.options"}}
</a>
+ {{if not DisableWebhooks}}
<a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.OrgLink}}/settings/hooks">
{{.i18n.Tr "repo.settings.hooks"}}
</a>
+ {{end}}
<a class="{{if .PageIsOrgSettingsLabels}}active{{end}} item" href="{{.OrgLink}}/settings/labels">
{{.i18n.Tr "repo.labels"}}
</a>
<li {{if .PageIsSettingsOptions}}class="current"{{end}}><a href="{{.RepoLink}}/settings">{{.i18n.Tr "repo.settings.options"}}</a></li>
<li {{if .PageIsSettingsCollaboration}}class="current"{{end}}><a href="{{.RepoLink}}/settings/collaboration">{{.i18n.Tr "repo.settings.collaboration"}}</a></li>
<li {{if .PageIsSettingsBranches}}class="current"{{end}}><a href="{{.RepoLink}}/settings/branches">{{.i18n.Tr "repo.settings.branches"}}</a></li>
+ {{if not DisableWebhooks}}
<li {{if .PageIsSettingsHooks}}class="current"{{end}}><a href="{{.RepoLink}}/settings/hooks">{{.i18n.Tr "repo.settings.hooks"}}</a></li>
+ {{end}}
{{if or .SignedUser.AllowGitHook .SignedUser.IsAdmin}}
<li {{if .PageIsSettingsGitHooks}}class="current"{{end}}><a href="{{.RepoLink}}/settings/hooks/git">{{.i18n.Tr "repo.settings.githooks"}}</a></li>
{{end}}
{{.i18n.Tr "repo.settings.branches"}}
</a>
{{end}}
- <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks">
- {{.i18n.Tr "repo.settings.hooks"}}
- </a>
+ {{if not DisableWebhooks}}
+ <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks">
+ {{.i18n.Tr "repo.settings.hooks"}}
+ </a>
+ {{end}}
{{if .SignedUser.CanEditGitHook}}
<a class="{{if .PageIsSettingsGitHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks/git">
{{.i18n.Tr "repo.settings.githooks"}}