2017-04-25 03:24:51 -04:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2017-04-25 03:24:51 -04:00
2021-06-09 07:33:54 +08:00
package web
2017-04-25 03:24:51 -04:00
import (
2021-01-26 23:36:53 +08:00
"net/http"
2023-09-12 08:15:16 +02:00
"strings"
2017-04-25 03:24:51 -04:00
2023-09-18 07:32:56 +08:00
auth_model "code.gitea.io/gitea/models/auth"
2023-10-11 06:24:07 +02:00
"code.gitea.io/gitea/models/db"
2022-03-30 10:42:47 +02:00
"code.gitea.io/gitea/models/perm"
2021-11-10 03:57:58 +08:00
"code.gitea.io/gitea/models/unit"
2025-01-13 23:35:34 -08:00
"code.gitea.io/gitea/modules/git"
2017-04-25 03:24:51 -04:00
"code.gitea.io/gitea/modules/log"
2021-01-26 23:36:53 +08:00
"code.gitea.io/gitea/modules/metrics"
"code.gitea.io/gitea/modules/public"
2017-04-25 03:24:51 -04:00
"code.gitea.io/gitea/modules/setting"
2021-01-26 23:36:53 +08:00
"code.gitea.io/gitea/modules/storage"
2022-04-08 02:59:56 +08:00
"code.gitea.io/gitea/modules/structs"
2022-08-28 10:43:25 +01:00
"code.gitea.io/gitea/modules/templates"
2017-04-25 03:24:51 -04:00
"code.gitea.io/gitea/modules/validation"
2021-01-26 23:36:53 +08:00
"code.gitea.io/gitea/modules/web"
2023-09-12 08:15:16 +02:00
"code.gitea.io/gitea/modules/web/middleware"
2022-01-20 19:41:25 +08:00
"code.gitea.io/gitea/modules/web/routing"
2023-04-27 14:06:45 +08:00
"code.gitea.io/gitea/routers/common"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/routers/web/admin"
2022-01-02 21:12:35 +08:00
"code.gitea.io/gitea/routers/web/auth"
2023-04-03 18:06:57 +08:00
"code.gitea.io/gitea/routers/web/devtest"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/routers/web/events"
"code.gitea.io/gitea/routers/web/explore"
2022-03-26 10:04:22 +01:00
"code.gitea.io/gitea/routers/web/feed"
2022-05-04 19:56:20 +08:00
"code.gitea.io/gitea/routers/web/healthcheck"
2022-04-08 12:22:10 +08:00
"code.gitea.io/gitea/routers/web/misc"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/routers/web/org"
2023-04-28 08:08:47 +08:00
org_setting "code.gitea.io/gitea/routers/web/org/setting"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/routers/web/repo"
2023-01-31 09:45:19 +08:00
"code.gitea.io/gitea/routers/web/repo/actions"
2023-04-28 08:08:47 +08:00
repo_setting "code.gitea.io/gitea/routers/web/repo/setting"
2024-05-08 21:44:57 +08:00
"code.gitea.io/gitea/routers/web/shared/project"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/routers/web/user"
2022-01-02 21:12:35 +08:00
user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/routers/web/user/setting/security"
auth_service "code.gitea.io/gitea/services/auth"
2024-02-27 15:12:22 +08:00
"code.gitea.io/gitea/services/context"
2021-04-06 20:44:05 +01:00
"code.gitea.io/gitea/services/forms"
2017-04-25 03:24:51 -04:00
2021-11-17 20:34:35 +08:00
_ "code.gitea.io/gitea/modules/session" // to registers all internal adapters
2019-07-17 09:04:37 +08:00
2021-01-26 23:36:53 +08:00
"gitea.com/go-chi/captcha"
2023-09-12 08:15:16 +02:00
chi_middleware "github.com/go-chi/chi/v5/middleware"
2021-03-04 01:25:30 +00:00
"github.com/go-chi/cors"
2024-04-21 08:53:45 +08:00
"github.com/klauspost/compress/gzhttp"
2021-01-26 23:36:53 +08:00
"github.com/prometheus/client_golang/prometheus"
2017-04-25 03:24:51 -04:00
)
2024-05-02 10:27:25 +08:00
var GzipMinSize = 1400 // min size to compress for the body size of response
2020-11-13 20:51:07 +08:00
2023-12-25 20:13:18 +08:00
// optionsCorsHandler return a http handler which sets CORS options if enabled by config, it blocks non-CORS OPTIONS requests.
func optionsCorsHandler ( ) func ( next http . Handler ) http . Handler {
var corsHandler func ( next http . Handler ) http . Handler
2021-05-30 18:25:11 +08:00
if setting . CORSConfig . Enabled {
2023-12-25 20:13:18 +08:00
corsHandler = cors . Handler ( cors . Options {
AllowedOrigins : setting . CORSConfig . AllowDomain ,
2021-05-30 18:25:11 +08:00
AllowedMethods : setting . CORSConfig . Methods ,
AllowCredentials : setting . CORSConfig . AllowCredentials ,
2022-11-11 01:39:27 -05:00
AllowedHeaders : setting . CORSConfig . Headers ,
2021-05-30 18:25:11 +08:00
MaxAge : int ( setting . CORSConfig . MaxAge . Seconds ( ) ) ,
} )
}
2021-06-09 07:33:54 +08:00
return func ( next http . Handler ) http . Handler {
2023-12-25 20:13:18 +08:00
return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
if r . Method == http . MethodOptions {
if corsHandler != nil && r . Header . Get ( "Access-Control-Request-Method" ) != "" {
corsHandler ( next ) . ServeHTTP ( w , r )
} else {
// it should explicitly deny OPTIONS requests if CORS handler is not executed, to avoid the next GET/POST handler being incorrectly called by the OPTIONS request
w . WriteHeader ( http . StatusMethodNotAllowed )
}
return
}
// for non-OPTIONS requests, call the CORS handler to add some related headers like "Vary"
if corsHandler != nil {
corsHandler ( next ) . ServeHTTP ( w , r )
} else {
next . ServeHTTP ( w , r )
}
} )
2021-06-09 07:33:54 +08:00
}
2021-01-26 23:36:53 +08:00
}
2017-04-25 03:24:51 -04:00
2022-03-28 12:46:28 +08:00
// The OAuth2 plugin is expected to be executed first, as it must ignore the user id stored
// in the session (if there is a user id stored in session other plugins might return the user
// object for that id).
//
// The Session plugin is expected to be executed second, in order to skip authentication
// for users that have already signed in.
func buildAuthGroup ( ) * auth_service . Group {
2024-05-11 22:55:49 +08:00
group := auth_service . NewGroup ( )
group . Add ( & auth_service . OAuth2 { } ) // FIXME: this should be removed and only applied in download and oauth related routers
group . Add ( & auth_service . Basic { } ) // FIXME: this should be removed and only applied in download and git/lfs routers
2022-03-28 12:46:28 +08:00
if setting . Service . EnableReverseProxyAuth {
2025-01-14 09:53:34 +08:00
group . Add ( & auth_service . ReverseProxy { } ) // reverse-proxy should before Session, otherwise the header will be ignored if user has login
2022-03-28 12:46:28 +08:00
}
2024-05-11 22:55:49 +08:00
group . Add ( & auth_service . Session { } )
2023-09-18 07:32:56 +08:00
2023-10-11 06:24:07 +02:00
if setting . IsWindows && auth_model . IsSSPIEnabled ( db . DefaultContext ) {
2023-09-18 07:32:56 +08:00
group . Add ( & auth_service . SSPI { } ) // it MUST be the last, see the comment of SSPI
}
2022-03-28 12:46:28 +08:00
return group
}
2023-09-12 08:15:16 +02:00
func webAuth ( authMethod auth_service . Method ) func ( * context . Context ) {
return func ( ctx * context . Context ) {
ar , err := common . AuthShared ( ctx . Base , ctx . Session , authMethod )
if err != nil {
log . Error ( "Failed to verify user: %v" , err )
ctx . Error ( http . StatusUnauthorized , "Verify" )
return
}
ctx . Doer = ar . Doer
ctx . IsSigned = ar . Doer != nil
ctx . IsBasicAuth = ar . IsBasicAuth
if ctx . Doer == nil {
// ensure the session uid is deleted
_ = ctx . Session . Delete ( "uid" )
}
2024-09-18 15:17:25 +08:00
ctx . Csrf . PrepareForSessionUser ( ctx )
2023-09-12 08:15:16 +02:00
}
}
// 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" ) {
2024-02-15 05:48:45 +08:00
ctx . Error ( http . StatusUnauthorized , ctx . Locale . TrString ( "auth.must_change_password" ) )
2023-09-12 08:15:16 +02:00
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 ( ) != "/" {
2024-03-21 20:02:34 +08:00
ctx . RedirectToCurrentSite ( ctx . FormString ( "redirect_to" ) )
2023-09-12 08:15:16 +02:00
return
}
if ! options . SignOutRequired && ! options . DisableCSRF && ctx . Req . Method == "POST" {
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 &&
2023-10-14 02:56:41 +02:00
ctx . GetSiteCookie ( setting . CookieRememberName ) != "" {
2023-09-12 08:15:16 +02:00
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 . Error ( http . StatusForbidden )
return
}
ctx . Data [ "PageIsAdmin" ] = true
}
}
}
2023-04-28 08:08:47 +08:00
func ctxDataSet ( args ... any ) func ( ctx * context . Context ) {
return func ( ctx * context . Context ) {
for i := 0 ; i < len ( args ) ; i += 2 {
ctx . Data [ args [ i ] . ( string ) ] = args [ i + 1 ]
}
}
}
2021-06-09 07:33:54 +08:00
// Routes returns all web routes
2024-06-19 06:32:45 +08:00
func Routes ( ) * web . Router {
routes := web . NewRouter ( )
2017-04-25 03:24:51 -04:00
2023-04-27 14:06:45 +08:00
routes . Head ( "/" , misc . DummyOK ) // for health check - doesn't need to be passed through gzip handler
2023-12-25 20:13:18 +08:00
routes . Methods ( "GET, HEAD, OPTIONS" , "/assets/*" , optionsCorsHandler ( ) , public . FileHandlerFunc ( ) )
2023-07-21 06:43:49 +08:00
routes . Methods ( "GET, HEAD" , "/avatars/*" , storageHandler ( setting . Avatar . Storage , "avatars" , storage . Avatars ) )
routes . Methods ( "GET, HEAD" , "/repo-avatars/*" , storageHandler ( setting . RepoAvatar . Storage , "repo-avatars" , storage . RepoAvatars ) )
routes . Methods ( "GET, HEAD" , "/apple-touch-icon.png" , misc . StaticRedirect ( "/assets/img/apple-touch-icon.png" ) )
routes . Methods ( "GET, HEAD" , "/apple-touch-icon-precomposed.png" , misc . StaticRedirect ( "/assets/img/apple-touch-icon.png" ) )
routes . Methods ( "GET, HEAD" , "/favicon.ico" , misc . StaticRedirect ( "/assets/img/favicon.png" ) )
2021-05-04 22:48:31 +01:00
2023-04-30 20:22:23 +08:00
_ = templates . HTMLRenderer ( )
2023-05-04 14:36:34 +08:00
var mid [ ] any
2021-05-04 22:48:31 +01:00
2021-01-26 23:36:53 +08:00
if setting . EnableGzip {
2024-04-21 08:53:45 +08:00
// random jitter is recommended by: https://pkg.go.dev/github.com/klauspost/compress/gzhttp#readme-breach-mitigation
// compression level 6 is the gzip default and a good general tradeoff between speed, CPU usage, and compression
wrapper , err := gzhttp . NewWrapper ( gzhttp . RandomJitter ( 32 , 0 , false ) , gzhttp . MinSize ( GzipMinSize ) , gzhttp . CompressionLevel ( 6 ) )
2021-01-26 23:36:53 +08:00
if err != nil {
2024-04-21 08:53:45 +08:00
log . Fatal ( "gzhttp.NewWrapper failed: %v" , err )
2021-01-26 23:36:53 +08:00
}
2024-04-21 08:53:45 +08:00
mid = append ( mid , wrapper )
2021-01-26 23:36:53 +08:00
}
2021-01-27 22:56:54 +08:00
if setting . Service . EnableCaptcha {
2021-05-04 22:48:31 +01:00
// The captcha http.Handler should only fire on /captcha/* so we can just mount this on that url
2023-07-21 06:43:49 +08:00
routes . Methods ( "GET,HEAD" , "/captcha/*" , append ( mid , captcha . Captchaer ( context . GetImageCaptcha ( ) ) ) ... )
2021-01-28 01:46:35 +08:00
}
2021-01-26 23:36:53 +08:00
if setting . Metrics . Enabled {
2023-04-27 14:06:45 +08:00
prometheus . MustRegister ( metrics . NewCollector ( ) )
2023-05-04 14:36:34 +08:00
routes . Get ( "/metrics" , append ( mid , Metrics ) ... )
2021-01-26 23:36:53 +08:00
}
2024-04-19 21:43:56 +08:00
routes . Methods ( "GET,HEAD" , "/robots.txt" , append ( mid , misc . RobotsTxt ) ... )
2023-04-27 14:06:45 +08:00
routes . Get ( "/ssh_info" , misc . SSHInfo )
2022-05-04 19:56:20 +08:00
routes . Get ( "/api/healthz" , healthcheck . Check )
2023-05-04 14:36:34 +08:00
mid = append ( mid , common . Sessioner ( ) , context . Contexter ( ) )
2021-05-04 22:48:31 +01:00
2021-06-10 01:53:16 +08:00
// Get user from session if logged in.
2023-09-12 08:15:16 +02:00
mid = append ( mid , webAuth ( buildAuthGroup ( ) ) )
2021-06-10 01:53:16 +08:00
2021-05-04 22:48:31 +01:00
// GetHead allows a HEAD request redirect to GET if HEAD method is not defined for that route
2023-09-12 08:15:16 +02:00
mid = append ( mid , chi_middleware . GetHead )
2021-05-04 22:48:31 +01:00
2021-01-26 23:36:53 +08:00
if setting . API . EnableSwagger {
2023-04-27 14:06:45 +08:00
// Note: The route is here but no in API routes because it renders a web page
2023-05-04 14:36:34 +08:00
routes . Get ( "/api/swagger" , append ( mid , misc . Swagger ) ... ) // Render V1 by default
2021-01-26 23:36:53 +08:00
}
2021-05-04 22:48:31 +01:00
// TODO: These really seem like things that could be folded into Contexter or as helper functions
2023-05-04 14:36:34 +08:00
mid = append ( mid , user . GetNotificationCount )
mid = append ( mid , repo . GetActiveStopwatch )
mid = append ( mid , goGet )
2021-01-26 23:36:53 +08:00
2024-06-19 06:32:45 +08:00
others := web . NewRouter ( )
2023-05-04 14:36:34 +08:00
others . Use ( mid ... )
2023-04-27 14:06:45 +08:00
registerRoutes ( others )
2021-05-04 22:48:31 +01:00
routes . Mount ( "" , others )
return routes
2020-10-19 22:03:08 +01:00
}
2024-11-13 16:58:09 +08:00
var optSignInIgnoreCsrf = verifyAuthWithOptions ( & common . VerifyOptions { DisableCSRF : true } )
2023-11-02 22:14:33 +08:00
2023-04-27 14:06:45 +08:00
// registerRoutes register routes
2024-06-19 06:32:45 +08:00
func registerRoutes ( m * web . Router ) {
2024-11-13 16:58:09 +08:00
// required to be signed in or signed out
2023-09-12 08:15:16 +02:00
reqSignIn := verifyAuthWithOptions ( & common . VerifyOptions { SignInRequired : true } )
reqSignOut := verifyAuthWithOptions ( & common . VerifyOptions { SignOutRequired : true } )
2024-11-13 16:58:09 +08:00
// optional sign in (if signed in, use the user as doer, if not, no doer)
optSignIn := verifyAuthWithOptions ( & common . VerifyOptions { SignInRequired : setting . Service . RequireSignInView } )
optExploreSignIn := verifyAuthWithOptions ( & common . VerifyOptions { SignInRequired : setting . Service . RequireSignInView || setting . Service . Explore . RequireSigninView } )
2023-11-02 22:14:33 +08:00
2017-04-25 03:24:51 -04:00
validation . AddBindingRules ( )
2022-02-09 21:33:36 +01:00
linkAccountEnabled := func ( ctx * context . Context ) {
2024-01-28 07:36:44 -05:00
if ! setting . Service . EnableOpenIDSignIn && ! setting . Service . EnableOpenIDSignUp && ! setting . OAuth2 . Enabled {
2022-02-09 21:33:36 +01:00
ctx . Error ( http . StatusForbidden )
return
}
}
2017-08-19 17:34:49 +02:00
openIDSignInEnabled := func ( ctx * context . Context ) {
if ! setting . Service . EnableOpenIDSignIn {
2021-04-05 17:30:52 +02:00
ctx . Error ( http . StatusForbidden )
2017-08-19 17:34:49 +02:00
return
}
}
openIDSignUpEnabled := func ( ctx * context . Context ) {
if ! setting . Service . EnableOpenIDSignUp {
2021-04-05 17:30:52 +02:00
ctx . Error ( http . StatusForbidden )
2017-08-19 17:34:49 +02:00
return
}
}
2024-11-12 13:33:35 -08:00
oauth2Enabled := func ( ctx * context . Context ) {
if ! setting . OAuth2 . Enabled {
ctx . Error ( http . StatusForbidden )
return
}
}
2019-12-15 08:20:08 -06:00
reqMilestonesDashboardPageEnabled := func ( ctx * context . Context ) {
if ! setting . Service . ShowMilestonesDashboardPage {
2021-04-05 17:30:52 +02:00
ctx . Error ( http . StatusForbidden )
2019-12-15 08:20:08 -06:00
return
}
}
2021-02-11 18:34:34 +01:00
// webhooksEnabled requires webhooks to be enabled by admin.
webhooksEnabled := func ( ctx * context . Context ) {
if setting . DisableWebhooks {
2021-04-05 17:30:52 +02:00
ctx . Error ( http . StatusForbidden )
2021-02-11 18:34:34 +01:00
return
}
}
2021-06-06 01:59:27 +02:00
lfsServerEnabled := func ( ctx * context . Context ) {
if ! setting . LFS . StartServer {
ctx . Error ( http . StatusNotFound )
return
}
}
2022-05-09 20:20:21 +02:00
federationEnabled := func ( ctx * context . Context ) {
if ! setting . Federation . Enabled {
ctx . Error ( http . StatusNotFound )
return
}
}
2022-08-01 00:57:02 +08:00
dlSourceEnabled := func ( ctx * context . Context ) {
if setting . Repository . DisableDownloadSourceArchives {
ctx . Error ( http . StatusNotFound )
return
}
}
2022-10-28 23:17:38 +08:00
sitemapEnabled := func ( ctx * context . Context ) {
2023-04-23 07:38:25 +08:00
if ! setting . Other . EnableSitemap {
2022-10-28 23:17:38 +08:00
ctx . Error ( http . StatusNotFound )
return
}
}
2022-11-20 15:08:38 +01:00
packagesEnabled := func ( ctx * context . Context ) {
if ! setting . Packages . Enabled {
ctx . Error ( http . StatusForbidden )
return
}
}
2022-11-21 13:14:58 +08:00
feedEnabled := func ( ctx * context . Context ) {
2023-04-23 07:38:25 +08:00
if ! setting . Other . EnableFeed {
2022-11-21 13:14:58 +08:00
ctx . Error ( http . StatusNotFound )
return
}
}
2023-07-29 22:13:24 +08:00
reqUnitAccess := func ( unitType unit . Type , accessMode perm . AccessMode , ignoreGlobal bool ) func ( ctx * context . Context ) {
2023-05-06 17:39:06 +08:00
return func ( ctx * context . Context ) {
2023-07-29 22:13:24 +08:00
// only check global disabled units when ignoreGlobal is false
if ! ignoreGlobal && unitType . UnitGlobalDisabled ( ) {
2024-06-18 08:51:13 +08:00
ctx . NotFound ( "Repo unit is is disabled: " + unitType . LogString ( ) , nil )
2023-05-06 17:39:06 +08:00
return
}
if ctx . ContextUser == nil {
2024-06-18 08:51:13 +08:00
ctx . NotFound ( "ContextUser is nil" , nil )
2023-05-06 17:39:06 +08:00
return
}
if ctx . ContextUser . IsOrganization ( ) {
if ctx . Org . Organization . UnitPermission ( ctx , ctx . Doer , unitType ) < accessMode {
2024-06-18 08:51:13 +08:00
ctx . NotFound ( "ContextUser is org but doer has no access to unit" , nil )
2023-05-06 17:39:06 +08:00
return
}
}
}
}
2023-03-10 15:28:32 +01:00
addWebhookAddRoutes := func ( ) {
2023-07-02 08:59:32 +08:00
m . Get ( "/{type}/new" , repo_setting . WebhooksNew )
m . Post ( "/gitea/new" , web . Bind ( forms . NewWebhookForm { } ) , repo_setting . GiteaHooksNewPost )
m . Post ( "/gogs/new" , web . Bind ( forms . NewGogshookForm { } ) , repo_setting . GogsHooksNewPost )
m . Post ( "/slack/new" , web . Bind ( forms . NewSlackHookForm { } ) , repo_setting . SlackHooksNewPost )
m . Post ( "/discord/new" , web . Bind ( forms . NewDiscordHookForm { } ) , repo_setting . DiscordHooksNewPost )
m . Post ( "/dingtalk/new" , web . Bind ( forms . NewDingtalkHookForm { } ) , repo_setting . DingtalkHooksNewPost )
m . Post ( "/telegram/new" , web . Bind ( forms . NewTelegramHookForm { } ) , repo_setting . TelegramHooksNewPost )
m . Post ( "/matrix/new" , web . Bind ( forms . NewMatrixHookForm { } ) , repo_setting . MatrixHooksNewPost )
m . Post ( "/msteams/new" , web . Bind ( forms . NewMSTeamsHookForm { } ) , repo_setting . MSTeamsHooksNewPost )
m . Post ( "/feishu/new" , web . Bind ( forms . NewFeishuHookForm { } ) , repo_setting . FeishuHooksNewPost )
m . Post ( "/wechatwork/new" , web . Bind ( forms . NewWechatWorkHookForm { } ) , repo_setting . WechatworkHooksNewPost )
m . Post ( "/packagist/new" , web . Bind ( forms . NewPackagistHookForm { } ) , repo_setting . PackagistHooksNewPost )
2023-03-10 15:28:32 +01:00
}
addWebhookEditRoutes := func ( ) {
2023-07-02 08:59:32 +08:00
m . Post ( "/gitea/{id}" , web . Bind ( forms . NewWebhookForm { } ) , repo_setting . GiteaHooksEditPost )
m . Post ( "/gogs/{id}" , web . Bind ( forms . NewGogshookForm { } ) , repo_setting . GogsHooksEditPost )
m . Post ( "/slack/{id}" , web . Bind ( forms . NewSlackHookForm { } ) , repo_setting . SlackHooksEditPost )
m . Post ( "/discord/{id}" , web . Bind ( forms . NewDiscordHookForm { } ) , repo_setting . DiscordHooksEditPost )
m . Post ( "/dingtalk/{id}" , web . Bind ( forms . NewDingtalkHookForm { } ) , repo_setting . DingtalkHooksEditPost )
m . Post ( "/telegram/{id}" , web . Bind ( forms . NewTelegramHookForm { } ) , repo_setting . TelegramHooksEditPost )
m . Post ( "/matrix/{id}" , web . Bind ( forms . NewMatrixHookForm { } ) , repo_setting . MatrixHooksEditPost )
m . Post ( "/msteams/{id}" , web . Bind ( forms . NewMSTeamsHookForm { } ) , repo_setting . MSTeamsHooksEditPost )
m . Post ( "/feishu/{id}" , web . Bind ( forms . NewFeishuHookForm { } ) , repo_setting . FeishuHooksEditPost )
m . Post ( "/wechatwork/{id}" , web . Bind ( forms . NewWechatWorkHookForm { } ) , repo_setting . WechatworkHooksEditPost )
m . Post ( "/packagist/{id}" , web . Bind ( forms . NewPackagistHookForm { } ) , repo_setting . PackagistHooksEditPost )
2023-03-10 15:28:32 +01:00
}
2023-12-25 08:28:59 +01:00
addSettingsVariablesRoutes := func ( ) {
2023-06-21 06:54:15 +08:00
m . Group ( "/variables" , func ( ) {
m . Get ( "" , repo_setting . Variables )
m . Post ( "/new" , web . Bind ( forms . EditVariableForm { } ) , repo_setting . VariableCreate )
m . Post ( "/{variable_id}/edit" , web . Bind ( forms . EditVariableForm { } ) , repo_setting . VariableUpdate )
m . Post ( "/{variable_id}/delete" , repo_setting . VariableDelete )
} )
}
2023-04-28 08:08:47 +08:00
addSettingsSecretsRoutes := func ( ) {
m . Group ( "/secrets" , func ( ) {
m . Get ( "" , repo_setting . Secrets )
m . Post ( "" , web . Bind ( forms . AddSecretForm { } ) , repo_setting . SecretsPost )
m . Post ( "/delete" , repo_setting . SecretsDelete )
} )
}
addSettingsRunnersRoutes := func ( ) {
m . Group ( "/runners" , func ( ) {
m . Get ( "" , repo_setting . Runners )
m . Combo ( "/{runnerid}" ) . Get ( repo_setting . RunnersEdit ) .
Post ( web . Bind ( forms . EditRunnerForm { } ) , repo_setting . RunnersEditPost )
m . Post ( "/{runnerid}/delete" , repo_setting . RunnerDeletePost )
2024-12-23 17:59:16 +08:00
m . Post ( "/reset_registration_token" , repo_setting . ResetRunnerRegistrationToken )
2023-04-28 08:08:47 +08:00
} )
}
2021-01-30 16:55:53 +08:00
// FIXME: not all routes need go through same middleware.
2017-04-25 03:24:51 -04:00
// Especially some AJAX requests, we can reduce middleware number to improve performance.
2023-07-21 20:14:20 +08:00
2021-06-09 07:33:54 +08:00
m . Get ( "/" , Home )
2024-11-13 16:58:09 +08:00
m . Get ( "/sitemap.xml" , sitemapEnabled , optExploreSignIn , HomeSitemap )
2021-11-26 15:55:11 +01:00
m . Group ( "/.well-known" , func ( ) {
2022-01-02 21:12:35 +08:00
m . Get ( "/openid-configuration" , auth . OIDCWellKnown )
2022-05-09 20:20:21 +02:00
m . Group ( "" , func ( ) {
2021-11-26 15:55:11 +01:00
m . Get ( "/nodeinfo" , NodeInfoLinks )
2022-05-09 20:20:21 +02:00
m . Get ( "/webfinger" , WebfingerQuery )
} , federationEnabled )
2023-04-27 14:06:45 +08:00
m . Get ( "/change-password" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/user/settings/account" )
2021-11-26 15:55:11 +01:00
} )
2024-02-15 18:49:13 +01:00
m . Get ( "/passkey-endpoints" , passkeyEndpoints )
2023-12-25 20:13:18 +08:00
m . Methods ( "GET, HEAD" , "/*" , public . FileHandlerFunc ( ) )
} , optionsCorsHandler ( ) )
2021-11-26 15:55:11 +01:00
2024-12-04 10:11:34 +08:00
m . Post ( "/-/markup" , reqSignIn , web . Bind ( structs . MarkupOption { } ) , misc . Markup )
2017-04-25 03:24:51 -04:00
m . Group ( "/explore" , func ( ) {
m . Get ( "" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/explore/repos" )
} )
2021-06-09 07:33:54 +08:00
m . Get ( "/repos" , explore . Repos )
2022-10-28 23:17:38 +08:00
m . Get ( "/repos/sitemap-{idx}.xml" , sitemapEnabled , explore . Repos )
2021-06-09 07:33:54 +08:00
m . Get ( "/users" , explore . Users )
2022-10-28 23:17:38 +08:00
m . Get ( "/users/sitemap-{idx}.xml" , sitemapEnabled , explore . Users )
2021-06-09 07:33:54 +08:00
m . Get ( "/organizations" , explore . Organizations )
2023-06-10 03:02:33 +08:00
m . Get ( "/code" , func ( ctx * context . Context ) {
if unit . TypeCode . UnitGlobalDisabled ( ) {
2024-06-18 08:51:13 +08:00
ctx . NotFound ( "Repo unit code is disabled" , nil )
2023-06-10 03:02:33 +08:00
return
}
} , explore . Code )
2022-04-08 02:59:56 +08:00
m . Get ( "/topics/search" , explore . TopicSearch )
2024-11-13 16:58:09 +08:00
} , optExploreSignIn )
2024-04-17 16:31:37 +08:00
2022-04-08 02:59:56 +08:00
m . Group ( "/issues" , func ( ) {
m . Get ( "" , user . Issues )
m . Get ( "/search" , repo . SearchIssues )
} , reqSignIn )
2021-01-13 05:19:17 +01:00
m . Get ( "/pulls" , reqSignIn , user . Pulls )
2019-12-15 08:20:08 -06:00
m . Get ( "/milestones" , reqSignIn , reqMilestonesDashboardPageEnabled , user . Milestones )
2017-04-25 03:24:51 -04:00
// ***** START: User *****
2023-07-27 02:08:51 -03:00
// "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 ( "/user/login" , auth . SignIn )
2017-04-25 03:24:51 -04:00
m . Group ( "/user" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Post ( "/login" , web . Bind ( forms . SignInForm { } ) , auth . SignInPost )
2017-08-19 17:34:49 +02:00
m . Group ( "" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Combo ( "/login/openid" ) .
2022-01-02 21:12:35 +08:00
Get ( auth . SignInOpenID ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . SignInOpenIDForm { } ) , auth . SignInOpenIDPost )
2017-08-19 17:34:49 +02:00
} , openIDSignInEnabled )
m . Group ( "/openid" , func ( ) {
m . Combo ( "/connect" ) .
2022-01-02 21:12:35 +08:00
Get ( auth . ConnectOpenID ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . ConnectOpenIDForm { } ) , auth . ConnectOpenIDPost )
2017-08-19 17:34:49 +02:00
m . Group ( "/register" , func ( ) {
m . Combo ( "" ) .
2022-01-02 21:12:35 +08:00
Get ( auth . RegisterOpenID , openIDSignUpEnabled ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . SignUpOpenIDForm { } ) , auth . RegisterOpenIDPost )
2017-08-19 17:34:49 +02:00
} , openIDSignUpEnabled )
} , openIDSignInEnabled )
2022-01-02 21:12:35 +08:00
m . Get ( "/sign_up" , auth . SignUp )
2022-12-12 16:09:26 +08:00
m . Post ( "/sign_up" , web . Bind ( forms . RegisterForm { } ) , auth . SignUpPost )
2022-02-09 21:33:36 +01:00
m . Get ( "/link_account" , linkAccountEnabled , auth . LinkAccount )
2022-12-12 16:09:26 +08:00
m . Post ( "/link_account_signin" , linkAccountEnabled , web . Bind ( forms . SignInForm { } ) , auth . LinkAccountPostSignIn )
m . Post ( "/link_account_signup" , linkAccountEnabled , web . Bind ( forms . RegisterForm { } ) , auth . LinkAccountPostRegister )
2017-04-25 03:24:51 -04:00
m . Group ( "/two_factor" , func ( ) {
2022-01-02 21:12:35 +08:00
m . Get ( "" , auth . TwoFactor )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . TwoFactorAuthForm { } ) , auth . TwoFactorPost )
2022-01-02 21:12:35 +08:00
m . Get ( "/scratch" , auth . TwoFactorScratch )
2022-12-12 16:09:26 +08:00
m . Post ( "/scratch" , web . Bind ( forms . TwoFactorScratchAuthForm { } ) , auth . TwoFactorScratchPost )
2017-04-25 03:24:51 -04:00
} )
2022-01-14 23:03:31 +08:00
m . Group ( "/webauthn" , func ( ) {
m . Get ( "" , auth . WebAuthn )
2024-06-30 00:50:03 +02:00
m . Get ( "/passkey/assertion" , auth . WebAuthnPasskeyAssertion )
m . Post ( "/passkey/login" , auth . WebAuthnPasskeyLogin )
2022-01-14 23:03:31 +08:00
m . Get ( "/assertion" , auth . WebAuthnLoginAssertion )
m . Post ( "/assertion" , auth . WebAuthnLoginAssertionPost )
2018-05-19 16:12:37 +02:00
} )
2017-04-25 03:24:51 -04:00
} , reqSignOut )
2022-01-20 19:41:25 +08:00
m . Any ( "/user/events" , routing . MarkLongPolling , events . Events )
2020-05-07 22:49:00 +01:00
2019-03-08 17:42:50 +01:00
m . Group ( "/login/oauth" , func ( ) {
2024-11-12 13:33:35 -08:00
m . Group ( "" , func ( ) {
m . Get ( "/authorize" , web . Bind ( forms . AuthorizationForm { } ) , auth . AuthorizeOAuth )
m . Post ( "/grant" , web . Bind ( forms . GrantApplicationForm { } ) , auth . GrantApplicationOAuth )
// TODO manage redirection
m . Post ( "/authorize" , web . Bind ( forms . AuthorizationForm { } ) , auth . AuthorizeOAuth )
2024-11-13 16:58:09 +08:00
} , optSignInIgnoreCsrf , reqSignIn )
2024-11-12 13:33:35 -08:00
2024-11-20 15:22:48 +01:00
m . Methods ( "GET, POST, OPTIONS" , "/userinfo" , optionsCorsHandler ( ) , optSignInIgnoreCsrf , auth . InfoOAuth )
2024-11-13 16:58:09 +08:00
m . Methods ( "POST, OPTIONS" , "/access_token" , optionsCorsHandler ( ) , web . Bind ( forms . AccessTokenForm { } ) , optSignInIgnoreCsrf , auth . AccessTokenOAuth )
m . Methods ( "GET, OPTIONS" , "/keys" , optionsCorsHandler ( ) , optSignInIgnoreCsrf , auth . OIDCKeys )
m . Methods ( "POST, OPTIONS" , "/introspect" , optionsCorsHandler ( ) , web . Bind ( forms . IntrospectTokenForm { } ) , optSignInIgnoreCsrf , auth . IntrospectOAuth )
2024-11-12 13:33:35 -08:00
} , oauth2Enabled )
2019-03-08 17:42:50 +01:00
2017-04-25 03:24:51 -04:00
m . Group ( "/user/settings" , func ( ) {
2022-01-02 21:12:35 +08:00
m . Get ( "" , user_setting . Profile )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . UpdateProfileForm { } ) , user_setting . ProfilePost )
2022-01-02 21:12:35 +08:00
m . Get ( "/change_password" , auth . MustChangePassword )
2022-12-12 16:09:26 +08:00
m . Post ( "/change_password" , web . Bind ( forms . MustChangePasswordForm { } ) , auth . MustChangePasswordPost )
m . Post ( "/avatar" , web . Bind ( forms . AvatarForm { } ) , user_setting . AvatarPost )
2022-01-02 21:12:35 +08:00
m . Post ( "/avatar/delete" , user_setting . DeleteAvatar )
2018-05-15 12:07:32 +02:00
m . Group ( "/account" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Combo ( "" ) . Get ( user_setting . Account ) . Post ( web . Bind ( forms . ChangePasswordForm { } ) , user_setting . AccountPost )
m . Post ( "/email" , web . Bind ( forms . AddEmailForm { } ) , user_setting . EmailPost )
2022-01-02 21:12:35 +08:00
m . Post ( "/email/delete" , user_setting . DeleteEmail )
m . Post ( "/delete" , user_setting . DeleteAccount )
2021-10-27 17:40:08 +02:00
} )
m . Group ( "/appearance" , func ( ) {
2022-01-02 21:12:35 +08:00
m . Get ( "" , user_setting . Appearance )
2022-12-12 16:09:26 +08:00
m . Post ( "/language" , web . Bind ( forms . UpdateLanguageForm { } ) , user_setting . UpdateUserLang )
2022-01-21 18:59:26 +01:00
m . Post ( "/hidden_comments" , user_setting . UpdateUserHiddenComments )
2022-12-12 16:09:26 +08:00
m . Post ( "/theme" , web . Bind ( forms . UpdateThemeForm { } ) , user_setting . UpdateUIThemePost )
2018-05-15 12:07:32 +02:00
} )
m . Group ( "/security" , func ( ) {
2022-01-02 21:12:35 +08:00
m . Get ( "" , security . Security )
2018-05-15 12:07:32 +02:00
m . Group ( "/two_factor" , func ( ) {
2022-01-02 21:12:35 +08:00
m . Post ( "/regenerate_scratch" , security . RegenerateScratchTwoFactor )
m . Post ( "/disable" , security . DisableTwoFactor )
m . Get ( "/enroll" , security . EnrollTwoFactor )
2022-12-12 16:09:26 +08:00
m . Post ( "/enroll" , web . Bind ( forms . TwoFactorAuthForm { } ) , security . EnrollTwoFactorPost )
2018-05-15 12:07:32 +02:00
} )
2022-01-14 23:03:31 +08:00
m . Group ( "/webauthn" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Post ( "/request_register" , web . Bind ( forms . WebauthnRegistrationForm { } ) , security . WebAuthnRegister )
2022-01-14 23:03:31 +08:00
m . Post ( "/register" , security . WebauthnRegisterPost )
2022-12-12 16:09:26 +08:00
m . Post ( "/delete" , web . Bind ( forms . WebauthnDeleteForm { } ) , security . WebauthnDelete )
2018-05-19 16:12:37 +02:00
} )
2018-05-15 12:07:32 +02:00
m . Group ( "/openid" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . AddOpenIDForm { } ) , security . OpenIDPost )
2022-01-02 21:12:35 +08:00
m . Post ( "/delete" , security . DeleteOpenID )
m . Post ( "/toggle_visibility" , security . ToggleOpenIDVisibility )
2018-05-15 12:07:32 +02:00
} , openIDSignInEnabled )
2022-02-09 21:33:36 +01:00
m . Post ( "/account_link" , linkAccountEnabled , security . DeleteAccountLink )
2018-05-15 12:07:32 +02:00
} )
2024-11-12 13:33:35 -08:00
m . Group ( "/applications" , func ( ) {
// oauth2 applications
m . Group ( "/oauth2" , func ( ) {
m . Get ( "/{id}" , user_setting . OAuth2ApplicationShow )
m . Post ( "/{id}" , web . Bind ( forms . EditOAuth2ApplicationForm { } ) , user_setting . OAuthApplicationsEdit )
m . Post ( "/{id}/regenerate_secret" , user_setting . OAuthApplicationsRegenerateSecret )
m . Post ( "" , web . Bind ( forms . EditOAuth2ApplicationForm { } ) , user_setting . OAuthApplicationsPost )
m . Post ( "/{id}/delete" , user_setting . DeleteOAuth2Application )
m . Post ( "/{id}/revoke/{grantId}" , user_setting . RevokeOAuth2Grant )
} , oauth2Enabled )
// access token applications
m . Combo ( "" ) . Get ( user_setting . Applications ) .
Post ( web . Bind ( forms . NewAccessTokenForm { } ) , user_setting . ApplicationsPost )
m . Post ( "/delete" , user_setting . DeleteApplication )
2019-03-08 17:42:50 +01:00
} )
2024-11-12 13:33:35 -08:00
2022-01-02 21:12:35 +08:00
m . Combo ( "/keys" ) . Get ( user_setting . Keys ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . AddKeyForm { } ) , user_setting . KeysPost )
2022-01-02 21:12:35 +08:00
m . Post ( "/keys/delete" , user_setting . DeleteKey )
2022-11-20 15:08:38 +01:00
m . Group ( "/packages" , func ( ) {
m . Get ( "" , user_setting . Packages )
m . Group ( "/rules" , func ( ) {
m . Group ( "/add" , func ( ) {
m . Get ( "" , user_setting . PackagesRuleAdd )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . PackageCleanupRuleForm { } ) , user_setting . PackagesRuleAddPost )
2022-11-20 15:08:38 +01:00
} )
m . Group ( "/{id}" , func ( ) {
m . Get ( "" , user_setting . PackagesRuleEdit )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . PackageCleanupRuleForm { } ) , user_setting . PackagesRuleEditPost )
2022-11-20 15:08:38 +01:00
m . Get ( "/preview" , user_setting . PackagesRulePreview )
} )
} )
2023-02-05 11:12:31 +01:00
m . Group ( "/cargo" , func ( ) {
m . Post ( "/initialize" , user_setting . InitializeCargoIndex )
m . Post ( "/rebuild" , user_setting . RebuildCargoIndex )
} )
2023-02-06 02:49:21 +01:00
m . Post ( "/chef/regenerate_keypair" , user_setting . RegenerateChefKeyPair )
2022-11-20 15:08:38 +01:00
} , packagesEnabled )
2023-04-28 08:08:47 +08:00
m . Group ( "/actions" , func ( ) {
m . Get ( "" , user_setting . RedirectToDefaultSetting )
2023-05-31 09:39:54 +08:00
addSettingsRunnersRoutes ( )
2023-04-28 08:08:47 +08:00
addSettingsSecretsRoutes ( )
2023-12-25 08:28:59 +01:00
addSettingsVariablesRoutes ( )
2023-04-28 08:08:47 +08:00
} , actions . MustEnableActions )
2022-01-02 21:12:35 +08:00
m . Get ( "/organization" , user_setting . Organization )
m . Get ( "/repos" , user_setting . Repos )
m . Post ( "/repos/unadopted" , user_setting . AdoptOrDeleteRepository )
2023-03-10 15:28:32 +01:00
m . Group ( "/hooks" , func ( ) {
m . Get ( "" , user_setting . Webhooks )
m . Post ( "/delete" , user_setting . DeleteWebhook )
addWebhookAddRoutes ( )
m . Group ( "/{id}" , func ( ) {
2023-07-02 08:59:32 +08:00
m . Get ( "" , repo_setting . WebHooksEdit )
m . Post ( "/replay/{uuid}" , repo_setting . ReplayWebhook )
2023-03-10 15:28:32 +01:00
} )
addWebhookEditRoutes ( )
2023-04-28 08:08:47 +08:00
} , webhooksEnabled )
2024-03-04 09:16:03 +01:00
m . Group ( "/blocked_users" , func ( ) {
m . Get ( "" , user_setting . BlockedUsers )
m . Post ( "" , web . Bind ( forms . BlockUserForm { } ) , user_setting . BlockedUsersPost )
} )
2024-04-24 00:18:41 +08:00
} , reqSignIn , ctxDataSet ( "PageIsUserSettings" , true , "EnablePackages" , setting . Packages . Enabled ) )
2017-04-25 03:24:51 -04:00
m . Group ( "/user" , func ( ) {
2022-04-12 04:02:58 +02:00
m . Get ( "/activate" , auth . Activate )
m . Post ( "/activate" , auth . ActivatePost )
2022-01-02 21:12:35 +08:00
m . Any ( "/activate_email" , auth . ActivateEmail )
2025-01-30 07:33:50 +08:00
m . Get ( "/avatar/{username}/{size}" , user . AvatarByUsernameSize )
2022-01-02 21:12:35 +08:00
m . Get ( "/recover_account" , auth . ResetPasswd )
m . Post ( "/recover_account" , auth . ResetPasswdPost )
m . Get ( "/forgot_password" , auth . ForgotPasswd )
m . Post ( "/forgot_password" , auth . ForgotPasswdPost )
m . Post ( "/logout" , auth . SignOut )
2022-04-12 04:02:58 +02:00
m . Get ( "/stopwatches" , reqSignIn , user . GetStopwatches )
2024-11-13 16:58:09 +08:00
m . Get ( "/search_candidates" , optExploreSignIn , user . SearchCandidates )
2022-05-29 02:03:17 +02:00
m . Group ( "/oauth2" , func ( ) {
m . Get ( "/{provider}" , auth . SignInOAuth )
m . Get ( "/{provider}/callback" , auth . SignInOAuthCallback )
} )
2017-04-25 03:24:51 -04:00
} )
// ***** END: User *****
2021-01-26 23:36:53 +08:00
m . Get ( "/avatar/{hash}" , user . AvatarByEmailHash )
2020-03-27 12:34:39 +00:00
2023-09-12 08:15:16 +02:00
adminReq := verifyAuthWithOptions ( & common . VerifyOptions { SignInRequired : true , AdminRequired : true } )
2017-04-25 03:24:51 -04:00
// ***** START: Admin *****
2024-10-10 12:56:49 +08:00
m . Group ( "/-/admin" , func ( ) {
2023-06-03 22:03:41 +08:00
m . Get ( "" , admin . Dashboard )
2024-02-16 04:52:25 +02:00
m . Get ( "/system_status" , admin . SystemStatus )
2023-06-03 22:03:41 +08:00
m . Post ( "" , web . Bind ( forms . AdminDashboardForm { } ) , admin . DashboardPost )
2022-10-17 07:29:26 +08:00
2024-01-10 19:03:23 +08:00
m . Get ( "/self_check" , admin . SelfCheck )
2024-05-10 20:07:01 +08:00
m . Post ( "/self_check" , admin . SelfCheckPost )
2024-01-10 19:03:23 +08:00
2022-10-17 07:29:26 +08:00
m . Group ( "/config" , func ( ) {
m . Get ( "" , admin . Config )
m . Post ( "" , admin . ChangeConfig )
m . Post ( "/test_mail" , admin . SendTestMail )
2024-06-17 21:22:39 +02:00
m . Post ( "/test_cache" , admin . TestCache )
2024-02-24 21:12:17 +08:00
m . Get ( "/settings" , admin . ConfigSettings )
2022-10-17 07:29:26 +08:00
} )
2020-01-07 11:23:09 +00:00
m . Group ( "/monitor" , func ( ) {
2023-06-03 22:03:41 +08:00
m . Get ( "/stats" , admin . MonitorStats )
2023-05-11 15:45:47 +08:00
m . Get ( "/cron" , admin . CronTasks )
2025-01-22 02:57:07 +08:00
m . Get ( "/perftrace" , admin . PerfTrace )
2023-05-11 15:45:47 +08:00
m . Get ( "/stacktrace" , admin . Stacktrace )
m . Post ( "/stacktrace/cancel/{pid}" , admin . StacktraceCancel )
m . Get ( "/queue" , admin . Queues )
2021-01-26 23:36:53 +08:00
m . Group ( "/queue/{qid}" , func ( ) {
2023-05-11 15:45:47 +08:00
m . Get ( "" , admin . QueueManage )
2023-05-08 19:49:59 +08:00
m . Post ( "/set" , admin . QueueSet )
2023-05-11 15:45:47 +08:00
m . Post ( "/remove-all-items" , admin . QueueRemoveAllItems )
2020-01-07 11:23:09 +00:00
} )
2023-05-11 15:45:47 +08:00
m . Get ( "/diagnosis" , admin . MonitorDiagnosis )
2020-01-07 11:23:09 +00:00
} )
2017-04-25 03:24:51 -04:00
m . Group ( "/users" , func ( ) {
m . Get ( "" , admin . Users )
2022-12-12 16:09:26 +08:00
m . Combo ( "/new" ) . Get ( admin . NewUser ) . Post ( web . Bind ( forms . AdminCreateUserForm { } ) , admin . NewUserPost )
2023-08-31 11:21:18 +02:00
m . Get ( "/{userid}" , admin . ViewUser )
m . Combo ( "/{userid}/edit" ) . Get ( admin . EditUser ) . Post ( web . Bind ( forms . AdminEditUserForm { } ) , admin . EditUserPost )
2021-01-26 23:36:53 +08:00
m . Post ( "/{userid}/delete" , admin . DeleteUser )
2022-12-12 16:09:26 +08:00
m . Post ( "/{userid}/avatar" , web . Bind ( forms . AvatarForm { } ) , admin . AvatarPost )
2021-11-16 20:13:13 +01:00
m . Post ( "/{userid}/avatar/delete" , admin . DeleteAvatar )
2017-04-25 03:24:51 -04:00
} )
2020-03-02 15:25:36 -03:00
m . Group ( "/emails" , func ( ) {
m . Get ( "" , admin . Emails )
m . Post ( "/activate" , admin . ActivateEmail )
2024-07-25 19:11:04 +09:00
m . Post ( "/delete" , admin . DeleteEmail )
2020-03-02 15:25:36 -03:00
} )
2017-04-25 03:24:51 -04:00
m . Group ( "/orgs" , func ( ) {
m . Get ( "" , admin . Organizations )
} )
m . Group ( "/repos" , func ( ) {
m . Get ( "" , admin . Repos )
2020-09-25 05:09:23 +01:00
m . Combo ( "/unadopted" ) . Get ( admin . UnadoptedRepos ) . Post ( admin . AdoptOrDeleteRepository )
2017-04-25 03:24:51 -04:00
m . Post ( "/delete" , admin . DeleteRepo )
} )
2022-11-20 15:08:38 +01:00
m . Group ( "/packages" , func ( ) {
m . Get ( "" , admin . Packages )
m . Post ( "/delete" , admin . DeletePackageVersion )
2023-08-08 02:46:10 +02:00
m . Post ( "/cleanup" , admin . CleanupExpiredData )
2022-11-20 15:08:38 +01:00
} , packagesEnabled )
2022-03-30 10:42:47 +02:00
2021-01-15 01:24:03 +02:00
m . Group ( "/hooks" , func ( ) {
2020-03-08 22:08:05 +00:00
m . Get ( "" , admin . DefaultOrSystemWebhooks )
m . Post ( "/delete" , admin . DeleteDefaultOrSystemWebhook )
2022-01-05 22:00:20 +01:00
m . Group ( "/{id}" , func ( ) {
2023-07-02 08:59:32 +08:00
m . Get ( "" , repo_setting . WebHooksEdit )
m . Post ( "/replay/{uuid}" , repo_setting . ReplayWebhook )
2022-01-05 22:00:20 +01:00
} )
2023-03-10 15:28:32 +01:00
addWebhookEditRoutes ( )
2021-02-11 18:34:34 +01:00
} , webhooksEnabled )
2019-03-18 22:33:20 -04:00
2021-01-26 23:36:53 +08:00
m . Group ( "/{configType:default-hooks|system-hooks}" , func ( ) {
2023-03-10 15:28:32 +01:00
addWebhookAddRoutes ( )
2021-01-15 01:24:03 +02:00
} )
2017-04-25 03:24:51 -04:00
m . Group ( "/auths" , func ( ) {
m . Get ( "" , admin . Authentications )
2022-12-12 16:09:26 +08:00
m . Combo ( "/new" ) . Get ( admin . NewAuthSource ) . Post ( web . Bind ( forms . AuthenticationForm { } ) , admin . NewAuthSourcePost )
2021-01-26 23:36:53 +08:00
m . Combo ( "/{authid}" ) . Get ( admin . EditAuthSource ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . AuthenticationForm { } ) , admin . EditAuthSourcePost )
2021-01-26 23:36:53 +08:00
m . Post ( "/{authid}/delete" , admin . DeleteAuthSource )
2017-04-25 03:24:51 -04:00
} )
m . Group ( "/notices" , func ( ) {
m . Get ( "" , admin . Notices )
m . Post ( "/delete" , admin . DeleteNotices )
2020-02-26 10:25:54 -06:00
m . Post ( "/empty" , admin . EmptyNotices )
2017-04-25 03:24:51 -04:00
} )
2022-10-12 16:08:29 +02:00
m . Group ( "/applications" , func ( ) {
m . Get ( "" , admin . Applications )
2022-12-12 16:09:26 +08:00
m . Post ( "/oauth2" , web . Bind ( forms . EditOAuth2ApplicationForm { } ) , admin . ApplicationsPost )
2022-10-12 16:08:29 +02:00
m . Group ( "/oauth2/{id}" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Combo ( "" ) . Get ( admin . EditApplication ) . Post ( web . Bind ( forms . EditOAuth2ApplicationForm { } ) , admin . EditApplicationPost )
2022-10-12 16:08:29 +02:00
m . Post ( "/regenerate_secret" , admin . ApplicationsRegenerateSecret )
m . Post ( "/delete" , admin . DeleteApplication )
} )
2024-11-12 13:33:35 -08:00
} , oauth2Enabled )
2023-01-31 09:45:19 +08:00
2023-04-28 08:08:47 +08:00
m . Group ( "/actions" , func ( ) {
m . Get ( "" , admin . RedirectToDefaultSetting )
addSettingsRunnersRoutes ( )
2023-12-25 08:28:59 +01:00
addSettingsVariablesRoutes ( )
2023-04-28 08:08:47 +08:00
} )
2024-01-28 07:36:44 -05:00
} , adminReq , ctxDataSet ( "EnableOAuth2" , setting . OAuth2 . Enabled , "EnablePackages" , setting . Packages . Enabled ) )
2017-04-25 03:24:51 -04:00
// ***** END: Admin *****
m . Group ( "" , func ( ) {
2023-04-27 14:06:45 +08:00
m . Get ( "/{username}" , user . UsernameSubRoute )
2023-12-25 20:13:18 +08:00
m . Methods ( "GET, OPTIONS" , "/attachments/{uuid}" , optionsCorsHandler ( ) , repo . GetAttachment )
2024-11-13 16:58:09 +08:00
} , optSignIn )
2017-04-25 03:24:51 -04:00
2024-02-27 15:12:22 +08:00
m . Post ( "/{username}" , reqSignIn , context . UserAssignmentWeb ( ) , user . Action )
2017-04-25 03:24:51 -04:00
reqRepoAdmin := context . RequireRepoAdmin ( )
2025-01-14 09:53:34 +08:00
reqRepoCodeWriter := context . RequireUnitWriter ( unit . TypeCode )
reqRepoReleaseWriter := context . RequireUnitWriter ( unit . TypeReleases )
reqRepoReleaseReader := context . RequireUnitReader ( unit . TypeReleases )
reqRepoIssuesOrPullsWriter := context . RequireUnitWriter ( unit . TypeIssues , unit . TypePullRequests )
reqRepoIssuesOrPullsReader := context . RequireUnitReader ( unit . TypeIssues , unit . TypePullRequests )
reqRepoProjectsReader := context . RequireUnitReader ( unit . TypeProjects )
reqRepoProjectsWriter := context . RequireUnitWriter ( unit . TypeProjects )
reqRepoActionsReader := context . RequireUnitReader ( unit . TypeActions )
reqRepoActionsWriter := context . RequireUnitWriter ( unit . TypeActions )
// the legacy names "reqRepoXxx" should be renamed to the correct name "reqUnitXxx", these permissions are for units, not repos
reqUnitsWithMarkdown := context . RequireUnitReader ( unit . TypeCode , unit . TypeIssues , unit . TypePullRequests , unit . TypeReleases , unit . TypeWiki )
reqUnitCodeReader := context . RequireUnitReader ( unit . TypeCode )
reqUnitIssuesReader := context . RequireUnitReader ( unit . TypeIssues )
reqUnitPullsReader := context . RequireUnitReader ( unit . TypePullRequests )
reqUnitWikiReader := context . RequireUnitReader ( unit . TypeWiki )
reqUnitWikiWriter := context . RequireUnitWriter ( unit . TypeWiki )
2017-04-25 03:24:51 -04:00
2022-03-30 10:42:47 +02:00
reqPackageAccess := func ( accessMode perm . AccessMode ) func ( ctx * context . Context ) {
return func ( ctx * context . Context ) {
if ctx . Package . AccessMode < accessMode && ! ctx . IsUserSiteAdmin ( ) {
ctx . NotFound ( "" , nil )
}
}
}
2023-12-12 13:01:17 +08:00
individualPermsChecker := func ( ctx * context . Context ) {
// org permissions have been checked in context.OrgAssignment(), but individual permissions haven't been checked.
if ctx . ContextUser . IsIndividual ( ) {
switch {
case ctx . ContextUser . Visibility == structs . VisibleTypePrivate :
if ctx . Doer == nil || ( ctx . ContextUser . ID != ctx . Doer . ID && ! ctx . Doer . IsAdmin ) {
ctx . NotFound ( "Visit Project" , nil )
return
}
case ctx . ContextUser . Visibility == structs . VisibleTypeLimited :
if ctx . Doer == nil {
ctx . NotFound ( "Visit Project" , nil )
return
}
}
}
}
2022-07-15 22:21:54 +08:00
m . Group ( "/org" , func ( ) {
m . Group ( "/{org}" , func ( ) {
m . Get ( "/members" , org . Members )
} , context . OrgAssignment ( ) )
2024-11-13 16:58:09 +08:00
} , optSignIn )
2024-04-17 16:31:37 +08:00
// end "/org": members
2022-07-15 22:21:54 +08:00
2017-04-25 03:24:51 -04:00
m . Group ( "/org" , func ( ) {
m . Group ( "" , func ( ) {
m . Get ( "/create" , org . Create )
2022-12-12 16:09:26 +08:00
m . Post ( "/create" , web . Bind ( forms . CreateOrgForm { } ) , org . CreatePost )
2017-04-25 03:24:51 -04:00
} )
2022-10-19 14:40:28 +02:00
m . Group ( "/invite/{token}" , func ( ) {
m . Get ( "" , org . TeamInvite )
m . Post ( "" , org . TeamInvitePost )
} )
2021-01-26 23:36:53 +08:00
m . Group ( "/{org}" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Get ( "/dashboard" , user . Dashboard )
2021-01-26 23:36:53 +08:00
m . Get ( "/dashboard/{team}" , user . Dashboard )
2021-01-13 05:19:17 +01:00
m . Get ( "/issues" , user . Issues )
2021-01-26 23:36:53 +08:00
m . Get ( "/issues/{team}" , user . Issues )
2021-01-13 05:19:17 +01:00
m . Get ( "/pulls" , user . Pulls )
2021-01-26 23:36:53 +08:00
m . Get ( "/pulls/{team}" , user . Pulls )
2019-12-15 08:20:08 -06:00
m . Get ( "/milestones" , reqMilestonesDashboardPageEnabled , user . Milestones )
2021-01-26 23:36:53 +08:00
m . Get ( "/milestones/{team}" , reqMilestonesDashboardPageEnabled , user . Milestones )
m . Post ( "/members/action/{action}" , org . MembersAction )
2017-04-25 03:24:51 -04:00
m . Get ( "/teams" , org . Teams )
2020-12-27 20:58:03 +01:00
} , context . OrgAssignment ( true , false , true ) )
2017-04-25 03:24:51 -04:00
2021-01-26 23:36:53 +08:00
m . Group ( "/{org}" , func ( ) {
m . Get ( "/teams/{team}" , org . TeamMembers )
m . Get ( "/teams/{team}/repositories" , org . TeamRepositories )
m . Post ( "/teams/{team}/action/{action}" , org . TeamsAction )
m . Post ( "/teams/{team}/action/repo/{action}" , org . TeamsRepoAction )
2017-04-25 03:24:51 -04:00
} , context . OrgAssignment ( true , false , true ) )
2024-08-29 21:26:25 +08:00
// require admin permission
m . Group ( "/{org}" , func ( ) {
m . Get ( "/teams/-/search" , org . SearchTeam )
} , context . OrgAssignment ( true , false , false , true ) )
// require owner permission
2021-01-26 23:36:53 +08:00
m . Group ( "/{org}" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Get ( "/teams/new" , org . NewTeam )
2022-12-12 16:09:26 +08:00
m . Post ( "/teams/new" , web . Bind ( forms . CreateTeamForm { } ) , org . NewTeamPost )
2021-01-26 23:36:53 +08:00
m . Get ( "/teams/{team}/edit" , org . EditTeam )
2022-12-12 16:09:26 +08:00
m . Post ( "/teams/{team}/edit" , web . Bind ( forms . CreateTeamForm { } ) , org . EditTeamPost )
2021-01-26 23:36:53 +08:00
m . Post ( "/teams/{team}/delete" , org . DeleteTeam )
2017-04-25 03:24:51 -04:00
m . Group ( "/settings" , func ( ) {
m . Combo ( "" ) . Get ( org . Settings ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . UpdateOrgSettingForm { } ) , org . SettingsPost )
m . Post ( "/avatar" , web . Bind ( forms . AvatarForm { } ) , org . SettingsAvatar )
2017-04-25 03:24:51 -04:00
m . Post ( "/avatar/delete" , org . SettingsDeleteAvatar )
2022-10-09 14:07:41 +02:00
m . Group ( "/applications" , func ( ) {
m . Get ( "" , org . Applications )
2022-12-12 16:09:26 +08:00
m . Post ( "/oauth2" , web . Bind ( forms . EditOAuth2ApplicationForm { } ) , org . OAuthApplicationsPost )
2022-10-09 14:07:41 +02:00
m . Group ( "/oauth2/{id}" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Combo ( "" ) . Get ( org . OAuth2ApplicationShow ) . Post ( web . Bind ( forms . EditOAuth2ApplicationForm { } ) , org . OAuth2ApplicationEdit )
2022-10-09 14:07:41 +02:00
m . Post ( "/regenerate_secret" , org . OAuthApplicationsRegenerateSecret )
m . Post ( "/delete" , org . DeleteOAuth2Application )
} )
2024-11-12 13:33:35 -08:00
} , oauth2Enabled )
2017-04-25 03:24:51 -04:00
m . Group ( "/hooks" , func ( ) {
m . Get ( "" , org . Webhooks )
m . Post ( "/delete" , org . DeleteWebhook )
2023-03-10 15:28:32 +01:00
addWebhookAddRoutes ( )
2022-01-05 22:00:20 +01:00
m . Group ( "/{id}" , func ( ) {
2023-07-02 08:59:32 +08:00
m . Get ( "" , repo_setting . WebHooksEdit )
m . Post ( "/replay/{uuid}" , repo_setting . ReplayWebhook )
2022-01-05 22:00:20 +01:00
} )
2023-03-10 15:28:32 +01:00
addWebhookEditRoutes ( )
2023-04-28 08:08:47 +08:00
} , webhooksEnabled )
2017-04-25 03:24:51 -04:00
2020-04-01 00:14:46 -04:00
m . Group ( "/labels" , func ( ) {
m . Get ( "" , org . RetrieveLabels , org . Labels )
2022-12-12 16:09:26 +08:00
m . Post ( "/new" , web . Bind ( forms . CreateLabelForm { } ) , org . NewLabel )
m . Post ( "/edit" , web . Bind ( forms . CreateLabelForm { } ) , org . UpdateLabel )
2020-04-01 00:14:46 -04:00
m . Post ( "/delete" , org . DeleteLabel )
2022-12-12 16:09:26 +08:00
m . Post ( "/initialize" , web . Bind ( forms . InitializeLabelsForm { } ) , org . InitializeLabels )
2020-04-01 00:14:46 -04:00
} )
2023-04-28 08:08:47 +08:00
m . Group ( "/actions" , func ( ) {
m . Get ( "" , org_setting . RedirectToDefaultSetting )
addSettingsRunnersRoutes ( )
addSettingsSecretsRoutes ( )
2023-12-25 08:28:59 +01:00
addSettingsVariablesRoutes ( )
2023-01-31 09:45:19 +08:00
} , actions . MustEnableActions )
2023-07-21 06:43:49 +08:00
m . Methods ( "GET,POST" , "/delete" , org . SettingsDelete )
2022-11-20 15:08:38 +01:00
m . Group ( "/packages" , func ( ) {
m . Get ( "" , org . Packages )
m . Group ( "/rules" , func ( ) {
m . Group ( "/add" , func ( ) {
m . Get ( "" , org . PackagesRuleAdd )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . PackageCleanupRuleForm { } ) , org . PackagesRuleAddPost )
2022-11-20 15:08:38 +01:00
} )
m . Group ( "/{id}" , func ( ) {
m . Get ( "" , org . PackagesRuleEdit )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . PackageCleanupRuleForm { } ) , org . PackagesRuleEditPost )
2022-11-20 15:08:38 +01:00
m . Get ( "/preview" , org . PackagesRulePreview )
} )
} )
2023-02-05 11:12:31 +01:00
m . Group ( "/cargo" , func ( ) {
m . Post ( "/initialize" , org . InitializeCargoIndex )
m . Post ( "/rebuild" , org . RebuildCargoIndex )
} )
2022-11-20 15:08:38 +01:00
} , packagesEnabled )
2024-03-04 09:16:03 +01:00
m . Group ( "/blocked_users" , func ( ) {
m . Get ( "" , org . BlockedUsers )
m . Post ( "" , web . Bind ( forms . BlockUserForm { } ) , org . BlockedUsersPost )
} )
2024-01-28 07:36:44 -05:00
} , ctxDataSet ( "EnableOAuth2" , setting . OAuth2 . Enabled , "EnablePackages" , setting . Packages . Enabled , "PageIsOrgSettings" , true ) )
2017-04-25 03:24:51 -04:00
} , context . OrgAssignment ( true , true ) )
} , reqSignIn )
2024-04-17 16:31:37 +08:00
// end "/org": most org routes
2017-04-25 03:24:51 -04:00
m . Group ( "/repo" , func ( ) {
m . Get ( "/create" , repo . Create )
2022-12-12 16:09:26 +08:00
m . Post ( "/create" , web . Bind ( forms . CreateRepoForm { } ) , repo . CreatePost )
2017-04-25 03:24:51 -04:00
m . Get ( "/migrate" , repo . Migrate )
2022-12-12 16:09:26 +08:00
m . Post ( "/migrate" , web . Bind ( forms . MigrateRepoForm { } ) , repo . MigratePost )
2022-04-08 02:59:56 +08:00
m . Get ( "/search" , repo . SearchRepo )
2017-04-25 03:24:51 -04:00
} , reqSignIn )
2024-04-17 16:31:37 +08:00
// end "/repo": create, migrate, search
2017-04-25 03:24:51 -04:00
2022-03-30 10:42:47 +02:00
m . Group ( "/{username}/-" , func ( ) {
2022-04-01 01:31:53 +08:00
if setting . Packages . Enabled {
m . Group ( "/packages" , func ( ) {
m . Get ( "" , user . ListPackages )
m . Group ( "/{type}/{name}" , func ( ) {
m . Get ( "" , user . RedirectToLastVersion )
m . Get ( "/versions" , user . ListPackageVersions )
m . Group ( "/{version}" , func ( ) {
m . Get ( "" , user . ViewPackageVersion )
m . Get ( "/files/{fileid}" , user . DownloadPackageFile )
m . Group ( "/settings" , func ( ) {
m . Get ( "" , user . PackageSettings )
2022-12-12 16:09:26 +08:00
m . Post ( "" , web . Bind ( forms . PackageSettingForm { } ) , user . PackageSettingsPost )
2022-04-01 01:31:53 +08:00
} , reqPackageAccess ( perm . AccessModeWrite ) )
} )
2022-03-30 10:42:47 +02:00
} )
2023-05-04 20:07:15 +08:00
} , context . PackageAssignment ( ) , reqPackageAccess ( perm . AccessModeRead ) )
2022-04-01 01:31:53 +08:00
}
2023-01-20 19:42:33 +08:00
2024-08-27 10:54:12 +08:00
m . Get ( "/repositories" , org . Repositories )
2023-01-20 19:42:33 +08:00
m . Group ( "/projects" , func ( ) {
2023-03-11 00:18:20 +09:00
m . Group ( "" , func ( ) {
m . Get ( "" , org . Projects )
m . Get ( "/{id}" , org . ViewProject )
2023-07-29 22:13:24 +08:00
} , reqUnitAccess ( unit . TypeProjects , perm . AccessModeRead , true ) )
2023-01-20 19:42:33 +08:00
m . Group ( "" , func ( ) { //nolint:dupl
2023-05-31 08:50:18 +02:00
m . Get ( "/new" , org . RenderNewProject )
2023-01-20 19:42:33 +08:00
m . Post ( "/new" , web . Bind ( forms . CreateProjectForm { } ) , org . NewProjectPost )
m . Group ( "/{id}" , func ( ) {
m . Post ( "/delete" , org . DeleteProject )
2023-05-31 08:50:18 +02:00
m . Get ( "/edit" , org . RenderEditProject )
2023-01-20 19:42:33 +08:00
m . Post ( "/edit" , web . Bind ( forms . CreateProjectForm { } ) , org . EditProjectPost )
m . Post ( "/{action:open|close}" , org . ChangeProjectStatus )
2024-12-19 09:37:12 +01:00
// TODO: improper name. Others are "delete project", "edit project", but this one is "move columns"
m . Post ( "/move" , project . MoveColumns )
m . Post ( "/columns/new" , web . Bind ( forms . EditProjectColumnForm { } ) , org . AddColumnToProjectPost )
2024-05-27 16:59:54 +08:00
m . Group ( "/{columnID}" , func ( ) {
m . Put ( "" , web . Bind ( forms . EditProjectColumnForm { } ) , org . EditProjectColumn )
m . Delete ( "" , org . DeleteProjectColumn )
m . Post ( "/default" , org . SetDefaultProjectColumn )
2023-01-20 19:42:33 +08:00
m . Post ( "/move" , org . MoveIssues )
} )
} )
2023-07-29 22:13:24 +08:00
} , reqSignIn , reqUnitAccess ( unit . TypeProjects , perm . AccessModeWrite , true ) , func ( ctx * context . Context ) {
2023-03-11 00:18:20 +09:00
if ctx . ContextUser . IsIndividual ( ) && ctx . ContextUser . ID != ctx . Doer . ID {
2023-01-20 19:42:33 +08:00
ctx . NotFound ( "NewProject" , nil )
return
}
} )
2023-12-12 13:01:17 +08:00
} , reqUnitAccess ( unit . TypeProjects , perm . AccessModeRead , true ) , individualPermsChecker )
2023-01-20 19:42:33 +08:00
2023-03-11 00:18:20 +09:00
m . Group ( "" , func ( ) {
m . Get ( "/code" , user . CodeSearch )
2023-12-12 13:01:17 +08:00
} , reqUnitAccess ( unit . TypeCode , perm . AccessModeRead , false ) , individualPermsChecker )
2024-11-13 16:58:09 +08:00
} , optSignIn , context . UserAssignmentWeb ( ) , context . OrgAssignment ( ) )
2024-04-17 16:31:37 +08:00
// end "/{username}/-": packages, projects, code
2022-03-30 10:42:47 +02:00
2024-10-02 12:37:16 +08:00
m . Group ( "/{username}/{reponame}/-" , func ( ) {
m . Group ( "/migrate" , func ( ) {
m . Get ( "/status" , repo . MigrateStatus )
} )
2025-01-14 09:53:34 +08:00
} , optSignIn , context . RepoAssignment , reqUnitCodeReader )
2024-10-02 12:37:16 +08:00
// end "/{username}/{reponame}/-": migrate
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}/settings" , func ( ) {
m . Group ( "" , func ( ) {
m . Combo ( "" ) . Get ( repo_setting . Settings ) .
Post ( web . Bind ( forms . RepoSettingForm { } ) , repo_setting . SettingsPost )
} , repo_setting . SettingsCtxData )
m . Post ( "/avatar" , web . Bind ( forms . AvatarForm { } ) , repo_setting . SettingsAvatar )
m . Post ( "/avatar/delete" , repo_setting . SettingsDeleteAvatar )
m . Group ( "/collaboration" , func ( ) {
m . Combo ( "" ) . Get ( repo_setting . Collaboration ) . Post ( repo_setting . CollaborationPost )
m . Post ( "/access_mode" , repo_setting . ChangeCollaborationAccessMode )
m . Post ( "/delete" , repo_setting . DeleteCollaboration )
m . Group ( "/team" , func ( ) {
m . Post ( "" , repo_setting . AddTeamPost )
m . Post ( "/delete" , repo_setting . DeleteTeam )
2017-04-25 03:24:51 -04:00
} )
2024-04-17 16:31:37 +08:00
} )
2021-06-25 16:28:55 +02:00
2024-04-17 16:31:37 +08:00
m . Group ( "/branches" , func ( ) {
m . Post ( "/" , repo_setting . SetDefaultBranchPost )
} , repo . MustBeNotEmpty )
2021-06-25 16:28:55 +02:00
2024-04-17 16:31:37 +08:00
m . Group ( "/branches" , func ( ) {
m . Get ( "/" , repo_setting . ProtectedBranchRules )
m . Combo ( "/edit" ) . Get ( repo_setting . SettingsProtectedBranch ) .
Post ( web . Bind ( forms . ProtectBranchForm { } ) , context . RepoMustNotBeArchived ( ) , repo_setting . SettingsProtectedBranchPost )
m . Post ( "/{id}/delete" , repo_setting . DeleteProtectedBranchRulePost )
2024-11-27 05:41:06 +01:00
m . Post ( "/priority" , web . Bind ( forms . ProtectBranchPriorityForm { } ) , context . RepoMustNotBeArchived ( ) , repo_setting . UpdateBranchProtectionPriories )
2024-09-24 10:06:28 +08:00
} )
2021-02-11 18:34:34 +01:00
2024-04-17 16:31:37 +08:00
m . Group ( "/tags" , func ( ) {
m . Get ( "" , repo_setting . ProtectedTags )
m . Post ( "" , web . Bind ( forms . ProtectTagForm { } ) , context . RepoMustNotBeArchived ( ) , repo_setting . NewProtectedTagPost )
m . Post ( "/delete" , context . RepoMustNotBeArchived ( ) , repo_setting . DeleteProtectedTagPost )
m . Get ( "/{id}" , repo_setting . EditProtectedTag )
m . Post ( "/{id}" , web . Bind ( forms . ProtectTagForm { } ) , context . RepoMustNotBeArchived ( ) , repo_setting . EditProtectedTagPost )
} )
2023-02-01 13:53:04 +01:00
2024-04-17 16:31:37 +08:00
m . Group ( "/hooks/git" , func ( ) {
m . Get ( "" , repo_setting . GitHooks )
m . Combo ( "/{name}" ) . Get ( repo_setting . GitHooksEdit ) .
Post ( repo_setting . GitHooksEditPost )
} , context . GitHookService ( ) )
m . Group ( "/hooks" , func ( ) {
m . Get ( "" , repo_setting . Webhooks )
m . Post ( "/delete" , repo_setting . DeleteWebhook )
addWebhookAddRoutes ( )
m . Group ( "/{id}" , func ( ) {
m . Get ( "" , repo_setting . WebHooksEdit )
m . Post ( "/test" , repo_setting . TestWebhook )
m . Post ( "/replay/{uuid}" , repo_setting . ReplayWebhook )
2019-10-28 18:31:55 +00:00
} )
2024-04-17 16:31:37 +08:00
addWebhookEditRoutes ( )
} , webhooksEnabled )
m . Group ( "/keys" , func ( ) {
m . Combo ( "" ) . Get ( repo_setting . DeployKeys ) .
Post ( web . Bind ( forms . AddKeyForm { } ) , repo_setting . DeployKeysPost )
m . Post ( "/delete" , repo_setting . DeleteDeployKey )
} )
m . Group ( "/lfs" , func ( ) {
m . Get ( "/" , repo_setting . LFSFiles )
m . Get ( "/show/{oid}" , repo_setting . LFSFileGet )
m . Post ( "/delete/{oid}" , repo_setting . LFSDelete )
m . Get ( "/pointers" , repo_setting . LFSPointerFiles )
m . Post ( "/pointers/associate" , repo_setting . LFSAutoAssociate )
m . Get ( "/find" , repo_setting . LFSFileFind )
m . Group ( "/locks" , func ( ) {
m . Get ( "/" , repo_setting . LFSLocks )
m . Post ( "/" , repo_setting . LFSLockFile )
m . Post ( "/{lid}/unlock" , repo_setting . LFSUnlock )
2023-08-04 10:21:32 +08:00
} )
2024-04-17 16:31:37 +08:00
} )
m . Group ( "/actions" , func ( ) {
m . Get ( "" , repo_setting . RedirectToDefaultSetting )
addSettingsRunnersRoutes ( )
addSettingsSecretsRoutes ( )
addSettingsVariablesRoutes ( )
} , actions . MustEnableActions )
// the follow handler must be under "settings", otherwise this incomplete repo can't be accessed
m . Group ( "/migrate" , func ( ) {
m . Post ( "/retry" , repo . MigrateRetryPost )
m . Post ( "/cancel" , repo . MigrateCancelPost )
} )
} ,
2025-01-20 15:43:49 +08:00
reqSignIn , context . RepoAssignment , reqRepoAdmin ,
2024-04-17 16:31:37 +08:00
ctxDataSet ( "PageIsRepoSettings" , true , "LFSStartServer" , setting . LFS . StartServer ) ,
)
// end "/{username}/{reponame}/settings"
2017-04-25 03:24:51 -04:00
2025-01-25 22:36:47 +08:00
// user/org home, including rss feeds like "/{username}/{reponame}.rss"
2025-01-13 23:35:34 -08:00
m . Get ( "/{username}/{reponame}" , optSignIn , context . RepoAssignment , context . RepoRefByType ( git . RefTypeBranch ) , repo . SetEditorconfigIfExists , repo . Home )
2017-05-18 22:54:24 +08:00
2025-01-14 09:53:34 +08:00
m . Post ( "/{username}/{reponame}/markup" , optSignIn , context . RepoAssignment , reqUnitsWithMarkdown , web . Bind ( structs . MarkupOption { } ) , misc . Markup )
2024-05-30 00:28:55 +08:00
2021-01-26 23:36:53 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
2022-06-09 19:15:08 +08:00
m . Get ( "/find/*" , repo . FindFiles )
m . Group ( "/tree-list" , func ( ) {
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . TreeList )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . TreeList )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . TreeList )
2022-06-09 19:15:08 +08:00
} )
2024-04-17 16:31:37 +08:00
m . Get ( "/compare" , repo . MustBeNotEmpty , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . CompareDiff )
m . Combo ( "/compare/*" , repo . MustBeNotEmpty , repo . SetEditorconfigIfExists ) .
2023-05-04 20:07:15 +08:00
Get ( repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . CompareDiff ) .
2025-01-14 09:53:34 +08:00
Post ( reqSignIn , context . RepoMustNotBeArchived ( ) , reqUnitPullsReader , repo . MustAllowPulls , web . Bind ( forms . CreateIssueForm { } ) , repo . SetWhitespaceBehavior , repo . CompareAndPullRequestPost )
} , optSignIn , context . RepoAssignment , reqUnitCodeReader )
2024-12-25 00:51:13 +08:00
// end "/{username}/{reponame}": repo code: find, compare, list
2024-04-17 16:31:37 +08:00
2025-01-14 09:53:34 +08:00
addIssuesPullsViewRoutes := func ( ) {
// for /{username}/{reponame}/issues" or "/{username}/{reponame}/pulls"
m . Get ( "/posters" , repo . IssuePullPosters )
m . Group ( "/{index}" , func ( ) {
m . Get ( "/info" , repo . GetIssueInfo )
m . Get ( "/attachments" , repo . GetIssueAttachments )
m . Get ( "/attachments/{uuid}" , repo . GetAttachment )
m . Group ( "/content-history" , func ( ) {
m . Get ( "/overview" , repo . GetContentHistoryOverview )
m . Get ( "/list" , repo . GetContentHistoryList )
m . Get ( "/detail" , repo . GetContentHistoryDetail )
} )
} )
}
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
m . Get ( "/comments/{id}/attachments" , repo . GetCommentAttachments )
2024-11-10 16:26:42 +08:00
m . Get ( "/labels" , repo . RetrieveLabelsForList , repo . Labels )
2024-04-17 16:31:37 +08:00
m . Get ( "/milestones" , repo . Milestones )
m . Get ( "/milestone/{id}" , context . RepoRef ( ) , repo . MilestoneIssuesAndPulls )
2024-10-29 10:20:49 +01:00
m . Get ( "/issues/suggestions" , repo . IssueSuggestions )
2025-01-14 09:53:34 +08:00
} , optSignIn , context . RepoAssignment , reqRepoIssuesOrPullsReader ) // issue/pull attachments, labels, milestones
m . Group ( "/{username}/{reponame}/{type:issues}" , addIssuesPullsViewRoutes , optSignIn , context . RepoAssignment , reqUnitIssuesReader )
m . Group ( "/{username}/{reponame}/{type:pulls}" , addIssuesPullsViewRoutes , optSignIn , context . RepoAssignment , reqUnitPullsReader )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": view milestone, label, issue, pull, etc
2020-05-03 04:07:04 -05:00
2025-01-14 09:53:34 +08:00
m . Group ( "/{username}/{reponame}/{type:issues}" , func ( ) {
m . Get ( "" , repo . Issues )
m . Get ( "/{index}" , repo . ViewIssue )
} , optSignIn , context . RepoAssignment , context . RequireUnitReader ( unit . TypeIssues , unit . TypeExternalTracker ) )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": issue/pull list, issue/pull view, external tracker
m . Group ( "/{username}/{reponame}" , func ( ) { // edit issues, pulls, labels, milestones, etc
2017-04-25 03:24:51 -04:00
m . Group ( "/issues" , func ( ) {
2020-09-11 09:48:39 -05:00
m . Group ( "/new" , func ( ) {
m . Combo ( "" ) . Get ( context . RepoRef ( ) , repo . NewIssue ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . CreateIssueForm { } ) , repo . NewIssuePost )
2020-09-11 09:48:39 -05:00
m . Get ( "/choose" , context . RepoRef ( ) , repo . NewIssueChooseTemplate )
} )
2024-12-11 14:33:24 +08:00
m . Get ( "/search" , repo . SearchRepoIssuesJSON )
2025-01-14 09:53:34 +08:00
} , reqUnitIssuesReader )
2024-04-17 16:31:37 +08:00
2025-01-14 09:53:34 +08:00
addIssuesPullsRoutes := func ( ) {
// for "/{username}/{reponame}/issues" or "/{username}/{reponame}/pulls"
2021-01-26 23:36:53 +08:00
m . Group ( "/{index}" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Post ( "/title" , repo . UpdateIssueTitle )
m . Post ( "/content" , repo . UpdateIssueContent )
2024-11-04 23:46:40 -08:00
m . Post ( "/deadline" , repo . UpdateIssueDeadline )
2017-04-25 03:24:51 -04:00
m . Post ( "/watch" , repo . IssueWatch )
2020-09-08 18:29:51 +02:00
m . Post ( "/ref" , repo . UpdateIssueRef )
2023-05-25 15:17:19 +02:00
m . Post ( "/pin" , reqRepoAdmin , repo . IssuePinOrUnpin )
2022-05-07 20:28:10 +02:00
m . Post ( "/viewed-files" , repo . UpdateViewedFiles )
2018-07-17 23:23:58 +02:00
m . Group ( "/dependency" , func ( ) {
m . Post ( "/add" , repo . AddDependency )
m . Post ( "/delete" , repo . RemoveDependency )
} )
2022-12-12 16:09:26 +08:00
m . Combo ( "/comments" ) . Post ( repo . MustAllowUserComment , web . Bind ( forms . CreateCommentForm { } ) , repo . NewComment )
2017-09-12 08:48:13 +02:00
m . Group ( "/times" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Post ( "/add" , web . Bind ( forms . AddTimeManuallyForm { } ) , repo . AddTimeManually )
2021-02-19 10:52:11 +00:00
m . Post ( "/{timeid}/delete" , repo . DeleteTime )
2017-09-12 08:48:13 +02:00
m . Group ( "/stopwatch" , func ( ) {
m . Post ( "/toggle" , repo . IssueStopwatch )
m . Post ( "/cancel" , repo . CancelStopwatch )
} )
} )
2024-12-05 15:07:53 +02:00
m . Post ( "/time_estimate" , repo . UpdateIssueTimeEstimate )
2022-12-12 16:09:26 +08:00
m . Post ( "/reactions/{action}" , web . Bind ( forms . ReactionForm { } ) , repo . ChangeIssueReaction )
2022-12-12 23:02:51 +08:00
m . Post ( "/lock" , reqRepoIssuesOrPullsWriter , web . Bind ( forms . IssueLockForm { } ) , repo . LockIssue )
m . Post ( "/unlock" , reqRepoIssuesOrPullsWriter , repo . UnlockIssue )
2022-03-09 01:38:11 +01:00
m . Post ( "/delete" , reqRepoAdmin , repo . DeleteIssue )
2021-10-11 06:40:03 +08:00
m . Post ( "/content-history/soft-delete" , repo . SoftDeleteContentHistory )
} )
2017-04-25 03:24:51 -04:00
2025-01-14 09:53:34 +08:00
m . Post ( "/attachments" , repo . UploadIssueAttachment )
m . Post ( "/attachments/remove" , repo . DeleteAttachment )
2025-01-15 03:03:02 +08:00
m . Post ( "/labels" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueLabel )
m . Post ( "/milestone" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueMilestone )
2022-06-30 23:55:08 +08:00
m . Post ( "/projects" , reqRepoIssuesOrPullsWriter , reqRepoProjectsReader , repo . UpdateIssueProject )
2018-11-28 19:26:14 +08:00
m . Post ( "/assignee" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueAssignee )
m . Post ( "/status" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueStatus )
2023-06-19 15:46:50 +08:00
m . Post ( "/delete" , reqRepoAdmin , repo . BatchDeleteIssues )
2023-05-30 17:26:51 +02:00
m . Delete ( "/unpin/{index}" , reqRepoAdmin , repo . IssueUnpin )
m . Post ( "/move_pin" , reqRepoAdmin , repo . IssuePinMove )
2025-01-14 09:53:34 +08:00
}
m . Group ( "/{type:issues}" , addIssuesPullsRoutes , reqUnitIssuesReader , context . RepoMustNotBeArchived ( ) )
m . Group ( "/{type:pulls}" , addIssuesPullsRoutes , reqUnitPullsReader , context . RepoMustNotBeArchived ( ) )
2024-04-17 16:31:37 +08:00
2021-01-26 23:36:53 +08:00
m . Group ( "/comments/{id}" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Post ( "" , repo . UpdateCommentContent )
m . Post ( "/delete" , repo . DeleteComment )
2022-12-12 16:09:26 +08:00
m . Post ( "/reactions/{action}" , web . Bind ( forms . ReactionForm { } ) , repo . ChangeCommentReaction )
2025-01-14 09:53:34 +08:00
} , reqRepoIssuesOrPullsReader ) // edit issue/pull comment
2024-04-17 16:31:37 +08:00
2017-04-25 03:24:51 -04:00
m . Group ( "/labels" , func ( ) {
2022-12-12 16:09:26 +08:00
m . Post ( "/new" , web . Bind ( forms . CreateLabelForm { } ) , repo . NewLabel )
m . Post ( "/edit" , web . Bind ( forms . CreateLabelForm { } ) , repo . UpdateLabel )
2017-04-25 03:24:51 -04:00
m . Post ( "/delete" , repo . DeleteLabel )
2022-12-12 16:09:26 +08:00
m . Post ( "/initialize" , web . Bind ( forms . InitializeLabelsForm { } ) , repo . InitializeLabels )
2025-01-14 09:53:34 +08:00
} , reqRepoIssuesOrPullsWriter , context . RepoRef ( ) )
2017-04-25 03:24:51 -04:00
m . Group ( "/milestones" , func ( ) {
m . Combo ( "/new" ) . Get ( repo . NewMilestone ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . CreateMilestoneForm { } ) , repo . NewMilestonePost )
2021-01-26 23:36:53 +08:00
m . Get ( "/{id}/edit" , repo . EditMilestone )
2022-12-12 16:09:26 +08:00
m . Post ( "/{id}/edit" , web . Bind ( forms . CreateMilestoneForm { } ) , repo . EditMilestonePost )
2021-01-26 23:36:53 +08:00
m . Post ( "/{id}/{action}" , repo . ChangeMilestoneStatus )
2017-04-25 03:24:51 -04:00
m . Post ( "/delete" , repo . DeleteMilestone )
2025-01-14 09:53:34 +08:00
} , reqRepoIssuesOrPullsWriter , context . RepoRef ( ) )
2025-01-15 03:03:02 +08:00
// FIXME: need to move these routes to the proper place
m . Group ( "/issues" , func ( ) {
2025-01-14 09:53:34 +08:00
m . Post ( "/request_review" , repo . UpdatePullReviewRequest )
m . Post ( "/dismiss_review" , reqRepoAdmin , web . Bind ( forms . DismissReviewForm { } ) , repo . DismissReview )
m . Post ( "/resolve_conversation" , repo . SetShowOutdatedComments , repo . UpdateResolveConversation )
} , reqUnitPullsReader )
2025-01-15 03:03:02 +08:00
m . Post ( "/pull/{index}/target_branch" , reqUnitPullsReader , repo . UpdatePullRequestTarget )
2025-01-14 09:53:34 +08:00
} , reqSignIn , context . RepoAssignment , context . RepoMustNotBeArchived ( ) )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": create or edit issues, pulls, labels, milestones
2017-04-25 03:24:51 -04:00
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) { // repo code
2017-04-25 03:24:51 -04:00
m . Group ( "" , func ( ) {
m . Group ( "" , func ( ) {
2025-01-31 10:36:18 +08:00
m . Post ( "/_preview/*" , web . Bind ( forms . EditPreviewDiffForm { } ) , repo . DiffPreviewPost )
2017-10-29 19:04:25 -07:00
m . Combo ( "/_edit/*" ) . Get ( repo . EditFile ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . EditRepoFileForm { } ) , repo . EditFilePost )
2017-10-29 19:04:25 -07:00
m . Combo ( "/_new/*" ) . Get ( repo . NewFile ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . EditRepoFileForm { } ) , repo . NewFilePost )
2017-10-29 19:04:25 -07:00
m . Combo ( "/_delete/*" ) . Get ( repo . DeleteFile ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . DeleteRepoFileForm { } ) , repo . DeleteFilePost )
2025-01-31 10:36:18 +08:00
m . Combo ( "/_upload/*" , repo . MustBeAbleToUpload ) . Get ( repo . UploadFile ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . UploadRepoFileForm { } ) , repo . UploadFilePost )
2022-02-09 20:28:55 +00:00
m . Combo ( "/_diffpatch/*" ) . Get ( repo . NewDiffPatch ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . EditRepoFileForm { } ) , repo . NewDiffPatchPost )
2024-01-19 16:05:02 +00:00
m . Combo ( "/_cherrypick/{sha:([a-f0-9]{7,64})}/*" ) . Get ( repo . CherryPick ) .
2022-12-12 16:09:26 +08:00
Post ( web . Bind ( forms . CherryPickForm { } ) , repo . CherryPickPost )
2025-01-31 10:36:18 +08:00
} , context . RepoRefByType ( git . RefTypeBranch ) , context . CanWriteToBranch ( ) , repo . WebGitOperationCommonData )
2017-10-29 19:04:25 -07:00
m . Group ( "" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Post ( "/upload-file" , repo . UploadFileToServer )
2022-12-12 16:09:26 +08:00
m . Post ( "/upload-remove" , web . Bind ( forms . RemoveUploadFileForm { } ) , repo . RemoveUploadFileFromServer )
2025-01-13 23:35:34 -08:00
} , repo . MustBeAbleToUpload , reqRepoCodeWriter )
} , repo . MustBeEditable , context . RepoMustNotBeArchived ( ) )
2017-10-15 22:59:24 +03:00
m . Group ( "/branches" , func ( ) {
2021-01-26 23:36:53 +08:00
m . Group ( "/_new" , func ( ) {
2025-01-13 23:35:34 -08:00
m . Post ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . CreateBranch )
m . Post ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . CreateBranch )
m . Post ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . CreateBranch )
2022-12-12 16:09:26 +08:00
} , web . Bind ( forms . NewBranchForm { } ) )
2017-10-26 02:49:16 +02:00
m . Post ( "/delete" , repo . DeleteBranchPost )
m . Post ( "/restore" , repo . RestoreBranchPost )
2024-09-23 02:08:27 +08:00
m . Post ( "/rename" , web . Bind ( forms . RenameBranchForm { } ) , repo_setting . RenameBranchPost )
2024-12-07 05:10:35 +08:00
m . Post ( "/merge-upstream" , repo . MergeUpstream )
2019-01-23 19:58:38 +01:00
} , context . RepoMustNotBeArchived ( ) , reqRepoCodeWriter , repo . MustBeNotEmpty )
2024-03-01 20:52:30 +08:00
2024-04-17 16:31:37 +08:00
m . Combo ( "/fork" ) . Get ( repo . Fork ) . Post ( web . Bind ( forms . CreateRepoForm { } ) , repo . ForkPost )
2025-01-14 09:53:34 +08:00
} , reqSignIn , context . RepoAssignment , reqUnitCodeReader )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": repo code
2017-05-18 22:54:24 +08:00
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) { // repo tags
2022-12-22 04:06:26 +07:00
m . Group ( "/tags" , func ( ) {
2025-01-16 21:52:21 +08:00
m . Get ( "" , context . RepoRefByDefaultBranch ( ) /* for the "commits" tab */ , repo . TagsList )
2022-12-22 04:06:26 +07:00
m . Get ( ".rss" , feedEnabled , repo . TagsListFeedRSS )
m . Get ( ".atom" , feedEnabled , repo . TagsListFeedAtom )
2025-01-13 23:35:34 -08:00
m . Get ( "/list" , repo . GetTagList )
} , ctxDataSet ( "EnableFeed" , setting . Other . EnableFeed ) )
m . Post ( "/tags/delete" , reqSignIn , reqRepoCodeWriter , context . RepoMustNotBeArchived ( ) , repo . DeleteTag )
} , optSignIn , context . RepoAssignment , repo . MustBeNotEmpty , reqUnitCodeReader )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": repo tags
2023-04-26 00:29:00 +08:00
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) { // repo releases
2017-05-18 22:54:24 +08:00
m . Group ( "/releases" , func ( ) {
2024-04-17 16:31:37 +08:00
m . Get ( "" , repo . Releases )
2022-12-22 04:06:26 +07:00
m . Get ( ".rss" , feedEnabled , repo . ReleasesFeedRSS )
m . Get ( ".atom" , feedEnabled , repo . ReleasesFeedAtom )
2025-01-13 23:35:34 -08:00
m . Get ( "/tag/*" , repo . SingleRelease )
m . Get ( "/latest" , repo . LatestRelease )
} , ctxDataSet ( "EnableFeed" , setting . Other . EnableFeed ) )
m . Get ( "/releases/attachments/{uuid}" , repo . GetAttachment )
m . Get ( "/releases/download/{vTag}/{fileName}" , repo . RedirectDownload )
2017-06-17 23:38:24 -04:00
m . Group ( "/releases" , func ( ) {
2017-05-18 22:54:24 +08:00
m . Get ( "/new" , repo . NewRelease )
2022-12-12 16:09:26 +08:00
m . Post ( "/new" , web . Bind ( forms . NewReleaseForm { } ) , repo . NewReleasePost )
2017-05-18 22:54:24 +08:00
m . Post ( "/delete" , repo . DeleteRelease )
2020-10-05 07:49:33 +02:00
m . Post ( "/attachments" , repo . UploadReleaseAttachment )
m . Post ( "/attachments/remove" , repo . DeleteAttachment )
2025-01-13 23:35:34 -08:00
} , reqSignIn , context . RepoMustNotBeArchived ( ) , reqRepoReleaseWriter , context . RepoRef ( ) )
2017-05-18 22:54:24 +08:00
m . Group ( "/releases" , func ( ) {
m . Get ( "/edit/*" , repo . EditRelease )
2022-12-12 16:09:26 +08:00
m . Post ( "/edit/*" , web . Bind ( forms . EditReleaseForm { } ) , repo . EditReleasePost )
2025-01-13 23:35:34 -08:00
} , reqSignIn , context . RepoMustNotBeArchived ( ) , reqRepoReleaseWriter , repo . CommitInfoCache )
} , optSignIn , context . RepoAssignment , repo . MustBeNotEmpty , reqRepoReleaseReader )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": repo releases
2017-04-25 03:24:51 -04:00
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) { // to maintain compatibility with old attachments
2021-07-24 02:08:04 +08:00
m . Get ( "/attachments/{uuid}" , repo . GetAttachment )
2024-11-13 16:58:09 +08:00
} , optSignIn , context . RepoAssignment )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": compatibility with old attachments
2021-07-24 02:08:04 +08:00
2021-01-26 23:36:53 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
2018-06-21 12:09:46 +03:00
m . Post ( "/topics" , repo . TopicsPost )
2024-04-17 16:31:37 +08:00
} , context . RepoAssignment , reqRepoAdmin , context . RepoMustNotBeArchived ( ) )
2018-04-11 10:51:44 +08:00
2021-01-26 23:36:53 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
2022-04-01 01:31:53 +08:00
if setting . Packages . Enabled {
m . Get ( "/packages" , repo . Packages )
}
2024-11-13 16:58:09 +08:00
} , optSignIn , context . RepoAssignment )
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}/projects" , func ( ) {
m . Get ( "" , repo . Projects )
m . Get ( "/{id}" , repo . ViewProject )
m . Group ( "" , func ( ) { //nolint:dupl
m . Get ( "/new" , repo . RenderNewProject )
m . Post ( "/new" , web . Bind ( forms . CreateProjectForm { } ) , repo . NewProjectPost )
m . Group ( "/{id}" , func ( ) {
m . Post ( "/delete" , repo . DeleteProject )
m . Get ( "/edit" , repo . RenderEditProject )
m . Post ( "/edit" , web . Bind ( forms . CreateProjectForm { } ) , repo . EditProjectPost )
m . Post ( "/{action:open|close}" , repo . ChangeProjectStatus )
2024-12-19 09:37:12 +01:00
// TODO: improper name. Others are "delete project", "edit project", but this one is "move columns"
m . Post ( "/move" , project . MoveColumns )
m . Post ( "/columns/new" , web . Bind ( forms . EditProjectColumnForm { } ) , repo . AddColumnToProjectPost )
2024-05-27 16:59:54 +08:00
m . Group ( "/{columnID}" , func ( ) {
m . Put ( "" , web . Bind ( forms . EditProjectColumnForm { } ) , repo . EditProjectColumn )
m . Delete ( "" , repo . DeleteProjectColumn )
m . Post ( "/default" , repo . SetDefaultProjectColumn )
2024-04-17 16:31:37 +08:00
m . Post ( "/move" , repo . MoveIssues )
2020-08-17 04:07:38 +01:00
} )
2024-04-17 16:31:37 +08:00
} )
} , reqRepoProjectsWriter , context . RepoMustNotBeArchived ( ) )
2024-11-13 16:58:09 +08:00
} , optSignIn , context . RepoAssignment , reqRepoProjectsReader , repo . MustEnableRepoProjects )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}/projects"
m . Group ( "/{username}/{reponame}/actions" , func ( ) {
m . Get ( "" , actions . List )
m . Post ( "/disable" , reqRepoAdmin , actions . DisableWorkflowFile )
m . Post ( "/enable" , reqRepoAdmin , actions . EnableWorkflowFile )
2024-11-28 04:18:23 -03:00
m . Post ( "/run" , reqRepoActionsWriter , actions . Run )
2025-01-05 14:47:18 +01:00
m . Get ( "/workflow-dispatch-inputs" , reqRepoActionsWriter , actions . WorkflowDispatchInputs )
2024-04-17 16:31:37 +08:00
m . Group ( "/runs/{run}" , func ( ) {
m . Combo ( "" ) .
Get ( actions . View ) .
Post ( web . Bind ( actions . ViewRequest { } ) , actions . ViewPost )
m . Group ( "/jobs/{job}" , func ( ) {
2023-01-31 09:45:19 +08:00
m . Combo ( "" ) .
Get ( actions . View ) .
Post ( web . Bind ( actions . ViewRequest { } ) , actions . ViewPost )
2023-08-22 11:30:02 +09:00
m . Post ( "/rerun" , reqRepoActionsWriter , actions . Rerun )
2024-04-17 16:31:37 +08:00
m . Get ( "/logs" , actions . Logs )
2023-01-31 09:45:19 +08:00
} )
2024-04-17 16:31:37 +08:00
m . Post ( "/cancel" , reqRepoActionsWriter , actions . Cancel )
m . Post ( "/approve" , reqRepoActionsWriter , actions . Approve )
m . Get ( "/artifacts/{artifact_name}" , actions . ArtifactsDownloadView )
m . Delete ( "/artifacts/{artifact_name}" , actions . ArtifactsDeleteView )
m . Post ( "/rerun" , reqRepoActionsWriter , actions . Rerun )
2020-05-16 12:38:40 -04:00
} )
2024-04-17 16:31:37 +08:00
m . Group ( "/workflows/{workflow_name}" , func ( ) {
m . Get ( "/badge.svg" , actions . GetWorkflowBadge )
} )
2025-01-05 14:47:18 +01:00
} , optSignIn , context . RepoAssignment , repo . MustBeNotEmpty , reqRepoActionsReader , actions . MustEnableActions )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}/actions"
m . Group ( "/{username}/{reponame}/wiki" , func ( ) {
m . Combo ( "" ) .
Get ( repo . Wiki ) .
2025-01-14 09:53:34 +08:00
Post ( context . RepoMustNotBeArchived ( ) , reqSignIn , reqUnitWikiWriter , web . Bind ( forms . NewWikiForm { } ) , repo . WikiPost )
2024-04-17 16:31:37 +08:00
m . Combo ( "/*" ) .
Get ( repo . Wiki ) .
2025-01-14 09:53:34 +08:00
Post ( context . RepoMustNotBeArchived ( ) , reqSignIn , reqUnitWikiWriter , web . Bind ( forms . NewWikiForm { } ) , repo . WikiPost )
2024-12-25 00:51:13 +08:00
m . Get ( "/blob_excerpt/{sha}" , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . ExcerptBlob )
2024-04-17 16:31:37 +08:00
m . Get ( "/commit/{sha:[a-f0-9]{7,64}}" , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . Diff )
m . Get ( "/commit/{sha:[a-f0-9]{7,64}}.{ext:patch|diff}" , repo . RawDiff )
m . Get ( "/raw/*" , repo . WikiRaw )
2025-01-14 09:53:34 +08:00
} , optSignIn , context . RepoAssignment , repo . MustEnableWiki , reqUnitWikiReader , func ( ctx * context . Context ) {
2024-04-17 16:31:37 +08:00
ctx . Data [ "PageIsWiki" ] = true
2025-01-07 13:17:44 +08:00
ctx . Data [ "CloneButtonOriginLink" ] = ctx . Repo . Repository . WikiCloneLink ( ctx , ctx . Doer )
2024-04-17 16:31:37 +08:00
} )
// end "/{username}/{reponame}/wiki"
m . Group ( "/{username}/{reponame}/activity" , func ( ) {
2025-01-14 09:53:34 +08:00
// activity has its own permission checks
2024-04-17 16:31:37 +08:00
m . Get ( "" , repo . Activity )
m . Get ( "/{period}" , repo . Activity )
2025-01-14 09:53:34 +08:00
m . Group ( "" , func ( ) {
m . Group ( "/contributors" , func ( ) {
m . Get ( "" , repo . Contributors )
m . Get ( "/data" , repo . ContributorsData )
} )
m . Group ( "/code-frequency" , func ( ) {
m . Get ( "" , repo . CodeFrequency )
m . Get ( "/data" , repo . CodeFrequencyData )
} )
m . Group ( "/recent-commits" , func ( ) {
m . Get ( "" , repo . RecentCommits )
m . Get ( "/data" , repo . RecentCommitsData )
} )
} , reqUnitCodeReader )
2024-04-17 16:31:37 +08:00
} ,
2025-01-14 09:53:34 +08:00
optSignIn , context . RepoAssignment , repo . MustBeNotEmpty ,
context . RequireUnitReader ( unit . TypeCode , unit . TypeIssues , unit . TypePullRequests , unit . TypeReleases ) ,
2024-04-17 16:31:37 +08:00
)
// end "/{username}/{reponame}/activity"
2017-04-25 03:24:51 -04:00
2024-10-15 14:47:07 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
2025-01-14 09:53:34 +08:00
m . Get ( "/{type:pulls}" , repo . Issues )
m . Group ( "/{type:pulls}/{index}" , func ( ) {
2024-10-15 14:47:07 +08:00
m . Get ( "" , repo . SetWhitespaceBehavior , repo . GetPullDiffStats , repo . ViewIssue )
m . Get ( ".diff" , repo . DownloadPullDiff )
m . Get ( ".patch" , repo . DownloadPullPatch )
m . Group ( "/commits" , func ( ) {
m . Get ( "" , context . RepoRef ( ) , repo . SetWhitespaceBehavior , repo . GetPullDiffStats , repo . ViewPullCommits )
m . Get ( "/list" , context . RepoRef ( ) , repo . GetPullCommits )
m . Get ( "/{sha:[a-f0-9]{7,40}}" , context . RepoRef ( ) , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . SetShowOutdatedComments , repo . ViewPullFilesForSingleCommit )
} )
m . Post ( "/merge" , context . RepoMustNotBeArchived ( ) , web . Bind ( forms . MergePullRequestForm { } ) , repo . MergePullRequest )
m . Post ( "/cancel_auto_merge" , context . RepoMustNotBeArchived ( ) , repo . CancelAutoMergePullRequest )
m . Post ( "/update" , repo . UpdatePullRequest )
m . Post ( "/set_allow_maintainer_edit" , web . Bind ( forms . UpdateAllowEditsForm { } ) , repo . SetAllowEdits )
m . Post ( "/cleanup" , context . RepoMustNotBeArchived ( ) , context . RepoRef ( ) , repo . CleanUpPullRequest )
m . Group ( "/files" , func ( ) {
m . Get ( "" , context . RepoRef ( ) , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . SetShowOutdatedComments , repo . ViewPullFilesForAllCommitsOfPr )
m . Get ( "/{sha:[a-f0-9]{7,40}}" , context . RepoRef ( ) , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . SetShowOutdatedComments , repo . ViewPullFilesStartingFromCommit )
m . Get ( "/{shaFrom:[a-f0-9]{7,40}}..{shaTo:[a-f0-9]{7,40}}" , context . RepoRef ( ) , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . SetShowOutdatedComments , repo . ViewPullFilesForRange )
m . Group ( "/reviews" , func ( ) {
m . Get ( "/new_comment" , repo . RenderNewCodeCommentForm )
m . Post ( "/comments" , web . Bind ( forms . CodeCommentForm { } ) , repo . SetShowOutdatedComments , repo . CreateCodeComment )
m . Post ( "/submit" , web . Bind ( forms . SubmitReviewForm { } ) , repo . SubmitReview )
} , context . RepoMustNotBeArchived ( ) )
} )
} )
2025-01-14 09:53:34 +08:00
} , optSignIn , context . RepoAssignment , repo . MustAllowPulls , reqUnitPullsReader )
2024-10-15 14:47:07 +08:00
// end "/{username}/{reponame}/pulls/{index}": repo pull request
2024-04-17 16:31:37 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
2019-05-04 15:39:03 +03:00
m . Group ( "/activity_author_data" , func ( ) {
m . Get ( "" , repo . ActivityAuthors )
2021-01-26 23:36:53 +08:00
m . Get ( "/{period}" , repo . ActivityAuthors )
2025-01-20 15:43:49 +08:00
} , repo . MustBeNotEmpty )
2019-05-04 15:39:03 +03:00
2020-11-07 14:27:28 -06:00
m . Group ( "/archive" , func ( ) {
2021-06-24 05:12:38 +08:00
m . Get ( "/*" , repo . Download )
2020-11-07 14:27:28 -06:00
m . Post ( "/*" , repo . InitiateDownload )
2024-04-17 16:31:37 +08:00
} , repo . MustBeNotEmpty , dlSourceEnabled )
2017-04-25 03:24:51 -04:00
2017-10-26 02:49:16 +02:00
m . Group ( "/branches" , func ( ) {
2023-07-22 19:47:06 +08:00
m . Get ( "/list" , repo . GetBranchesList )
2025-01-16 21:52:21 +08:00
m . Get ( "" , context . RepoRefByDefaultBranch ( ) /* for the "commits" tab */ , repo . Branches )
} , repo . MustBeNotEmpty )
2017-10-26 02:49:16 +02:00
2019-02-12 15:09:43 +00:00
m . Group ( "/media" , func ( ) {
2025-01-13 16:27:11 +08:00
m . Get ( "/blob/{sha}" , repo . DownloadByIDOrLFS )
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . SingleDownloadOrLFS )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . SingleDownloadOrLFS )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . SingleDownloadOrLFS )
m . Get ( "/*" , context . RepoRefByType ( "" ) , repo . SingleDownloadOrLFS ) // "/*" route is deprecated, and kept for backward compatibility
2024-04-17 16:31:37 +08:00
} , repo . MustBeNotEmpty )
2019-02-12 15:09:43 +00:00
2017-10-29 19:04:25 -07:00
m . Group ( "/raw" , func ( ) {
2025-01-13 16:27:11 +08:00
m . Get ( "/blob/{sha}" , repo . DownloadByID )
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . SingleDownload )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . SingleDownload )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . SingleDownload )
m . Get ( "/*" , context . RepoRefByType ( "" ) , repo . SingleDownload ) // "/*" route is deprecated, and kept for backward compatibility
2024-04-17 16:31:37 +08:00
} , repo . MustBeNotEmpty )
2017-10-29 19:04:25 -07:00
2022-06-16 11:33:23 +08:00
m . Group ( "/render" , func ( ) {
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . RenderFile )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . RenderFile )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . RenderFile )
2025-01-13 16:27:11 +08:00
m . Get ( "/blob/{sha}" , repo . RenderFile )
2024-04-17 16:31:37 +08:00
} , repo . MustBeNotEmpty )
2022-06-16 11:33:23 +08:00
2017-10-29 19:04:25 -07:00
m . Group ( "/commits" , func ( ) {
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . RefCommits )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . RefCommits )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . RefCommits )
m . Get ( "/*" , context . RepoRefByType ( "" ) , repo . RefCommits ) // "/*" route is deprecated, and kept for backward compatibility
2024-04-17 16:31:37 +08:00
} , repo . MustBeNotEmpty )
2017-10-29 19:04:25 -07:00
2019-04-20 04:47:00 +02:00
m . Group ( "/blame" , func ( ) {
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . RefBlame )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . RefBlame )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . RefBlame )
2024-04-17 16:31:37 +08:00
} , repo . MustBeNotEmpty )
2019-04-20 04:47:00 +02:00
2024-12-25 00:51:13 +08:00
m . Get ( "/blob_excerpt/{sha}" , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . ExcerptBlob )
2017-04-25 03:24:51 -04:00
m . Group ( "" , func ( ) {
m . Get ( "/graph" , repo . Graph )
2024-01-19 16:05:02 +00:00
m . Get ( "/commit/{sha:([a-f0-9]{7,64})$}" , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . Diff )
m . Get ( "/commit/{sha:([a-f0-9]{7,64})$}/load-branches-and-tags" , repo . LoadBranchesAndTags )
2025-01-16 21:52:21 +08:00
// FIXME: this route `/cherry-pick/{sha}` doesn't seem useful or right, the new code always uses `/_cherrypick/` which could handle branch name correctly
m . Get ( "/cherry-pick/{sha:([a-f0-9]{7,64})$}" , repo . SetEditorconfigIfExists , context . RepoRefByDefaultBranch ( ) , repo . CherryPick )
} , repo . MustBeNotEmpty )
2017-07-27 02:23:38 -07:00
2025-01-13 23:35:34 -08:00
m . Get ( "/rss/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , feedEnabled , feed . RenderBranchFeed )
m . Get ( "/atom/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , feedEnabled , feed . RenderBranchFeed )
2023-04-25 15:08:29 +01:00
2017-10-29 19:04:25 -07:00
m . Group ( "/src" , func ( ) {
2025-01-13 14:01:53 +08:00
m . Get ( "" , func ( ctx * context . Context ) { ctx . Redirect ( ctx . Repo . RepoLink ) } ) // there is no "{owner}/{repo}/src" page, so redirect to "{owner}/{repo}" to avoid 404
2025-01-13 23:35:34 -08:00
m . Get ( "/branch/*" , context . RepoRefByType ( git . RefTypeBranch ) , repo . Home )
m . Get ( "/tag/*" , context . RepoRefByType ( git . RefTypeTag ) , repo . Home )
m . Get ( "/commit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . Home )
m . Get ( "/*" , context . RepoRefByType ( "" ) , repo . Home ) // "/*" route is deprecated, and kept for backward compatibility
2017-10-29 19:04:25 -07:00
} , repo . SetEditorconfigIfExists )
2025-01-31 04:12:14 +08:00
m . Get ( "/tree/*" , repo . RedirectRepoTreeToSrc ) // redirect "/owner/repo/tree/*" requests to "/owner/repo/src/*"
2025-01-29 18:09:52 -06:00
2024-04-17 16:31:37 +08:00
m . Get ( "/forks" , context . RepoRef ( ) , repo . Forks )
m . Get ( "/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}" , repo . MustBeNotEmpty , repo . RawDiff )
2025-01-13 23:35:34 -08:00
m . Post ( "/lastcommit/*" , context . RepoRefByType ( git . RefTypeCommit ) , repo . LastCommit )
2025-01-14 09:53:34 +08:00
} , optSignIn , context . RepoAssignment , reqUnitCodeReader )
2024-04-17 16:31:37 +08:00
// end "/{username}/{reponame}": repo code
2021-10-08 14:08:22 +01:00
2021-01-26 23:36:53 +08:00
m . Group ( "/{username}/{reponame}" , func ( ) {
2017-04-25 03:24:51 -04:00
m . Get ( "/stars" , repo . Stars )
m . Get ( "/watchers" , repo . Watchers )
2025-01-14 09:53:34 +08:00
m . Get ( "/search" , reqUnitCodeReader , repo . Search )
2024-04-17 16:31:37 +08:00
m . Post ( "/action/{action}" , reqSignIn , repo . Action )
2025-01-15 17:34:55 +08:00
} , optSignIn , context . RepoAssignment )
2021-01-26 23:36:53 +08:00
2024-11-13 16:58:09 +08:00
common . AddOwnerRepoGitLFSRoutes ( m , optSignInIgnoreCsrf , lfsServerEnabled ) // "/{username}/{reponame}/{lfs-paths}": git-lfs support
addOwnerRepoGitHTTPRouters ( m ) // "/{username}/{reponame}/{git-paths}": git http support
2017-04-25 03:24:51 -04:00
m . Group ( "/notifications" , func ( ) {
m . Get ( "" , user . Notifications )
2022-09-29 21:09:14 +02:00
m . Get ( "/subscriptions" , user . NotificationSubscriptions )
m . Get ( "/watching" , user . NotificationWatching )
2017-04-25 03:24:51 -04:00
m . Post ( "/status" , user . NotificationStatusPost )
2017-12-07 12:52:57 +07:00
m . Post ( "/purge" , user . NotificationPurgePost )
2022-04-08 02:59:56 +08:00
m . Get ( "/new" , user . NewAvailable )
2017-04-25 03:24:51 -04:00
} , reqSignIn )
2018-07-28 02:19:01 +02:00
if setting . API . EnableSwagger {
2021-06-09 07:33:54 +08:00
m . Get ( "/swagger.v1.json" , SwaggerV1Json )
2019-08-26 04:33:06 -07:00
}
2023-04-03 18:06:57 +08:00
if ! setting . IsProd {
2024-12-06 12:04:16 +08:00
m . Group ( "/devtest" , func ( ) {
m . Any ( "" , devtest . List )
m . Any ( "/fetch-action-test" , devtest . FetchActionTest )
m . Any ( "/{sub}" , devtest . Tmpl )
m . Post ( "/actions-mock/runs/{run}/jobs/{job}" , web . Bind ( actions . ViewRequest { } ) , devtest . MockActionsRunsJobs )
} )
2023-04-03 18:06:57 +08:00
}
2021-12-22 10:39:28 +00:00
m . NotFound ( func ( w http . ResponseWriter , req * http . Request ) {
2023-05-23 09:29:15 +08:00
ctx := context . GetWebContext ( req )
2025-01-16 04:05:18 +08:00
defer routing . RecordFuncInfo ( ctx , routing . GetFuncInfo ( ctx . NotFound , "WebNotFound" ) ) ( )
2021-12-22 10:39:28 +00:00
ctx . NotFound ( "" , nil )
} )
2017-04-25 03:24:51 -04:00
}