2017-04-25 10:24:51 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package routes
import (
2018-05-19 17:12:37 +03:00
"encoding/gob"
2019-02-06 06:06:41 +03:00
"fmt"
2018-05-19 17:12:37 +03:00
"net/http"
2017-04-25 10:24:51 +03:00
"os"
"path"
2018-02-04 01:37:05 +03:00
"time"
2017-04-25 10:24:51 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/context"
2019-01-23 11:56:51 +03:00
"code.gitea.io/gitea/modules/gzip"
2017-04-25 10:24:51 +03:00
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
2018-11-05 06:20:00 +03:00
"code.gitea.io/gitea/modules/metrics"
2017-04-25 10:24:51 +03:00
"code.gitea.io/gitea/modules/options"
"code.gitea.io/gitea/modules/public"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/routers"
"code.gitea.io/gitea/routers/admin"
apiv1 "code.gitea.io/gitea/routers/api/v1"
"code.gitea.io/gitea/routers/dev"
"code.gitea.io/gitea/routers/org"
"code.gitea.io/gitea/routers/private"
"code.gitea.io/gitea/routers/repo"
"code.gitea.io/gitea/routers/user"
2018-05-17 07:05:00 +03:00
userSetting "code.gitea.io/gitea/routers/user/setting"
2017-04-25 10:24:51 +03:00
"github.com/go-macaron/binding"
"github.com/go-macaron/cache"
"github.com/go-macaron/captcha"
"github.com/go-macaron/csrf"
"github.com/go-macaron/i18n"
"github.com/go-macaron/session"
"github.com/go-macaron/toolbox"
2018-11-05 06:20:00 +03:00
"github.com/prometheus/client_golang/prometheus"
2018-05-19 17:12:37 +03:00
"github.com/tstranex/u2f"
2019-01-09 20:22:57 +03:00
macaron "gopkg.in/macaron.v1"
2017-04-25 10:24:51 +03:00
)
2019-02-06 06:06:41 +03:00
func giteaLogger ( l * log . LoggerAsWriter ) macaron . Handler {
return func ( ctx * macaron . Context ) {
start := time . Now ( )
l . Log ( fmt . Sprintf ( "[Macaron] Started %s %s for %s" , ctx . Req . Method , ctx . Req . RequestURI , ctx . RemoteAddr ( ) ) )
ctx . Next ( )
rw := ctx . Resp . ( macaron . ResponseWriter )
l . Log ( fmt . Sprintf ( "[Macaron] Completed %s %s %v %s in %v" , ctx . Req . Method , ctx . Req . RequestURI , rw . Status ( ) , http . StatusText ( rw . Status ( ) ) , time . Since ( start ) ) )
}
}
2017-04-25 10:24:51 +03:00
// NewMacaron initializes Macaron instance.
func NewMacaron ( ) * macaron . Macaron {
2018-05-19 17:12:37 +03:00
gob . Register ( & u2f . Challenge { } )
2019-02-06 06:06:41 +03:00
var m * macaron . Macaron
if setting . RedirectMacaronLog {
loggerAsWriter := log . NewLoggerAsWriter ( "INFO" )
m = macaron . NewWithLogger ( loggerAsWriter )
if ! setting . DisableRouterLog {
m . Use ( giteaLogger ( loggerAsWriter ) )
}
} else {
m = macaron . New ( )
if ! setting . DisableRouterLog {
m . Use ( macaron . Logger ( ) )
}
2017-04-25 10:24:51 +03:00
}
m . Use ( macaron . Recovery ( ) )
if setting . EnableGzip {
2019-01-23 11:56:51 +03:00
m . Use ( gzip . Middleware ( ) )
2017-04-25 10:24:51 +03:00
}
if setting . Protocol == setting . FCGI {
m . SetURLPrefix ( setting . AppSubURL )
}
m . Use ( public . Custom (
& public . Options {
2018-02-04 01:37:05 +03:00
SkipLogging : setting . DisableRouterLog ,
ExpiresAfter : time . Hour * 6 ,
2017-04-25 10:24:51 +03:00
} ,
) )
m . Use ( public . Static (
& public . Options {
2018-02-04 01:37:05 +03:00
Directory : path . Join ( setting . StaticRootPath , "public" ) ,
SkipLogging : setting . DisableRouterLog ,
ExpiresAfter : time . Hour * 6 ,
2017-04-25 10:24:51 +03:00
} ,
) )
2018-02-04 01:37:05 +03:00
m . Use ( public . StaticHandler (
2017-04-25 10:24:51 +03:00
setting . AvatarUploadPath ,
2018-02-04 01:37:05 +03:00
& public . Options {
Prefix : "avatars" ,
SkipLogging : setting . DisableRouterLog ,
ExpiresAfter : time . Hour * 6 ,
2017-04-25 10:24:51 +03:00
} ,
) )
2018-07-28 03:19:01 +03:00
m . Use ( templates . HTMLRenderer ( ) )
2017-04-25 10:24:51 +03:00
models . InitMailRender ( templates . Mailer ( ) )
localeNames , err := options . Dir ( "locale" )
if err != nil {
log . Fatal ( 4 , "Failed to list locale files: %v" , err )
}
localFiles := make ( map [ string ] [ ] byte )
for _ , name := range localeNames {
localFiles [ name ] , err = options . Locale ( name )
if err != nil {
log . Fatal ( 4 , "Failed to load %s locale file. %v" , name , err )
}
}
m . Use ( i18n . I18n ( i18n . Options {
SubURL : setting . AppSubURL ,
Files : localFiles ,
Langs : setting . Langs ,
Names : setting . Names ,
DefaultLang : "en-US" ,
2019-01-31 17:38:20 +03:00
Redirect : false ,
2017-04-25 10:24:51 +03:00
} ) )
m . Use ( cache . Cacher ( cache . Options {
2017-10-26 04:37:33 +03:00
Adapter : setting . CacheService . Adapter ,
AdapterConfig : setting . CacheService . Conn ,
Interval : setting . CacheService . Interval ,
2017-04-25 10:24:51 +03:00
} ) )
m . Use ( captcha . Captchaer ( captcha . Options {
SubURL : setting . AppSubURL ,
} ) )
m . Use ( session . Sessioner ( setting . SessionConfig ) )
m . Use ( csrf . Csrfer ( csrf . Options {
2018-08-14 23:16:37 +03:00
Secret : setting . SecretKey ,
Cookie : setting . CSRFCookieName ,
SetCookie : true ,
Secure : setting . SessionConfig . Secure ,
CookieHttpOnly : true ,
Header : "X-Csrf-Token" ,
CookiePath : setting . AppSubURL ,
2017-04-25 10:24:51 +03:00
} ) )
m . Use ( toolbox . Toolboxer ( m , toolbox . Options {
HealthCheckFuncs : [ ] * toolbox . HealthCheckFuncDesc {
{
Desc : "Database connection" ,
Func : models . Ping ,
} ,
} ,
2018-09-30 01:44:06 +03:00
DisableDebug : ! setting . EnablePprof ,
2017-04-25 10:24:51 +03:00
} ) )
m . Use ( context . Contexter ( ) )
2019-01-31 01:00:00 +03:00
// OK we are now set-up enough to allow us to create a nicer recovery than
// the default macaron recovery
m . Use ( context . Recovery ( ) )
2018-10-30 18:08:49 +03:00
m . SetAutoHead ( true )
2017-04-25 10:24:51 +03:00
return m
}
// RegisterRoutes routes routes to Macaron
func RegisterRoutes ( m * macaron . Macaron ) {
reqSignIn := context . Toggle ( & context . ToggleOptions { SignInRequired : true } )
ignSignIn := context . Toggle ( & context . ToggleOptions { SignInRequired : setting . Service . RequireSignInView } )
ignSignInAndCsrf := context . Toggle ( & context . ToggleOptions { DisableCSRF : true } )
reqSignOut := context . Toggle ( & context . ToggleOptions { SignOutRequired : true } )
bindIgnErr := binding . BindIgnErr
validation . AddBindingRules ( )
2017-08-19 18:34:49 +03:00
openIDSignInEnabled := func ( ctx * context . Context ) {
if ! setting . Service . EnableOpenIDSignIn {
ctx . Error ( 403 )
return
}
}
openIDSignUpEnabled := func ( ctx * context . Context ) {
if ! setting . Service . EnableOpenIDSignUp {
ctx . Error ( 403 )
return
}
}
2017-04-25 10:24:51 +03:00
m . Use ( user . GetNotificationCount )
// FIXME: not all routes need go through same middlewares.
// Especially some AJAX requests, we can reduce middleware number to improve performance.
// Routers.
// for health check
m . Head ( "/" , func ( ) string {
return ""
} )
2018-05-24 22:51:28 +03:00
m . Get ( "/" , routers . Home )
2017-04-25 10:24:51 +03:00
m . Group ( "/explore" , func ( ) {
m . Get ( "" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/explore/repos" )
} )
m . Get ( "/repos" , routers . ExploreRepos )
m . Get ( "/users" , routers . ExploreUsers )
m . Get ( "/organizations" , routers . ExploreOrganizations )
2018-03-16 17:04:33 +03:00
m . Get ( "/code" , routers . ExploreCode )
2017-04-25 10:24:51 +03:00
} , ignSignIn )
m . Combo ( "/install" , routers . InstallInit ) . Get ( routers . Install ) .
Post ( bindIgnErr ( auth . InstallForm { } ) , routers . InstallPost )
m . Get ( "/^:type(issues|pulls)$" , reqSignIn , user . Issues )
// ***** START: User *****
m . Group ( "/user" , func ( ) {
m . Get ( "/login" , user . SignIn )
m . Post ( "/login" , bindIgnErr ( auth . SignInForm { } ) , user . SignInPost )
2017-08-19 18:34:49 +03:00
m . Group ( "" , func ( ) {
2017-04-25 10:24:51 +03:00
m . Combo ( "/login/openid" ) .
Get ( user . SignInOpenID ) .
Post ( bindIgnErr ( auth . SignInOpenIDForm { } ) , user . SignInOpenIDPost )
2017-08-19 18:34:49 +03:00
} , openIDSignInEnabled )
m . Group ( "/openid" , func ( ) {
m . Combo ( "/connect" ) .
Get ( user . ConnectOpenID ) .
Post ( bindIgnErr ( auth . ConnectOpenIDForm { } ) , user . ConnectOpenIDPost )
m . Group ( "/register" , func ( ) {
m . Combo ( "" ) .
Get ( user . RegisterOpenID , openIDSignUpEnabled ) .
2017-04-25 10:24:51 +03:00
Post ( bindIgnErr ( auth . SignUpOpenIDForm { } ) , user . RegisterOpenIDPost )
2017-08-19 18:34:49 +03:00
} , openIDSignUpEnabled )
} , openIDSignInEnabled )
2017-04-25 10:24:51 +03:00
m . Get ( "/sign_up" , user . SignUp )
m . Post ( "/sign_up" , bindIgnErr ( auth . RegisterForm { } ) , user . SignUpPost )
m . Get ( "/reset_password" , user . ResetPasswd )
m . Post ( "/reset_password" , user . ResetPasswdPost )
m . Group ( "/oauth2" , func ( ) {
m . Get ( "/:provider" , user . SignInOAuth )
m . Get ( "/:provider/callback" , user . SignInOAuthCallback )
} )
m . Get ( "/link_account" , user . LinkAccount )
m . Post ( "/link_account_signin" , bindIgnErr ( auth . SignInForm { } ) , user . LinkAccountPostSignIn )
m . Post ( "/link_account_signup" , bindIgnErr ( auth . RegisterForm { } ) , user . LinkAccountPostRegister )
m . Group ( "/two_factor" , func ( ) {
m . Get ( "" , user . TwoFactor )
m . Post ( "" , bindIgnErr ( auth . TwoFactorAuthForm { } ) , user . TwoFactorPost )
m . Get ( "/scratch" , user . TwoFactorScratch )
m . Post ( "/scratch" , bindIgnErr ( auth . TwoFactorScratchAuthForm { } ) , user . TwoFactorScratchPost )
} )
2018-05-19 17:12:37 +03:00
m . Group ( "/u2f" , func ( ) {
m . Get ( "" , user . U2F )
m . Get ( "/challenge" , user . U2FChallenge )
m . Post ( "/sign" , bindIgnErr ( u2f . SignResponse { } ) , user . U2FSign )
} )
2017-04-25 10:24:51 +03:00
} , reqSignOut )
2019-03-08 19:42:50 +03:00
m . Group ( "/login/oauth" , func ( ) {
m . Get ( "/authorize" , bindIgnErr ( auth . AuthorizationForm { } ) , user . AuthorizeOAuth )
m . Post ( "/grant" , bindIgnErr ( auth . GrantApplicationForm { } ) , user . GrantApplicationOAuth )
// TODO manage redirection
m . Post ( "/authorize" , bindIgnErr ( auth . AuthorizationForm { } ) , user . AuthorizeOAuth )
} , ignSignInAndCsrf , reqSignIn )
m . Post ( "/login/oauth/access_token" , bindIgnErr ( auth . AccessTokenForm { } ) , ignSignInAndCsrf , user . AccessTokenOAuth )
2017-04-25 10:24:51 +03:00
m . Group ( "/user/settings" , func ( ) {
2018-05-17 07:05:00 +03:00
m . Get ( "" , userSetting . Profile )
m . Post ( "" , bindIgnErr ( auth . UpdateProfileForm { } ) , userSetting . ProfilePost )
2018-09-13 15:04:25 +03:00
m . Get ( "/change_password" , user . MustChangePassword )
m . Post ( "/change_password" , bindIgnErr ( auth . MustChangePasswordForm { } ) , user . MustChangePasswordPost )
2018-05-17 07:05:00 +03:00
m . Post ( "/avatar" , binding . MultipartForm ( auth . AvatarForm { } ) , userSetting . AvatarPost )
m . Post ( "/avatar/delete" , userSetting . DeleteAvatar )
2018-05-15 13:07:32 +03:00
m . Group ( "/account" , func ( ) {
2018-05-17 07:05:00 +03:00
m . Combo ( "" ) . Get ( userSetting . Account ) . Post ( bindIgnErr ( auth . ChangePasswordForm { } ) , userSetting . AccountPost )
m . Post ( "/email" , bindIgnErr ( auth . AddEmailForm { } ) , userSetting . EmailPost )
m . Post ( "/email/delete" , userSetting . DeleteEmail )
m . Post ( "/delete" , userSetting . DeleteAccount )
2019-01-09 20:22:57 +03:00
m . Post ( "/theme" , bindIgnErr ( auth . UpdateThemeForm { } ) , userSetting . UpdateUIThemePost )
2018-05-15 13:07:32 +03:00
} )
m . Group ( "/security" , func ( ) {
2018-05-17 07:05:00 +03:00
m . Get ( "" , userSetting . Security )
2018-05-15 13:07:32 +03:00
m . Group ( "/two_factor" , func ( ) {
2018-05-17 07:05:00 +03:00
m . Post ( "/regenerate_scratch" , userSetting . RegenerateScratchTwoFactor )
m . Post ( "/disable" , userSetting . DisableTwoFactor )
m . Get ( "/enroll" , userSetting . EnrollTwoFactor )
m . Post ( "/enroll" , bindIgnErr ( auth . TwoFactorAuthForm { } ) , userSetting . EnrollTwoFactorPost )
2018-05-15 13:07:32 +03:00
} )
2018-05-19 17:12:37 +03:00
m . Group ( "/u2f" , func ( ) {
m . Post ( "/request_register" , bindIgnErr ( auth . U2FRegistrationForm { } ) , userSetting . U2FRegister )
m . Post ( "/register" , bindIgnErr ( u2f . RegisterResponse { } ) , userSetting . U2FRegisterPost )
m . Post ( "/delete" , bindIgnErr ( auth . U2FDeleteForm { } ) , userSetting . U2FDelete )
} )
2018-05-15 13:07:32 +03:00
m . Group ( "/openid" , func ( ) {
2018-05-17 07:05:00 +03:00
m . Post ( "" , bindIgnErr ( auth . AddOpenIDForm { } ) , userSetting . OpenIDPost )
m . Post ( "/delete" , userSetting . DeleteOpenID )
m . Post ( "/toggle_visibility" , userSetting . ToggleOpenIDVisibility )
2018-05-15 13:07:32 +03:00
} , openIDSignInEnabled )
2018-05-17 07:05:00 +03:00
m . Post ( "/account_link" , userSetting . DeleteAccountLink )
2018-05-15 13:07:32 +03:00
} )
2019-03-08 19:42:50 +03:00
m . Group ( "/applications/oauth2" , func ( ) {
m . Get ( "/:id" , userSetting . OAuth2ApplicationShow )
m . Post ( "/:id" , bindIgnErr ( auth . EditOAuth2ApplicationForm { } ) , userSetting . OAuthApplicationsEdit )
2019-03-09 19:29:58 +03:00
m . Post ( "/:id/regenerate_secret" , userSetting . OAuthApplicationsRegenerateSecret )
2019-03-08 19:42:50 +03:00
m . Post ( "" , bindIgnErr ( auth . EditOAuth2ApplicationForm { } ) , userSetting . OAuthApplicationsPost )
m . Post ( "/delete" , userSetting . DeleteOAuth2Application )
} )
2018-05-17 07:05:00 +03:00
m . Combo ( "/applications" ) . Get ( userSetting . Applications ) .
Post ( bindIgnErr ( auth . NewAccessTokenForm { } ) , userSetting . ApplicationsPost )
m . Post ( "/applications/delete" , userSetting . DeleteApplication )
m . Combo ( "/keys" ) . Get ( userSetting . Keys ) .
Post ( bindIgnErr ( auth . AddKeyForm { } ) , userSetting . KeysPost )
m . Post ( "/keys/delete" , userSetting . DeleteKey )
m . Get ( "/organization" , userSetting . Organization )
m . Get ( "/repos" , userSetting . Repos )
2018-05-15 13:07:32 +03:00
// redirects from old settings urls to new ones
// TODO: can be removed on next major version
m . Get ( "/avatar" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/user/settings" , http . StatusMovedPermanently )
} )
m . Get ( "/email" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/user/settings/account" , http . StatusMovedPermanently )
} )
m . Get ( "/delete" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/user/settings/account" , http . StatusMovedPermanently )
} )
m . Get ( "/openid" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/user/settings/security" , http . StatusMovedPermanently )
} )
m . Get ( "/account_link" , func ( ctx * context . Context ) {
ctx . Redirect ( setting . AppSubURL + "/user/settings/security" , http . StatusMovedPermanently )
2017-04-25 10:24:51 +03:00
} )
} , reqSignIn , func ( ctx * context . Context ) {
ctx . Data [ "PageIsUserSettings" ] = true
2019-01-09 20:22:57 +03:00
ctx . Data [ "AllThemes" ] = setting . UI . Themes
2017-04-25 10:24:51 +03:00
} )
m . Group ( "/user" , func ( ) {
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
m . Any ( "/activate" , user . Activate )
m . Any ( "/activate_email" , user . ActivateEmail )
m . Get ( "/email2user" , user . Email2User )
m . Get ( "/forgot_password" , user . ForgotPasswd )
m . Post ( "/forgot_password" , user . ForgotPasswdPost )
m . Get ( "/logout" , user . SignOut )
} )
// ***** END: User *****
adminReq := context . Toggle ( & context . ToggleOptions { SignInRequired : true , AdminRequired : true } )
// ***** START: Admin *****
m . Group ( "/admin" , func ( ) {
m . Get ( "" , adminReq , admin . Dashboard )
m . Get ( "/config" , admin . Config )
m . Post ( "/config/test_mail" , admin . SendTestMail )
m . Get ( "/monitor" , admin . Monitor )
m . Group ( "/users" , func ( ) {
m . Get ( "" , admin . Users )
m . Combo ( "/new" ) . Get ( admin . NewUser ) . Post ( bindIgnErr ( auth . AdminCreateUserForm { } ) , admin . NewUserPost )
m . Combo ( "/:userid" ) . Get ( admin . EditUser ) . Post ( bindIgnErr ( auth . AdminEditUserForm { } ) , admin . EditUserPost )
m . Post ( "/:userid/delete" , admin . DeleteUser )
} )
m . Group ( "/orgs" , func ( ) {
m . Get ( "" , admin . Organizations )
} )
m . Group ( "/repos" , func ( ) {
m . Get ( "" , admin . Repos )
m . Post ( "/delete" , admin . DeleteRepo )
} )
2019-03-19 05:33:20 +03:00
m . Group ( "/hooks" , func ( ) {
m . Get ( "" , admin . DefaultWebhooks )
m . Post ( "/delete" , admin . DeleteDefaultWebhook )
m . Get ( "/:type/new" , repo . WebhooksNew )
m . Post ( "/gitea/new" , bindIgnErr ( auth . NewWebhookForm { } ) , repo . WebHooksNewPost )
m . Post ( "/gogs/new" , bindIgnErr ( auth . NewGogshookForm { } ) , repo . GogsHooksNewPost )
m . Post ( "/slack/new" , bindIgnErr ( auth . NewSlackHookForm { } ) , repo . SlackHooksNewPost )
m . Post ( "/discord/new" , bindIgnErr ( auth . NewDiscordHookForm { } ) , repo . DiscordHooksNewPost )
m . Post ( "/dingtalk/new" , bindIgnErr ( auth . NewDingtalkHookForm { } ) , repo . DingtalkHooksNewPost )
m . Get ( "/:id" , repo . WebHooksEdit )
m . Post ( "/gitea/:id" , bindIgnErr ( auth . NewWebhookForm { } ) , repo . WebHooksEditPost )
m . Post ( "/gogs/:id" , bindIgnErr ( auth . NewGogshookForm { } ) , repo . GogsHooksEditPost )
m . Post ( "/slack/:id" , bindIgnErr ( auth . NewSlackHookForm { } ) , repo . SlackHooksEditPost )
m . Post ( "/discord/:id" , bindIgnErr ( auth . NewDiscordHookForm { } ) , repo . DiscordHooksEditPost )
m . Post ( "/dingtalk/:id" , bindIgnErr ( auth . NewDingtalkHookForm { } ) , repo . DingtalkHooksEditPost )
} )
2017-04-25 10:24:51 +03:00
m . Group ( "/auths" , func ( ) {
m . Get ( "" , admin . Authentications )
m . Combo ( "/new" ) . Get ( admin . NewAuthSource ) . Post ( bindIgnErr ( auth . AuthenticationForm { } ) , admin . NewAuthSourcePost )
m . Combo ( "/:authid" ) . Get ( admin . EditAuthSource ) .
Post ( bindIgnErr ( auth . AuthenticationForm { } ) , admin . EditAuthSourcePost )
m . Post ( "/:authid/delete" , admin . DeleteAuthSource )
} )
m . Group ( "/notices" , func ( ) {
m . Get ( "" , admin . Notices )
m . Post ( "/delete" , admin . DeleteNotices )
m . Get ( "/empty" , admin . EmptyNotices )
} )
} , adminReq )
// ***** END: Admin *****
m . Group ( "" , func ( ) {
m . Group ( "/:username" , func ( ) {
m . Get ( "" , user . Profile )
m . Get ( "/followers" , user . Followers )
m . Get ( "/following" , user . Following )
} )
m . Get ( "/attachments/:uuid" , func ( ctx * context . Context ) {
attach , err := models . GetAttachmentByUUID ( ctx . Params ( ":uuid" ) )
if err != nil {
if models . IsErrAttachmentNotExist ( err ) {
ctx . Error ( 404 )
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetAttachmentByUUID" , err )
2017-04-25 10:24:51 +03:00
}
return
}
fr , err := os . Open ( attach . LocalPath ( ) )
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "Open" , err )
2017-04-25 10:24:51 +03:00
return
}
defer fr . Close ( )
if err := attach . IncreaseDownloadCount ( ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "Update" , err )
2017-04-25 10:24:51 +03:00
return
}
if err = repo . ServeData ( ctx , attach . Name , fr ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "ServeData" , err )
2017-04-25 10:24:51 +03:00
return
}
} )
m . Post ( "/attachments" , repo . UploadAttachment )
} , ignSignIn )
m . Group ( "/:username" , func ( ) {
m . Get ( "/action/:action" , user . Action )
} , reqSignIn )
if macaron . Env == macaron . DEV {
m . Get ( "/template/*" , dev . TemplatePreview )
}
reqRepoAdmin := context . RequireRepoAdmin ( )
2018-11-28 14:26:14 +03:00
reqRepoCodeWriter := context . RequireRepoWriter ( models . UnitTypeCode )
reqRepoCodeReader := context . RequireRepoReader ( models . UnitTypeCode )
reqRepoReleaseWriter := context . RequireRepoWriter ( models . UnitTypeReleases )
reqRepoReleaseReader := context . RequireRepoReader ( models . UnitTypeReleases )
reqRepoWikiWriter := context . RequireRepoWriter ( models . UnitTypeWiki )
reqRepoIssueReader := context . RequireRepoReader ( models . UnitTypeIssues )
reqRepoPullsWriter := context . RequireRepoWriter ( models . UnitTypePullRequests )
reqRepoPullsReader := context . RequireRepoReader ( models . UnitTypePullRequests )
reqRepoIssuesOrPullsWriter := context . RequireRepoWriterOr ( models . UnitTypeIssues , models . UnitTypePullRequests )
reqRepoIssuesOrPullsReader := context . RequireRepoReaderOr ( models . UnitTypeIssues , models . UnitTypePullRequests )
2017-04-25 10:24:51 +03:00
2019-02-18 23:55:04 +03:00
reqRepoIssueWriter := func ( ctx * context . Context ) {
if ! ctx . Repo . CanWrite ( models . UnitTypeIssues ) {
ctx . Error ( 403 )
return
}
}
2017-04-25 10:24:51 +03:00
// ***** START: Organization *****
m . Group ( "/org" , func ( ) {
m . Group ( "" , func ( ) {
m . Get ( "/create" , org . Create )
m . Post ( "/create" , bindIgnErr ( auth . CreateOrgForm { } ) , org . CreatePost )
} )
m . Group ( "/:org" , func ( ) {
m . Get ( "/dashboard" , user . Dashboard )
m . Get ( "/^:type(issues|pulls)$" , user . Issues )
m . Get ( "/members" , org . Members )
m . Get ( "/members/action/:action" , org . MembersAction )
m . Get ( "/teams" , org . Teams )
} , context . OrgAssignment ( true ) )
m . Group ( "/:org" , func ( ) {
m . Get ( "/teams/:team" , org . TeamMembers )
m . Get ( "/teams/:team/repositories" , org . TeamRepositories )
m . Route ( "/teams/:team/action/:action" , "GET,POST" , org . TeamsAction )
m . Route ( "/teams/:team/action/repo/:action" , "GET,POST" , org . TeamsRepoAction )
} , context . OrgAssignment ( true , false , true ) )
m . Group ( "/:org" , func ( ) {
m . Get ( "/teams/new" , org . NewTeam )
m . Post ( "/teams/new" , bindIgnErr ( auth . CreateTeamForm { } ) , org . NewTeamPost )
m . Get ( "/teams/:team/edit" , org . EditTeam )
m . Post ( "/teams/:team/edit" , bindIgnErr ( auth . CreateTeamForm { } ) , org . EditTeamPost )
m . Post ( "/teams/:team/delete" , org . DeleteTeam )
m . Group ( "/settings" , func ( ) {
m . Combo ( "" ) . Get ( org . Settings ) .
Post ( bindIgnErr ( auth . UpdateOrgSettingForm { } ) , org . SettingsPost )
m . Post ( "/avatar" , binding . MultipartForm ( auth . AvatarForm { } ) , org . SettingsAvatar )
m . Post ( "/avatar/delete" , org . SettingsDeleteAvatar )
m . Group ( "/hooks" , func ( ) {
m . Get ( "" , org . Webhooks )
m . Post ( "/delete" , org . DeleteWebhook )
m . Get ( "/:type/new" , repo . WebhooksNew )
2017-05-29 10:17:15 +03:00
m . Post ( "/gitea/new" , bindIgnErr ( auth . NewWebhookForm { } ) , repo . WebHooksNewPost )
m . Post ( "/gogs/new" , bindIgnErr ( auth . NewGogshookForm { } ) , repo . GogsHooksNewPost )
2017-04-25 10:24:51 +03:00
m . Post ( "/slack/new" , bindIgnErr ( auth . NewSlackHookForm { } ) , repo . SlackHooksNewPost )
2017-08-30 08:36:52 +03:00
m . Post ( "/discord/new" , bindIgnErr ( auth . NewDiscordHookForm { } ) , repo . DiscordHooksNewPost )
2017-11-21 07:26:43 +03:00
m . Post ( "/dingtalk/new" , bindIgnErr ( auth . NewDingtalkHookForm { } ) , repo . DingtalkHooksNewPost )
2017-04-25 10:24:51 +03:00
m . Get ( "/:id" , repo . WebHooksEdit )
2017-05-29 10:17:15 +03:00
m . Post ( "/gitea/:id" , bindIgnErr ( auth . NewWebhookForm { } ) , repo . WebHooksEditPost )
m . Post ( "/gogs/:id" , bindIgnErr ( auth . NewGogshookForm { } ) , repo . GogsHooksEditPost )
2017-04-25 10:24:51 +03:00
m . Post ( "/slack/:id" , bindIgnErr ( auth . NewSlackHookForm { } ) , repo . SlackHooksEditPost )
2017-08-29 04:20:35 +03:00
m . Post ( "/discord/:id" , bindIgnErr ( auth . NewDiscordHookForm { } ) , repo . DiscordHooksEditPost )
2017-11-21 07:26:43 +03:00
m . Post ( "/dingtalk/:id" , bindIgnErr ( auth . NewDingtalkHookForm { } ) , repo . DingtalkHooksEditPost )
2017-04-25 10:24:51 +03:00
} )
m . Route ( "/delete" , "GET,POST" , org . SettingsDelete )
} )
} , context . OrgAssignment ( true , true ) )
} , reqSignIn )
// ***** END: Organization *****
// ***** START: Repository *****
m . Group ( "/repo" , func ( ) {
m . Get ( "/create" , repo . Create )
m . Post ( "/create" , bindIgnErr ( auth . CreateRepoForm { } ) , repo . CreatePost )
m . Get ( "/migrate" , repo . Migrate )
m . Post ( "/migrate" , bindIgnErr ( auth . MigrateRepoForm { } ) , repo . MigratePost )
2017-09-18 17:52:20 +03:00
m . Group ( "/fork" , func ( ) {
m . Combo ( "/:repoid" ) . Get ( repo . Fork ) .
Post ( bindIgnErr ( auth . CreateRepoForm { } ) , repo . ForkPost )
2018-11-28 14:26:14 +03:00
} , context . RepoIDAssignment ( ) , context . UnitTypes ( ) , reqRepoCodeReader )
2017-04-25 10:24:51 +03:00
} , reqSignIn )
2019-01-07 01:37:30 +03:00
// ***** Release Attachment Download without Signin
2019-01-18 03:01:04 +03:00
m . Get ( "/:username/:reponame/releases/download/:vTag/:fileName" , ignSignIn , context . RepoAssignment ( ) , repo . MustBeNotEmpty , repo . RedirectDownload )
2019-01-07 01:37:30 +03:00
2017-04-25 10:24:51 +03:00
m . Group ( "/:username/:reponame" , func ( ) {
m . Group ( "/settings" , func ( ) {
m . Combo ( "" ) . Get ( repo . Settings ) .
Post ( bindIgnErr ( auth . RepoSettingForm { } ) , repo . SettingsPost )
m . Group ( "/collaboration" , func ( ) {
m . Combo ( "" ) . Get ( repo . Collaboration ) . Post ( repo . CollaborationPost )
m . Post ( "/access_mode" , repo . ChangeCollaborationAccessMode )
m . Post ( "/delete" , repo . DeleteCollaboration )
} )
m . Group ( "/branches" , func ( ) {
m . Combo ( "" ) . Get ( repo . ProtectedBranch ) . Post ( repo . ProtectedBranchPost )
2017-09-14 11:16:22 +03:00
m . Combo ( "/*" ) . Get ( repo . SettingsProtectedBranch ) .
2019-01-23 21:58:38 +03:00
Post ( bindIgnErr ( auth . ProtectBranchForm { } ) , context . RepoMustNotBeArchived ( ) , repo . SettingsProtectedBranchPost )
2019-01-18 03:01:04 +03:00
} , repo . MustBeNotEmpty )
2017-04-25 10:24:51 +03:00
m . Group ( "/hooks" , func ( ) {
m . Get ( "" , repo . Webhooks )
m . Post ( "/delete" , repo . DeleteWebhook )
m . Get ( "/:type/new" , repo . WebhooksNew )
2017-05-29 10:17:15 +03:00
m . Post ( "/gitea/new" , bindIgnErr ( auth . NewWebhookForm { } ) , repo . WebHooksNewPost )
m . Post ( "/gogs/new" , bindIgnErr ( auth . NewGogshookForm { } ) , repo . GogsHooksNewPost )
2017-04-25 10:24:51 +03:00
m . Post ( "/slack/new" , bindIgnErr ( auth . NewSlackHookForm { } ) , repo . SlackHooksNewPost )
2017-08-28 08:06:45 +03:00
m . Post ( "/discord/new" , bindIgnErr ( auth . NewDiscordHookForm { } ) , repo . DiscordHooksNewPost )
2017-11-21 07:26:43 +03:00
m . Post ( "/dingtalk/new" , bindIgnErr ( auth . NewDingtalkHookForm { } ) , repo . DingtalkHooksNewPost )
2017-04-25 10:24:51 +03:00
m . Get ( "/:id" , repo . WebHooksEdit )
m . Post ( "/:id/test" , repo . TestWebhook )
2017-05-29 10:17:15 +03:00
m . Post ( "/gitea/:id" , bindIgnErr ( auth . NewWebhookForm { } ) , repo . WebHooksEditPost )
2018-06-21 08:22:03 +03:00
m . Post ( "/gogs/:id" , bindIgnErr ( auth . NewGogshookForm { } ) , repo . GogsHooksEditPost )
2017-04-25 10:24:51 +03:00
m . Post ( "/slack/:id" , bindIgnErr ( auth . NewSlackHookForm { } ) , repo . SlackHooksEditPost )
2017-08-28 08:06:45 +03:00
m . Post ( "/discord/:id" , bindIgnErr ( auth . NewDiscordHookForm { } ) , repo . DiscordHooksEditPost )
2017-11-21 07:26:43 +03:00
m . Post ( "/dingtalk/:id" , bindIgnErr ( auth . NewDingtalkHookForm { } ) , repo . DingtalkHooksEditPost )
2017-04-25 10:24:51 +03:00
m . Group ( "/git" , func ( ) {
m . Get ( "" , repo . GitHooks )
m . Combo ( "/:name" ) . Get ( repo . GitHooksEdit ) .
Post ( repo . GitHooksEditPost )
} , context . GitHookService ( ) )
} )
m . Group ( "/keys" , func ( ) {
m . Combo ( "" ) . Get ( repo . DeployKeys ) .
2017-04-26 16:10:43 +03:00
Post ( bindIgnErr ( auth . AddKeyForm { } ) , repo . DeployKeysPost )
2017-04-25 10:24:51 +03:00
m . Post ( "/delete" , repo . DeleteDeployKey )
} )
} , func ( ctx * context . Context ) {
ctx . Data [ "PageIsSettings" ] = true
2017-07-17 05:04:43 +03:00
} )
2018-11-28 14:26:14 +03:00
} , reqSignIn , context . RepoAssignment ( ) , reqRepoAdmin , context . UnitTypes ( ) , context . RepoRef ( ) )
2017-04-25 10:24:51 +03:00
2019-03-09 14:00:38 +03:00
m . Get ( "/:username/:reponame/action/:action" , reqSignIn , context . RepoAssignment ( ) , context . UnitTypes ( ) , context . RepoMustNotBeArchived ( ) , repo . Action )
2017-05-18 17:54:24 +03:00
2017-04-25 10:24:51 +03:00
m . Group ( "/:username/:reponame" , func ( ) {
m . Group ( "/issues" , func ( ) {
2017-09-30 07:04:16 +03:00
m . Combo ( "/new" ) . Get ( context . RepoRef ( ) , repo . NewIssue ) .
2017-04-25 10:24:51 +03:00
Post ( bindIgnErr ( auth . CreateIssueForm { } ) , repo . NewIssuePost )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) , reqRepoIssueReader )
2017-10-16 10:55:43 +03:00
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
// So they can apply their own enable/disable logic on routers.
m . Group ( "/issues" , func ( ) {
2017-04-25 10:24:51 +03:00
m . Group ( "/:index" , func ( ) {
m . Post ( "/title" , repo . UpdateIssueTitle )
m . Post ( "/content" , repo . UpdateIssueContent )
m . Post ( "/watch" , repo . IssueWatch )
2018-07-18 00:23:58 +03:00
m . Group ( "/dependency" , func ( ) {
m . Post ( "/add" , repo . AddDependency )
m . Post ( "/delete" , repo . RemoveDependency )
} )
2019-02-18 23:55:04 +03:00
m . Combo ( "/comments" ) . Post ( repo . MustAllowUserComment , bindIgnErr ( auth . CreateCommentForm { } ) , repo . NewComment )
2017-09-12 09:48:13 +03:00
m . Group ( "/times" , func ( ) {
m . Post ( "/add" , bindIgnErr ( auth . AddTimeManuallyForm { } ) , repo . AddTimeManually )
m . Group ( "/stopwatch" , func ( ) {
m . Post ( "/toggle" , repo . IssueStopwatch )
m . Post ( "/cancel" , repo . CancelStopwatch )
} )
} )
2017-12-04 02:14:26 +03:00
m . Post ( "/reactions/:action" , bindIgnErr ( auth . ReactionForm { } ) , repo . ChangeIssueReaction )
2019-02-18 23:55:04 +03:00
m . Post ( "/lock" , reqRepoIssueWriter , bindIgnErr ( auth . IssueLockForm { } ) , repo . LockIssue )
m . Post ( "/unlock" , reqRepoIssueWriter , repo . UnlockIssue )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) )
2017-04-25 10:24:51 +03:00
2018-11-28 14:26:14 +03:00
m . Post ( "/labels" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueLabel )
m . Post ( "/milestone" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueMilestone )
m . Post ( "/assignee" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueAssignee )
m . Post ( "/status" , reqRepoIssuesOrPullsWriter , repo . UpdateIssueStatus )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/comments/:id" , func ( ) {
m . Post ( "" , repo . UpdateCommentContent )
m . Post ( "/delete" , repo . DeleteComment )
2017-12-04 02:14:26 +03:00
m . Post ( "/reactions/:action" , bindIgnErr ( auth . ReactionForm { } ) , repo . ChangeCommentReaction )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/labels" , func ( ) {
m . Post ( "/new" , bindIgnErr ( auth . CreateLabelForm { } ) , repo . NewLabel )
m . Post ( "/edit" , bindIgnErr ( auth . CreateLabelForm { } ) , repo . UpdateLabel )
m . Post ( "/delete" , repo . DeleteLabel )
m . Post ( "/initialize" , bindIgnErr ( auth . InitializeLabelsForm { } ) , repo . InitializeLabels )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) , reqRepoIssuesOrPullsWriter , context . RepoRef ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/milestones" , func ( ) {
m . Combo ( "/new" ) . Get ( repo . NewMilestone ) .
Post ( bindIgnErr ( auth . CreateMilestoneForm { } ) , repo . NewMilestonePost )
m . Get ( "/:id/edit" , repo . EditMilestone )
m . Post ( "/:id/edit" , bindIgnErr ( auth . CreateMilestoneForm { } ) , repo . EditMilestonePost )
m . Get ( "/:id/:action" , repo . ChangeMilestonStatus )
m . Post ( "/delete" , repo . DeleteMilestone )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) , reqRepoIssuesOrPullsWriter , context . RepoRef ( ) )
2018-11-29 04:46:30 +03:00
m . Group ( "/milestone" , func ( ) {
m . Get ( "/:id" , repo . MilestoneIssuesAndPulls )
2019-03-15 18:50:27 +03:00
} , reqRepoIssuesOrPullsReader , context . RepoRef ( ) )
2019-01-30 20:20:40 +03:00
m . Combo ( "/compare/*" , context . RepoMustNotBeArchived ( ) , reqRepoCodeReader , reqRepoPullsReader , repo . MustAllowPulls , repo . SetEditorconfigIfExists ) .
2018-08-12 03:20:33 +03:00
Get ( repo . SetDiffViewStyle , repo . CompareAndPullRequest ) .
2017-04-25 10:24:51 +03:00
Post ( bindIgnErr ( auth . CreateIssueForm { } ) , repo . CompareAndPullRequestPost )
m . Group ( "" , func ( ) {
m . Group ( "" , func ( ) {
2017-10-30 05:04:25 +03:00
m . Combo ( "/_edit/*" ) . Get ( repo . EditFile ) .
Post ( bindIgnErr ( auth . EditRepoFileForm { } ) , repo . EditFilePost )
m . Combo ( "/_new/*" ) . Get ( repo . NewFile ) .
Post ( bindIgnErr ( auth . EditRepoFileForm { } ) , repo . NewFilePost )
m . Post ( "/_preview/*" , bindIgnErr ( auth . EditPreviewDiffForm { } ) , repo . DiffPreviewPost )
m . Combo ( "/_delete/*" ) . Get ( repo . DeleteFile ) .
Post ( bindIgnErr ( auth . DeleteRepoFileForm { } ) , repo . DeleteFilePost )
m . Combo ( "/_upload/*" , repo . MustBeAbleToUpload ) .
Get ( repo . UploadFile ) .
2017-04-25 10:24:51 +03:00
Post ( bindIgnErr ( auth . UploadRepoFileForm { } ) , repo . UploadFilePost )
2017-10-30 05:04:25 +03:00
} , context . RepoRefByType ( context . RepoRefBranch ) , repo . MustBeEditable )
m . Group ( "" , func ( ) {
2017-04-25 10:24:51 +03:00
m . Post ( "/upload-file" , repo . UploadFileToServer )
m . Post ( "/upload-remove" , bindIgnErr ( auth . RemoveUploadFileForm { } ) , repo . RemoveUploadFileFromServer )
2017-10-30 05:04:25 +03:00
} , context . RepoRef ( ) , repo . MustBeEditable , repo . MustBeAbleToUpload )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) , reqRepoCodeWriter , repo . MustBeNotEmpty )
2017-10-15 22:59:24 +03:00
m . Group ( "/branches" , func ( ) {
2017-10-30 05:04:25 +03:00
m . Group ( "/_new/" , func ( ) {
m . Post ( "/branch/*" , context . RepoRefByType ( context . RepoRefBranch ) , repo . CreateBranch )
m . Post ( "/tag/*" , context . RepoRefByType ( context . RepoRefTag ) , repo . CreateBranch )
m . Post ( "/commit/*" , context . RepoRefByType ( context . RepoRefCommit ) , repo . CreateBranch )
} , bindIgnErr ( auth . NewBranchForm { } ) )
2017-10-26 03:49:16 +03:00
m . Post ( "/delete" , repo . DeleteBranchPost )
m . Post ( "/restore" , repo . RestoreBranchPost )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) , reqRepoCodeWriter , repo . MustBeNotEmpty )
2017-10-26 03:49:16 +03:00
2018-11-28 14:26:14 +03:00
} , reqSignIn , context . RepoAssignment ( ) , context . UnitTypes ( ) )
2017-05-18 17:54:24 +03:00
// Releases
m . Group ( "/:username/:reponame" , func ( ) {
m . Group ( "/releases" , func ( ) {
2019-01-18 03:01:04 +03:00
m . Get ( "/" , repo . MustBeNotEmpty , repo . Releases )
} , repo . MustBeNotEmpty , context . RepoRef ( ) )
2017-06-18 06:38:24 +03:00
m . Group ( "/releases" , func ( ) {
2017-05-18 17:54:24 +03:00
m . Get ( "/new" , repo . NewRelease )
m . Post ( "/new" , bindIgnErr ( auth . NewReleaseForm { } ) , repo . NewReleasePost )
m . Post ( "/delete" , repo . DeleteRelease )
2019-01-23 21:58:38 +03:00
} , reqSignIn , repo . MustBeNotEmpty , context . RepoMustNotBeArchived ( ) , reqRepoReleaseWriter , context . RepoRef ( ) )
2017-05-18 17:54:24 +03:00
m . Group ( "/releases" , func ( ) {
m . Get ( "/edit/*" , repo . EditRelease )
m . Post ( "/edit/*" , bindIgnErr ( auth . EditReleaseForm { } ) , repo . EditReleasePost )
2019-01-23 21:58:38 +03:00
} , reqSignIn , repo . MustBeNotEmpty , context . RepoMustNotBeArchived ( ) , reqRepoReleaseWriter , func ( ctx * context . Context ) {
2017-05-18 17:54:24 +03:00
var err error
ctx . Repo . Commit , err = ctx . Repo . GitRepo . GetBranchCommit ( ctx . Repo . Repository . DefaultBranch )
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetBranchCommit" , err )
2017-05-18 17:54:24 +03:00
return
}
2017-10-26 04:37:33 +03:00
ctx . Repo . CommitsCount , err = ctx . Repo . GetCommitsCount ( )
2017-05-18 17:54:24 +03:00
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetCommitsCount" , err )
2017-05-18 17:54:24 +03:00
return
}
ctx . Data [ "CommitsCount" ] = ctx . Repo . CommitsCount
} )
2019-01-30 19:45:48 +03:00
} , ignSignIn , context . RepoAssignment ( ) , context . UnitTypes ( ) , reqRepoReleaseReader )
2017-04-25 10:24:51 +03:00
2018-04-11 05:51:44 +03:00
m . Group ( "/:username/:reponame" , func ( ) {
2018-06-21 12:09:46 +03:00
m . Post ( "/topics" , repo . TopicsPost )
2019-01-24 13:22:27 +03:00
} , context . RepoAssignment ( ) , context . RepoMustNotBeArchived ( ) , reqRepoAdmin )
2018-04-11 05:51:44 +03:00
2017-04-25 10:24:51 +03:00
m . Group ( "/:username/:reponame" , func ( ) {
m . Group ( "" , func ( ) {
2019-01-23 07:10:38 +03:00
m . Get ( "/^:type(issues|pulls)$" , repo . Issues )
2017-04-25 10:24:51 +03:00
m . Get ( "/^:type(issues|pulls)$/:index" , repo . ViewIssue )
2018-11-28 14:26:14 +03:00
m . Get ( "/labels/" , reqRepoIssuesOrPullsReader , repo . RetrieveLabels , repo . Labels )
m . Get ( "/milestones" , reqRepoIssuesOrPullsReader , repo . Milestones )
2017-06-03 08:56:36 +03:00
} , context . RepoRef ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/wiki" , func ( ) {
m . Get ( "/?:page" , repo . Wiki )
m . Get ( "/_pages" , repo . WikiPages )
m . Group ( "" , func ( ) {
m . Combo ( "/_new" ) . Get ( repo . NewWiki ) .
Post ( bindIgnErr ( auth . NewWikiForm { } ) , repo . NewWikiPost )
m . Combo ( "/:page/_edit" ) . Get ( repo . EditWiki ) .
Post ( bindIgnErr ( auth . NewWikiForm { } ) , repo . EditWikiPost )
m . Post ( "/:page/delete" , repo . DeleteWikiPagePost )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) , reqSignIn , reqRepoWikiWriter )
2017-09-30 07:04:16 +03:00
} , repo . MustEnableWiki , context . RepoRef ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/wiki" , func ( ) {
m . Get ( "/raw/*" , repo . WikiRaw )
2017-09-30 07:04:16 +03:00
} , repo . MustEnableWiki )
2017-04-25 10:24:51 +03:00
2017-10-15 02:17:39 +03:00
m . Group ( "/activity" , func ( ) {
m . Get ( "" , repo . Activity )
m . Get ( "/:period" , repo . Activity )
2019-01-18 03:01:04 +03:00
} , context . RepoRef ( ) , repo . MustBeNotEmpty , context . RequireRepoReaderOr ( models . UnitTypePullRequests , models . UnitTypeIssues , models . UnitTypeReleases ) )
2017-10-15 02:17:39 +03:00
2019-01-18 03:01:04 +03:00
m . Get ( "/archive/*" , repo . MustBeNotEmpty , reqRepoCodeReader , repo . Download )
2017-04-25 10:24:51 +03:00
2017-10-26 03:49:16 +03:00
m . Group ( "/branches" , func ( ) {
m . Get ( "" , repo . Branches )
2019-01-18 03:01:04 +03:00
} , repo . MustBeNotEmpty , context . RepoRef ( ) , reqRepoCodeReader )
2017-10-26 03:49:16 +03:00
2017-04-25 10:24:51 +03:00
m . Group ( "/pulls/:index" , func ( ) {
2018-01-05 13:56:52 +03:00
m . Get ( ".diff" , repo . DownloadPullDiff )
2018-01-07 16:10:20 +03:00
m . Get ( ".patch" , repo . DownloadPullPatch )
2017-04-25 10:24:51 +03:00
m . Get ( "/commits" , context . RepoRef ( ) , repo . ViewPullCommits )
2019-01-23 21:58:38 +03:00
m . Post ( "/merge" , context . RepoMustNotBeArchived ( ) , reqRepoPullsWriter , bindIgnErr ( auth . MergePullRequestForm { } ) , repo . MergePullRequest )
m . Post ( "/cleanup" , context . RepoMustNotBeArchived ( ) , context . RepoRef ( ) , repo . CleanUpPullRequest )
2018-08-06 07:43:22 +03:00
m . Group ( "/files" , func ( ) {
2018-08-14 20:49:33 +03:00
m . Get ( "" , context . RepoRef ( ) , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . SetWhitespaceBehavior , repo . ViewPullFiles )
2018-08-06 07:43:22 +03:00
m . Group ( "/reviews" , func ( ) {
m . Post ( "/comments" , bindIgnErr ( auth . CodeCommentForm { } ) , repo . CreateCodeComment )
m . Post ( "/submit" , bindIgnErr ( auth . SubmitReviewForm { } ) , repo . SubmitReview )
2019-01-23 21:58:38 +03:00
} , context . RepoMustNotBeArchived ( ) )
2018-08-06 07:43:22 +03:00
} )
2017-09-30 07:04:16 +03:00
} , repo . MustAllowPulls )
2017-04-25 10:24:51 +03:00
2019-02-12 18:09:43 +03:00
m . Group ( "/media" , func ( ) {
m . Get ( "/branch/*" , context . RepoRefByType ( context . RepoRefBranch ) , repo . SingleDownloadOrLFS )
m . Get ( "/tag/*" , context . RepoRefByType ( context . RepoRefTag ) , repo . SingleDownloadOrLFS )
m . Get ( "/commit/*" , context . RepoRefByType ( context . RepoRefCommit ) , repo . SingleDownloadOrLFS )
m . Get ( "/blob/:sha" , context . RepoRefByType ( context . RepoRefBlob ) , repo . DownloadByIDOrLFS )
// "/*" route is deprecated, and kept for backward compatibility
m . Get ( "/*" , context . RepoRefByType ( context . RepoRefLegacy ) , repo . SingleDownloadOrLFS )
} , repo . MustBeNotEmpty , reqRepoCodeReader )
2017-10-30 05:04:25 +03:00
m . Group ( "/raw" , func ( ) {
m . Get ( "/branch/*" , context . RepoRefByType ( context . RepoRefBranch ) , repo . SingleDownload )
m . Get ( "/tag/*" , context . RepoRefByType ( context . RepoRefTag ) , repo . SingleDownload )
m . Get ( "/commit/*" , context . RepoRefByType ( context . RepoRefCommit ) , repo . SingleDownload )
2018-11-18 21:45:40 +03:00
m . Get ( "/blob/:sha" , context . RepoRefByType ( context . RepoRefBlob ) , repo . DownloadByID )
2017-10-30 05:04:25 +03:00
// "/*" route is deprecated, and kept for backward compatibility
m . Get ( "/*" , context . RepoRefByType ( context . RepoRefLegacy ) , repo . SingleDownload )
2019-01-18 03:01:04 +03:00
} , repo . MustBeNotEmpty , reqRepoCodeReader )
2017-10-30 05:04:25 +03:00
m . Group ( "/commits" , func ( ) {
m . Get ( "/branch/*" , context . RepoRefByType ( context . RepoRefBranch ) , repo . RefCommits )
m . Get ( "/tag/*" , context . RepoRefByType ( context . RepoRefTag ) , repo . RefCommits )
m . Get ( "/commit/*" , context . RepoRefByType ( context . RepoRefCommit ) , repo . RefCommits )
// "/*" route is deprecated, and kept for backward compatibility
m . Get ( "/*" , context . RepoRefByType ( context . RepoRefLegacy ) , repo . RefCommits )
2019-01-18 03:01:04 +03:00
} , repo . MustBeNotEmpty , reqRepoCodeReader )
2017-10-30 05:04:25 +03:00
2017-04-25 10:24:51 +03:00
m . Group ( "" , func ( ) {
m . Get ( "/graph" , repo . Graph )
m . Get ( "/commit/:sha([a-f0-9]{7,40})$" , repo . SetEditorconfigIfExists , repo . SetDiffViewStyle , repo . Diff )
2019-01-18 03:01:04 +03:00
} , repo . MustBeNotEmpty , context . RepoRef ( ) , reqRepoCodeReader )
2017-07-27 12:23:38 +03:00
2017-10-30 05:04:25 +03:00
m . Group ( "/src" , func ( ) {
m . Get ( "/branch/*" , context . RepoRefByType ( context . RepoRefBranch ) , repo . Home )
m . Get ( "/tag/*" , context . RepoRefByType ( context . RepoRefTag ) , repo . Home )
m . Get ( "/commit/*" , context . RepoRefByType ( context . RepoRefCommit ) , repo . Home )
// "/*" route is deprecated, and kept for backward compatibility
m . Get ( "/*" , context . RepoRefByType ( context . RepoRefLegacy ) , repo . Home )
} , repo . SetEditorconfigIfExists )
2017-07-27 12:23:38 +03:00
m . Group ( "" , func ( ) {
2017-04-25 10:24:51 +03:00
m . Get ( "/forks" , repo . Forks )
2018-11-28 14:26:14 +03:00
} , context . RepoRef ( ) , reqRepoCodeReader )
2017-08-29 09:53:51 +03:00
m . Get ( "/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)" ,
2019-01-18 03:01:04 +03:00
repo . MustBeNotEmpty , reqRepoCodeReader , repo . RawDiff )
2017-04-25 10:24:51 +03:00
2017-05-18 17:54:24 +03:00
m . Get ( "/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})" , repo . SetEditorconfigIfExists ,
2019-01-18 03:01:04 +03:00
repo . SetDiffViewStyle , repo . MustBeNotEmpty , reqRepoCodeReader , repo . CompareDiff )
2018-11-28 14:26:14 +03:00
} , ignSignIn , context . RepoAssignment ( ) , context . UnitTypes ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/:username/:reponame" , func ( ) {
m . Get ( "/stars" , repo . Stars )
m . Get ( "/watchers" , repo . Watchers )
2018-11-28 14:26:14 +03:00
m . Get ( "/search" , reqRepoCodeReader , repo . Search )
} , ignSignIn , context . RepoAssignment ( ) , context . RepoRef ( ) , context . UnitTypes ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/:username" , func ( ) {
m . Group ( "/:reponame" , func ( ) {
m . Get ( "" , repo . SetEditorconfigIfExists , repo . Home )
m . Get ( "\\.git$" , repo . SetEditorconfigIfExists , repo . Home )
2018-11-28 14:26:14 +03:00
} , ignSignIn , context . RepoAssignment ( ) , context . RepoRef ( ) , context . UnitTypes ( ) )
2017-04-25 10:24:51 +03:00
m . Group ( "/:reponame" , func ( ) {
2017-11-29 02:35:23 +03:00
m . Group ( "\\.git/info/lfs" , func ( ) {
2017-04-25 10:24:51 +03:00
m . Post ( "/objects/batch" , lfs . BatchHandler )
m . Get ( "/objects/:oid/:filename" , lfs . ObjectOidHandler )
m . Any ( "/objects/:oid" , lfs . ObjectOidHandler )
m . Post ( "/objects" , lfs . PostHandler )
2017-11-08 16:04:19 +03:00
m . Post ( "/verify" , lfs . VerifyHandler )
2017-11-28 23:58:37 +03:00
m . Group ( "/locks" , func ( ) {
m . Get ( "/" , lfs . GetListLockHandler )
m . Post ( "/" , lfs . PostLockHandler )
m . Post ( "/verify" , lfs . VerifyLockHandler )
m . Post ( "/:lid/unlock" , lfs . UnLockHandler )
} , context . RepoAssignment ( ) )
2017-04-25 10:24:51 +03:00
m . Any ( "/*" , func ( ctx * context . Context ) {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "" , nil )
2017-04-25 10:24:51 +03:00
} )
} , ignSignInAndCsrf )
m . Any ( "/*" , ignSignInAndCsrf , repo . HTTP )
m . Head ( "/tasks/trigger" , repo . TriggerTask )
} )
} )
// ***** END: Repository *****
m . Group ( "/notifications" , func ( ) {
m . Get ( "" , user . Notifications )
m . Post ( "/status" , user . NotificationStatusPost )
2017-12-07 08:52:57 +03:00
m . Post ( "/purge" , user . NotificationPurgePost )
2017-04-25 10:24:51 +03:00
} , reqSignIn )
2018-07-28 03:19:01 +03:00
if setting . API . EnableSwagger {
m . Get ( "/swagger.v1.json" , templates . JSONRenderer ( ) , routers . SwaggerV1Json )
}
2017-04-25 10:24:51 +03:00
m . Group ( "/api" , func ( ) {
apiv1 . RegisterRoutes ( m )
} , ignSignIn )
m . Group ( "/api/internal" , func ( ) {
// package name internal is ideal but Golang is not allowed, so we use private as package name.
private . RegisterRoutes ( m )
} )
// robots.txt
m . Get ( "/robots.txt" , func ( ctx * context . Context ) {
if setting . HasRobotsTxt {
ctx . ServeFileContent ( path . Join ( setting . CustomPath , "robots.txt" ) )
} else {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "" , nil )
2017-04-25 10:24:51 +03:00
}
} )
2018-11-27 18:18:26 +03:00
// Progressive Web App
m . Get ( "/manifest.json" , templates . JSONRenderer ( ) , func ( ctx * context . Context ) {
ctx . HTML ( 200 , "pwa/manifest_json" )
} )
m . Get ( "/serviceworker.js" , templates . JSRenderer ( ) , func ( ctx * context . Context ) {
ctx . HTML ( 200 , "pwa/serviceworker_js" )
} )
2018-11-05 06:20:00 +03:00
// prometheus metrics endpoint
if setting . Metrics . Enabled {
c := metrics . NewCollector ( )
prometheus . MustRegister ( c )
m . Get ( "/metrics" , routers . Metrics )
}
2017-04-25 10:24:51 +03:00
// Not found handler.
m . NotFound ( routers . NotFound )
}