Skip to content

DRAFT: try split web.go (registerWebRoutes) #34151

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions routers/web/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/web/shared"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/context"
Expand Down Expand Up @@ -864,3 +865,57 @@ func updateSession(ctx *context.Context, deletes []string, updates map[string]an
}
return nil
}

// /user/* auth routes
func ProvideUserAuthRouter(m *web.Router) {
// "user/login" doesn't need signOut, then logged-in users can still access this route for redirection purposes by "/user/login?redirec_to=..."
m.Get("/login", SignIn)

m.Group("", provideUserAuthRouterRequestSignOut(m), shared.ReqSignOut)
}

func provideUserAuthRouterRequestSignOut(m *web.Router) func() {
linkAccountEnabled := func(ctx *context.Context) {
if !setting.Service.EnableOpenIDSignIn && !setting.Service.EnableOpenIDSignUp && !setting.OAuth2.Enabled {
ctx.HTTPError(http.StatusForbidden)
return
}
}

return func() {
m.Post("/login", web.Bind(forms.SignInForm{}), SignInPost)
m.Group("", func() {
m.Combo("/login/openid").
Get(SignInOpenID).
Post(web.Bind(forms.SignInOpenIDForm{}), SignInOpenIDPost)
}, shared.OpenIDSignInEnabled)
m.Group("/openid", func() {
m.Combo("/connect").
Get(ConnectOpenID).
Post(web.Bind(forms.ConnectOpenIDForm{}), ConnectOpenIDPost)
m.Group("/register", func() {
m.Combo("").
Get(RegisterOpenID, shared.OpenIDSignUpEnabled).
Post(web.Bind(forms.SignUpOpenIDForm{}), RegisterOpenIDPost)
}, shared.OpenIDSignUpEnabled)
}, shared.OpenIDSignInEnabled)
m.Get("/sign_up", SignUp)
m.Post("/sign_up", web.Bind(forms.RegisterForm{}), SignUpPost)
m.Get("/link_account", linkAccountEnabled, LinkAccount)
m.Post("/link_account_signin", linkAccountEnabled, web.Bind(forms.SignInForm{}), LinkAccountPostSignIn)
m.Post("/link_account_signup", linkAccountEnabled, web.Bind(forms.RegisterForm{}), LinkAccountPostRegister)
m.Group("/two_factor", func() {
m.Get("", TwoFactor)
m.Post("", web.Bind(forms.TwoFactorAuthForm{}), TwoFactorPost)
m.Get("/scratch", TwoFactorScratch)
m.Post("/scratch", web.Bind(forms.TwoFactorScratchAuthForm{}), TwoFactorScratchPost)
})
m.Group("/webauthn", func() {
m.Get("", WebAuthn)
m.Get("/passkey/assertion", WebAuthnPasskeyAssertion)
m.Post("/passkey/login", WebAuthnPasskeyLogin)
m.Get("/assertion", WebAuthnLoginAssertion)
m.Post("/assertion", WebAuthnLoginAssertionPost)
})
}
}
33 changes: 33 additions & 0 deletions routers/web/explore/explore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package explore

import (
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/shared"
"code.gitea.io/gitea/services/context"
)

// /explore/* routes
func ProvideExploreRoutes(m *web.Router) func() {
return func() {
m.Get("", func(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/explore/repos")
})
m.Get("/repos", Repos)
m.Get("/repos/sitemap-{idx}.xml", shared.SitemapEnabled, Repos)
m.Get("/users", Users)
m.Get("/users/sitemap-{idx}.xml", shared.SitemapEnabled, Users)
m.Get("/organizations", Organizations)
m.Get("/code", func(ctx *context.Context) {
if unit.TypeCode.UnitGlobalDisabled() {
ctx.NotFound(nil)
return
}
}, Code)
m.Get("/topics/search", TopicSearch)
}
}
3 changes: 2 additions & 1 deletion routers/web/githttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package web
import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/routers/web/shared"
"code.gitea.io/gitea/services/context"
)

Expand All @@ -22,5 +23,5 @@ func addOwnerRepoGitHTTPRouters(m *web.Router) {
m.Methods("GET,OPTIONS", "/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38,62}}", repo.GetLooseObject)
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.pack", repo.GetPackFile)
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.idx", repo.GetIdxFile)
}, optSignInIgnoreCsrf, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context.UserAssignmentWeb())
}, shared.OptSignInIgnoreCsrf, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context.UserAssignmentWeb())
}
10 changes: 10 additions & 0 deletions routers/web/repo/setting/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
shared "code.gitea.io/gitea/routers/web/shared/secrets"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)

const (
Expand Down Expand Up @@ -127,3 +129,11 @@ func SecretsDelete(ctx *context.Context) {
sCtx.RedirectLink,
)
}

func AddSettingsSecretsRoutes(m *web.Router) {
m.Group("/secrets", func() {
m.Get("", Secrets)
m.Post("", web.Bind(forms.AddSecretForm{}), SecretsPost)
m.Post("/delete", SecretsDelete)
})
}
29 changes: 29 additions & 0 deletions routers/web/repo/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -1068,3 +1068,32 @@ func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.R
}
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, form)
}

func AddWebhookAddRoutes(m *web.Router) {
m.Get("/{type}/new", WebhooksNew)
m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), GiteaHooksNewPost)
m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), GogsHooksNewPost)
m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), SlackHooksNewPost)
m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), DiscordHooksNewPost)
m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), DingtalkHooksNewPost)
m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), TelegramHooksNewPost)
m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), MatrixHooksNewPost)
m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), MSTeamsHooksNewPost)
m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), FeishuHooksNewPost)
m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), WechatworkHooksNewPost)
m.Post("/packagist/new", web.Bind(forms.NewPackagistHookForm{}), PackagistHooksNewPost)
}

func AddWebhookEditRoutes(m *web.Router) {
m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), GiteaHooksEditPost)
m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), GogsHooksEditPost)
m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), SlackHooksEditPost)
m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), DiscordHooksEditPost)
m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), DingtalkHooksEditPost)
m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), TelegramHooksEditPost)
m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), MatrixHooksEditPost)
m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), MSTeamsHooksEditPost)
m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), FeishuHooksEditPost)
m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), WechatworkHooksEditPost)
m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), PackagistHooksEditPost)
}
29 changes: 29 additions & 0 deletions routers/web/shared/actions/actions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package actions

import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms"
)

// AddSettingsRunnersRoutes adds routes for settings runners
func AddSettingsRunnersRoutes(m *web.Router) {
m.Group("/runners", func() {
m.Get("", Runners)
m.Combo("/{runnerid}").Get(RunnersEdit).
Post(web.Bind(forms.EditRunnerForm{}), RunnersEditPost)
m.Post("/{runnerid}/delete", RunnerDeletePost)
m.Post("/reset_registration_token", ResetRunnerRegistrationToken)
})
}

func AddSettingsVariablesRoutes(m *web.Router) {
m.Group("/variables", func() {
m.Get("", Variables)
m.Post("/new", web.Bind(forms.EditVariableForm{}), VariableCreate)
m.Post("/{variable_id}/edit", web.Bind(forms.EditVariableForm{}), VariableUpdate)
m.Post("/{variable_id}/delete", VariableDelete)
})
}
163 changes: 163 additions & 0 deletions routers/web/shared/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package shared

import (
"net/http"
"strings"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
)

func SitemapEnabled(ctx *context.Context) {
if !setting.Other.EnableSitemap {
ctx.HTTPError(http.StatusNotFound)
return
}
}

// verifyAuthWithOptions checks authentication according to options
func verifyAuthWithOptions(options *common.VerifyOptions) func(ctx *context.Context) {
return func(ctx *context.Context) {
// Check prohibit login users.
if ctx.IsSigned {
if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(http.StatusOK, "user/auth/activate")
return
}
if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
log.Info("Failed authentication attempt for %s from %s", ctx.Doer.Name, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
return
}

if ctx.Doer.MustChangePassword {
if ctx.Req.URL.Path != "/user/settings/change_password" {
if strings.HasPrefix(ctx.Req.UserAgent(), "git") {
ctx.HTTPError(http.StatusUnauthorized, ctx.Locale.TrString("auth.must_change_password"))
return
}
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
if ctx.Req.URL.Path != "/user/events" {
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
}
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
return
}
} else if ctx.Req.URL.Path == "/user/settings/change_password" {
// make sure that the form cannot be accessed by users who don't need this
ctx.Redirect(setting.AppSubURL + "/")
return
}
}

// Redirect to dashboard (or alternate location) if user tries to visit any non-login page.
if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" {
ctx.RedirectToCurrentSite(ctx.FormString("redirect_to"))
return
}

if !options.SignOutRequired && !options.DisableCSRF && ctx.Req.Method == http.MethodPost {
ctx.Csrf.Validate(ctx)
if ctx.Written() {
return
}
}

if options.SignInRequired {
if !ctx.IsSigned {
if ctx.Req.URL.Path != "/user/events" {
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
}
ctx.Redirect(setting.AppSubURL + "/user/login")
return
} else if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(http.StatusOK, "user/auth/activate")
return
}
}

// Redirect to log in page if auto-signin info is provided and has not signed in.
if !options.SignOutRequired && !ctx.IsSigned &&
ctx.GetSiteCookie(setting.CookieRememberName) != "" {
if ctx.Req.URL.Path != "/user/events" {
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
}
ctx.Redirect(setting.AppSubURL + "/user/login")
return
}

if options.AdminRequired {
if !ctx.Doer.IsAdmin {
ctx.HTTPError(http.StatusForbidden)
return
}
ctx.Data["PageIsAdmin"] = true
}
}
}

var (
OptSignInIgnoreCsrf = verifyAuthWithOptions(&common.VerifyOptions{DisableCSRF: true})

// required to be signed in or signed out
ReqSignIn = verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true})
ReqSignOut = verifyAuthWithOptions(&common.VerifyOptions{SignOutRequired: true})
// optional sign in (if signed in, use the user as doer, if not, no doer)
OptSignIn = verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: setting.Service.RequireSignInViewStrict})
OptExploreSignIn = verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: setting.Service.RequireSignInViewStrict || setting.Service.Explore.RequireSigninView})

AdminReq = verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true, AdminRequired: true})
)

func OpenIDSignUpEnabled(ctx *context.Context) {
if !setting.Service.EnableOpenIDSignUp {
ctx.HTTPError(http.StatusForbidden)
return
}
}

func OpenIDSignInEnabled(ctx *context.Context) {
if !setting.Service.EnableOpenIDSignIn {
ctx.HTTPError(http.StatusForbidden)
return
}
}

func LinkAccountEnabled(ctx *context.Context) {
if !setting.Service.EnableOpenIDSignIn && !setting.Service.EnableOpenIDSignUp && !setting.OAuth2.Enabled {
ctx.HTTPError(http.StatusForbidden)
return
}
}

func Oauth2Enabled(ctx *context.Context) {
if !setting.OAuth2.Enabled {
ctx.HTTPError(http.StatusForbidden)
return
}
}

func PackagesEnabled(ctx *context.Context) {
if !setting.Packages.Enabled {
ctx.HTTPError(http.StatusForbidden)
return
}
}

// WebhooksEnabled requires webhooks to be enabled by admin.
func WebhooksEnabled(ctx *context.Context) {
if setting.DisableWebhooks {
ctx.HTTPError(http.StatusForbidden)
return
}
}
Loading
Loading