diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2021-01-26 23:36:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-26 16:36:53 +0100 |
commit | 6433ba0ec3dfde67f45267aa12bd713c4a44c740 (patch) | |
tree | 8813388f7e58ff23ad24af9ccbdb5f0350cb3a09 /routers | |
parent | 3adbbb4255c42cde04d59b6ebf5ead7e3edda3e7 (diff) | |
download | gitea-6433ba0ec3dfde67f45267aa12bd713c4a44c740.tar.gz gitea-6433ba0ec3dfde67f45267aa12bd713c4a44c740.zip |
Move macaron to chi (#14293)
Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR.
- [x] Define `context.ResponseWriter` interface with an implementation `context.Response`.
- [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before.
- [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic .
- [x] Use https://github.com/unrolled/render instead of macaron's internal render
- [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip
- [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK**
- [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha
- [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache
- [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding
- [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors
- [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation`
- [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle.
- [x] Removed macaron log service because it's not need any more. **BREAK**
- [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition.
- [x] Move Git HTTP protocol implementation to use routers directly.
- [x] Fix the problem that chi routes don't support trailing slash but macaron did.
- [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render.
Notices:
- Chi router don't support request with trailing slash
- Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI.
Co-authored-by: 6543 <6543@obermui.de>
Diffstat (limited to 'routers')
96 files changed, 1363 insertions, 1058 deletions
diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 4180076b08..250bc5da5e 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -16,20 +16,20 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/cron" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/mailer" - "gitea.com/macaron/macaron" - "gitea.com/macaron/session" + "gitea.com/go-chi/session" ) const ( @@ -132,7 +132,8 @@ func Dashboard(ctx *context.Context) { } // DashboardPost run an admin operation -func DashboardPost(ctx *context.Context, form auth.AdminDashboardForm) { +func DashboardPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AdminDashboardForm) ctx.Data["Title"] = ctx.Tr("admin.dashboard") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminDashboard"] = true @@ -239,7 +240,7 @@ func Config(ctx *context.Context) { ctx.Data["OfflineMode"] = setting.OfflineMode ctx.Data["DisableRouterLog"] = setting.DisableRouterLog ctx.Data["RunUser"] = setting.RunUser - ctx.Data["RunMode"] = strings.Title(macaron.Env) + ctx.Data["RunMode"] = strings.Title(setting.RunMode) if version, err := git.LocalVersion(); err == nil { ctx.Data["GitVersion"] = version.Original() } diff --git a/routers/admin/auths.go b/routers/admin/auths.go index 7a9d286373..12d0a2ccfa 100644 --- a/routers/admin/auths.go +++ b/routers/admin/auths.go @@ -10,15 +10,16 @@ import ( "regexp" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth/ldap" "code.gitea.io/gitea/modules/auth/oauth2" "code.gitea.io/gitea/modules/auth/pam" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "xorm.io/xorm/convert" ) @@ -206,7 +207,8 @@ func parseSSPIConfig(ctx *context.Context, form auth.AuthenticationForm) (*model } // NewAuthSourcePost response for adding an auth source -func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { +func NewAuthSourcePost(ctx *context.Context) { + form := *web.GetForm(ctx).(*auth.AuthenticationForm) ctx.Data["Title"] = ctx.Tr("admin.auths.new") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true @@ -312,7 +314,8 @@ func EditAuthSource(ctx *context.Context) { } // EditAuthSourcePost response for editing auth source -func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { +func EditAuthSourcePost(ctx *context.Context) { + form := *web.GetForm(ctx).(*auth.AuthenticationForm) ctx.Data["Title"] = ctx.Tr("admin.auths.edit") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true diff --git a/routers/admin/users.go b/routers/admin/users.go index 74fce9a10c..2d40a883af 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -11,12 +11,13 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers" router_user_setting "code.gitea.io/gitea/routers/user/setting" "code.gitea.io/gitea/services/mailer" @@ -63,7 +64,8 @@ func NewUser(ctx *context.Context) { } // NewUserPost response for adding a new user -func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) { +func NewUserPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AdminCreateUserForm) ctx.Data["Title"] = ctx.Tr("admin.users.new_account") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true @@ -214,7 +216,8 @@ func EditUser(ctx *context.Context) { } // EditUserPost response for editting user -func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { +func EditUserPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AdminEditUserForm) ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true diff --git a/routers/admin/users_test.go b/routers/admin/users_test.go index a282507f56..bd00bb2bf1 100644 --- a/routers/admin/users_test.go +++ b/routers/admin/users_test.go @@ -8,8 +8,9 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/web" "github.com/stretchr/testify/assert" ) @@ -39,7 +40,8 @@ func TestNewUserPost_MustChangePassword(t *testing.T) { MustChangePassword: true, } - NewUserPost(ctx, form) + web.SetForm(ctx, &form) + NewUserPost(ctx) assert.NotEmpty(t, ctx.Flash.SuccessMsg) @@ -76,7 +78,8 @@ func TestNewUserPost_MustChangePasswordFalse(t *testing.T) { MustChangePassword: false, } - NewUserPost(ctx, form) + web.SetForm(ctx, &form) + NewUserPost(ctx) assert.NotEmpty(t, ctx.Flash.SuccessMsg) @@ -113,7 +116,8 @@ func TestNewUserPost_InvalidEmail(t *testing.T) { MustChangePassword: false, } - NewUserPost(ctx, form) + web.SetForm(ctx, &form) + NewUserPost(ctx) assert.NotEmpty(t, ctx.Flash.ErrorMsg) } diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go index 0fd9e17f41..1356276f07 100644 --- a/routers/api/v1/admin/org.go +++ b/routers/api/v1/admin/org.go @@ -13,12 +13,13 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" ) // CreateOrg api for create organization -func CreateOrg(ctx *context.APIContext, form api.CreateOrgOption) { +func CreateOrg(ctx *context.APIContext) { // swagger:operation POST /admin/users/{username}/orgs admin adminCreateOrg // --- // summary: Create an organization @@ -43,7 +44,7 @@ func CreateOrg(ctx *context.APIContext, form api.CreateOrgOption) { // "$ref": "#/responses/forbidden" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateOrgOption) u := user.GetUserByParams(ctx) if ctx.Written() { return diff --git a/routers/api/v1/admin/repo.go b/routers/api/v1/admin/repo.go index 73c7d740f8..467f8a22ff 100644 --- a/routers/api/v1/admin/repo.go +++ b/routers/api/v1/admin/repo.go @@ -7,12 +7,13 @@ package admin import ( "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/repo" "code.gitea.io/gitea/routers/api/v1/user" ) // CreateRepo api for creating a repository -func CreateRepo(ctx *context.APIContext, form api.CreateRepoOption) { +func CreateRepo(ctx *context.APIContext) { // swagger:operation POST /admin/users/{username}/repos admin adminCreateRepo // --- // summary: Create a repository on behalf of a user @@ -41,11 +42,11 @@ func CreateRepo(ctx *context.APIContext, form api.CreateRepoOption) { // "$ref": "#/responses/error" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateRepoOption) owner := user.GetUserByParams(ctx) if ctx.Written() { return } - repo.CreateUserRepo(ctx, owner, form) + repo.CreateUserRepo(ctx, owner, *form) } diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 670baf020b..f148710c79 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/password" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/services/mailer" @@ -42,7 +43,7 @@ func parseLoginSource(ctx *context.APIContext, u *models.User, sourceID int64, l } // CreateUser create a user -func CreateUser(ctx *context.APIContext, form api.CreateUserOption) { +func CreateUser(ctx *context.APIContext) { // swagger:operation POST /admin/users admin adminCreateUser // --- // summary: Create a user @@ -64,7 +65,7 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) { // "$ref": "#/responses/forbidden" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateUserOption) u := &models.User{ Name: form.Username, FullName: form.FullName, @@ -119,7 +120,7 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) { } // EditUser api for modifying a user's information -func EditUser(ctx *context.APIContext, form api.EditUserOption) { +func EditUser(ctx *context.APIContext) { // swagger:operation PATCH /admin/users/{username} admin adminEditUser // --- // summary: Edit an existing user @@ -144,7 +145,7 @@ func EditUser(ctx *context.APIContext, form api.EditUserOption) { // "$ref": "#/responses/forbidden" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.EditUserOption) u := user.GetUserByParams(ctx) if ctx.Written() { return @@ -283,7 +284,7 @@ func DeleteUser(ctx *context.APIContext) { } // CreatePublicKey api for creating a public key to a user -func CreatePublicKey(ctx *context.APIContext, form api.CreateKeyOption) { +func CreatePublicKey(ctx *context.APIContext) { // swagger:operation POST /admin/users/{username}/keys admin adminCreatePublicKey // --- // summary: Add a public key on behalf of a user @@ -308,12 +309,12 @@ func CreatePublicKey(ctx *context.APIContext, form api.CreateKeyOption) { // "$ref": "#/responses/forbidden" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateKeyOption) u := user.GetUserByParams(ctx) if ctx.Written() { return } - user.CreateUserPublicKey(ctx, form, u.ID) + user.CreateUserPublicKey(ctx, *form, u.ID) } // DeleteUserPublicKey api for deleting a user's public key diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 876f48ca5c..593551d770 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -66,14 +66,16 @@ package v1 import ( "net/http" + "reflect" "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/admin" "code.gitea.io/gitea/routers/api/v1/misc" "code.gitea.io/gitea/routers/api/v1/notify" @@ -83,11 +85,12 @@ import ( _ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation "code.gitea.io/gitea/routers/api/v1/user" - "gitea.com/macaron/binding" - "gitea.com/macaron/macaron" + "gitea.com/go-chi/binding" + "gitea.com/go-chi/session" + "github.com/go-chi/cors" ) -func sudo() macaron.Handler { +func sudo() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { sudo := ctx.Query("sudo") if len(sudo) == 0 { @@ -117,10 +120,10 @@ func sudo() macaron.Handler { } } -func repoAssignment() macaron.Handler { +func repoAssignment() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - userName := ctx.Params(":username") - repoName := ctx.Params(":reponame") + userName := ctx.Params("username") + repoName := ctx.Params("reponame") var ( owner *models.User @@ -184,7 +187,7 @@ func repoAssignment() macaron.Handler { } // Contexter middleware already checks token for user sign in process. -func reqToken() macaron.Handler { +func reqToken() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if true == ctx.Data["IsApiToken"] { return @@ -201,7 +204,7 @@ func reqToken() macaron.Handler { } } -func reqBasicAuth() macaron.Handler { +func reqBasicAuth() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.Context.IsBasicAuth { ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "basic auth required") @@ -212,7 +215,7 @@ func reqBasicAuth() macaron.Handler { } // reqSiteAdmin user should be the site admin -func reqSiteAdmin() macaron.Handler { +func reqSiteAdmin() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.IsUserSiteAdmin() { ctx.Error(http.StatusForbidden, "reqSiteAdmin", "user should be the site admin") @@ -222,7 +225,7 @@ func reqSiteAdmin() macaron.Handler { } // reqOwner user should be the owner of the repo or site admin. -func reqOwner() macaron.Handler { +func reqOwner() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.IsUserRepoOwner() && !ctx.IsUserSiteAdmin() { ctx.Error(http.StatusForbidden, "reqOwner", "user should be the owner of the repo") @@ -232,7 +235,7 @@ func reqOwner() macaron.Handler { } // reqAdmin user should be an owner or a collaborator with admin write of a repository, or site admin -func reqAdmin() macaron.Handler { +func reqAdmin() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { ctx.Error(http.StatusForbidden, "reqAdmin", "user should be an owner or a collaborator with admin write of a repository") @@ -242,7 +245,7 @@ func reqAdmin() macaron.Handler { } // reqRepoWriter user should have a permission to write to a repo, or be a site admin -func reqRepoWriter(unitTypes ...models.UnitType) macaron.Handler { +func reqRepoWriter(unitTypes ...models.UnitType) func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.IsUserRepoWriter(unitTypes) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { ctx.Error(http.StatusForbidden, "reqRepoWriter", "user should have a permission to write to a repo") @@ -252,7 +255,7 @@ func reqRepoWriter(unitTypes ...models.UnitType) macaron.Handler { } // reqRepoReader user should have specific read permission or be a repo admin or a site admin -func reqRepoReader(unitType models.UnitType) macaron.Handler { +func reqRepoReader(unitType models.UnitType) func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.IsUserRepoReaderSpecific(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { ctx.Error(http.StatusForbidden, "reqRepoReader", "user should have specific read permission or be a repo admin or a site admin") @@ -262,7 +265,7 @@ func reqRepoReader(unitType models.UnitType) macaron.Handler { } // reqAnyRepoReader user should have any permission to read repository or permissions of site admin -func reqAnyRepoReader() macaron.Handler { +func reqAnyRepoReader() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.IsUserRepoReaderAny() && !ctx.IsUserSiteAdmin() { ctx.Error(http.StatusForbidden, "reqAnyRepoReader", "user should have any permission to read repository or permissions of site admin") @@ -272,7 +275,7 @@ func reqAnyRepoReader() macaron.Handler { } // reqOrgOwnership user should be an organization owner, or a site admin -func reqOrgOwnership() macaron.Handler { +func reqOrgOwnership() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if ctx.Context.IsUserSiteAdmin() { return @@ -304,7 +307,7 @@ func reqOrgOwnership() macaron.Handler { } // reqTeamMembership user should be an team member, or a site admin -func reqTeamMembership() macaron.Handler { +func reqTeamMembership() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if ctx.Context.IsUserSiteAdmin() { return @@ -341,7 +344,7 @@ func reqTeamMembership() macaron.Handler { } // reqOrgMembership user should be an organization member, or a site admin -func reqOrgMembership() macaron.Handler { +func reqOrgMembership() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if ctx.Context.IsUserSiteAdmin() { return @@ -371,7 +374,7 @@ func reqOrgMembership() macaron.Handler { } } -func reqGitHook() macaron.Handler { +func reqGitHook() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { if !ctx.User.CanEditGitHook() { ctx.Error(http.StatusForbidden, "", "must be allowed to edit Git hooks") @@ -380,7 +383,7 @@ func reqGitHook() macaron.Handler { } } -func orgAssignment(args ...bool) macaron.Handler { +func orgAssignment(args ...bool) func(ctx *context.APIContext) { var ( assignOrg bool assignTeam bool @@ -500,13 +503,6 @@ func mustEnableIssuesOrPulls(ctx *context.APIContext) { } } -func mustEnableUserHeatmap(ctx *context.APIContext) { - if !setting.Service.EnableUserHeatmap { - ctx.NotFound() - return - } -} - func mustNotBeArchived(ctx *context.APIContext) { if ctx.Repo.Repository.IsArchived { ctx.NotFound() @@ -514,18 +510,59 @@ func mustNotBeArchived(ctx *context.APIContext) { } } -// RegisterRoutes registers all v1 APIs routes to web application. -func RegisterRoutes(m *macaron.Macaron) { - bind := binding.Bind +// bind binding an obj to a func(ctx *context.APIContext) +func bind(obj interface{}) http.HandlerFunc { + var tp = reflect.TypeOf(obj) + for tp.Kind() == reflect.Ptr { + tp = tp.Elem() + } + return web.Wrap(func(ctx *context.APIContext) { + var theObj = reflect.New(tp).Interface() // create a new form obj for every request but not use obj directly + errs := binding.Bind(ctx.Req, theObj) + if len(errs) > 0 { + ctx.Error(422, "validationError", errs[0].Error()) + return + } + web.SetForm(ctx, theObj) + }) +} - if setting.API.EnableSwagger { - m.Get("/swagger", misc.Swagger) // Render V1 by default +// Routes registers all v1 APIs routes to web application. +func Routes() *web.Route { + var m = web.NewRoute() + + m.Use(session.Sessioner(session.Options{ + Provider: setting.SessionConfig.Provider, + ProviderConfig: setting.SessionConfig.ProviderConfig, + CookieName: setting.SessionConfig.CookieName, + CookiePath: setting.SessionConfig.CookiePath, + Gclifetime: setting.SessionConfig.Gclifetime, + Maxlifetime: setting.SessionConfig.Maxlifetime, + Secure: setting.SessionConfig.Secure, + Domain: setting.SessionConfig.Domain, + })) + m.Use(securityHeaders()) + if setting.CORSConfig.Enabled { + m.Use(cors.Handler(cors.Options{ + //Scheme: setting.CORSConfig.Scheme, // FIXME: the cors middleware needs scheme option + AllowedOrigins: setting.CORSConfig.AllowDomain, + //setting.CORSConfig.AllowSubdomain // FIXME: the cors middleware needs allowSubdomain option + AllowedMethods: setting.CORSConfig.Methods, + AllowCredentials: setting.CORSConfig.AllowCredentials, + MaxAge: int(setting.CORSConfig.MaxAge.Seconds()), + })) } + m.Use(context.APIContexter()) + m.Use(context.ToggleAPI(&context.ToggleOptions{ + SignInRequired: setting.Service.RequireSignInView, + })) - m.Group("/v1", func() { + m.Group("", func() { // Miscellaneous if setting.API.EnableSwagger { - m.Get("/swagger", misc.Swagger) + m.Get("/swagger", func(ctx *context.APIContext) { + ctx.Redirect("/api/swagger") + }) } m.Get("/version", misc.Version) m.Get("/signing-key.gpg", misc.SigningKey) @@ -544,7 +581,7 @@ func RegisterRoutes(m *macaron.Macaron) { Get(notify.ListNotifications). Put(notify.ReadNotifications) m.Get("/new", notify.NewAvailable) - m.Combo("/threads/:id"). + m.Combo("/threads/{id}"). Get(notify.GetThread). Patch(notify.ReadThread) }, reqToken()) @@ -553,28 +590,31 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/users", func() { m.Get("/search", user.Search) - m.Group("/:username", func() { + m.Group("/{username}", func() { m.Get("", user.GetInfo) - m.Get("/heatmap", mustEnableUserHeatmap, user.GetUserHeatmapData) + + if setting.Service.EnableUserHeatmap { + m.Get("/heatmap", user.GetUserHeatmapData) + } m.Get("/repos", user.ListUserRepos) m.Group("/tokens", func() { m.Combo("").Get(user.ListAccessTokens). Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) - m.Combo("/:id").Delete(user.DeleteAccessToken) + m.Combo("/{id}").Delete(user.DeleteAccessToken) }, reqBasicAuth()) }) }) m.Group("/users", func() { - m.Group("/:username", func() { + m.Group("/{username}", func() { m.Get("/keys", user.ListPublicKeys) m.Get("/gpg_keys", user.ListGPGKeys) m.Get("/followers", user.ListFollowers) m.Group("/following", func() { m.Get("", user.ListFollowing) - m.Get("/:target", user.CheckFollowing) + m.Get("/{target}", user.CheckFollowing) }) m.Get("/starred", user.GetStarredRepos) @@ -592,20 +632,20 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/followers", user.ListMyFollowers) m.Group("/following", func() { m.Get("", user.ListMyFollowing) - m.Combo("/:username").Get(user.CheckMyFollowing).Put(user.Follow).Delete(user.Unfollow) + m.Combo("/{username}").Get(user.CheckMyFollowing).Put(user.Follow).Delete(user.Unfollow) }) m.Group("/keys", func() { m.Combo("").Get(user.ListMyPublicKeys). Post(bind(api.CreateKeyOption{}), user.CreatePublicKey) - m.Combo("/:id").Get(user.GetPublicKey). + m.Combo("/{id}").Get(user.GetPublicKey). Delete(user.DeletePublicKey) }) m.Group("/applications", func() { m.Combo("/oauth2"). Get(user.ListOauth2Applications). Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application) - m.Combo("/oauth2/:id"). + m.Combo("/oauth2/{id}"). Delete(user.DeleteOauth2Application). Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application). Get(user.GetOauth2Application) @@ -614,7 +654,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/gpg_keys", func() { m.Combo("").Get(user.ListMyGPGKeys). Post(bind(api.CreateGPGKeyOption{}), user.CreateGPGKey) - m.Combo("/:id").Get(user.GetGPGKey). + m.Combo("/{id}").Get(user.GetGPGKey). Delete(user.DeleteGPGKey) }) @@ -623,7 +663,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/starred", func() { m.Get("", user.GetMyStarredRepos) - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Get("", user.IsStarring) m.Put("", user.Star) m.Delete("", user.Unstar) @@ -639,9 +679,9 @@ func RegisterRoutes(m *macaron.Macaron) { }, reqToken()) // Repositories - m.Post("/org/:org/repos", reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated) + m.Post("/org/{org}/repos", reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated) - m.Combo("/repositories/:id", reqToken()).Get(repo.GetByID) + m.Combo("/repositories/{id}", reqToken()).Get(repo.GetByID) m.Group("/repos", func() { m.Get("/search", repo.Search) @@ -650,10 +690,10 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate) - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Combo("").Get(reqAnyRepoReader(), repo.Get). Delete(reqToken(), reqOwner(), repo.Delete). - Patch(reqToken(), reqAdmin(), context.RepoRefForAPI(), bind(api.EditRepoOption{}), repo.Edit) + Patch(reqToken(), reqAdmin(), context.RepoRefForAPI, bind(api.EditRepoOption{}), repo.Edit) m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer) m.Combo("/notifications"). Get(reqToken(), notify.ListRepoNotifications). @@ -661,15 +701,15 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/hooks", func() { m.Combo("").Get(repo.ListHooks). Post(bind(api.CreateHookOption{}), repo.CreateHook) - m.Group("/:id", func() { + m.Group("/{id}", func() { m.Combo("").Get(repo.GetHook). Patch(bind(api.EditHookOption{}), repo.EditHook). Delete(repo.DeleteHook) - m.Post("/tests", context.RepoRefForAPI(), repo.TestHook) + m.Post("/tests", context.RepoRefForAPI, repo.TestHook) }) m.Group("/git", func() { m.Combo("").Get(repo.ListGitHooks) - m.Group("/:id", func() { + m.Group("/{id}", func() { m.Combo("").Get(repo.GetGitHook). Patch(bind(api.EditGitHookOption{}), repo.EditGitHook). Delete(repo.DeleteGitHook) @@ -678,11 +718,11 @@ func RegisterRoutes(m *macaron.Macaron) { }, reqToken(), reqAdmin()) m.Group("/collaborators", func() { m.Get("", reqAnyRepoReader(), repo.ListCollaborators) - m.Combo("/:collaborator").Get(reqAnyRepoReader(), repo.IsCollaborator). + m.Combo("/{collaborator}").Get(reqAnyRepoReader(), repo.IsCollaborator). Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator). Delete(reqAdmin(), repo.DeleteCollaborator) }, reqToken()) - m.Get("/raw/*", context.RepoRefForAPI(), reqRepoReader(models.UnitTypeCode), repo.GetRawFile) + m.Get("/raw/*", context.RepoRefForAPI, reqRepoReader(models.UnitTypeCode), repo.GetRawFile) m.Get("/archive/*", reqRepoReader(models.UnitTypeCode), repo.GetArchive) m.Combo("/forks").Get(repo.ListForks). Post(reqToken(), reqRepoReader(models.UnitTypeCode), bind(api.CreateForkOption{}), repo.CreateFork) @@ -695,7 +735,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/branch_protections", func() { m.Get("", repo.ListBranchProtections) m.Post("", bind(api.CreateBranchProtectionOption{}), repo.CreateBranchProtection) - m.Group("/:name", func() { + m.Group("/{name}", func() { m.Get("", repo.GetBranchProtection) m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection) m.Delete("", repo.DeleteBranchProtection) @@ -707,19 +747,19 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/keys", func() { m.Combo("").Get(repo.ListDeployKeys). Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey) - m.Combo("/:id").Get(repo.GetDeployKey). + m.Combo("/{id}").Get(repo.GetDeployKey). Delete(repo.DeleteDeploykey) }, reqToken(), reqAdmin()) m.Group("/times", func() { m.Combo("").Get(repo.ListTrackedTimesByRepository) - m.Combo("/:timetrackingusername").Get(repo.ListTrackedTimesByUser) + m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser) }, mustEnableIssues, reqToken()) m.Group("/issues", func() { m.Combo("").Get(repo.ListIssues). Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue) m.Group("/comments", func() { m.Get("", repo.ListRepoIssueComments) - m.Group("/:id", func() { + m.Group("/{id}", func() { m.Combo(""). Get(repo.GetIssueComment). Patch(mustNotBeArchived, reqToken(), bind(api.EditIssueCommentOption{}), repo.EditIssueComment). @@ -730,13 +770,13 @@ func RegisterRoutes(m *macaron.Macaron) { Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction) }) }) - m.Group("/:index", func() { + m.Group("/{index}", func() { m.Combo("").Get(repo.GetIssue). Patch(reqToken(), bind(api.EditIssueOption{}), repo.EditIssue) m.Group("/comments", func() { m.Combo("").Get(repo.ListIssueComments). Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment) - m.Combo("/:id", reqToken()).Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueCommentDeprecated). + m.Combo("/{id}", reqToken()).Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueCommentDeprecated). Delete(repo.DeleteIssueCommentDeprecated) }) m.Group("/labels", func() { @@ -744,14 +784,14 @@ func RegisterRoutes(m *macaron.Macaron) { Post(reqToken(), bind(api.IssueLabelsOption{}), repo.AddIssueLabels). Put(reqToken(), bind(api.IssueLabelsOption{}), repo.ReplaceIssueLabels). Delete(reqToken(), repo.ClearIssueLabels) - m.Delete("/:id", reqToken(), repo.DeleteIssueLabel) + m.Delete("/{id}", reqToken(), repo.DeleteIssueLabel) }) m.Group("/times", func() { m.Combo(""). Get(repo.ListTrackedTimes). Post(bind(api.AddTimeOption{}), repo.AddTime). Delete(repo.ResetIssueTime) - m.Delete("/:id", repo.DeleteTime) + m.Delete("/{id}", repo.DeleteTime) }, reqToken()) m.Combo("/deadline").Post(reqToken(), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline) m.Group("/stopwatch", func() { @@ -762,8 +802,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/subscriptions", func() { m.Get("", repo.GetIssueSubscribers) m.Get("/check", reqToken(), repo.CheckIssueSubscription) - m.Put("/:user", reqToken(), repo.AddIssueSubscription) - m.Delete("/:user", reqToken(), repo.DelIssueSubscription) + m.Put("/{user}", reqToken(), repo.AddIssueSubscription) + m.Delete("/{user}", reqToken(), repo.DelIssueSubscription) }) m.Combo("/reactions"). Get(repo.GetIssueReactions). @@ -774,7 +814,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/labels", func() { m.Combo("").Get(repo.ListLabels). Post(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.CreateLabelOption{}), repo.CreateLabel) - m.Combo("/:id").Get(repo.GetLabel). + m.Combo("/{id}").Get(repo.GetLabel). Patch(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel). Delete(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), repo.DeleteLabel) }) @@ -783,7 +823,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/milestones", func() { m.Combo("").Get(repo.ListMilestones). Post(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone) - m.Combo("/:id").Get(repo.GetMilestone). + m.Combo("/{id}").Get(repo.GetMilestone). Patch(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone). Delete(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), repo.DeleteMilestone) }) @@ -797,30 +837,30 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/releases", func() { m.Combo("").Get(repo.ListReleases). Post(reqToken(), reqRepoWriter(models.UnitTypeReleases), context.ReferencesGitRepo(false), bind(api.CreateReleaseOption{}), repo.CreateRelease) - m.Group("/:id", func() { + m.Group("/{id}", func() { m.Combo("").Get(repo.GetRelease). Patch(reqToken(), reqRepoWriter(models.UnitTypeReleases), context.ReferencesGitRepo(false), bind(api.EditReleaseOption{}), repo.EditRelease). Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteRelease) m.Group("/assets", func() { m.Combo("").Get(repo.ListReleaseAttachments). Post(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.CreateReleaseAttachment) - m.Combo("/:asset").Get(repo.GetReleaseAttachment). + m.Combo("/{asset}").Get(repo.GetReleaseAttachment). Patch(reqToken(), reqRepoWriter(models.UnitTypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment). Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteReleaseAttachment) }) }) m.Group("/tags", func() { - m.Combo("/:tag"). + m.Combo("/{tag}"). Get(repo.GetReleaseTag). Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteReleaseTag) }) }, reqRepoReader(models.UnitTypeReleases)) m.Post("/mirror-sync", reqToken(), reqRepoWriter(models.UnitTypeCode), repo.MirrorSync) - m.Get("/editorconfig/:filename", context.RepoRefForAPI(), reqRepoReader(models.UnitTypeCode), repo.GetEditorconfig) + m.Get("/editorconfig/{filename}", context.RepoRefForAPI, reqRepoReader(models.UnitTypeCode), repo.GetEditorconfig) m.Group("/pulls", func() { - m.Combo("").Get(bind(api.ListPullRequestsOptions{}), repo.ListPullRequests). + m.Combo("").Get(repo.ListPullRequests). Post(reqToken(), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest) - m.Group("/:index", func() { + m.Group("/{index}", func() { m.Combo("").Get(repo.GetPullRequest). Patch(reqToken(), reqRepoWriter(models.UnitTypePullRequests), bind(api.EditPullRequestOption{}), repo.EditPullRequest) m.Get(".diff", repo.DownloadPullDiff) @@ -832,7 +872,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo(""). Get(repo.ListPullReviews). Post(reqToken(), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview) - m.Group("/:id", func() { + m.Group("/{id}", func() { m.Combo(""). Get(repo.GetPullReview). Delete(reqToken(), repo.DeletePullReview). @@ -847,25 +887,25 @@ func RegisterRoutes(m *macaron.Macaron) { }) }, mustAllowPulls, reqRepoReader(models.UnitTypeCode), context.ReferencesGitRepo(false)) m.Group("/statuses", func() { - m.Combo("/:sha").Get(repo.GetCommitStatuses). + m.Combo("/{sha}").Get(repo.GetCommitStatuses). Post(reqToken(), bind(api.CreateStatusOption{}), repo.NewCommitStatus) }, reqRepoReader(models.UnitTypeCode)) m.Group("/commits", func() { m.Get("", repo.GetAllCommits) - m.Group("/:ref", func() { + m.Group("/{ref}", func() { m.Get("/status", repo.GetCombinedCommitStatusByRef) m.Get("/statuses", repo.GetCommitStatusesByRef) }) }, reqRepoReader(models.UnitTypeCode)) m.Group("/git", func() { m.Group("/commits", func() { - m.Get("/:sha", repo.GetSingleCommit) + m.Get("/{sha}", repo.GetSingleCommit) }) m.Get("/refs", repo.GetGitAllRefs) m.Get("/refs/*", repo.GetGitRefs) - m.Get("/trees/:sha", context.RepoRefForAPI(), repo.GetTree) - m.Get("/blobs/:sha", context.RepoRefForAPI(), repo.GetBlob) - m.Get("/tags/:sha", context.RepoRefForAPI(), repo.GetTag) + m.Get("/trees/{sha}", context.RepoRefForAPI, repo.GetTree) + m.Get("/blobs/{sha}", context.RepoRefForAPI, repo.GetBlob) + m.Get("/tags/{sha}", context.RepoRefForAPI, repo.GetTag) }, reqRepoReader(models.UnitTypeCode)) m.Group("/contents", func() { m.Get("", repo.GetContentsList) @@ -880,7 +920,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/topics", func() { m.Combo("").Get(repo.ListTopics). Put(reqToken(), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics) - m.Group("/:topic", func() { + m.Group("/{topic}", func() { m.Combo("").Put(reqToken(), repo.AddTopic). Delete(reqToken(), repo.DeleteTopic) }, reqAdmin()) @@ -892,10 +932,10 @@ func RegisterRoutes(m *macaron.Macaron) { // Organizations m.Get("/user/orgs", reqToken(), org.ListMyOrgs) - m.Get("/users/:username/orgs", org.ListUserOrgs) + m.Get("/users/{username}/orgs", org.ListUserOrgs) m.Post("/orgs", reqToken(), bind(api.CreateOrgOption{}), org.Create) m.Get("/orgs", org.GetAll) - m.Group("/orgs/:org", func() { + m.Group("/orgs/{org}", func() { m.Combo("").Get(org.Get). Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit). Delete(reqToken(), reqOrgOwnership(), org.Delete) @@ -903,12 +943,12 @@ func RegisterRoutes(m *macaron.Macaron) { Post(reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo) m.Group("/members", func() { m.Get("", org.ListMembers) - m.Combo("/:username").Get(org.IsMember). + m.Combo("/{username}").Get(org.IsMember). Delete(reqToken(), reqOrgOwnership(), org.DeleteMember) }) m.Group("/public_members", func() { m.Get("", org.ListPublicMembers) - m.Combo("/:username").Get(org.IsPublicMember). + m.Combo("/{username}").Get(org.IsPublicMember). Put(reqToken(), reqOrgMembership(), org.PublicizeMember). Delete(reqToken(), reqOrgMembership(), org.ConcealMember) }) @@ -920,56 +960,52 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/labels", func() { m.Get("", org.ListLabels) m.Post("", reqToken(), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel) - m.Combo("/:id").Get(org.GetLabel). + m.Combo("/{id}").Get(org.GetLabel). Patch(reqToken(), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel). Delete(reqToken(), reqOrgOwnership(), org.DeleteLabel) }) m.Group("/hooks", func() { m.Combo("").Get(org.ListHooks). Post(bind(api.CreateHookOption{}), org.CreateHook) - m.Combo("/:id").Get(org.GetHook). + m.Combo("/{id}").Get(org.GetHook). Patch(bind(api.EditHookOption{}), org.EditHook). Delete(org.DeleteHook) }, reqToken(), reqOrgOwnership()) }, orgAssignment(true)) - m.Group("/teams/:teamid", func() { + m.Group("/teams/{teamid}", func() { m.Combo("").Get(org.GetTeam). Patch(reqOrgOwnership(), bind(api.EditTeamOption{}), org.EditTeam). Delete(reqOrgOwnership(), org.DeleteTeam) m.Group("/members", func() { m.Get("", org.GetTeamMembers) - m.Combo("/:username"). + m.Combo("/{username}"). Get(org.GetTeamMember). Put(reqOrgOwnership(), org.AddTeamMember). Delete(reqOrgOwnership(), org.RemoveTeamMember) }) m.Group("/repos", func() { m.Get("", org.GetTeamRepos) - m.Combo("/:org/:reponame"). + m.Combo("/{org}/{reponame}"). Put(org.AddTeamRepository). Delete(org.RemoveTeamRepository) }) }, orgAssignment(false, true), reqToken(), reqTeamMembership()) - m.Any("/*", func(ctx *context.APIContext) { - ctx.NotFound() - }) - m.Group("/admin", func() { m.Group("/cron", func() { m.Get("", admin.ListCronTasks) - m.Post("/:task", admin.PostCronTask) + m.Post("/{task}", admin.PostCronTask) }) m.Get("/orgs", admin.GetAllOrgs) m.Group("/users", func() { m.Get("", admin.GetAllUsers) m.Post("", bind(api.CreateUserOption{}), admin.CreateUser) - m.Group("/:username", func() { + m.Group("/{username}", func() { m.Combo("").Patch(bind(api.EditUserOption{}), admin.EditUser). Delete(admin.DeleteUser) m.Group("/keys", func() { m.Post("", bind(api.CreateKeyOption{}), admin.CreatePublicKey) - m.Delete("/:id", admin.DeleteUserPublicKey) + m.Delete("/{id}", admin.DeleteUserPublicKey) }) m.Get("/orgs", org.ListUserOrgs) m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg) @@ -978,23 +1014,26 @@ func RegisterRoutes(m *macaron.Macaron) { }) m.Group("/unadopted", func() { m.Get("", admin.ListUnadoptedRepositories) - m.Post("/:username/:reponame", admin.AdoptRepository) - m.Delete("/:username/:reponame", admin.DeleteUnadoptedRepository) + m.Post("/{username}/{reponame}", admin.AdoptRepository) + m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository) }) }, reqToken(), reqSiteAdmin()) m.Group("/topics", func() { m.Get("/search", repo.TopicSearch) }) - }, securityHeaders(), context.APIContexter(), sudo()) + }, sudo()) + + return m } -func securityHeaders() macaron.Handler { - return func(ctx *macaron.Context) { - ctx.Resp.Before(func(w macaron.ResponseWriter) { +func securityHeaders() func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { // CORB: https://www.chromium.org/Home/chromium-security/corb-for-developers // http://stackoverflow.com/a/3146618/244009 - w.Header().Set("x-content-type-options", "nosniff") + resp.Header().Set("x-content-type-options", "nosniff") + next.ServeHTTP(resp, req) }) } } diff --git a/routers/api/v1/misc/markdown.go b/routers/api/v1/misc/markdown.go index a10c288df4..5718185309 100644 --- a/routers/api/v1/misc/markdown.go +++ b/routers/api/v1/misc/markdown.go @@ -5,6 +5,7 @@ package misc import ( + "io/ioutil" "net/http" "strings" @@ -13,12 +14,13 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "mvdan.cc/xurls/v2" ) // Markdown render markdown document to HTML -func Markdown(ctx *context.APIContext, form api.MarkdownOption) { +func Markdown(ctx *context.APIContext) { // swagger:operation POST /markdown miscellaneous renderMarkdown // --- // summary: Render a markdown document as HTML @@ -37,6 +39,8 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.MarkdownOption) + if ctx.HasAPIError() { ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) return @@ -117,7 +121,7 @@ func MarkdownRaw(ctx *context.APIContext) { // "422": // "$ref": "#/responses/validationError" - body, err := ctx.Req.Body().Bytes() + body, err := ioutil.ReadAll(ctx.Req.Body) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "", err) return diff --git a/routers/api/v1/misc/markdown_test.go b/routers/api/v1/misc/markdown_test.go index 6c81ec8eb4..3ae3165fd3 100644 --- a/routers/api/v1/misc/markdown_test.go +++ b/routers/api/v1/misc/markdown_test.go @@ -15,10 +15,10 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" - "gitea.com/macaron/inject" - "gitea.com/macaron/macaron" "github.com/stretchr/testify/assert" ) @@ -26,25 +26,21 @@ const AppURL = "http://localhost:3000/" const Repo = "gogits/gogs" const AppSubURL = AppURL + Repo + "/" -func createContext(req *http.Request) (*macaron.Context, *httptest.ResponseRecorder) { +func createContext(req *http.Request) (*context.Context, *httptest.ResponseRecorder) { + var rnd = templates.HTMLRenderer() resp := httptest.NewRecorder() - c := &macaron.Context{ - Injector: inject.New(), - Req: macaron.Request{Request: req}, - Resp: macaron.NewResponseWriter(req.Method, resp), - Render: &macaron.DummyRender{ResponseWriter: resp}, - Data: make(map[string]interface{}), + c := &context.Context{ + Req: req, + Resp: context.NewResponse(resp), + Render: rnd, + Data: make(map[string]interface{}), } - c.Map(c) - c.Map(req) return c, resp } -func wrap(ctx *macaron.Context) *context.APIContext { +func wrap(ctx *context.Context) *context.APIContext { return &context.APIContext{ - Context: &context.Context{ - Context: ctx, - }, + Context: ctx, } } @@ -115,7 +111,8 @@ Here are some links to the most important topics. You can find the full list of for i := 0; i < len(testCases); i += 2 { options.Text = testCases[i] - Markdown(ctx, options) + web.SetForm(ctx, &options) + Markdown(ctx) assert.Equal(t, testCases[i+1], resp.Body.String()) resp.Body.Reset() } @@ -156,7 +153,8 @@ func TestAPI_RenderSimple(t *testing.T) { for i := 0; i < len(simpleCases); i += 2 { options.Text = simpleCases[i] - Markdown(ctx, options) + web.SetForm(ctx, &options) + Markdown(ctx) assert.Equal(t, simpleCases[i+1], resp.Body.String()) resp.Body.Reset() } @@ -174,7 +172,7 @@ func TestAPI_RenderRaw(t *testing.T) { ctx := wrap(m) for i := 0; i < len(simpleCases); i += 2 { - ctx.Req.Request.Body = ioutil.NopCloser(strings.NewReader(simpleCases[i])) + ctx.Req.Body = ioutil.NopCloser(strings.NewReader(simpleCases[i])) MarkdownRaw(ctx) assert.Equal(t, simpleCases[i+1], resp.Body.String()) resp.Body.Reset() diff --git a/routers/api/v1/org/hook.go b/routers/api/v1/org/hook.go index cce959bb49..ed827c48d4 100644 --- a/routers/api/v1/org/hook.go +++ b/routers/api/v1/org/hook.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -85,7 +86,7 @@ func GetHook(ctx *context.APIContext) { } // CreateHook create a hook for an organization -func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { +func CreateHook(ctx *context.APIContext) { // swagger:operation POST /orgs/{org}/hooks/ organization orgCreateHook // --- // summary: Create a hook @@ -108,15 +109,16 @@ func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { // "201": // "$ref": "#/responses/Hook" + form := web.GetForm(ctx).(*api.CreateHookOption) //TODO in body params - if !utils.CheckCreateHookOption(ctx, &form) { + if !utils.CheckCreateHookOption(ctx, form) { return } - utils.AddOrgHook(ctx, &form) + utils.AddOrgHook(ctx, form) } // EditHook modify a hook of a repository -func EditHook(ctx *context.APIContext, form api.EditHookOption) { +func EditHook(ctx *context.APIContext) { // swagger:operation PATCH /orgs/{org}/hooks/{id} organization orgEditHook // --- // summary: Update a hook @@ -144,9 +146,11 @@ func EditHook(ctx *context.APIContext, form api.EditHookOption) { // "200": // "$ref": "#/responses/Hook" + form := web.GetForm(ctx).(*api.EditHookOption) + //TODO in body params hookID := ctx.ParamsInt64(":id") - utils.EditOrgHook(ctx, &form, hookID) + utils.EditOrgHook(ctx, form, hookID) } // DeleteHook delete a hook of an organization diff --git a/routers/api/v1/org/label.go b/routers/api/v1/org/label.go index 9a8a4fa291..76061f163a 100644 --- a/routers/api/v1/org/label.go +++ b/routers/api/v1/org/label.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -52,7 +53,7 @@ func ListLabels(ctx *context.APIContext) { } // CreateLabel create a label for a repository -func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { +func CreateLabel(ctx *context.APIContext) { // swagger:operation POST /orgs/{org}/labels organization orgCreateLabel // --- // summary: Create a label for an organization @@ -75,7 +76,7 @@ func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { // "$ref": "#/responses/Label" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateLabelOption) form.Color = strings.Trim(form.Color, " ") if len(form.Color) == 6 { form.Color = "#" + form.Color @@ -144,7 +145,7 @@ func GetLabel(ctx *context.APIContext) { } // EditLabel modify a label for an Organization -func EditLabel(ctx *context.APIContext, form api.EditLabelOption) { +func EditLabel(ctx *context.APIContext) { // swagger:operation PATCH /orgs/{org}/labels/{id} organization orgEditLabel // --- // summary: Update a label @@ -173,7 +174,7 @@ func EditLabel(ctx *context.APIContext, form api.EditLabelOption) { // "$ref": "#/responses/Label" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.EditLabelOption) label, err := models.GetLabelInOrgByID(ctx.Org.Organization.ID, ctx.ParamsInt64(":id")) if err != nil { if models.IsErrOrgLabelNotExist(err) { diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index ca3e10173b..61e09e1126 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -149,7 +150,7 @@ func GetAll(ctx *context.APIContext) { } // Create api for create organization -func Create(ctx *context.APIContext, form api.CreateOrgOption) { +func Create(ctx *context.APIContext) { // swagger:operation POST /orgs organization orgCreate // --- // summary: Create an organization @@ -169,7 +170,7 @@ func Create(ctx *context.APIContext, form api.CreateOrgOption) { // "$ref": "#/responses/forbidden" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateOrgOption) if !ctx.User.CanCreateOrganization() { ctx.Error(http.StatusForbidden, "Create organization not allowed", nil) return @@ -231,7 +232,7 @@ func Get(ctx *context.APIContext) { } // Edit change an organization's information -func Edit(ctx *context.APIContext, form api.EditOrgOption) { +func Edit(ctx *context.APIContext) { // swagger:operation PATCH /orgs/{org} organization orgEdit // --- // summary: Edit an organization @@ -253,7 +254,7 @@ func Edit(ctx *context.APIContext, form api.EditOrgOption) { // responses: // "200": // "$ref": "#/responses/Organization" - + form := web.GetForm(ctx).(*api.EditOrgOption) org := ctx.Org.Organization org.FullName = form.FullName org.Description = form.Description diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 72387dcbf7..c749751ac4 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -131,7 +132,7 @@ func GetTeam(ctx *context.APIContext) { } // CreateTeam api for create a team -func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) { +func CreateTeam(ctx *context.APIContext) { // swagger:operation POST /orgs/{org}/teams organization orgCreateTeam // --- // summary: Create a team @@ -154,7 +155,7 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) { // "$ref": "#/responses/Team" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateTeamOption) team := &models.Team{ OrgID: ctx.Org.Organization.ID, Name: form.Name, @@ -190,7 +191,7 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) { } // EditTeam api for edit a team -func EditTeam(ctx *context.APIContext, form api.EditTeamOption) { +func EditTeam(ctx *context.APIContext) { // swagger:operation PATCH /teams/{id} organization orgEditTeam // --- // summary: Edit a team @@ -212,6 +213,8 @@ func EditTeam(ctx *context.APIContext, form api.EditTeamOption) { // "200": // "$ref": "#/responses/Team" + form := web.GetForm(ctx).(*api.EditTeamOption) + team := ctx.Org.Team if err := team.GetUnits(); err != nil { ctx.InternalServerError(err) diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 9a0a552bad..790464c8bc 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" ) @@ -175,7 +176,7 @@ func DeleteBranch(ctx *context.APIContext) { } // CreateBranch creates a branch for a user's repository -func CreateBranch(ctx *context.APIContext, opt api.CreateBranchRepoOption) { +func CreateBranch(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/branches repository repoCreateBranch // --- // summary: Create a branch @@ -206,6 +207,7 @@ func CreateBranch(ctx *context.APIContext, opt api.CreateBranchRepoOption) { // "409": // description: The branch with the same name already exists. + opt := web.GetForm(ctx).(*api.CreateBranchRepoOption) if ctx.Repo.Repository.IsEmpty { ctx.Error(http.StatusNotFound, "", "Git Repository is empty.") return @@ -395,7 +397,7 @@ func ListBranchProtections(ctx *context.APIContext) { } // CreateBranchProtection creates a branch protection for a repo -func CreateBranchProtection(ctx *context.APIContext, form api.CreateBranchProtectionOption) { +func CreateBranchProtection(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/branch_protections repository repoCreateBranchProtection // --- // summary: Create a branch protections for a repository @@ -428,6 +430,7 @@ func CreateBranchProtection(ctx *context.APIContext, form api.CreateBranchProtec // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.CreateBranchProtectionOption) repo := ctx.Repo.Repository // Currently protection must match an actual branch @@ -561,7 +564,7 @@ func CreateBranchProtection(ctx *context.APIContext, form api.CreateBranchProtec } // EditBranchProtection edits a branch protection for a repo -func EditBranchProtection(ctx *context.APIContext, form api.EditBranchProtectionOption) { +func EditBranchProtection(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/branch_protections/{name} repository repoEditBranchProtection // --- // summary: Edit a branch protections for a repository. Only fields that are set will be changed @@ -596,7 +599,7 @@ func EditBranchProtection(ctx *context.APIContext, form api.EditBranchProtection // "$ref": "#/responses/notFound" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.EditBranchProtectionOption) repo := ctx.Repo.Repository bpName := ctx.Params(":name") protectBranch, err := models.GetProtectedBranchBy(repo.ID, bpName) diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 497255a474..a4fc1d8f11 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -111,7 +112,7 @@ func IsCollaborator(ctx *context.APIContext) { } // AddCollaborator add a collaborator to a repository -func AddCollaborator(ctx *context.APIContext, form api.AddCollaboratorOption) { +func AddCollaborator(ctx *context.APIContext) { // swagger:operation PUT /repos/{owner}/{repo}/collaborators/{collaborator} repository repoAddCollaborator // --- // summary: Add a collaborator to a repository @@ -143,6 +144,8 @@ func AddCollaborator(ctx *context.APIContext, form api.AddCollaboratorOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.AddCollaboratorOption) + collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) if err != nil { if models.IsErrUserNotExist(err) { diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go index 8c877285a8..a16cca0f4e 100644 --- a/routers/api/v1/repo/commits.go +++ b/routers/api/v1/repo/commits.go @@ -69,7 +69,11 @@ func getCommit(ctx *context.APIContext, identifier string) { defer gitRepo.Close() commit, err := gitRepo.GetCommit(identifier) if err != nil { - ctx.NotFoundOrServerError("GetCommit", git.IsErrNotExist, err) + if git.IsErrNotExist(err) { + ctx.NotFound(identifier) + return + } + ctx.Error(http.StatusInternalServerError, "gitRepo.GetCommit", err) return } diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index bc85fec630..044d0fe565 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/repofiles" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/repo" ) @@ -167,7 +168,7 @@ func canReadFiles(r *context.Repository) bool { } // CreateFile handles API call for creating a file -func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) { +func CreateFile(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/contents/{filepath} repository repoCreateFile // --- // summary: Create a file in a repository @@ -206,6 +207,7 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) { // "422": // "$ref": "#/responses/error" + apiOpts := web.GetForm(ctx).(*api.CreateFileOptions) if ctx.Repo.Repository.IsEmpty { ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty")) } @@ -253,7 +255,7 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) { } // UpdateFile handles API call for updating a file -func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) { +func UpdateFile(ctx *context.APIContext) { // swagger:operation PUT /repos/{owner}/{repo}/contents/{filepath} repository repoUpdateFile // --- // summary: Update a file in a repository @@ -291,7 +293,7 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) { // "$ref": "#/responses/notFound" // "422": // "$ref": "#/responses/error" - + apiOpts := web.GetForm(ctx).(*api.UpdateFileOptions) if ctx.Repo.Repository.IsEmpty { ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty")) } @@ -377,7 +379,7 @@ func createOrUpdateFile(ctx *context.APIContext, opts *repofiles.UpdateRepoFileO } // DeleteFile Delete a fle in a repository -func DeleteFile(ctx *context.APIContext, apiOpts api.DeleteFileOptions) { +func DeleteFile(ctx *context.APIContext) { // swagger:operation DELETE /repos/{owner}/{repo}/contents/{filepath} repository repoDeleteFile // --- // summary: Delete a file in a repository @@ -416,6 +418,7 @@ func DeleteFile(ctx *context.APIContext, apiOpts api.DeleteFileOptions) { // "404": // "$ref": "#/responses/error" + apiOpts := web.GetForm(ctx).(*api.DeleteFileOptions) if !canWriteFiles(ctx.Repo) { ctx.Error(http.StatusForbidden, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{ UserID: ctx.User.ID, diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index 24700f7a7f..55fcefaccc 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" repo_service "code.gitea.io/gitea/services/repository" ) @@ -65,7 +66,7 @@ func ListForks(ctx *context.APIContext) { } // CreateFork create a fork of a repo -func CreateFork(ctx *context.APIContext, form api.CreateForkOption) { +func CreateFork(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/forks repository createFork // --- // summary: Fork a repository @@ -94,6 +95,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.CreateForkOption) repo := ctx.Repo.Repository var forker *models.User // user/org that will own the fork if form.Organization == nil { diff --git a/routers/api/v1/repo/git_hook.go b/routers/api/v1/repo/git_hook.go index 0c538ac6b3..0b4e09cadd 100644 --- a/routers/api/v1/repo/git_hook.go +++ b/routers/api/v1/repo/git_hook.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" ) // ListGitHooks list all Git hooks of a repository @@ -91,7 +92,7 @@ func GetGitHook(ctx *context.APIContext) { } // EditGitHook modify a Git hook of a repository -func EditGitHook(ctx *context.APIContext, form api.EditGitHookOption) { +func EditGitHook(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/hooks/git/{id} repository repoEditGitHook // --- // summary: Edit a Git hook in a repository @@ -123,6 +124,7 @@ func EditGitHook(ctx *context.APIContext, form api.EditGitHookOption) { // "404": // "$ref": "#/responses/notFound" + form := web.GetForm(ctx).(*api.EditGitHookOption) hookID := ctx.Params(":id") hook, err := ctx.Repo.GitRepo.GetHook(hookID) if err != nil { diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 575b1fc480..520a7a0202 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/services/webhook" ) @@ -158,7 +159,7 @@ func TestHook(ctx *context.APIContext) { } // CreateHook create a hook for a repository -func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { +func CreateHook(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/hooks repository repoCreateHook // --- // summary: Create a hook @@ -184,14 +185,16 @@ func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { // responses: // "201": // "$ref": "#/responses/Hook" - if !utils.CheckCreateHookOption(ctx, &form) { + form := web.GetForm(ctx).(*api.CreateHookOption) + + if !utils.CheckCreateHookOption(ctx, form) { return } - utils.AddRepoHook(ctx, &form) + utils.AddRepoHook(ctx, form) } // EditHook modify a hook of a repository -func EditHook(ctx *context.APIContext, form api.EditHookOption) { +func EditHook(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/hooks/{id} repository repoEditHook // --- // summary: Edit a hook in a repository @@ -221,8 +224,9 @@ func EditHook(ctx *context.APIContext, form api.EditHookOption) { // responses: // "200": // "$ref": "#/responses/Hook" + form := web.GetForm(ctx).(*api.EditHookOption) hookID := ctx.ParamsInt64(":id") - utils.EditRepoHook(ctx, &form, hookID) + utils.EditRepoHook(ctx, form, hookID) } // DeleteHook delete a hook of a repository diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index bab8f373ce..17dad97945 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -22,6 +22,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" issue_service "code.gitea.io/gitea/services/issue" ) @@ -448,7 +449,7 @@ func GetIssue(ctx *context.APIContext) { } // CreateIssue create an issue of a repository -func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { +func CreateIssue(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/issues issue issueCreateIssue // --- // summary: Create an issue. If using deadline only the date will be taken into account, and time of day ignored. @@ -480,7 +481,7 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { // "$ref": "#/responses/error" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateIssueOption) var deadlineUnix timeutil.TimeStamp if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) @@ -564,7 +565,7 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { } // EditIssue modify an issue of a repository -func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { +func EditIssue(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/issues/{index} issue issueEditIssue // --- // summary: Edit an issue. If using deadline only the date will be taken into account, and time of day ignored. @@ -603,6 +604,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { // "412": // "$ref": "#/responses/error" + form := web.GetForm(ctx).(*api.EditIssueOption) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { @@ -723,7 +725,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { } // UpdateIssueDeadline updates an issue deadline -func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) { +func UpdateIssueDeadline(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/deadline issue issueEditIssueDeadline // --- // summary: Set an issue deadline. If set to null, the deadline is deleted. If using deadline only the date will be taken into account, and time of day ignored. @@ -759,7 +761,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) { // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" - + form := web.GetForm(ctx).(*api.EditDeadlineOption) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index af69ae981a..d62ca81314 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" comment_service "code.gitea.io/gitea/services/comments" ) @@ -174,7 +175,7 @@ func ListRepoIssueComments(ctx *context.APIContext) { } // CreateIssueComment create a comment for an issue -func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOption) { +func CreateIssueComment(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/comments issue issueCreateComment // --- // summary: Add a comment to an issue @@ -208,7 +209,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti // "$ref": "#/responses/Comment" // "403": // "$ref": "#/responses/forbidden" - + form := web.GetForm(ctx).(*api.CreateIssueCommentOption) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) @@ -298,7 +299,7 @@ func GetIssueComment(ctx *context.APIContext) { } // EditIssueComment modify a comment of an issue -func EditIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) { +func EditIssueComment(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/issues/comments/{id} issue issueEditComment // --- // summary: Edit a comment @@ -337,11 +338,12 @@ func EditIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) // "404": // "$ref": "#/responses/notFound" - editIssueComment(ctx, form) + form := web.GetForm(ctx).(*api.EditIssueCommentOption) + editIssueComment(ctx, *form) } // EditIssueCommentDeprecated modify a comment of an issue -func EditIssueCommentDeprecated(ctx *context.APIContext, form api.EditIssueCommentOption) { +func EditIssueCommentDeprecated(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/issues/{index}/comments/{id} issue issueEditCommentDeprecated // --- // summary: Edit a comment @@ -386,7 +388,8 @@ func EditIssueCommentDeprecated(ctx *context.APIContext, form api.EditIssueComme // "404": // "$ref": "#/responses/notFound" - editIssueComment(ctx, form) + form := web.GetForm(ctx).(*api.EditIssueCommentOption) + editIssueComment(ctx, *form) } func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) { diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go index 8b2a1988fa..d7f64b2d99 100644 --- a/routers/api/v1/repo/issue_label.go +++ b/routers/api/v1/repo/issue_label.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" issue_service "code.gitea.io/gitea/services/issue" ) @@ -64,7 +65,7 @@ func ListIssueLabels(ctx *context.APIContext) { } // AddIssueLabels add labels for an issue -func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { +func AddIssueLabels(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/labels issue issueAddLabel // --- // summary: Add a label to an issue @@ -99,7 +100,8 @@ func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { // "403": // "$ref": "#/responses/forbidden" - issue, labels, err := prepareForReplaceOrAdd(ctx, form) + form := web.GetForm(ctx).(*api.IssueLabelsOption) + issue, labels, err := prepareForReplaceOrAdd(ctx, *form) if err != nil { return } @@ -190,7 +192,7 @@ func DeleteIssueLabel(ctx *context.APIContext) { } // ReplaceIssueLabels replace labels for an issue -func ReplaceIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { +func ReplaceIssueLabels(ctx *context.APIContext) { // swagger:operation PUT /repos/{owner}/{repo}/issues/{index}/labels issue issueReplaceLabels // --- // summary: Replace an issue's labels @@ -224,8 +226,8 @@ func ReplaceIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { // "$ref": "#/responses/LabelList" // "403": // "$ref": "#/responses/forbidden" - - issue, labels, err := prepareForReplaceOrAdd(ctx, form) + form := web.GetForm(ctx).(*api.IssueLabelsOption) + issue, labels, err := prepareForReplaceOrAdd(ctx, *form) if err != nil { return } diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index dfe618480f..3994c6b941 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -90,7 +91,7 @@ func GetIssueCommentReactions(ctx *context.APIContext) { } // PostIssueCommentReaction add a reaction to a comment of an issue -func PostIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption) { +func PostIssueCommentReaction(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issuePostCommentReaction // --- // summary: Add a reaction to a comment of an issue @@ -127,11 +128,13 @@ func PostIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOpti // "403": // "$ref": "#/responses/forbidden" - changeIssueCommentReaction(ctx, form, true) + form := web.GetForm(ctx).(*api.EditReactionOption) + + changeIssueCommentReaction(ctx, *form, true) } // DeleteIssueCommentReaction remove a reaction from a comment of an issue -func DeleteIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption) { +func DeleteIssueCommentReaction(ctx *context.APIContext) { // swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueDeleteCommentReaction // --- // summary: Remove a reaction from a comment of an issue @@ -166,7 +169,9 @@ func DeleteIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp // "403": // "$ref": "#/responses/forbidden" - changeIssueCommentReaction(ctx, form, false) + form := web.GetForm(ctx).(*api.EditReactionOption) + + changeIssueCommentReaction(ctx, *form, false) } func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) { @@ -304,7 +309,7 @@ func GetIssueReactions(ctx *context.APIContext) { } // PostIssueReaction add a reaction to an issue -func PostIssueReaction(ctx *context.APIContext, form api.EditReactionOption) { +func PostIssueReaction(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/reactions issue issuePostIssueReaction // --- // summary: Add a reaction to an issue @@ -340,12 +345,12 @@ func PostIssueReaction(ctx *context.APIContext, form api.EditReactionOption) { // "$ref": "#/responses/Reaction" // "403": // "$ref": "#/responses/forbidden" - - changeIssueReaction(ctx, form, true) + form := web.GetForm(ctx).(*api.EditReactionOption) + changeIssueReaction(ctx, *form, true) } // DeleteIssueReaction remove a reaction from an issue -func DeleteIssueReaction(ctx *context.APIContext, form api.EditReactionOption) { +func DeleteIssueReaction(ctx *context.APIContext) { // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/reactions issue issueDeleteIssueReaction // --- // summary: Remove a reaction from an issue @@ -379,8 +384,8 @@ func DeleteIssueReaction(ctx *context.APIContext, form api.EditReactionOption) { // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/forbidden" - - changeIssueReaction(ctx, form, false) + form := web.GetForm(ctx).(*api.EditReactionOption) + changeIssueReaction(ctx, *form, false) } func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) { diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index 70ce420b77..642704800b 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -132,7 +133,7 @@ func ListTrackedTimes(ctx *context.APIContext) { } // AddTime add time manual to the given issue -func AddTime(ctx *context.APIContext, form api.AddTimeOption) { +func AddTime(ctx *context.APIContext) { // swagger:operation Post /repos/{owner}/{repo}/issues/{index}/times issue issueAddTime // --- // summary: Add tracked time to a issue @@ -168,7 +169,7 @@ func AddTime(ctx *context.APIContext, form api.AddTimeOption) { // "$ref": "#/responses/error" // "403": // "$ref": "#/responses/forbidden" - + form := web.GetForm(ctx).(*api.AddTimeOption) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go index 3e6174f621..b1b465ca11 100644 --- a/routers/api/v1/repo/key.go +++ b/routers/api/v1/repo/key.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -185,7 +186,7 @@ func HandleAddKeyError(ctx *context.APIContext, err error) { } // CreateDeployKey create deploy key for a repository -func CreateDeployKey(ctx *context.APIContext, form api.CreateKeyOption) { +func CreateDeployKey(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/keys repository repoCreateKey // --- // summary: Add a key to a repository @@ -214,6 +215,7 @@ func CreateDeployKey(ctx *context.APIContext, form api.CreateKeyOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.CreateKeyOption) content, err := models.CheckPublicKeyString(form.Key) if err != nil { HandleCheckKeyStringError(ctx, err) diff --git a/routers/api/v1/repo/label.go b/routers/api/v1/repo/label.go index fef6ebf07a..f71683f6ec 100644 --- a/routers/api/v1/repo/label.go +++ b/routers/api/v1/repo/label.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -108,7 +109,7 @@ func GetLabel(ctx *context.APIContext) { } // CreateLabel create a label for a repository -func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { +func CreateLabel(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/labels issue issueCreateLabel // --- // summary: Create a label @@ -137,6 +138,7 @@ func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.CreateLabelOption) form.Color = strings.Trim(form.Color, " ") if len(form.Color) == 6 { form.Color = "#" + form.Color @@ -160,7 +162,7 @@ func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { } // EditLabel modify a label for a repository -func EditLabel(ctx *context.APIContext, form api.EditLabelOption) { +func EditLabel(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/labels/{id} issue issueEditLabel // --- // summary: Update a label @@ -195,6 +197,7 @@ func EditLabel(ctx *context.APIContext, form api.EditLabelOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.EditLabelOption) label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) if err != nil { if models.IsErrRepoLabelNotExist(err) { diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index 0b829c9dfb..61cd12b991 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -12,9 +12,9 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/migrations" @@ -24,10 +24,11 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" ) // Migrate migrate remote git repository to gitea -func Migrate(ctx *context.APIContext, form api.MigrateRepoOptions) { +func Migrate(ctx *context.APIContext) { // swagger:operation POST /repos/migrate repository repoMigrate // --- // summary: Migrate a remote git repository @@ -48,6 +49,8 @@ func Migrate(ctx *context.APIContext, form api.MigrateRepoOptions) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.MigrateRepoOptions) + //get repoOwner var ( repoOwner *models.User diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go index db86d0868f..fc8b4efdbb 100644 --- a/routers/api/v1/repo/milestone.go +++ b/routers/api/v1/repo/milestone.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -110,7 +111,7 @@ func GetMilestone(ctx *context.APIContext) { } // CreateMilestone create a milestone for a repository -func CreateMilestone(ctx *context.APIContext, form api.CreateMilestoneOption) { +func CreateMilestone(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/milestones issue issueCreateMilestone // --- // summary: Create a milestone @@ -136,6 +137,7 @@ func CreateMilestone(ctx *context.APIContext, form api.CreateMilestoneOption) { // responses: // "201": // "$ref": "#/responses/Milestone" + form := web.GetForm(ctx).(*api.CreateMilestoneOption) if form.Deadline == nil { defaultDeadline, _ := time.ParseInLocation("2006-01-02", "9999-12-31", time.Local) @@ -162,7 +164,7 @@ func CreateMilestone(ctx *context.APIContext, form api.CreateMilestoneOption) { } // EditMilestone modify a milestone for a repository by ID and if not available by name -func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) { +func EditMilestone(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/milestones/{id} issue issueEditMilestone // --- // summary: Update a milestone @@ -193,7 +195,7 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) { // responses: // "200": // "$ref": "#/responses/Milestone" - + form := web.GetForm(ctx).(*api.EditMilestoneOption) milestone := getMilestoneByIDOrName(ctx) if ctx.Written() { return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index b2b71180a4..38dac36553 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -11,21 +11,22 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" ) // ListPullRequests returns a list of all PRs -func ListPullRequests(ctx *context.APIContext, form api.ListPullRequestsOptions) { +func ListPullRequests(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/pulls repository repoListPullRequests // --- // summary: List a repo's pull requests @@ -253,7 +254,7 @@ func DownloadPullDiffOrPatch(ctx *context.APIContext, patch bool) { } // CreatePullRequest does what it says -func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption) { +func CreatePullRequest(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/pulls repository repoCreatePullRequest // --- // summary: Create a pull request @@ -284,6 +285,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption // "422": // "$ref": "#/responses/validationError" + form := *web.GetForm(ctx).(*api.CreatePullRequestOption) if form.Head == form.Base { ctx.Error(http.StatusUnprocessableEntity, "BaseHeadSame", "Invalid PullRequest: There are no changes between the head and the base") @@ -437,7 +439,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption } // EditPullRequest does what it says -func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { +func EditPullRequest(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/pulls/{index} repository repoEditPullRequest // --- // summary: Update a pull request. If using deadline only the date will be taken into account, and time of day ignored. @@ -478,6 +480,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { // "422": // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.EditPullRequestOption) pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrPullRequestNotExist(err) { @@ -685,7 +688,7 @@ func IsPullRequestMerged(ctx *context.APIContext) { } // MergePullRequest merges a PR given an index -func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) { +func MergePullRequest(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/merge repository repoMergePullRequest // --- // summary: Merge a pull request @@ -720,6 +723,7 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) { // "409": // "$ref": "#/responses/error" + form := web.GetForm(ctx).(*auth.MergePullRequestForm) pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrPullRequestNotExist(err) { diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index 9e7fd15664..d39db4c660 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" @@ -258,7 +259,7 @@ func DeletePullReview(ctx *context.APIContext) { } // CreatePullReview create a review to an pull request -func CreatePullReview(ctx *context.APIContext, opts api.CreatePullReviewOptions) { +func CreatePullReview(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/reviews repository repoCreatePullReview // --- // summary: Create a review to an pull request @@ -294,6 +295,7 @@ func CreatePullReview(ctx *context.APIContext, opts api.CreatePullReviewOptions) // "422": // "$ref": "#/responses/validationError" + opts := web.GetForm(ctx).(*api.CreatePullReviewOptions) pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrPullRequestNotExist(err) { @@ -373,7 +375,7 @@ func CreatePullReview(ctx *context.APIContext, opts api.CreatePullReviewOptions) } // SubmitPullReview submit a pending review to an pull request -func SubmitPullReview(ctx *context.APIContext, opts api.SubmitPullReviewOptions) { +func SubmitPullReview(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id} repository repoSubmitPullReview // --- // summary: Submit a pending review to an pull request @@ -415,6 +417,7 @@ func SubmitPullReview(ctx *context.APIContext, opts api.SubmitPullReviewOptions) // "422": // "$ref": "#/responses/validationError" + opts := web.GetForm(ctx).(*api.SubmitPullReviewOptions) review, pr, isWrong := prepareSingleReview(ctx) if isWrong { return @@ -542,7 +545,7 @@ func prepareSingleReview(ctx *context.APIContext) (*models.Review, *models.PullR } // CreateReviewRequests create review requests to an pull request -func CreateReviewRequests(ctx *context.APIContext, opts api.PullReviewRequestOptions) { +func CreateReviewRequests(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/requested_reviewers repository repoCreatePullReviewRequests // --- // summary: create review requests for a pull request @@ -577,11 +580,13 @@ func CreateReviewRequests(ctx *context.APIContext, opts api.PullReviewRequestOpt // "$ref": "#/responses/validationError" // "404": // "$ref": "#/responses/notFound" - apiReviewRequest(ctx, opts, true) + + opts := web.GetForm(ctx).(*api.PullReviewRequestOptions) + apiReviewRequest(ctx, *opts, true) } // DeleteReviewRequests delete review requests to an pull request -func DeleteReviewRequests(ctx *context.APIContext, opts api.PullReviewRequestOptions) { +func DeleteReviewRequests(ctx *context.APIContext) { // swagger:operation DELETE /repos/{owner}/{repo}/pulls/{index}/requested_reviewers repository repoDeletePullReviewRequests // --- // summary: cancel review requests for a pull request @@ -616,7 +621,8 @@ func DeleteReviewRequests(ctx *context.APIContext, opts api.PullReviewRequestOpt // "$ref": "#/responses/validationError" // "404": // "$ref": "#/responses/notFound" - apiReviewRequest(ctx, opts, false) + opts := web.GetForm(ctx).(*api.PullReviewRequestOptions) + apiReviewRequest(ctx, *opts, false) } func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions, isAdd bool) { diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index 358cc01143..08d92e6c0a 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" releaseservice "code.gitea.io/gitea/services/release" ) @@ -124,7 +125,7 @@ func ListReleases(ctx *context.APIContext) { } // CreateRelease create a release -func CreateRelease(ctx *context.APIContext, form api.CreateReleaseOption) { +func CreateRelease(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/releases repository repoCreateRelease // --- // summary: Create a release @@ -154,7 +155,7 @@ func CreateRelease(ctx *context.APIContext, form api.CreateReleaseOption) { // "$ref": "#/responses/notFound" // "409": // "$ref": "#/responses/error" - + form := web.GetForm(ctx).(*api.CreateReleaseOption) rel, err := models.GetRelease(ctx.Repo.Repository.ID, form.TagName) if err != nil { if !models.IsErrReleaseNotExist(err) { @@ -210,7 +211,7 @@ func CreateRelease(ctx *context.APIContext, form api.CreateReleaseOption) { } // EditRelease edit a release -func EditRelease(ctx *context.APIContext, form api.EditReleaseOption) { +func EditRelease(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/releases/{id} repository repoEditRelease // --- // summary: Update a release @@ -245,6 +246,7 @@ func EditRelease(ctx *context.APIContext, form api.EditReleaseOption) { // "404": // "$ref": "#/responses/notFound" + form := web.GetForm(ctx).(*api.EditReleaseOption) id := ctx.ParamsInt64(":id") rel, err := models.GetReleaseByID(id) if err != nil && !models.IsErrReleaseNotExist(err) { diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index 51e1b160da..0a6425cddc 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/upload" + "code.gitea.io/gitea/modules/web" ) // GetReleaseAttachment gets a single attachment of the release @@ -168,7 +169,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) { } // Get uploaded file from request - file, header, err := ctx.GetFile("attachment") + file, header, err := ctx.Req.FormFile("attachment") if err != nil { ctx.Error(http.StatusInternalServerError, "GetFile", err) return @@ -208,7 +209,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) { } // EditReleaseAttachment updates the given attachment -func EditReleaseAttachment(ctx *context.APIContext, form api.EditAttachmentOptions) { +func EditReleaseAttachment(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoEditReleaseAttachment // --- // summary: Edit a release attachment @@ -247,6 +248,8 @@ func EditReleaseAttachment(ctx *context.APIContext, form api.EditAttachmentOptio // "201": // "$ref": "#/responses/Attachment" + form := web.GetForm(ctx).(*api.EditAttachmentOptions) + // Check if release exists an load release releaseID := ctx.ParamsInt64(":id") attachID := ctx.ParamsInt64(":asset") diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 82d380a814..375f2418b9 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -20,6 +20,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" repo_service "code.gitea.io/gitea/services/repository" ) @@ -277,7 +278,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR } // Create one repository of mine -func Create(ctx *context.APIContext, opt api.CreateRepoOption) { +func Create(ctx *context.APIContext) { // swagger:operation POST /user/repos repository user createCurrentUserRepo // --- // summary: Create a repository @@ -297,17 +298,17 @@ func Create(ctx *context.APIContext, opt api.CreateRepoOption) { // description: The repository with the same name already exists. // "422": // "$ref": "#/responses/validationError" - + opt := web.GetForm(ctx).(*api.CreateRepoOption) if ctx.User.IsOrganization() { // Shouldn't reach this condition, but just in case. ctx.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization") return } - CreateUserRepo(ctx, ctx.User, opt) + CreateUserRepo(ctx, ctx.User, *opt) } // CreateOrgRepoDeprecated create one repository of the organization -func CreateOrgRepoDeprecated(ctx *context.APIContext, opt api.CreateRepoOption) { +func CreateOrgRepoDeprecated(ctx *context.APIContext) { // swagger:operation POST /org/{org}/repos organization createOrgRepoDeprecated // --- // summary: Create a repository in an organization @@ -334,11 +335,11 @@ func CreateOrgRepoDeprecated(ctx *context.APIContext, opt api.CreateRepoOption) // "403": // "$ref": "#/responses/forbidden" - CreateOrgRepo(ctx, opt) + CreateOrgRepo(ctx) } // CreateOrgRepo create one repository of the organization -func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) { +func CreateOrgRepo(ctx *context.APIContext) { // swagger:operation POST /orgs/{org}/repos organization createOrgRepo // --- // summary: Create a repository in an organization @@ -363,7 +364,7 @@ func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) { // "$ref": "#/responses/notFound" // "403": // "$ref": "#/responses/forbidden" - + opt := web.GetForm(ctx).(*api.CreateRepoOption) org, err := models.GetOrgByName(ctx.Params(":org")) if err != nil { if models.IsErrOrgNotExist(err) { @@ -389,7 +390,7 @@ func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) { return } } - CreateUserRepo(ctx, org, opt) + CreateUserRepo(ctx, org, *opt) } // Get one repository @@ -457,7 +458,7 @@ func GetByID(ctx *context.APIContext) { } // Edit edit repository properties -func Edit(ctx *context.APIContext, opts api.EditRepoOption) { +func Edit(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo} repository repoEdit // --- // summary: Edit a repository's properties. Only fields that are set will be changed. @@ -488,6 +489,8 @@ func Edit(ctx *context.APIContext, opts api.EditRepoOption) { // "422": // "$ref": "#/responses/validationError" + opts := *web.GetForm(ctx).(*api.EditRepoOption) + if err := updateBasicProperties(ctx, opts); err != nil { return } diff --git a/routers/api/v1/repo/repo_test.go b/routers/api/v1/repo/repo_test.go index 053134ec61..a1bd3e85d7 100644 --- a/routers/api/v1/repo/repo_test.go +++ b/routers/api/v1/repo/repo_test.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/web" "github.com/stretchr/testify/assert" ) @@ -53,7 +54,9 @@ func TestRepoEdit(t *testing.T) { Archived: &archived, } - Edit(&context.APIContext{Context: ctx, Org: nil}, opts) + var apiCtx = &context.APIContext{Context: ctx, Org: nil} + web.SetForm(apiCtx, &opts) + Edit(apiCtx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.Repository{ @@ -73,7 +76,9 @@ func TestRepoEditNameChange(t *testing.T) { Name: &name, } - Edit(&context.APIContext{Context: ctx, Org: nil}, opts) + var apiCtx = &context.APIContext{Context: ctx, Org: nil} + web.SetForm(apiCtx, &opts) + Edit(apiCtx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.Repository{ diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go index 9c0d902f76..7ab399b572 100644 --- a/routers/api/v1/repo/status.go +++ b/routers/api/v1/repo/status.go @@ -13,11 +13,12 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/repofiles" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) // NewCommitStatus creates a new CommitStatus -func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) { +func NewCommitStatus(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/statuses/{sha} repository repoCreateStatus // --- // summary: Create a commit status @@ -49,6 +50,7 @@ func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) { // "400": // "$ref": "#/responses/error" + form := web.GetForm(ctx).(*api.CreateStatusOption) sha := ctx.Params("sha") if len(sha) == 0 { ctx.Error(http.StatusBadRequest, "sha not given", nil) diff --git a/routers/api/v1/repo/topic.go b/routers/api/v1/repo/topic.go index 41fa37a2c1..c612c2942c 100644 --- a/routers/api/v1/repo/topic.go +++ b/routers/api/v1/repo/topic.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -66,7 +67,7 @@ func ListTopics(ctx *context.APIContext) { } // UpdateTopics updates repo with a new set of topics -func UpdateTopics(ctx *context.APIContext, form api.RepoTopicOptions) { +func UpdateTopics(ctx *context.APIContext) { // swagger:operation PUT /repos/{owner}/{repo}/topics repository repoUpdateTopics // --- // summary: Replace list of topics for a repository @@ -93,6 +94,7 @@ func UpdateTopics(ctx *context.APIContext, form api.RepoTopicOptions) { // "422": // "$ref": "#/responses/invalidTopicsError" + form := web.GetForm(ctx).(*api.RepoTopicOptions) topicNames := form.Topics validTopics, invalidTopics := models.SanitizeAndValidateTopics(topicNames) diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go index a0999a6ce2..656ace032e 100644 --- a/routers/api/v1/repo/transfer.go +++ b/routers/api/v1/repo/transfer.go @@ -14,11 +14,12 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" repo_service "code.gitea.io/gitea/services/repository" ) // Transfer transfers the ownership of a repository -func Transfer(ctx *context.APIContext, opts api.TransferRepoOption) { +func Transfer(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/transfer repository repoTransfer // --- // summary: Transfer a repo ownership @@ -51,6 +52,8 @@ func Transfer(ctx *context.APIContext, opts api.TransferRepoOption) { // "422": // "$ref": "#/responses/validationError" + opts := web.GetForm(ctx).(*api.TransferRepoOption) + newOwner, err := models.GetUserByName(opts.NewOwner) if err != nil { if models.IsErrUserNotExist(err) { diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go index a3bb9cc657..8919a969ec 100644 --- a/routers/api/v1/swagger/options.go +++ b/routers/api/v1/swagger/options.go @@ -5,7 +5,7 @@ package swagger import ( - "code.gitea.io/gitea/modules/auth" + auth "code.gitea.io/gitea/modules/forms" api "code.gitea.io/gitea/modules/structs" ) diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index 547730ea57..33b27d60e0 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -61,7 +62,7 @@ func ListAccessTokens(ctx *context.APIContext) { } // CreateAccessToken create access tokens -func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption) { +func CreateAccessToken(ctx *context.APIContext) { // swagger:operation POST /users/{username}/tokens user userCreateToken // --- // summary: Create an access token @@ -88,6 +89,8 @@ func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption // "201": // "$ref": "#/responses/AccessToken" + form := web.GetForm(ctx).(*api.CreateAccessTokenOption) + t := &models.AccessToken{ UID: ctx.User.ID, Name: form.Name, @@ -181,7 +184,7 @@ func DeleteAccessToken(ctx *context.APIContext) { } // CreateOauth2Application is the handler to create a new OAuth2 Application for the authenticated user -func CreateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2ApplicationOptions) { +func CreateOauth2Application(ctx *context.APIContext) { // swagger:operation POST /user/applications/oauth2 user userCreateOAuth2Application // --- // summary: creates a new OAuth2 application @@ -196,6 +199,9 @@ func CreateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2Appli // responses: // "201": // "$ref": "#/responses/OAuth2Application" + + data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions) + app, err := models.CreateOAuth2Application(models.CreateOAuth2ApplicationOptions{ Name: data.Name, UserID: ctx.User.ID, @@ -309,7 +315,7 @@ func GetOauth2Application(ctx *context.APIContext) { } // UpdateOauth2Application update OAuth2 Application -func UpdateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2ApplicationOptions) { +func UpdateOauth2Application(ctx *context.APIContext) { // swagger:operation PATCH /user/applications/oauth2/{id} user userUpdateOAuth2Application // --- // summary: update an OAuth2 Application, this includes regenerating the client secret @@ -332,6 +338,8 @@ func UpdateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2Appli // "$ref": "#/responses/OAuth2Application" appID := ctx.ParamsInt64(":id") + data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions) + app, err := models.UpdateOAuth2Application(models.UpdateOAuth2ApplicationOptions{ Name: data.Name, UserID: ctx.User.ID, diff --git a/routers/api/v1/user/email.go b/routers/api/v1/user/email.go index d848f5e58d..bc8b2fa87b 100644 --- a/routers/api/v1/user/email.go +++ b/routers/api/v1/user/email.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" ) // ListEmails list all of the authenticated user's email addresses @@ -40,7 +41,7 @@ func ListEmails(ctx *context.APIContext) { } // AddEmail add an email address -func AddEmail(ctx *context.APIContext, form api.CreateEmailOption) { +func AddEmail(ctx *context.APIContext) { // swagger:operation POST /user/emails user userAddEmail // --- // summary: Add email addresses @@ -61,7 +62,7 @@ func AddEmail(ctx *context.APIContext, form api.CreateEmailOption) { // "$ref": "#/responses/EmailList" // "422": // "$ref": "#/responses/validationError" - + form := web.GetForm(ctx).(*api.CreateEmailOption) if len(form.Emails) == 0 { ctx.Error(http.StatusUnprocessableEntity, "", "Email list empty") return @@ -96,7 +97,7 @@ func AddEmail(ctx *context.APIContext, form api.CreateEmailOption) { } // DeleteEmail delete email -func DeleteEmail(ctx *context.APIContext, form api.DeleteEmailOption) { +func DeleteEmail(ctx *context.APIContext) { // swagger:operation DELETE /user/emails user userDeleteEmail // --- // summary: Delete email addresses @@ -110,7 +111,7 @@ func DeleteEmail(ctx *context.APIContext, form api.DeleteEmailOption) { // responses: // "204": // "$ref": "#/responses/empty" - + form := web.GetForm(ctx).(*api.DeleteEmailOption) if len(form.Emails) == 0 { ctx.Status(http.StatusNoContent) return diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go index 7290ef485a..51bcaeacc6 100644 --- a/routers/api/v1/user/gpg_key.go +++ b/routers/api/v1/user/gpg_key.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -133,7 +134,7 @@ type swaggerUserCurrentPostGPGKey struct { } //CreateGPGKey create a GPG key belonging to the authenticated user -func CreateGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption) { +func CreateGPGKey(ctx *context.APIContext) { // swagger:operation POST /user/gpg_keys user userCurrentPostGPGKey // --- // summary: Create a GPG key @@ -149,7 +150,8 @@ func CreateGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption) { // "422": // "$ref": "#/responses/validationError" - CreateUserGPGKey(ctx, form, ctx.User.ID) + form := web.GetForm(ctx).(*api.CreateGPGKeyOption) + CreateUserGPGKey(ctx, *form, ctx.User.ID) } //DeleteGPGKey remove a GPG key belonging to the authenticated user diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index fa16df1836..df8a11c61f 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/repo" "code.gitea.io/gitea/routers/api/v1/utils" ) @@ -204,7 +205,7 @@ func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid } // CreatePublicKey create one public key for me -func CreatePublicKey(ctx *context.APIContext, form api.CreateKeyOption) { +func CreatePublicKey(ctx *context.APIContext) { // swagger:operation POST /user/keys user userCurrentPostKey // --- // summary: Create a public key @@ -223,7 +224,8 @@ func CreatePublicKey(ctx *context.APIContext, form api.CreateKeyOption) { // "422": // "$ref": "#/responses/validationError" - CreateUserPublicKey(ctx, form, ctx.User.ID) + form := web.GetForm(ctx).(*api.CreateKeyOption) + CreateUserPublicKey(ctx, *form, ctx.User.ID) } // DeletePublicKey delete one public key diff --git a/routers/init.go b/routers/init.go index 79e2f9130a..9d13bc9ed5 100644 --- a/routers/init.go +++ b/routers/init.go @@ -37,22 +37,16 @@ import ( pull_service "code.gitea.io/gitea/services/pull" "code.gitea.io/gitea/services/repository" "code.gitea.io/gitea/services/webhook" - - "gitea.com/macaron/macaron" ) func checkRunMode() { switch setting.RunMode { - case "dev": - git.Debug = true - case "test": + case "dev", "test": git.Debug = true default: - macaron.Env = macaron.PROD - macaron.ColorLog = false git.Debug = false } - log.Info("Run Mode: %s", strings.Title(macaron.Env)) + log.Info("Run Mode: %s", strings.Title(setting.RunMode)) } // NewServices init new services diff --git a/routers/install.go b/routers/install.go index 50e929b6f3..5dcd1d48a3 100644 --- a/routers/install.go +++ b/routers/install.go @@ -11,18 +11,23 @@ import ( "os/exec" "path/filepath" "strings" + "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/middlewares" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/user" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" + "gitea.com/go-chi/session" "gopkg.in/ini.v1" ) @@ -33,17 +38,39 @@ const ( ) // InstallInit prepare for rendering installation page -func InstallInit(ctx *context.Context) { - if setting.InstallLock { - ctx.Header().Add("Refresh", "1; url="+setting.AppURL+"user/login") - ctx.HTML(200, tplPostInstall) - return - } - - ctx.Data["Title"] = ctx.Tr("install.install") - ctx.Data["PageIsInstall"] = true +func InstallInit(next http.Handler) http.Handler { + var rnd = templates.HTMLRenderer() - ctx.Data["DbOptions"] = setting.SupportedDatabases + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + if setting.InstallLock { + resp.Header().Add("Refresh", "1; url="+setting.AppURL+"user/login") + _ = rnd.HTML(resp, 200, string(tplPostInstall), nil) + return + } + var locale = middlewares.Locale(resp, req) + var startTime = time.Now() + var ctx = context.Context{ + Resp: context.NewResponse(resp), + Flash: &middlewares.Flash{}, + Locale: locale, + Render: rnd, + Session: session.GetSession(req), + Data: map[string]interface{}{ + "Title": locale.Tr("install.install"), + "PageIsInstall": true, + "DbOptions": setting.SupportedDatabases, + "i18n": locale, + "Language": locale.Language(), + "CurrentURL": setting.AppSubURL + req.URL.RequestURI(), + "PageStartTime": startTime, + "TmplLoadTimes": func() string { + return time.Since(startTime).String() + }, + }, + } + ctx.Req = context.WithContext(req, &ctx) + next.ServeHTTP(resp, ctx.Req) + }) } // Install render installation page @@ -116,12 +143,13 @@ func Install(ctx *context.Context) { form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking form.NoReplyAddress = setting.Service.NoReplyAddress - auth.AssignForm(form, ctx.Data) + middlewares.AssignForm(form, ctx.Data) ctx.HTML(200, tplInstall) } // InstallPost response for submit install items -func InstallPost(ctx *context.Context, form auth.InstallForm) { +func InstallPost(ctx *context.Context) { + form := *web.GetForm(ctx).(*auth.InstallForm) var err error ctx.Data["CurDbOption"] = form.DbType diff --git a/routers/org/org.go b/routers/org/org.go index 85bc25217b..98a327a97e 100644 --- a/routers/org/org.go +++ b/routers/org/org.go @@ -9,11 +9,12 @@ import ( "errors" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" ) const ( @@ -33,7 +34,8 @@ func Create(ctx *context.Context) { } // CreatePost response for create organization -func CreatePost(ctx *context.Context, form auth.CreateOrgForm) { +func CreatePost(ctx *context.Context) { + form := *web.GetForm(ctx).(*auth.CreateOrgForm) ctx.Data["Title"] = ctx.Tr("new_org") if !ctx.User.CanCreateOrganization() { diff --git a/routers/org/org_labels.go b/routers/org/org_labels.go index e5b9d9ddee..554f86c964 100644 --- a/routers/org/org_labels.go +++ b/routers/org/org_labels.go @@ -6,8 +6,9 @@ package org import ( "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" + "code.gitea.io/gitea/modules/web" ) // RetrieveLabels find all the labels of an organization @@ -26,7 +27,8 @@ func RetrieveLabels(ctx *context.Context) { } // NewLabel create new label for organization -func NewLabel(ctx *context.Context, form auth.CreateLabelForm) { +func NewLabel(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateLabelForm) ctx.Data["Title"] = ctx.Tr("repo.labels") ctx.Data["PageIsLabels"] = true @@ -50,7 +52,8 @@ func NewLabel(ctx *context.Context, form auth.CreateLabelForm) { } // UpdateLabel update a label's name and color -func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) { +func UpdateLabel(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateLabelForm) l, err := models.GetLabelInOrgByID(ctx.Org.Organization.ID, form.ID) if err != nil { switch { @@ -86,7 +89,8 @@ func DeleteLabel(ctx *context.Context) { } // InitializeLabels init labels for an organization -func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) { +func InitializeLabels(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.InitializeLabelsForm) if ctx.HasError() { ctx.Redirect(ctx.Repo.RepoLink + "/labels") return diff --git a/routers/org/setting.go b/routers/org/setting.go index 05075ca820..ac12066258 100644 --- a/routers/org/setting.go +++ b/routers/org/setting.go @@ -9,11 +9,12 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" userSetting "code.gitea.io/gitea/routers/user/setting" ) @@ -38,7 +39,8 @@ func Settings(ctx *context.Context) { } // SettingsPost response for settings change submited -func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) { +func SettingsPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.UpdateOrgSettingForm) ctx.Data["Title"] = ctx.Tr("org.settings") ctx.Data["PageIsSettingsOptions"] = true ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility @@ -115,7 +117,8 @@ func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) { } // SettingsAvatar response for change avatar on settings page -func SettingsAvatar(ctx *context.Context, form auth.AvatarForm) { +func SettingsAvatar(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AvatarForm) form.Source = auth.AvatarLocal if err := userSetting.UpdateAvatarSetting(ctx, form, ctx.Org.Organization); err != nil { ctx.Flash.Error(err.Error()) diff --git a/routers/org/teams.go b/routers/org/teams.go index fa98add601..cfa49d4e97 100644 --- a/routers/org/teams.go +++ b/routers/org/teams.go @@ -11,10 +11,11 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" ) @@ -186,7 +187,8 @@ func NewTeam(ctx *context.Context) { } // NewTeamPost response for create new team -func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) { +func NewTeamPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateTeamForm) ctx.Data["Title"] = ctx.Org.Organization.FullName ctx.Data["PageIsOrgTeams"] = true ctx.Data["PageIsOrgTeamsNew"] = true @@ -274,7 +276,8 @@ func EditTeam(ctx *context.Context) { } // EditTeamPost response for modify team information -func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) { +func EditTeamPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateTeamForm) t := ctx.Org.Team ctx.Data["Title"] = ctx.Org.Organization.FullName ctx.Data["PageIsOrgTeams"] = true diff --git a/routers/private/hook.go b/routers/private/hook.go index 34e849f6f7..853d3069ec 100644 --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -15,16 +15,16 @@ import ( "strings" "code.gitea.io/gitea/models" + gitea_context "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" - - "gitea.com/macaron/macaron" ) func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []string) error { @@ -117,7 +117,8 @@ func isErrUnverifiedCommit(err error) bool { } // HookPreReceive checks whether a individual commit is acceptable -func HookPreReceive(ctx *macaron.Context, opts private.HookOptions) { +func HookPreReceive(ctx *gitea_context.PrivateContext) { + opts := web.GetForm(ctx).(*private.HookOptions) ownerName := ctx.Params(":owner") repoName := ctx.Params(":repo") repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName) @@ -370,7 +371,8 @@ func HookPreReceive(ctx *macaron.Context, opts private.HookOptions) { } // HookPostReceive updates services and users -func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) { +func HookPostReceive(ctx *gitea_context.PrivateContext) { + opts := web.GetForm(ctx).(*private.HookOptions) ownerName := ctx.Params(":owner") repoName := ctx.Params(":repo") @@ -540,7 +542,7 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) { } // SetDefaultBranch updates the default branch -func SetDefaultBranch(ctx *macaron.Context) { +func SetDefaultBranch(ctx *gitea_context.PrivateContext) { ownerName := ctx.Params(":owner") repoName := ctx.Params(":repo") branch := ctx.Params(":branch") diff --git a/routers/private/internal.go b/routers/private/internal.go index 4fb267a49a..e541591a38 100644 --- a/routers/private/internal.go +++ b/routers/private/internal.go @@ -6,47 +6,69 @@ package private import ( + "net/http" + "reflect" "strings" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" - "gitea.com/macaron/binding" - "gitea.com/macaron/macaron" + "gitea.com/go-chi/binding" ) // CheckInternalToken check internal token is set -func CheckInternalToken(ctx *macaron.Context) { - tokens := ctx.Req.Header.Get("Authorization") - fields := strings.Fields(tokens) - if len(fields) != 2 || fields[0] != "Bearer" || fields[1] != setting.InternalToken { - log.Debug("Forbidden attempt to access internal url: Authorization header: %s", tokens) - ctx.Error(403) +func CheckInternalToken(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + tokens := req.Header.Get("Authorization") + fields := strings.Fields(tokens) + if len(fields) != 2 || fields[0] != "Bearer" || fields[1] != setting.InternalToken { + log.Debug("Forbidden attempt to access internal url: Authorization header: %s", tokens) + http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden) + } else { + next.ServeHTTP(w, req) + } + }) +} + +// bind binding an obj to a handler +func bind(obj interface{}) http.HandlerFunc { + var tp = reflect.TypeOf(obj) + for tp.Kind() == reflect.Ptr { + tp = tp.Elem() } + return web.Wrap(func(ctx *context.PrivateContext) { + var theObj = reflect.New(tp).Interface() // create a new form obj for every request but not use obj directly + binding.Bind(ctx.Req, theObj) + web.SetForm(ctx, theObj) + }) } -// RegisterRoutes registers all internal APIs routes to web application. +// Routes registers all internal APIs routes to web application. // These APIs will be invoked by internal commands for example `gitea serv` and etc. -func RegisterRoutes(m *macaron.Macaron) { - bind := binding.Bind - - m.Group("/", func() { - m.Post("/ssh/authorized_keys", AuthorizedPublicKeyByContent) - m.Post("/ssh/:id/update/:repoid", UpdatePublicKeyInRepo) - m.Post("/hook/pre-receive/:owner/:repo", bind(private.HookOptions{}), HookPreReceive) - m.Post("/hook/post-receive/:owner/:repo", bind(private.HookOptions{}), HookPostReceive) - m.Post("/hook/set-default-branch/:owner/:repo/:branch", SetDefaultBranch) - m.Get("/serv/none/:keyid", ServNoCommand) - m.Get("/serv/command/:keyid/:owner/:repo", ServCommand) - m.Post("/manager/shutdown", Shutdown) - m.Post("/manager/restart", Restart) - m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) - m.Post("/manager/pause-logging", PauseLogging) - m.Post("/manager/resume-logging", ResumeLogging) - m.Post("/manager/release-and-reopen-logging", ReleaseReopenLogging) - m.Post("/manager/add-logger", bind(private.LoggerOptions{}), AddLogger) - m.Post("/manager/remove-logger/:group/:name", RemoveLogger) - m.Post("/mail/send", SendEmail) - }, CheckInternalToken) +func Routes() *web.Route { + var r = web.NewRoute() + r.Use(context.PrivateContexter()) + r.Use(CheckInternalToken) + + r.Post("/ssh/authorized_keys", AuthorizedPublicKeyByContent) + r.Post("/ssh/{id}/update/{repoid}", UpdatePublicKeyInRepo) + r.Post("/hook/pre-receive/{owner}/{repo}", bind(private.HookOptions{}), HookPreReceive) + r.Post("/hook/post-receive/{owner}/{repo}", bind(private.HookOptions{}), HookPostReceive) + r.Post("/hook/set-default-branch/{owner}/{repo}/{branch}", SetDefaultBranch) + r.Get("/serv/none/{keyid}", ServNoCommand) + r.Get("/serv/command/{keyid}/{owner}/{repo}", ServCommand) + r.Post("/manager/shutdown", Shutdown) + r.Post("/manager/restart", Restart) + r.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) + r.Post("/manager/pause-logging", PauseLogging) + r.Post("/manager/resume-logging", ResumeLogging) + r.Post("/manager/release-and-reopen-logging", ReleaseReopenLogging) + r.Post("/manager/add-logger", bind(private.LoggerOptions{}), AddLogger) + r.Post("/manager/remove-logger/{group}/{name}", RemoveLogger) + r.Post("/mail/send", SendEmail) + + return r } diff --git a/routers/private/key.go b/routers/private/key.go index c00330fe88..b90faa22a4 100644 --- a/routers/private/key.go +++ b/routers/private/key.go @@ -9,13 +9,12 @@ import ( "net/http" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/timeutil" - - "gitea.com/macaron/macaron" ) // UpdatePublicKeyInRepo update public key and deploy key updates -func UpdatePublicKeyInRepo(ctx *macaron.Context) { +func UpdatePublicKeyInRepo(ctx *context.PrivateContext) { keyID := ctx.ParamsInt64(":id") repoID := ctx.ParamsInt64(":repoid") if err := models.UpdatePublicKeyUpdated(keyID); err != nil { @@ -49,7 +48,7 @@ func UpdatePublicKeyInRepo(ctx *macaron.Context) { // AuthorizedPublicKeyByContent searches content as prefix (leak e-mail part) // and returns public key found. -func AuthorizedPublicKeyByContent(ctx *macaron.Context) { +func AuthorizedPublicKeyByContent(ctx *context.PrivateContext) { content := ctx.Query("content") publicKey, err := models.SearchPublicKeyByContent(content) diff --git a/routers/private/mail.go b/routers/private/mail.go index b3b21d042f..330de14c46 100644 --- a/routers/private/mail.go +++ b/routers/private/mail.go @@ -11,17 +11,17 @@ import ( "strconv" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/services/mailer" - "gitea.com/macaron/macaron" ) // SendEmail pushes messages to mail queue // // It doesn't wait before each message will be processed -func SendEmail(ctx *macaron.Context) { +func SendEmail(ctx *context.PrivateContext) { if setting.MailService == nil { ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ "err": "Mail service is not enabled.", @@ -30,7 +30,7 @@ func SendEmail(ctx *macaron.Context) { } var mail private.Email - rd := ctx.Req.Body().ReadCloser() + rd := ctx.Req.Body defer rd.Close() if err := json.NewDecoder(rd).Decode(&mail); err != nil { log.Error("%v", err) @@ -77,7 +77,7 @@ func SendEmail(ctx *macaron.Context) { sendEmail(ctx, mail.Subject, mail.Message, emails) } -func sendEmail(ctx *macaron.Context, subject, message string, to []string) { +func sendEmail(ctx *context.PrivateContext, subject, message string, to []string) { for _, email := range to { msg := mailer.NewMessage([]string{email}, subject, message) mailer.SendAsync(msg) diff --git a/routers/private/manager.go b/routers/private/manager.go index 67bd92003f..e5b4583fd1 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -9,17 +9,18 @@ import ( "fmt" "net/http" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" - - "gitea.com/macaron/macaron" + "code.gitea.io/gitea/modules/web" ) // FlushQueues flushes all the Queues -func FlushQueues(ctx *macaron.Context, opts private.FlushOptions) { +func FlushQueues(ctx *context.PrivateContext) { + opts := web.GetForm(ctx).(*private.FlushOptions) if opts.NonBlocking { // Save the hammer ctx here - as a new one is created each time you call this. baseCtx := graceful.GetManager().HammerContext() @@ -34,7 +35,7 @@ func FlushQueues(ctx *macaron.Context, opts private.FlushOptions) { }) return } - err := queue.GetManager().FlushAll(ctx.Req.Request.Context(), opts.Timeout) + err := queue.GetManager().FlushAll(ctx.Req.Context(), opts.Timeout) if err != nil { ctx.JSON(http.StatusRequestTimeout, map[string]interface{}{ "err": fmt.Sprintf("%v", err), @@ -44,19 +45,19 @@ func FlushQueues(ctx *macaron.Context, opts private.FlushOptions) { } // PauseLogging pauses logging -func PauseLogging(ctx *macaron.Context) { +func PauseLogging(ctx *context.PrivateContext) { log.Pause() ctx.PlainText(http.StatusOK, []byte("success")) } // ResumeLogging resumes logging -func ResumeLogging(ctx *macaron.Context) { +func ResumeLogging(ctx *context.PrivateContext) { log.Resume() ctx.PlainText(http.StatusOK, []byte("success")) } // ReleaseReopenLogging releases and reopens logging files -func ReleaseReopenLogging(ctx *macaron.Context) { +func ReleaseReopenLogging(ctx *context.PrivateContext) { if err := log.ReleaseReopen(); err != nil { ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ "err": fmt.Sprintf("Error during release and reopen: %v", err), @@ -67,7 +68,7 @@ func ReleaseReopenLogging(ctx *macaron.Context) { } // RemoveLogger removes a logger -func RemoveLogger(ctx *macaron.Context) { +func RemoveLogger(ctx *context.PrivateContext) { group := ctx.Params("group") name := ctx.Params("name") ok, err := log.GetLogger(group).DelLogger(name) @@ -84,7 +85,8 @@ func RemoveLogger(ctx *macaron.Context) { } // AddLogger adds a logger -func AddLogger(ctx *macaron.Context, opts private.LoggerOptions) { +func AddLogger(ctx *context.PrivateContext) { + opts := web.GetForm(ctx).(*private.LoggerOptions) if len(opts.Group) == 0 { opts.Group = log.DEFAULT } diff --git a/routers/private/manager_unix.go b/routers/private/manager_unix.go index ec5e976059..60ae9b68e8 100644 --- a/routers/private/manager_unix.go +++ b/routers/private/manager_unix.go @@ -9,20 +9,19 @@ package private import ( "net/http" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/graceful" - - "gitea.com/macaron/macaron" ) // Restart causes the server to perform a graceful restart -func Restart(ctx *macaron.Context) { +func Restart(ctx *context.PrivateContext) { graceful.GetManager().DoGracefulRestart() ctx.PlainText(http.StatusOK, []byte("success")) } // Shutdown causes the server to perform a graceful shutdown -func Shutdown(ctx *macaron.Context) { +func Shutdown(ctx *context.PrivateContext) { graceful.GetManager().DoGracefulShutdown() ctx.PlainText(http.StatusOK, []byte("success")) } diff --git a/routers/private/manager_windows.go b/routers/private/manager_windows.go index ac840a9d81..244dbbe4df 100644 --- a/routers/private/manager_windows.go +++ b/routers/private/manager_windows.go @@ -9,20 +9,19 @@ package private import ( "net/http" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/graceful" - - "gitea.com/macaron/macaron" ) // Restart is not implemented for Windows based servers as they can't fork -func Restart(ctx *macaron.Context) { +func Restart(ctx *context.PrivateContext) { ctx.JSON(http.StatusNotImplemented, map[string]interface{}{ "err": "windows servers cannot be gracefully restarted - shutdown and restart manually", }) } // Shutdown causes the server to perform a graceful shutdown -func Shutdown(ctx *macaron.Context) { +func Shutdown(ctx *context.PrivateContext) { graceful.GetManager().DoGracefulShutdown() ctx.PlainText(http.StatusOK, []byte("success")) } diff --git a/routers/private/serv.go b/routers/private/serv.go index 90e1d30b01..1461194e7f 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -11,17 +11,16 @@ import ( "strings" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" "code.gitea.io/gitea/modules/setting" repo_service "code.gitea.io/gitea/services/repository" wiki_service "code.gitea.io/gitea/services/wiki" - - "gitea.com/macaron/macaron" ) // ServNoCommand returns information about the provided keyid -func ServNoCommand(ctx *macaron.Context) { +func ServNoCommand(ctx *context.PrivateContext) { keyID := ctx.ParamsInt64(":keyid") if keyID <= 0 { ctx.JSON(http.StatusBadRequest, map[string]interface{}{ @@ -73,7 +72,7 @@ func ServNoCommand(ctx *macaron.Context) { } // ServCommand returns information about the provided keyid -func ServCommand(ctx *macaron.Context) { +func ServCommand(ctx *context.PrivateContext) { keyID := ctx.ParamsInt64(":keyid") ownerName := ctx.Params(":owner") repoName := ctx.Params(":repo") diff --git a/routers/repo/branch.go b/routers/repo/branch.go index bf9f2e6a36..7d844abe5a 100644 --- a/routers/repo/branch.go +++ b/routers/repo/branch.go @@ -10,14 +10,15 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repofiles" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" repo_service "code.gitea.io/gitea/services/repository" ) @@ -367,7 +368,8 @@ func getDeletedBranches(ctx *context.Context) ([]*Branch, error) { } // CreateBranch creates new branch in repository -func CreateBranch(ctx *context.Context, form auth.NewBranchForm) { +func CreateBranch(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewBranchForm) if !ctx.Repo.CanCreateBranch() { ctx.NotFound("CreateBranch", nil) return diff --git a/routers/repo/editor.go b/routers/repo/editor.go index 0bc76504f9..619912fef7 100644 --- a/routers/repo/editor.go +++ b/routers/repo/editor.go @@ -12,10 +12,10 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repofiles" @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" ) @@ -325,17 +326,20 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo } // EditFilePost response for editing file -func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) { - editFilePost(ctx, form, false) +func EditFilePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditRepoFileForm) + editFilePost(ctx, *form, false) } // NewFilePost response for creating file -func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) { - editFilePost(ctx, form, true) +func NewFilePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditRepoFileForm) + editFilePost(ctx, *form, true) } // DiffPreviewPost render preview diff page -func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) { +func DiffPreviewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditPreviewDiffForm) treePath := cleanUploadFileName(ctx.Repo.TreePath) if len(treePath) == 0 { ctx.Error(500, "file name to diff is invalid") @@ -394,7 +398,8 @@ func DeleteFile(ctx *context.Context) { } // DeleteFilePost response for deleting file -func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) { +func DeleteFilePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.DeleteRepoFileForm) canCommit := renderCommitRights(ctx) branchName := ctx.Repo.BranchName if form.CommitChoice == frmCommitChoiceNewBranch { @@ -556,7 +561,8 @@ func UploadFile(ctx *context.Context) { } // UploadFilePost response for uploading file -func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) { +func UploadFilePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.UploadRepoFileForm) ctx.Data["PageIsUpload"] = true ctx.Data["RequireTribute"] = true ctx.Data["RequireSimpleMDE"] = true @@ -760,7 +766,8 @@ func UploadFileToServer(ctx *context.Context) { } // RemoveUploadFileFromServer remove file from server file dir -func RemoveUploadFileFromServer(ctx *context.Context, form auth.RemoveUploadFileForm) { +func RemoveUploadFileFromServer(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.RemoveUploadFileForm) if len(form.File) == 0 { ctx.Status(204) return diff --git a/routers/repo/http.go b/routers/repo/http.go index 3de45698e8..0377979e8b 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -35,8 +35,17 @@ import ( repo_service "code.gitea.io/gitea/services/repository" ) -// HTTP implmentation git smart HTTP protocol -func HTTP(ctx *context.Context) { +// httpBase implmentation git smart HTTP protocol +func httpBase(ctx *context.Context) (h *serviceHandler) { + if setting.Repository.DisableHTTPGit { + ctx.Resp.WriteHeader(http.StatusForbidden) + _, err := ctx.Resp.Write([]byte("Interacting with repositories by HTTP protocol is not allowed")) + if err != nil { + log.Error(err.Error()) + } + return + } + if len(setting.Repository.AccessControlAllowOrigin) > 0 { allowedOrigin := setting.Repository.AccessControlAllowOrigin // Set CORS headers for browser-based git clients @@ -344,7 +353,7 @@ func HTTP(ctx *context.Context) { environ = append(environ, models.EnvRepoID+fmt.Sprintf("=%d", repo.ID)) w := ctx.Resp - r := ctx.Req.Request + r := ctx.Req cfg := &serviceConfig{ UploadPack: true, ReceivePack: true, @@ -353,47 +362,9 @@ func HTTP(ctx *context.Context) { r.URL.Path = strings.ToLower(r.URL.Path) // blue: In case some repo name has upper case name - for _, route := range routes { - if m := route.reg.FindStringSubmatch(r.URL.Path); m != nil { - if setting.Repository.DisableHTTPGit { - w.WriteHeader(http.StatusForbidden) - _, err := w.Write([]byte("Interacting with repositories by HTTP protocol is not allowed")) - if err != nil { - log.Error(err.Error()) - } - return - } - if route.method != r.Method { - if r.Proto == "HTTP/1.1" { - w.WriteHeader(http.StatusMethodNotAllowed) - _, err := w.Write([]byte("Method Not Allowed")) - if err != nil { - log.Error(err.Error()) - } - } else { - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("Bad Request")) - if err != nil { - log.Error(err.Error()) - } - } - return - } - - file := strings.Replace(r.URL.Path, m[1]+"/", "", 1) - dir, err := getGitRepoPath(m[1]) - if err != nil { - log.Error(err.Error()) - ctx.NotFound("Smart Git HTTP", err) - return - } - - route.handler(serviceHandler{cfg, w, r, dir, file, cfg.Env}) - return - } - } + dir := models.RepoPath(username, reponame) - ctx.NotFound("Smart Git HTTP", nil) + return &serviceHandler{cfg, w, r, dir, cfg.Env} } var ( @@ -449,7 +420,6 @@ type serviceHandler struct { w http.ResponseWriter r *http.Request dir string - file string environ []string } @@ -467,8 +437,8 @@ func (h *serviceHandler) setHeaderCacheForever() { h.w.Header().Set("Cache-Control", "public, max-age=31536000") } -func (h *serviceHandler) sendFile(contentType string) { - reqFile := path.Join(h.dir, h.file) +func (h *serviceHandler) sendFile(contentType, file string) { + reqFile := path.Join(h.dir, file) fi, err := os.Stat(reqFile) if os.IsNotExist(err) { @@ -482,26 +452,6 @@ func (h *serviceHandler) sendFile(contentType string) { http.ServeFile(h.w, h.r, reqFile) } -type route struct { - reg *regexp.Regexp - method string - handler func(serviceHandler) -} - -var routes = []route{ - {regexp.MustCompile(`(.*?)/git-upload-pack$`), "POST", serviceUploadPack}, - {regexp.MustCompile(`(.*?)/git-receive-pack$`), "POST", serviceReceivePack}, - {regexp.MustCompile(`(.*?)/info/refs$`), "GET", getInfoRefs}, - {regexp.MustCompile(`(.*?)/HEAD$`), "GET", getTextFile}, - {regexp.MustCompile(`(.*?)/objects/info/alternates$`), "GET", getTextFile}, - {regexp.MustCompile(`(.*?)/objects/info/http-alternates$`), "GET", getTextFile}, - {regexp.MustCompile(`(.*?)/objects/info/packs$`), "GET", getInfoPacks}, - {regexp.MustCompile(`(.*?)/objects/info/[^/]*$`), "GET", getTextFile}, - {regexp.MustCompile(`(.*?)/objects/[0-9a-f]{2}/[0-9a-f]{38}$`), "GET", getLooseObject}, - {regexp.MustCompile(`(.*?)/objects/pack/pack-[0-9a-f]{40}\.pack$`), "GET", getPackFile}, - {regexp.MustCompile(`(.*?)/objects/pack/pack-[0-9a-f]{40}\.idx$`), "GET", getIdxFile}, -} - // one or more key=value pairs separated by colons var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`) @@ -598,12 +548,20 @@ func serviceRPC(h serviceHandler, service string) { } } -func serviceUploadPack(h serviceHandler) { - serviceRPC(h, "upload-pack") +// ServiceUploadPack implements Git Smart HTTP protocol +func ServiceUploadPack(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + serviceRPC(*h, "upload-pack") + } } -func serviceReceivePack(h serviceHandler) { - serviceRPC(h, "receive-pack") +// ServiceReceivePack implements Git Smart HTTP protocol +func ServiceReceivePack(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + serviceRPC(*h, "receive-pack") + } } func getServiceType(r *http.Request) string { @@ -630,9 +588,14 @@ func packetWrite(str string) []byte { return []byte(s + str) } -func getInfoRefs(h serviceHandler) { +// GetInfoRefs implements Git dumb HTTP +func GetInfoRefs(ctx *context.Context) { + h := httpBase(ctx) + if h == nil { + return + } h.setHeaderNoCache() - if hasAccess(getServiceType(h.r), h, false) { + if hasAccess(getServiceType(h.r), *h, false) { service := getServiceType(h.r) if protocol := h.r.Header.Get("Git-Protocol"); protocol != "" && safeGitProtocolHeader.MatchString(protocol) { @@ -652,44 +615,59 @@ func getInfoRefs(h serviceHandler) { _, _ = h.w.Write(refs) } else { updateServerInfo(h.dir) - h.sendFile("text/plain; charset=utf-8") + h.sendFile("text/plain; charset=utf-8", "info/refs") } } -func getTextFile(h serviceHandler) { - h.setHeaderNoCache() - h.sendFile("text/plain") -} - -func getInfoPacks(h serviceHandler) { - h.setHeaderCacheForever() - h.sendFile("text/plain; charset=utf-8") -} - -func getLooseObject(h serviceHandler) { - h.setHeaderCacheForever() - h.sendFile("application/x-git-loose-object") +// GetTextFile implements Git dumb HTTP +func GetTextFile(p string) func(*context.Context) { + return func(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + h.setHeaderNoCache() + file := ctx.Params("file") + if file != "" { + h.sendFile("text/plain", "objects/info/"+file) + } else { + h.sendFile("text/plain", p) + } + } + } } -func getPackFile(h serviceHandler) { - h.setHeaderCacheForever() - h.sendFile("application/x-git-packed-objects") +// GetInfoPacks implements Git dumb HTTP +func GetInfoPacks(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + h.setHeaderCacheForever() + h.sendFile("text/plain; charset=utf-8", "objects/info/packs") + } } -func getIdxFile(h serviceHandler) { - h.setHeaderCacheForever() - h.sendFile("application/x-git-packed-objects-toc") +// GetLooseObject implements Git dumb HTTP +func GetLooseObject(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + h.setHeaderCacheForever() + h.sendFile("application/x-git-loose-object", fmt.Sprintf("objects/%s/%s", + ctx.Params("head"), ctx.Params("hash"))) + } } -func getGitRepoPath(subdir string) (string, error) { - if !strings.HasSuffix(subdir, ".git") { - subdir += ".git" +// GetPackFile implements Git dumb HTTP +func GetPackFile(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + h.setHeaderCacheForever() + h.sendFile("application/x-git-packed-objects", "objects/pack/pack-"+ctx.Params("file")+".pack") } +} - fpath := path.Join(setting.RepoRootPath, subdir) - if _, err := os.Stat(fpath); os.IsNotExist(err) { - return "", err +// GetIdxFile implements Git dumb HTTP +func GetIdxFile(ctx *context.Context) { + h := httpBase(ctx) + if h != nil { + h.setHeaderCacheForever() + h.sendFile("application/x-git-packed-objects-toc", "objects/pack/pack-"+ctx.Params("file")+".idx") } - - return fpath, nil } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index fbeae75ab5..fb7107451f 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -16,10 +16,10 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" issue_indexer "code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/log" @@ -29,6 +29,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" comment_service "code.gitea.io/gitea/services/comments" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" @@ -924,7 +925,8 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm, isPull b } // NewIssuePost response for creating new issue -func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { +func NewIssuePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateIssueForm) ctx.Data["Title"] = ctx.Tr("repo.issues.new") ctx.Data["PageIsIssueList"] = true ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0 @@ -940,7 +942,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { attachments []string ) - labelIDs, assigneeIDs, milestoneID, projectID := ValidateRepoMetas(ctx, form, false) + labelIDs, assigneeIDs, milestoneID, projectID := ValidateRepoMetas(ctx, *form, false) if ctx.Written() { return } @@ -1925,7 +1927,8 @@ func UpdateIssueStatus(ctx *context.Context) { } // NewComment create a comment for issue -func NewComment(ctx *context.Context, form auth.CreateCommentForm) { +func NewComment(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateCommentForm) issue := GetActionIssue(ctx) if ctx.Written() { return @@ -2134,7 +2137,8 @@ func DeleteComment(ctx *context.Context) { } // ChangeIssueReaction create a reaction for issue -func ChangeIssueReaction(ctx *context.Context, form auth.ReactionForm) { +func ChangeIssueReaction(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.ReactionForm) issue := GetActionIssue(ctx) if ctx.Written() { return @@ -2229,7 +2233,8 @@ func ChangeIssueReaction(ctx *context.Context, form auth.ReactionForm) { } // ChangeCommentReaction create a reaction for comment -func ChangeCommentReaction(ctx *context.Context, form auth.ReactionForm) { +func ChangeCommentReaction(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.ReactionForm) comment, err := models.GetCommentByID(ctx.ParamsInt64(":id")) if err != nil { ctx.NotFoundOrServerError("GetCommentByID", models.IsErrCommentNotExist, err) diff --git a/routers/repo/issue_label.go b/routers/repo/issue_label.go index f1e188fe3a..35035103d5 100644 --- a/routers/repo/issue_label.go +++ b/routers/repo/issue_label.go @@ -6,11 +6,12 @@ package repo import ( "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" issue_service "code.gitea.io/gitea/services/issue" ) @@ -29,7 +30,8 @@ func Labels(ctx *context.Context) { } // InitializeLabels init labels for a repository -func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) { +func InitializeLabels(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.InitializeLabelsForm) if ctx.HasError() { ctx.Redirect(ctx.Repo.RepoLink + "/labels") return @@ -94,7 +96,8 @@ func RetrieveLabels(ctx *context.Context) { } // NewLabel create new label for repository -func NewLabel(ctx *context.Context, form auth.CreateLabelForm) { +func NewLabel(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateLabelForm) ctx.Data["Title"] = ctx.Tr("repo.labels") ctx.Data["PageIsLabels"] = true @@ -118,7 +121,8 @@ func NewLabel(ctx *context.Context, form auth.CreateLabelForm) { } // UpdateLabel update a label's name and color -func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) { +func UpdateLabel(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateLabelForm) l, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, form.ID) if err != nil { switch { diff --git a/routers/repo/issue_label_test.go b/routers/repo/issue_label_test.go index bf62511258..d67c70085d 100644 --- a/routers/repo/issue_label_test.go +++ b/routers/repo/issue_label_test.go @@ -10,8 +10,9 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/web" "github.com/stretchr/testify/assert" ) @@ -32,7 +33,8 @@ func TestInitializeLabels(t *testing.T) { ctx := test.MockContext(t, "user2/repo1/labels/initialize") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 2) - InitializeLabels(ctx, auth.InitializeLabelsForm{TemplateName: "Default"}) + web.SetForm(ctx, &auth.InitializeLabelsForm{TemplateName: "Default"}) + InitializeLabels(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.Label{ RepoID: 2, @@ -74,10 +76,11 @@ func TestNewLabel(t *testing.T) { ctx := test.MockContext(t, "user2/repo1/labels/edit") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) - NewLabel(ctx, auth.CreateLabelForm{ + web.SetForm(ctx, &auth.CreateLabelForm{ Title: "newlabel", Color: "#abcdef", }) + NewLabel(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.Label{ Name: "newlabel", @@ -91,11 +94,12 @@ func TestUpdateLabel(t *testing.T) { ctx := test.MockContext(t, "user2/repo1/labels/edit") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) - UpdateLabel(ctx, auth.CreateLabelForm{ + web.SetForm(ctx, &auth.CreateLabelForm{ ID: 2, Title: "newnameforlabel", Color: "#abcdef", }) + UpdateLabel(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.Label{ ID: 2, diff --git a/routers/repo/issue_lock.go b/routers/repo/issue_lock.go index fa87588319..f8131e46aa 100644 --- a/routers/repo/issue_lock.go +++ b/routers/repo/issue_lock.go @@ -8,14 +8,15 @@ import ( "net/http" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" + "code.gitea.io/gitea/modules/web" ) // LockIssue locks an issue. This would limit commenting abilities to // users with write access to the repo. -func LockIssue(ctx *context.Context, form auth.IssueLockForm) { - +func LockIssue(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.IssueLockForm) issue := GetActionIssue(ctx) if ctx.Written() { return diff --git a/routers/repo/issue_timetrack.go b/routers/repo/issue_timetrack.go index 0f711bc734..425f215110 100644 --- a/routers/repo/issue_timetrack.go +++ b/routers/repo/issue_timetrack.go @@ -9,12 +9,14 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" + "code.gitea.io/gitea/modules/web" ) // AddTimeManually tracks time manually -func AddTimeManually(c *context.Context, form auth.AddTimeManuallyForm) { +func AddTimeManually(c *context.Context) { + form := web.GetForm(c).(*auth.AddTimeManuallyForm) issue := GetActionIssue(c) if c.Written() { return diff --git a/routers/repo/migrate.go b/routers/repo/migrate.go index a628fd2e2f..89452de0fa 100644 --- a/routers/repo/migrate.go +++ b/routers/repo/migrate.go @@ -10,14 +10,15 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/migrations" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/task" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" ) const ( @@ -117,7 +118,8 @@ func handleMigrateError(ctx *context.Context, owner *models.User, err error, nam } // MigratePost response for migrating from external git repository -func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { +func MigratePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.MigrateRepoForm) if setting.Repository.DisableMigrations { ctx.Error(http.StatusForbidden, "MigratePost: the site administrator has disabled migrations") return @@ -192,7 +194,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName, false) if err != nil { - handleMigrateError(ctx, ctxUser, err, "MigratePost", tpl, &form) + handleMigrateError(ctx, ctxUser, err, "MigratePost", tpl, form) return } @@ -202,5 +204,5 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { return } - handleMigrateError(ctx, ctxUser, err, "MigratePost", tpl, &form) + handleMigrateError(ctx, ctxUser, err, "MigratePost", tpl, form) } diff --git a/routers/repo/milestone.go b/routers/repo/milestone.go index 96f5b4e5f0..a9beed75d7 100644 --- a/routers/repo/milestone.go +++ b/routers/repo/milestone.go @@ -8,14 +8,15 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "xorm.io/builder" ) @@ -106,7 +107,8 @@ func NewMilestone(ctx *context.Context) { } // NewMilestonePost response for creating milestone -func NewMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) { +func NewMilestonePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateMilestoneForm) ctx.Data["Title"] = ctx.Tr("repo.milestones.new") ctx.Data["PageIsIssueList"] = true ctx.Data["PageIsMilestones"] = true @@ -165,7 +167,8 @@ func EditMilestone(ctx *context.Context) { } // EditMilestonePost response for edting milestone -func EditMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) { +func EditMilestonePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateMilestoneForm) ctx.Data["Title"] = ctx.Tr("repo.milestones.edit") ctx.Data["PageIsMilestones"] = true ctx.Data["PageIsEditMilestone"] = true diff --git a/routers/repo/projects.go b/routers/repo/projects.go index 4cff199b34..49bcfef0ce 100644 --- a/routers/repo/projects.go +++ b/routers/repo/projects.go @@ -9,12 +9,13 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" ) const ( @@ -112,7 +113,8 @@ func NewProject(ctx *context.Context) { } // NewProjectPost creates a new project -func NewProjectPost(ctx *context.Context, form auth.CreateProjectForm) { +func NewProjectPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateProjectForm) ctx.Data["Title"] = ctx.Tr("repo.projects.new") if ctx.HasError() { @@ -217,7 +219,8 @@ func EditProject(ctx *context.Context) { } // EditProjectPost response for editing a project -func EditProjectPost(ctx *context.Context, form auth.CreateProjectForm) { +func EditProjectPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateProjectForm) ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsProjects"] = true ctx.Data["PageIsEditProjects"] = true @@ -399,8 +402,8 @@ func DeleteProjectBoard(ctx *context.Context) { } // AddBoardToProjectPost allows a new board to be added to a project. -func AddBoardToProjectPost(ctx *context.Context, form auth.EditProjectBoardTitleForm) { - +func AddBoardToProjectPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditProjectBoardTitleForm) if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(models.AccessModeWrite, models.UnitTypeProjects) { ctx.JSON(403, map[string]string{ "message": "Only authorized users are allowed to perform this action.", @@ -479,8 +482,8 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*models.Project, } // EditProjectBoardTitle allows a project board's title to be updated -func EditProjectBoardTitle(ctx *context.Context, form auth.EditProjectBoardTitleForm) { - +func EditProjectBoardTitle(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditProjectBoardTitleForm) _, board := checkProjectBoardChangePermissions(ctx) if ctx.Written() { return diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 01c6efaa1d..1862c15f43 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -16,17 +16,19 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/middlewares" "code.gitea.io/gitea/modules/notification" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" "code.gitea.io/gitea/services/gitdiff" pull_service "code.gitea.io/gitea/services/pull" @@ -168,7 +170,8 @@ func Fork(ctx *context.Context) { } // ForkPost response for forking a repository -func ForkPost(ctx *context.Context, form auth.CreateRepoForm) { +func ForkPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateRepoForm) ctx.Data["Title"] = ctx.Tr("new_fork") ctxUser := checkContextUser(ctx, form.UID) @@ -765,7 +768,8 @@ func UpdatePullRequest(ctx *context.Context) { } // MergePullRequest response for merging pull request -func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) { +func MergePullRequest(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.MergePullRequestForm) issue := checkPullInfo(ctx) if ctx.Written() { return @@ -954,7 +958,8 @@ func stopTimerIfAvailable(user *models.User, issue *models.Issue) error { } // CompareAndPullRequestPost response for creating pull request -func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) { +func CompareAndPullRequestPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateIssueForm) ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes") ctx.Data["PageIsComparePull"] = true ctx.Data["IsDiffCompare"] = true @@ -974,7 +979,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) } defer headGitRepo.Close() - labelIDs, assigneeIDs, milestoneID, _ := ValidateRepoMetas(ctx, form, true) + labelIDs, assigneeIDs, milestoneID, _ := ValidateRepoMetas(ctx, *form, true) if ctx.Written() { return } @@ -984,7 +989,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) } if ctx.HasError() { - auth.AssignForm(form, ctx.Data) + middlewares.AssignForm(form, ctx.Data) // This stage is already stop creating new pull request, so it does not matter if it has // something to compare or not. diff --git a/routers/repo/pull_review.go b/routers/repo/pull_review.go index 0bacc68232..df49b6cfe1 100644 --- a/routers/repo/pull_review.go +++ b/routers/repo/pull_review.go @@ -8,10 +8,11 @@ import ( "fmt" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/web" pull_service "code.gitea.io/gitea/services/pull" ) @@ -44,7 +45,8 @@ func RenderNewCodeCommentForm(ctx *context.Context) { } // CreateCodeComment will create a code comment including an pending review if required -func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) { +func CreateCodeComment(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CodeCommentForm) issue := GetActionIssue(ctx) if !issue.IsPull { return @@ -171,7 +173,8 @@ func renderConversation(ctx *context.Context, comment *models.Comment) { } // SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist -func SubmitReview(ctx *context.Context, form auth.SubmitReviewForm) { +func SubmitReview(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.SubmitReviewForm) issue := GetActionIssue(ctx) if !issue.IsPull { return diff --git a/routers/repo/release.go b/routers/repo/release.go index 4d75c37c87..54642f9b21 100644 --- a/routers/repo/release.go +++ b/routers/repo/release.go @@ -9,14 +9,15 @@ import ( "fmt" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/upload" + "code.gitea.io/gitea/modules/web" releaseservice "code.gitea.io/gitea/services/release" ) @@ -230,7 +231,8 @@ func NewRelease(ctx *context.Context) { } // NewReleasePost response for creating a release -func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) { +func NewReleasePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewReleaseForm) ctx.Data["Title"] = ctx.Tr("repo.release.new_release") ctx.Data["PageIsReleaseList"] = true @@ -336,7 +338,8 @@ func EditRelease(ctx *context.Context) { } // EditReleasePost response for edit release -func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) { +func EditReleasePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditReleaseForm) ctx.Data["Title"] = ctx.Tr("repo.release.edit_release") ctx.Data["PageIsReleaseList"] = true ctx.Data["PageIsEditRelease"] = true diff --git a/routers/repo/release_test.go b/routers/repo/release_test.go index 47d1a89b54..38c0d9fec0 100644 --- a/routers/repo/release_test.go +++ b/routers/repo/release_test.go @@ -8,8 +8,9 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/web" ) func TestNewReleasePost(t *testing.T) { @@ -48,7 +49,8 @@ func TestNewReleasePost(t *testing.T) { test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) test.LoadGitRepo(t, ctx) - NewReleasePost(ctx, testCase.Form) + web.SetForm(ctx, &testCase.Form) + NewReleasePost(ctx) models.AssertExistsAndLoadBean(t, &models.Release{ RepoID: 1, PublisherID: 2, diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 3832b89971..a8cfb9ad7c 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -11,11 +11,12 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" archiver_service "code.gitea.io/gitea/services/archiver" repo_service "code.gitea.io/gitea/services/repository" ) @@ -181,7 +182,8 @@ func handleCreateError(ctx *context.Context, owner *models.User, err error, name } // CreatePost response for creating repository -func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { +func CreatePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.CreateRepoForm) ctx.Data["Title"] = ctx.Tr("new_repo") ctx.Data["Gitignores"] = models.Gitignores diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 368879234b..3e22e8804e 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -15,9 +15,9 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repository" @@ -25,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/validation" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" "code.gitea.io/gitea/services/mailer" mirror_service "code.gitea.io/gitea/services/mirror" @@ -59,7 +60,8 @@ func Settings(ctx *context.Context) { } // SettingsPost response for changes of a repository -func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { +func SettingsPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.RepoSettingForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsOptions"] = true @@ -839,7 +841,8 @@ func DeployKeys(ctx *context.Context) { } // DeployKeysPost response for adding a deploy key of a repository -func DeployKeysPost(ctx *context.Context, form auth.AddKeyForm) { +func DeployKeysPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AddKeyForm) ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys") ctx.Data["PageIsSettingsKeys"] = true @@ -956,9 +959,10 @@ func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm) error { } // SettingsAvatar save new POSTed repository avatar -func SettingsAvatar(ctx *context.Context, form auth.AvatarForm) { +func SettingsAvatar(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AvatarForm) form.Source = auth.AvatarLocal - if err := UpdateAvatarSetting(ctx, form); err != nil { + if err := UpdateAvatarSetting(ctx, *form); err != nil { ctx.Flash.Error(err.Error()) } else { ctx.Flash.Success(ctx.Tr("repo.settings.update_avatar_success")) diff --git a/routers/repo/setting_protected_branch.go b/routers/repo/setting_protected_branch.go index c2e7bc8fac..017054d4c2 100644 --- a/routers/repo/setting_protected_branch.go +++ b/routers/repo/setting_protected_branch.go @@ -10,12 +10,13 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" pull_service "code.gitea.io/gitea/services/pull" ) @@ -168,7 +169,8 @@ func SettingsProtectedBranch(c *context.Context) { } // SettingsProtectedBranchPost updates the protected branch settings -func SettingsProtectedBranchPost(ctx *context.Context, f auth.ProtectBranchForm) { +func SettingsProtectedBranchPost(ctx *context.Context) { + f := web.GetForm(ctx).(*auth.ProtectBranchForm) branch := ctx.Params("*") if !ctx.Repo.GitRepo.IsBranchExist(branch) { ctx.NotFound("IsBranchExist", nil) diff --git a/routers/repo/settings_test.go b/routers/repo/settings_test.go index 679bb0d33c..85515121c7 100644 --- a/routers/repo/settings_test.go +++ b/routers/repo/settings_test.go @@ -10,11 +10,12 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "github.com/stretchr/testify/assert" ) @@ -52,7 +53,8 @@ func TestAddReadOnlyDeployKey(t *testing.T) { Title: "read-only", Content: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment\n", } - DeployKeysPost(ctx, addKeyForm) + web.SetForm(ctx, &addKeyForm) + DeployKeysPost(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.DeployKey{ @@ -81,7 +83,8 @@ func TestAddReadWriteOnlyDeployKey(t *testing.T) { Content: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment\n", IsWritable: true, } - DeployKeysPost(ctx, addKeyForm) + web.SetForm(ctx, &addKeyForm) + DeployKeysPost(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) models.AssertExistsAndLoadBean(t, &models.DeployKey{ diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index 5d7074b339..01d142843f 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -13,14 +13,15 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/webhook" ) @@ -181,7 +182,8 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent { } // GiteaHooksNewPost response for creating Gitea webhook -func GiteaHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { +func GiteaHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewWebhookForm) ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -230,8 +232,9 @@ func GiteaHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { } // GogsHooksNewPost response for creating webhook -func GogsHooksNewPost(ctx *context.Context, form auth.NewGogshookForm) { - newGogsWebhookPost(ctx, form, models.GOGS) +func GogsHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewGogshookForm) + newGogsWebhookPost(ctx, *form, models.GOGS) } // newGogsWebhookPost response for creating gogs hook @@ -283,7 +286,8 @@ func newGogsWebhookPost(ctx *context.Context, form auth.NewGogshookForm, kind mo } // DiscordHooksNewPost response for creating discord hook -func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) { +func DiscordHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewDiscordHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -334,7 +338,8 @@ func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) { } // DingtalkHooksNewPost response for creating dingtalk hook -func DingtalkHooksNewPost(ctx *context.Context, form auth.NewDingtalkHookForm) { +func DingtalkHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewDingtalkHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -376,7 +381,8 @@ func DingtalkHooksNewPost(ctx *context.Context, form auth.NewDingtalkHookForm) { } // TelegramHooksNewPost response for creating telegram hook -func TelegramHooksNewPost(ctx *context.Context, form auth.NewTelegramHookForm) { +func TelegramHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewTelegramHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -427,7 +433,8 @@ func TelegramHooksNewPost(ctx *context.Context, form auth.NewTelegramHookForm) { } // MatrixHooksNewPost response for creating a Matrix hook -func MatrixHooksNewPost(ctx *context.Context, form auth.NewMatrixHookForm) { +func MatrixHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewMatrixHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -481,7 +488,8 @@ func MatrixHooksNewPost(ctx *context.Context, form auth.NewMatrixHookForm) { } // MSTeamsHooksNewPost response for creating MS Teams hook -func MSTeamsHooksNewPost(ctx *context.Context, form auth.NewMSTeamsHookForm) { +func MSTeamsHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewMSTeamsHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -523,7 +531,8 @@ func MSTeamsHooksNewPost(ctx *context.Context, form auth.NewMSTeamsHookForm) { } // SlackHooksNewPost response for creating slack hook -func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) { +func SlackHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewSlackHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -582,7 +591,8 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) { } // FeishuHooksNewPost response for creating feishu hook -func FeishuHooksNewPost(ctx *context.Context, form auth.NewFeishuHookForm) { +func FeishuHooksNewPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewFeishuHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -685,7 +695,8 @@ func WebHooksEdit(ctx *context.Context) { } // WebHooksEditPost response for editing web hook -func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) { +func WebHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewWebhookForm) ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -725,7 +736,8 @@ func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) { } // GogsHooksEditPost response for editing gogs hook -func GogsHooksEditPost(ctx *context.Context, form auth.NewGogshookForm) { +func GogsHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewGogshookForm) ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -764,7 +776,8 @@ func GogsHooksEditPost(ctx *context.Context, form auth.NewGogshookForm) { } // SlackHooksEditPost response for editing slack hook -func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) { +func SlackHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewSlackHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -814,7 +827,8 @@ func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) { } // DiscordHooksEditPost response for editing discord hook -func DiscordHooksEditPost(ctx *context.Context, form auth.NewDiscordHookForm) { +func DiscordHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewDiscordHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -856,7 +870,8 @@ func DiscordHooksEditPost(ctx *context.Context, form auth.NewDiscordHookForm) { } // DingtalkHooksEditPost response for editing discord hook -func DingtalkHooksEditPost(ctx *context.Context, form auth.NewDingtalkHookForm) { +func DingtalkHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewDingtalkHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -888,7 +903,8 @@ func DingtalkHooksEditPost(ctx *context.Context, form auth.NewDingtalkHookForm) } // TelegramHooksEditPost response for editing discord hook -func TelegramHooksEditPost(ctx *context.Context, form auth.NewTelegramHookForm) { +func TelegramHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewTelegramHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -928,7 +944,8 @@ func TelegramHooksEditPost(ctx *context.Context, form auth.NewTelegramHookForm) } // MatrixHooksEditPost response for editing a Matrix hook -func MatrixHooksEditPost(ctx *context.Context, form auth.NewMatrixHookForm) { +func MatrixHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewMatrixHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -971,7 +988,8 @@ func MatrixHooksEditPost(ctx *context.Context, form auth.NewMatrixHookForm) { } // MSTeamsHooksEditPost response for editing MS Teams hook -func MSTeamsHooksEditPost(ctx *context.Context, form auth.NewMSTeamsHookForm) { +func MSTeamsHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewMSTeamsHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true @@ -1003,7 +1021,8 @@ func MSTeamsHooksEditPost(ctx *context.Context, form auth.NewMSTeamsHookForm) { } // FeishuHooksEditPost response for editing feishu hook -func FeishuHooksEditPost(ctx *context.Context, form auth.NewFeishuHookForm) { +func FeishuHooksEditPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewFeishuHookForm) ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true diff --git a/routers/repo/wiki.go b/routers/repo/wiki.go index ac650d3fc4..c4521a3071 100644 --- a/routers/repo/wiki.go +++ b/routers/repo/wiki.go @@ -13,15 +13,16 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" wiki_service "code.gitea.io/gitea/services/wiki" ) @@ -556,7 +557,8 @@ func NewWiki(ctx *context.Context) { } // NewWikiPost response for wiki create request -func NewWikiPost(ctx *context.Context, form auth.NewWikiForm) { +func NewWikiPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewWikiForm) ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page") ctx.Data["PageIsWiki"] = true ctx.Data["RequireSimpleMDE"] = true @@ -613,7 +615,8 @@ func EditWiki(ctx *context.Context) { } // EditWikiPost response for wiki modify request -func EditWikiPost(ctx *context.Context, form auth.NewWikiForm) { +func EditWikiPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewWikiForm) ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page") ctx.Data["PageIsWiki"] = true ctx.Data["RequireSimpleMDE"] = true diff --git a/routers/repo/wiki_test.go b/routers/repo/wiki_test.go index cc79c808f5..badd07f080 100644 --- a/routers/repo/wiki_test.go +++ b/routers/repo/wiki_test.go @@ -10,9 +10,10 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/web" wiki_service "code.gitea.io/gitea/services/wiki" "github.com/stretchr/testify/assert" @@ -114,11 +115,12 @@ func TestNewWikiPost(t *testing.T) { ctx := test.MockContext(t, "user2/repo1/wiki/_new") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) - NewWikiPost(ctx, auth.NewWikiForm{ + web.SetForm(ctx, &auth.NewWikiForm{ Title: title, Content: content, Message: message, }) + NewWikiPost(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) assertWikiExists(t, ctx.Repo.Repository, title) assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content) @@ -131,11 +133,12 @@ func TestNewWikiPost_ReservedName(t *testing.T) { ctx := test.MockContext(t, "user2/repo1/wiki/_new") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) - NewWikiPost(ctx, auth.NewWikiForm{ + web.SetForm(ctx, &auth.NewWikiForm{ Title: "_edit", Content: content, Message: message, }) + NewWikiPost(ctx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) assert.EqualValues(t, ctx.Tr("repo.wiki.reserved_page"), ctx.Flash.ErrorMsg) assertWikiNotExists(t, ctx.Repo.Repository, "_edit") @@ -164,11 +167,12 @@ func TestEditWikiPost(t *testing.T) { ctx.SetParams(":page", "Home") test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) - EditWikiPost(ctx, auth.NewWikiForm{ + web.SetForm(ctx, &auth.NewWikiForm{ Title: title, Content: content, Message: message, }) + EditWikiPost(ctx) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) assertWikiExists(t, ctx.Repo.Repository, title) assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content) diff --git a/routers/routes/chi.go b/routers/routes/base.go index 2400140ae6..a313032a88 100644 --- a/routers/routes/chi.go +++ b/routers/routes/base.go @@ -16,19 +16,16 @@ import ( "text/template" "time" + "code.gitea.io/gitea/modules/auth/sso" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/metrics" - "code.gitea.io/gitea/modules/public" + "code.gitea.io/gitea/modules/middlewares" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/routers" + "code.gitea.io/gitea/modules/templates" "gitea.com/go-chi/session" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" - "github.com/prometheus/client_golang/prometheus" ) type routerLoggerOptions struct { @@ -39,20 +36,21 @@ type routerLoggerOptions struct { } // SignedUserName returns signed user's name via context -// FIXME currently no any data stored on chi.Context but macaron.Context, so this will -// return "" before we remove macaron totally func SignedUserName(req *http.Request) string { - if v, ok := req.Context().Value("SignedUserName").(string); ok { - return v + ctx := context.GetContext(req) + if ctx != nil { + v := ctx.Data["SignedUserName"] + if res, ok := v.(string); ok { + return res + } } return "" } -func setupAccessLogger(c chi.Router) { +func accessLogger() func(http.Handler) http.Handler { logger := log.GetLogger("access") - logTemplate, _ := template.New("log").Parse(setting.AccessLogTemplate) - c.Use(func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { start := time.Now() next.ServeHTTP(w, req) @@ -70,15 +68,15 @@ func setupAccessLogger(c chi.Router) { ResponseWriter: rw, }) if err != nil { - log.Error("Could not set up macaron access logger: %v", err.Error()) + log.Error("Could not set up chi access logger: %v", err.Error()) } err = logger.SendLog(log.INFO, "", "", 0, buf.String(), "") if err != nil { - log.Error("Could not set up macaron access logger: %v", err.Error()) + log.Error("Could not set up chi access logger: %v", err.Error()) } }) - }) + } } // LoggerHandler is a handler that will log the routing to the default gitea log @@ -179,131 +177,70 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor } } -var ( - sessionManager *session.Manager -) - -// NewChi creates a chi Router -func NewChi() chi.Router { - c := chi.NewRouter() - c.Use(func(next http.Handler) http.Handler { - return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - next.ServeHTTP(context.NewResponse(resp), req) - }) - }) - c.Use(middleware.RealIP) - if !setting.DisableRouterLog && setting.RouterLogLevel != log.NONE { - if log.GetLogger("router").GetLevel() <= setting.RouterLogLevel { - c.Use(LoggerHandler(setting.RouterLogLevel)) - } - } - - var opt = session.Options{ - Provider: setting.SessionConfig.Provider, - ProviderConfig: setting.SessionConfig.ProviderConfig, - CookieName: setting.SessionConfig.CookieName, - CookiePath: setting.SessionConfig.CookiePath, - Gclifetime: setting.SessionConfig.Gclifetime, - Maxlifetime: setting.SessionConfig.Maxlifetime, - Secure: setting.SessionConfig.Secure, - Domain: setting.SessionConfig.Domain, - } - opt = session.PrepareOptions([]session.Options{opt}) - - var err error - sessionManager, err = session.NewManager(opt.Provider, opt) - if err != nil { - panic(err) - } - - c.Use(Recovery()) - if setting.EnableAccessLog { - setupAccessLogger(c) - } - - c.Use(public.Custom( - &public.Options{ - SkipLogging: setting.DisableRouterLog, - }, - )) - c.Use(public.Static( - &public.Options{ - Directory: path.Join(setting.StaticRootPath, "public"), - SkipLogging: setting.DisableRouterLog, - }, - )) - - c.Use(storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars)) - c.Use(storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars)) - - return c +type dataStore struct { + Data map[string]interface{} } -// RegisterInstallRoute registers the install routes -func RegisterInstallRoute(c chi.Router) { - m := NewMacaron() - RegisterMacaronInstallRoute(m) - - // We need at least one handler in chi so that it does not drop - // our middleware: https://github.com/go-gitea/gitea/issues/13725#issuecomment-735244395 - c.Get("/", func(w http.ResponseWriter, req *http.Request) { - m.ServeHTTP(w, req) - }) - - c.NotFound(func(w http.ResponseWriter, req *http.Request) { - m.ServeHTTP(w, req) - }) - - c.MethodNotAllowed(func(w http.ResponseWriter, req *http.Request) { - m.ServeHTTP(w, req) - }) +func (d *dataStore) GetData() map[string]interface{} { + return d.Data } -// NormalRoutes represents non install routes -func NormalRoutes() http.Handler { - r := chi.NewRouter() +// Recovery returns a middleware that recovers from any panics and writes a 500 and a log if so. +// This error will be created with the gitea 500 page. +func Recovery() func(next http.Handler) http.Handler { + var rnd = templates.HTMLRenderer() + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + defer func() { + if err := recover(); err != nil { + combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, string(log.Stack(2))) + log.Error("%v", combinedErr) + + sessionStore := session.GetSession(req) + if sessionStore == nil { + if setting.IsProd() { + http.Error(w, http.StatusText(500), 500) + } else { + http.Error(w, combinedErr, 500) + } + return + } - // for health check - r.Head("/", func(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusOK) - }) + var lc = middlewares.Locale(w, req) + var store = dataStore{ + Data: templates.Vars{ + "Language": lc.Language(), + "CurrentURL": setting.AppSubURL + req.URL.RequestURI(), + "i18n": lc, + }, + } - if setting.HasRobotsTxt { - r.Get("/robots.txt", func(w http.ResponseWriter, req *http.Request) { - filePath := path.Join(setting.CustomPath, "robots.txt") - fi, err := os.Stat(filePath) - if err == nil && httpcache.HandleTimeCache(req, w, fi) { - return - } - http.ServeFile(w, req, filePath) - }) - } + // Get user from session if logged in. + user, _ := sso.SignedInUser(req, w, &store, sessionStore) + if user != nil { + store.Data["IsSigned"] = true + store.Data["SignedUser"] = user + store.Data["SignedUserID"] = user.ID + store.Data["SignedUserName"] = user.Name + store.Data["IsAdmin"] = user.IsAdmin + } else { + store.Data["SignedUserID"] = int64(0) + store.Data["SignedUserName"] = "" + } - r.Get("/apple-touch-icon.png", func(w http.ResponseWriter, req *http.Request) { - http.Redirect(w, req, path.Join(setting.StaticURLPrefix, "img/apple-touch-icon.png"), 301) - }) + w.Header().Set(`X-Frame-Options`, `SAMEORIGIN`) - // prometheus metrics endpoint - if setting.Metrics.Enabled { - c := metrics.NewCollector() - prometheus.MustRegister(c) + if !setting.IsProd() { + store.Data["ErrorMsg"] = combinedErr + } + err = rnd.HTML(w, 500, "status/500", templates.BaseVars().Merge(store.Data)) + if err != nil { + log.Error("%v", err) + } + } + }() - r.Get("/metrics", routers.Metrics) + next.ServeHTTP(w, req) + }) } - - return r -} - -// DelegateToMacaron delegates other routes to macaron -func DelegateToMacaron(r chi.Router) { - m := NewMacaron() - RegisterMacaronRoutes(m) - - r.NotFound(func(w http.ResponseWriter, req *http.Request) { - m.ServeHTTP(w, req) - }) - - r.MethodNotAllowed(func(w http.ResponseWriter, req *http.Request) { - m.ServeHTTP(w, req) - }) } diff --git a/routers/routes/recovery.go b/routers/routes/install.go index cfe1a4114c..0dc066d600 100644 --- a/routers/routes/recovery.go +++ b/routers/routes/install.go @@ -7,38 +7,23 @@ package routes import ( "fmt" "net/http" + "path" - "code.gitea.io/gitea/modules/auth/sso" + "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/middlewares" + "code.gitea.io/gitea/modules/public" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" + "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers" - "github.com/unrolled/render" + "gitea.com/go-chi/session" ) -type dataStore struct { - Data map[string]interface{} -} - -func (d *dataStore) GetData() map[string]interface{} { - return d.Data -} - -// Recovery returns a middleware that recovers from any panics and writes a 500 and a log if so. -// Although similar to macaron.Recovery() the main difference is that this error will be created -// with the gitea 500 page. -func Recovery() func(next http.Handler) http.Handler { +func installRecovery() func(next http.Handler) http.Handler { + var rnd = templates.HTMLRenderer() return func(next http.Handler) http.Handler { - rnd := render.New(render.Options{ - Extensions: []string{".tmpl"}, - Directory: "templates", - Funcs: templates.NewFuncMap(), - Asset: templates.GetAsset, - AssetNames: templates.GetAssetNames, - IsDevelopment: !setting.IsProd(), - }) - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { defer func() { // Why we need this? The first recover will try to render a beautiful @@ -62,35 +47,16 @@ func Recovery() func(next http.Handler) http.Handler { log.Error("%v", combinedErr) lc := middlewares.Locale(w, req) - - // TODO: this should be replaced by real session after macaron removed totally - sessionStore, err := sessionManager.Start(w, req) - if err != nil { - // Just invoke the above recover catch - panic("session(start): " + err.Error()) - } - var store = dataStore{ Data: templates.Vars{ - "Language": lc.Language(), - "CurrentURL": setting.AppSubURL + req.URL.RequestURI(), - "i18n": lc, + "Language": lc.Language(), + "CurrentURL": setting.AppSubURL + req.URL.RequestURI(), + "i18n": lc, + "SignedUserID": int64(0), + "SignedUserName": "", }, } - // Get user from session if logged in. - user, _ := sso.SignedInUser(req, w, &store, sessionStore) - if user != nil { - store.Data["IsSigned"] = true - store.Data["SignedUser"] = user - store.Data["SignedUserID"] = user.ID - store.Data["SignedUserName"] = user.Name - store.Data["IsAdmin"] = user.IsAdmin - } else { - store.Data["SignedUserID"] = int64(0) - store.Data["SignedUserName"] = "" - } - w.Header().Set(`X-Frame-Options`, `SAMEORIGIN`) if !setting.IsProd() { @@ -107,3 +73,44 @@ func Recovery() func(next http.Handler) http.Handler { }) } } + +// InstallRoutes registers the install routes +func InstallRoutes() *web.Route { + r := web.NewRoute() + for _, middle := range commonMiddlewares() { + r.Use(middle) + } + + r.Use(session.Sessioner(session.Options{ + Provider: setting.SessionConfig.Provider, + ProviderConfig: setting.SessionConfig.ProviderConfig, + CookieName: setting.SessionConfig.CookieName, + CookiePath: setting.SessionConfig.CookiePath, + Gclifetime: setting.SessionConfig.Gclifetime, + Maxlifetime: setting.SessionConfig.Maxlifetime, + Secure: setting.SessionConfig.Secure, + Domain: setting.SessionConfig.Domain, + })) + + r.Use(installRecovery()) + + r.Use(public.Custom( + &public.Options{ + SkipLogging: setting.DisableRouterLog, + }, + )) + r.Use(public.Static( + &public.Options{ + Directory: path.Join(setting.StaticRootPath, "public"), + SkipLogging: setting.DisableRouterLog, + }, + )) + + r.Use(routers.InstallInit) + r.Get("/", routers.Install) + r.Post("/", web.Bind(forms.InstallForm{}), routers.InstallPost) + r.NotFound(func(w http.ResponseWriter, req *http.Request) { + http.Redirect(w, req, setting.AppURL, 302) + }) + return r +} diff --git a/routers/routes/macaron.go b/routers/routes/web.go index f64a0a597b..2433618581 100644 --- a/routers/routes/macaron.go +++ b/routers/routes/web.go @@ -6,19 +6,29 @@ package routes import ( "encoding/gob" + "fmt" + "net/http" + "os" + "path" + "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" + "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/options" + "code.gitea.io/gitea/modules/metrics" + "code.gitea.io/gitea/modules/public" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/validation" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers/admin" apiv1 "code.gitea.io/gitea/routers/api/v1" + "code.gitea.io/gitea/routers/api/v1/misc" "code.gitea.io/gitea/routers/dev" "code.gitea.io/gitea/routers/events" "code.gitea.io/gitea/routers/org" @@ -31,77 +41,79 @@ import ( // to registers all internal adapters _ "code.gitea.io/gitea/modules/session" - "gitea.com/macaron/binding" - "gitea.com/macaron/cache" - "gitea.com/macaron/captcha" - "gitea.com/macaron/cors" - "gitea.com/macaron/csrf" - "gitea.com/macaron/gzip" - "gitea.com/macaron/i18n" - "gitea.com/macaron/macaron" - "gitea.com/macaron/session" - "gitea.com/macaron/toolbox" + "gitea.com/go-chi/captcha" + "gitea.com/go-chi/session" + "github.com/NYTimes/gziphandler" + "github.com/go-chi/chi/middleware" + "github.com/prometheus/client_golang/prometheus" "github.com/tstranex/u2f" ) -// NewMacaron initializes Macaron instance. -func NewMacaron() *macaron.Macaron { - gob.Register(&u2f.Challenge{}) - var m *macaron.Macaron - if setting.RedirectMacaronLog { - loggerAsWriter := log.NewLoggerAsWriter("INFO", log.GetLogger("macaron")) - m = macaron.NewWithLogger(loggerAsWriter) - } else { - m = macaron.New() - } +const ( + // GzipMinSize represents min size to compress for the body size of response + GzipMinSize = 1400 +) - if setting.EnableGzip { - m.Use(gzip.Middleware()) +func commonMiddlewares() []func(http.Handler) http.Handler { + var handlers = []func(http.Handler) http.Handler{ + func(next http.Handler) http.Handler { + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + next.ServeHTTP(context.NewResponse(resp), req) + }) + }, + middleware.RealIP, } - if setting.Protocol == setting.FCGI || setting.Protocol == setting.FCGIUnix { - m.SetURLPrefix(setting.AppSubURL) + if !setting.DisableRouterLog && setting.RouterLogLevel != log.NONE { + if log.GetLogger("router").GetLevel() <= setting.RouterLogLevel { + handlers = append(handlers, LoggerHandler(setting.RouterLogLevel)) + } } + handlers = append(handlers, func(next http.Handler) http.Handler { + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + // Why we need this? The Recovery() will try to render a beautiful + // error page for user, but the process can still panic again, and other + // middleware like session also may panic then we have to recover twice + // and send a simple error page that should not panic any more. + defer func() { + if err := recover(); err != nil { + combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, string(log.Stack(2))) + log.Error("%v", combinedErr) + if setting.IsProd() { + http.Error(resp, http.StatusText(500), 500) + } else { + http.Error(resp, combinedErr, 500) + } + } + }() + next.ServeHTTP(resp, req) + }) + }) - m.Use(templates.HTMLRenderer()) - - mailer.InitMailRender(templates.Mailer()) - - localeNames, err := options.Dir("locale") - - if err != nil { - log.Fatal("Failed to list locale files: %v", err) + if setting.EnableAccessLog { + handlers = append(handlers, accessLogger()) } + return handlers +} - localFiles := make(map[string][]byte) +// NormalRoutes represents non install routes +func NormalRoutes() *web.Route { + r := web.NewRoute() + for _, middle := range commonMiddlewares() { + r.Use(middle) + } + r.Use(Recovery()) - for _, name := range localeNames { - localFiles[name], err = options.Locale(name) + r.Mount("/", WebRoutes()) + r.Mount("/api/v1", apiv1.Routes()) + r.Mount("/api/internal", private.Routes()) + return r +} - if err != nil { - log.Fatal("Failed to load %s locale file. %v", name, err) - } - } +// WebRoutes returns all web routes +func WebRoutes() *web.Route { + r := web.NewRoute() - m.Use(i18n.I18n(i18n.Options{ - SubURL: setting.AppSubURL, - Files: localFiles, - Langs: setting.Langs, - Names: setting.Names, - DefaultLang: "en-US", - Redirect: false, - CookieHttpOnly: true, - Secure: setting.SessionConfig.Secure, - CookieDomain: setting.SessionConfig.Domain, - })) - m.Use(cache.Cacher(cache.Options{ - Adapter: setting.CacheService.Adapter, - AdapterConfig: setting.CacheService.Conn, - Interval: setting.CacheService.Interval, - })) - m.Use(captcha.Captchaer(captcha.Options{ - SubURL: setting.AppSubURL, - })) - m.Use(session.Sessioner(session.Options{ + r.Use(session.Sessioner(session.Options{ Provider: setting.SessionConfig.Provider, ProviderConfig: setting.SessionConfig.ProviderConfig, CookieName: setting.SessionConfig.CookieName, @@ -111,47 +123,104 @@ func NewMacaron() *macaron.Macaron { Secure: setting.SessionConfig.Secure, Domain: setting.SessionConfig.Domain, })) - m.Use(csrf.Csrfer(csrf.Options{ - Secret: setting.SecretKey, - Cookie: setting.CSRFCookieName, - SetCookie: true, - Secure: setting.SessionConfig.Secure, - CookieHttpOnly: setting.CSRFCookieHTTPOnly, - Header: "X-Csrf-Token", - CookieDomain: setting.SessionConfig.Domain, - CookiePath: setting.AppSubURL, - })) - m.Use(toolbox.Toolboxer(m, toolbox.Options{ - HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{ - { - Desc: "Database connection", - Func: models.Ping, - }, + + r.Use(public.Custom( + &public.Options{ + SkipLogging: setting.DisableRouterLog, }, - DisableDebug: !setting.EnablePprof, - })) - m.Use(context.Contexter()) - m.SetAutoHead(true) - return m -} + )) + r.Use(public.Static( + &public.Options{ + Directory: path.Join(setting.StaticRootPath, "public"), + SkipLogging: setting.DisableRouterLog, + }, + )) + + r.Use(storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars)) + r.Use(storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars)) -// RegisterMacaronInstallRoute registers the install routes -func RegisterMacaronInstallRoute(m *macaron.Macaron) { - m.Combo("/", routers.InstallInit).Get(routers.Install). - Post(binding.BindIgnErr(auth.InstallForm{}), routers.InstallPost) - m.NotFound(func(ctx *context.Context) { - ctx.Redirect(setting.AppURL, 302) + gob.Register(&u2f.Challenge{}) + + if setting.EnableGzip { + h, err := gziphandler.GzipHandlerWithOpts(gziphandler.MinSize(GzipMinSize)) + if err != nil { + log.Fatal("GzipHandlerWithOpts failed: %v", err) + } + r.Use(h) + } + + if (setting.Protocol == setting.FCGI || setting.Protocol == setting.FCGIUnix) && setting.AppSubURL != "" { + r.Use(func(next http.Handler) http.Handler { + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + req.URL.Path = strings.TrimPrefix(req.URL.Path, setting.AppSubURL) + next.ServeHTTP(resp, req) + }) + }) + } + + mailer.InitMailRender(templates.Mailer()) + + r.Use(captcha.Captchaer(context.GetImageCaptcha())) + // Removed: toolbox.Toolboxer middleware will provide debug informations which seems unnecessary + r.Use(context.Contexter()) + // Removed: SetAutoHead allow a get request redirect to head if get method is not exist + + r.Use(user.GetNotificationCount) + r.Use(repo.GetActiveStopwatch) + r.Use(func(ctx *context.Context) { + ctx.Data["UnitWikiGlobalDisabled"] = models.UnitTypeWiki.UnitGlobalDisabled() + ctx.Data["UnitIssuesGlobalDisabled"] = models.UnitTypeIssues.UnitGlobalDisabled() + ctx.Data["UnitPullsGlobalDisabled"] = models.UnitTypePullRequests.UnitGlobalDisabled() + ctx.Data["UnitProjectsGlobalDisabled"] = models.UnitTypeProjects.UnitGlobalDisabled() + }) + + // for health check + r.Head("/", func(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(http.StatusOK) + }) + + if setting.HasRobotsTxt { + r.Get("/robots.txt", func(w http.ResponseWriter, req *http.Request) { + filePath := path.Join(setting.CustomPath, "robots.txt") + fi, err := os.Stat(filePath) + if err == nil && httpcache.HandleTimeCache(req, w, fi) { + return + } + http.ServeFile(w, req, filePath) + }) + } + + r.Get("/apple-touch-icon.png", func(w http.ResponseWriter, req *http.Request) { + http.Redirect(w, req, path.Join(setting.StaticURLPrefix, "img/apple-touch-icon.png"), 301) }) + + // prometheus metrics endpoint + if setting.Metrics.Enabled { + c := metrics.NewCollector() + prometheus.MustRegister(c) + + r.Get("/metrics", routers.Metrics) + } + + if setting.API.EnableSwagger { + // Note: The route moved from apiroutes because it's in fact want to render a web page + r.Get("/api/swagger", misc.Swagger) // Render V1 by default + } + + RegisterRoutes(r) + + return r } -// RegisterMacaronRoutes routes routes to Macaron -func RegisterMacaronRoutes(m *macaron.Macaron) { +// RegisterRoutes routes routes to Macaron +func RegisterRoutes(m *web.Route) { 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 + //bindIgnErr := binding.BindIgnErr + bindIgnErr := web.Bind validation.AddBindingRules() openIDSignInEnabled := func(ctx *context.Context) { @@ -175,15 +244,6 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { } } - m.Use(user.GetNotificationCount) - m.Use(repo.GetActiveStopwatch) - m.Use(func(ctx *context.Context) { - ctx.Data["UnitWikiGlobalDisabled"] = models.UnitTypeWiki.UnitGlobalDisabled() - ctx.Data["UnitIssuesGlobalDisabled"] = models.UnitTypeIssues.UnitGlobalDisabled() - ctx.Data["UnitPullsGlobalDisabled"] = models.UnitTypePullRequests.UnitGlobalDisabled() - ctx.Data["UnitProjectsGlobalDisabled"] = models.UnitTypeProjects.UnitGlobalDisabled() - }) - // FIXME: not all routes need go through same middlewares. // Especially some AJAX requests, we can reduce middleware number to improve performance. // Routers. @@ -198,8 +258,6 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Get("/organizations", routers.ExploreOrganizations) m.Get("/code", routers.ExploreCode) }, ignSignIn) - m.Combo("/install", routers.InstallInit).Get(routers.Install). - Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost) m.Get("/issues", reqSignIn, user.Issues) m.Get("/pulls", reqSignIn, user.Pulls) m.Get("/milestones", reqSignIn, reqMilestonesDashboardPageEnabled, user.Milestones) @@ -226,8 +284,8 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Get("/sign_up", user.SignUp) m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost) m.Group("/oauth2", func() { - m.Get("/:provider", user.SignInOAuth) - m.Get("/:provider/callback", user.SignInOAuthCallback) + 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) @@ -261,7 +319,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("", bindIgnErr(auth.UpdateProfileForm{}), userSetting.ProfilePost) m.Get("/change_password", user.MustChangePassword) m.Post("/change_password", bindIgnErr(auth.MustChangePasswordForm{}), user.MustChangePasswordPost) - m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), userSetting.AvatarPost) + m.Post("/avatar", bindIgnErr(auth.AvatarForm{}), userSetting.AvatarPost) m.Post("/avatar/delete", userSetting.DeleteAvatar) m.Group("/account", func() { m.Combo("").Get(userSetting.Account).Post(bindIgnErr(auth.ChangePasswordForm{}), userSetting.AccountPost) @@ -291,9 +349,9 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/account_link", userSetting.DeleteAccountLink) }) m.Group("/applications/oauth2", func() { - m.Get("/:id", userSetting.OAuth2ApplicationShow) - m.Post("/:id", bindIgnErr(auth.EditOAuth2ApplicationForm{}), userSetting.OAuthApplicationsEdit) - m.Post("/:id/regenerate_secret", userSetting.OAuthApplicationsRegenerateSecret) + m.Get("/{id}", userSetting.OAuth2ApplicationShow) + m.Post("/{id}", bindIgnErr(auth.EditOAuth2ApplicationForm{}), userSetting.OAuthApplicationsEdit) + m.Post("/{id}/regenerate_secret", userSetting.OAuthApplicationsRegenerateSecret) m.Post("", bindIgnErr(auth.EditOAuth2ApplicationForm{}), userSetting.OAuthApplicationsPost) m.Post("/delete", userSetting.DeleteOAuth2Application) m.Post("/revoke", userSetting.RevokeOAuth2Grant) @@ -316,18 +374,18 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) m.Any("/activate", user.Activate, reqSignIn) m.Any("/activate_email", user.ActivateEmail) - m.Get("/avatar/:username/:size", user.Avatar) + m.Get("/avatar/{username}/{size}", user.Avatar) m.Get("/email2user", user.Email2User) m.Get("/recover_account", user.ResetPasswd) m.Post("/recover_account", user.ResetPasswdPost) m.Get("/forgot_password", user.ForgotPasswd) m.Post("/forgot_password", user.ForgotPasswdPost) m.Post("/logout", user.SignOut) - m.Get("/task/:task", user.TaskStatus) + m.Get("/task/{task}", user.TaskStatus) }) // ***** END: User ***** - m.Get("/avatar/:hash", user.AvatarByEmailHash) + m.Get("/avatar/{hash}", user.AvatarByEmailHash) adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true}) @@ -339,12 +397,12 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/config/test_mail", admin.SendTestMail) m.Group("/monitor", func() { m.Get("", admin.Monitor) - m.Post("/cancel/:pid", admin.MonitorCancel) - m.Group("/queue/:qid", func() { + m.Post("/cancel/{pid}", admin.MonitorCancel) + m.Group("/queue/{qid}", func() { m.Get("", admin.Queue) m.Post("/set", admin.SetQueueSettings) m.Post("/add", admin.AddWorkers) - m.Post("/cancel/:pid", admin.WorkerCancel) + m.Post("/cancel/{pid}", admin.WorkerCancel) m.Post("/flush", admin.Flush) }) }) @@ -352,8 +410,8 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { 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.Combo("/{userid}").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost) + m.Post("/{userid}/delete", admin.DeleteUser) }) m.Group("/emails", func() { @@ -374,20 +432,20 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Group("/hooks", func() { m.Get("", admin.DefaultOrSystemWebhooks) m.Post("/delete", admin.DeleteDefaultOrSystemWebhook) - 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) - m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost) - m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) - m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) - m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) + m.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) + m.Post("/telegram/{id}", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost) + m.Post("/matrix/{id}", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) + m.Post("/msteams/{id}", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) + m.Post("/feishu/{id}", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) }) - m.Group("/^:configType(default-hooks|system-hooks)$", func() { - m.Get("/:type/new", repo.WebhooksNew) + m.Group("/{configType:default-hooks|system-hooks}", func() { + m.Get("/{type}/new", repo.WebhooksNew) m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) @@ -402,9 +460,9 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { 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). + m.Combo("/{authid}").Get(admin.EditAuthSource). Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost) - m.Post("/:authid/delete", admin.DeleteAuthSource) + m.Post("/{authid}/delete", admin.DeleteAuthSource) }) m.Group("/notices", func() { @@ -416,15 +474,15 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { // ***** END: Admin ***** m.Group("", func() { - m.Get("/:username", user.Profile) - m.Get("/attachments/:uuid", repo.GetAttachment) + m.Get("/{username}", user.Profile) + m.Get("/attachments/{uuid}", repo.GetAttachment) }, ignSignIn) - m.Group("/:username", func() { - m.Post("/action/:action", user.Action) + m.Group("/{username}", func() { + m.Post("/action/{action}", user.Action) }, reqSignIn) - if macaron.Env == macaron.DEV { + if !setting.IsProd() { m.Get("/template/*", dev.TemplatePreview) } @@ -449,44 +507,44 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost) }) - m.Group("/:org", func() { + m.Group("/{org}", func() { m.Get("/dashboard", user.Dashboard) - m.Get("/dashboard/:team", user.Dashboard) + m.Get("/dashboard/{team}", user.Dashboard) m.Get("/issues", user.Issues) - m.Get("/issues/:team", user.Issues) + m.Get("/issues/{team}", user.Issues) m.Get("/pulls", user.Pulls) - m.Get("/pulls/:team", user.Pulls) + m.Get("/pulls/{team}", user.Pulls) m.Get("/milestones", reqMilestonesDashboardPageEnabled, user.Milestones) - m.Get("/milestones/:team", reqMilestonesDashboardPageEnabled, user.Milestones) + m.Get("/milestones/{team}", reqMilestonesDashboardPageEnabled, user.Milestones) m.Get("/members", org.Members) - m.Post("/members/action/:action", org.MembersAction) + m.Post("/members/action/{action}", org.MembersAction) m.Get("/teams", org.Teams) }, context.OrgAssignment(true, false, true)) - 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) + 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) }, context.OrgAssignment(true, false, true)) - m.Group("/:org", func() { + 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.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", bindIgnErr(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) + m.Get("/{type}/new", repo.WebhooksNew) m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) @@ -496,16 +554,16 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/matrix/new", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksNewPost) m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost) m.Post("/feishu/new", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksNewPost) - 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) - m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost) - m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) - m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) - m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) + m.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) + m.Post("/telegram/{id}", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost) + m.Post("/matrix/{id}", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) + m.Post("/msteams/{id}", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) + m.Post("/feishu/{id}", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) }) m.Group("/labels", func() { @@ -529,19 +587,19 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Get("/migrate", repo.Migrate) m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost) m.Group("/fork", func() { - m.Combo("/:repoid").Get(repo.Fork). + m.Combo("/{repoid}").Get(repo.Fork). Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost) }, context.RepoIDAssignment(), context.UnitTypes(), reqRepoCodeReader) }, reqSignIn) // ***** Release Attachment Download without Signin - m.Get("/:username/:reponame/releases/download/:vTag/:fileName", ignSignIn, context.RepoAssignment(), repo.MustBeNotEmpty, repo.RedirectDownload) + m.Get("/{username}/{reponame}/releases/download/{vTag}/{fileName}", ignSignIn, context.RepoAssignment(), repo.MustBeNotEmpty, repo.RedirectDownload) - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Group("/settings", func() { m.Combo("").Get(repo.Settings). Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost) - m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), repo.SettingsAvatar) + m.Post("/avatar", bindIgnErr(auth.AvatarForm{}), repo.SettingsAvatar) m.Post("/avatar/delete", repo.SettingsDeleteAvatar) m.Group("/collaboration", func() { @@ -562,7 +620,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Group("/hooks", func() { m.Get("", repo.Webhooks) m.Post("/delete", repo.DeleteWebhook) - m.Get("/:type/new", repo.WebhooksNew) + m.Get("/{type}/new", repo.WebhooksNew) m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) @@ -572,21 +630,21 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/matrix/new", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksNewPost) m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost) m.Post("/feishu/new", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksNewPost) - m.Get("/:id", repo.WebHooksEdit) - m.Post("/:id/test", repo.TestWebhook) - 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) - m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost) - m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) - m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) - m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) + m.Get("/{id}", repo.WebHooksEdit) + m.Post("/{id}/test", repo.TestWebhook) + 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) + m.Post("/telegram/{id}", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost) + m.Post("/matrix/{id}", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) + m.Post("/msteams/{id}", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) + m.Post("/feishu/{id}", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) m.Group("/git", func() { m.Get("", repo.GitHooks) - m.Combo("/:name").Get(repo.GitHooksEdit). + m.Combo("/{name}").Get(repo.GitHooksEdit). Post(repo.GitHooksEditPost) }, context.GitHookService()) }) @@ -598,16 +656,16 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }) m.Group("/lfs", func() { - m.Get("", repo.LFSFiles) - m.Get("/show/:oid", repo.LFSFileGet) - m.Post("/delete/:oid", repo.LFSDelete) + m.Get("/", repo.LFSFiles) + m.Get("/show/{oid}", repo.LFSFileGet) + m.Post("/delete/{oid}", repo.LFSDelete) m.Get("/pointers", repo.LFSPointerFiles) m.Post("/pointers/associate", repo.LFSAutoAssociate) m.Get("/find", repo.LFSFileFind) m.Group("/locks", func() { m.Get("/", repo.LFSLocks) m.Post("/", repo.LFSLockFile) - m.Post("/:lid/unlock", repo.LFSUnlock) + m.Post("/{lid}/unlock", repo.LFSUnlock) }) }) @@ -617,12 +675,12 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }) }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef()) - m.Post("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) + m.Post("/{username}/{reponame}/action/{action}", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) // Grouping for those endpoints not requiring authentication - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Group("/milestone", func() { - m.Get("/:id", repo.MilestoneIssuesAndPulls) + m.Get("/{id}", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists). Get(ignSignIn, repo.SetDiffViewStyle, repo.CompareDiff). @@ -630,7 +688,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }, context.RepoAssignment(), context.UnitTypes()) // Grouping for those endpoints that do require authentication - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Group("/issues", func() { m.Group("/new", func() { m.Combo("").Get(context.RepoRef(), repo.NewIssue). @@ -641,7 +699,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { // 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() { - m.Group("/:index", func() { + m.Group("/{index}", func() { m.Post("/title", repo.UpdateIssueTitle) m.Post("/content", repo.UpdateIssueContent) m.Post("/watch", repo.IssueWatch) @@ -658,13 +716,13 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/cancel", repo.CancelStopwatch) }) }) - m.Post("/reactions/:action", bindIgnErr(auth.ReactionForm{}), repo.ChangeIssueReaction) + m.Post("/reactions/{action}", bindIgnErr(auth.ReactionForm{}), repo.ChangeIssueReaction) m.Post("/lock", reqRepoIssueWriter, bindIgnErr(auth.IssueLockForm{}), repo.LockIssue) m.Post("/unlock", reqRepoIssueWriter, repo.UnlockIssue) }, context.RepoMustNotBeArchived()) - m.Group("/:index", func() { + m.Group("/{index}", func() { m.Get("/attachments", repo.GetIssueAttachments) - m.Get("/attachments/:uuid", repo.GetAttachment) + m.Get("/attachments/{uuid}", repo.GetAttachment) }) m.Post("/labels", reqRepoIssuesOrPullsWriter, repo.UpdateIssueLabel) @@ -677,12 +735,12 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Post("/attachments", repo.UploadIssueAttachment) m.Post("/attachments/remove", repo.DeleteAttachment) }, context.RepoMustNotBeArchived()) - m.Group("/comments/:id", func() { + m.Group("/comments/{id}", func() { m.Post("", repo.UpdateCommentContent) m.Post("/delete", repo.DeleteComment) - m.Post("/reactions/:action", bindIgnErr(auth.ReactionForm{}), repo.ChangeCommentReaction) + m.Post("/reactions/{action}", bindIgnErr(auth.ReactionForm{}), repo.ChangeCommentReaction) }, context.RepoMustNotBeArchived()) - m.Group("/comments/:id", func() { + m.Group("/comments/{id}", func() { m.Get("/attachments", repo.GetCommentAttachments) }) m.Group("/labels", func() { @@ -694,13 +752,13 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { 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.Post("/:id/:action", repo.ChangeMilestoneStatus) + m.Get("/{id}/edit", repo.EditMilestone) + m.Post("/{id}/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost) + m.Post("/{id}/{action}", repo.ChangeMilestoneStatus) m.Post("/delete", repo.DeleteMilestone) }, context.RepoMustNotBeArchived(), reqRepoIssuesOrPullsWriter, context.RepoRef()) m.Group("/pull", func() { - m.Post("/:index/target_branch", repo.UpdatePullRequestTarget) + m.Post("/{index}/target_branch", repo.UpdatePullRequestTarget) }, context.RepoMustNotBeArchived()) m.Group("", func() { @@ -723,7 +781,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty) m.Group("/branches", func() { - m.Group("/_new/", func() { + 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) @@ -735,14 +793,14 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }, reqSignIn, context.RepoAssignment(), context.UnitTypes()) // Releases - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Get("/tags", repo.TagsList, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag)) m.Group("/releases", func() { m.Get("/", repo.Releases) m.Get("/tag/*", repo.SingleRelease) m.Get("/latest", repo.LatestRelease) - m.Get("/attachments/:uuid", repo.GetAttachment) + m.Get("/attachments/{uuid}", repo.GetAttachment) }, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag)) m.Group("/releases", func() { m.Get("/new", repo.NewRelease) @@ -772,56 +830,57 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }) }, ignSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoReleaseReader) - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Post("/topics", repo.TopicsPost) }, context.RepoAssignment(), context.RepoMustNotBeArchived(), reqRepoAdmin) - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Group("", func() { - m.Get("/^:type(issues|pulls)$", repo.Issues) - m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue) - m.Get("/labels/", reqRepoIssuesOrPullsReader, repo.RetrieveLabels, repo.Labels) + m.Get("/{type:issues|pulls}", repo.Issues) + m.Get("/{type:issues|pulls}/{index}", repo.ViewIssue) + m.Get("/labels", reqRepoIssuesOrPullsReader, repo.RetrieveLabels, repo.Labels) m.Get("/milestones", reqRepoIssuesOrPullsReader, repo.Milestones) }, context.RepoRef()) m.Group("/projects", func() { m.Get("", repo.Projects) - m.Get("/:id", repo.ViewProject) + m.Get("/{id}", repo.ViewProject) m.Group("", func() { m.Get("/new", repo.NewProject) m.Post("/new", bindIgnErr(auth.CreateProjectForm{}), repo.NewProjectPost) - m.Group("/:id", func() { + m.Group("/{id}", func() { m.Post("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.AddBoardToProjectPost) m.Post("/delete", repo.DeleteProject) m.Get("/edit", repo.EditProject) m.Post("/edit", bindIgnErr(auth.CreateProjectForm{}), repo.EditProjectPost) - m.Post("/^:action(open|close)$", repo.ChangeProjectStatus) + m.Post("/{action:open|close}", repo.ChangeProjectStatus) - m.Group("/:boardID", func() { + m.Group("/{boardID}", func() { m.Put("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.EditProjectBoardTitle) m.Delete("", repo.DeleteProjectBoard) m.Post("/default", repo.SetDefaultProjectBoard) - m.Post("/:index", repo.MoveIssueAcrossBoards) + m.Post("/{index}", repo.MoveIssueAcrossBoards) }) }) }, reqRepoProjectsWriter, context.RepoMustNotBeArchived()) }, reqRepoProjectsReader, repo.MustEnableProjects) m.Group("/wiki", func() { - m.Get("/?:page", repo.Wiki) + m.Get("/", repo.Wiki) + m.Get("/{page}", repo.Wiki) m.Get("/_pages", repo.WikiPages) - m.Get("/:page/_revision", repo.WikiRevision) - m.Get("/commit/:sha([a-f0-9]{7,40})$", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.Diff) - m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.RawDiff) + m.Get("/{page}/_revision", repo.WikiRevision) + m.Get("/commit/{sha:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.Diff) + m.Get("/commit/{sha:[a-f0-9]{7,40}}.{:patch|diff}", repo.RawDiff) m.Group("", func() { m.Combo("/_new").Get(repo.NewWiki). Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost) - m.Combo("/:page/_edit").Get(repo.EditWiki). + m.Combo("/{page}/_edit").Get(repo.EditWiki). Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost) - m.Post("/:page/delete", repo.DeleteWikiPagePost) + m.Post("/{page}/delete", repo.DeleteWikiPagePost) }, context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter) }, repo.MustEnableWiki, context.RepoRef(), func(ctx *context.Context) { ctx.Data["PageIsWiki"] = true @@ -833,12 +892,12 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Group("/activity", func() { m.Get("", repo.Activity) - m.Get("/:period", repo.Activity) + m.Get("/{period}", repo.Activity) }, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(models.UnitTypePullRequests, models.UnitTypeIssues, models.UnitTypeReleases)) m.Group("/activity_author_data", func() { m.Get("", repo.ActivityAuthors) - m.Get("/:period", repo.ActivityAuthors) + m.Get("/{period}", repo.ActivityAuthors) }, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(models.UnitTypeCode)) m.Group("/archive", func() { @@ -851,10 +910,10 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) m.Group("/blob_excerpt", func() { - m.Get("/:sha", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob) + m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob) }, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) - m.Group("/pulls/:index", func() { + m.Group("/pulls/{index}", func() { m.Get(".diff", repo.DownloadPullDiff) m.Get(".patch", repo.DownloadPullPatch) m.Get("/commits", context.RepoRef(), repo.ViewPullCommits) @@ -875,7 +934,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { 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) + 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) @@ -884,7 +943,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { 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) - m.Get("/blob/:sha", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByID) + m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByID) // "/*" route is deprecated, and kept for backward compatibility m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownload) }, repo.MustBeNotEmpty, reqRepoCodeReader) @@ -905,7 +964,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Group("", func() { m.Get("/graph", repo.Graph) - m.Get("/commit/:sha([a-f0-9]{7,40})$", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.Diff) + m.Get("/commit/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.Diff) }, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) m.Group("/src", func() { @@ -919,39 +978,52 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Group("", func() { m.Get("/forks", repo.Forks) }, context.RepoRef(), reqRepoCodeReader) - m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", + m.Get("/commit/{sha:([a-f0-9]{7,40})}.{ext:patch|diff}", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff) }, ignSignIn, context.RepoAssignment(), context.UnitTypes()) - m.Group("/:username/:reponame", func() { + m.Group("/{username}/{reponame}", func() { m.Get("/stars", repo.Stars) m.Get("/watchers", repo.Watchers) m.Get("/search", reqRepoCodeReader, repo.Search) }, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes()) - m.Group("/:username", func() { - m.Group("/:reponame", func() { + m.Group("/{username}", func() { + m.Group("/{reponame}", func() { m.Get("", repo.SetEditorconfigIfExists, repo.Home) - m.Get("\\.git$", repo.SetEditorconfigIfExists, repo.Home) }, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes()) - m.Group("/:reponame", func() { - m.Group("\\.git/info/lfs", func() { + m.Group("/{reponame}", func() { + m.Group("/info/lfs", func() { m.Post("/objects/batch", lfs.BatchHandler) - m.Get("/objects/:oid/:filename", lfs.ObjectOidHandler) - m.Any("/objects/:oid", lfs.ObjectOidHandler) + m.Get("/objects/{oid}/{filename}", lfs.ObjectOidHandler) + m.Any("/objects/{oid}", lfs.ObjectOidHandler) m.Post("/objects", lfs.PostHandler) m.Post("/verify", lfs.VerifyHandler) m.Group("/locks", func() { m.Get("/", lfs.GetListLockHandler) m.Post("/", lfs.PostLockHandler) m.Post("/verify", lfs.VerifyLockHandler) - m.Post("/:lid/unlock", lfs.UnLockHandler) + m.Post("/{lid}/unlock", lfs.UnLockHandler) }) m.Any("/*", func(ctx *context.Context) { ctx.NotFound("", nil) }) }, ignSignInAndCsrf) - m.Any("/*", ignSignInAndCsrf, repo.HTTP) + + m.Group("", func() { + m.Post("/git-upload-pack", repo.ServiceUploadPack) + m.Post("/git-receive-pack", repo.ServiceReceivePack) + m.Get("/info/refs", repo.GetInfoRefs) + m.Get("/HEAD", repo.GetTextFile("HEAD")) + m.Get("/objects/info/alternates", repo.GetTextFile("objects/info/alternates")) + m.Get("/objects/info/http-alternates", repo.GetTextFile("objects/info/http-alternates")) + m.Get("/objects/info/packs", repo.GetInfoPacks) + m.Get("/objects/info/{file:[^/]*}", repo.GetTextFile("")) + m.Get("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) + m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) + m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) + }, ignSignInAndCsrf) + m.Head("/tasks/trigger", repo.TriggerTask) }) }) @@ -964,30 +1036,9 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { }, reqSignIn) if setting.API.EnableSwagger { - m.Get("/swagger.v1.json", templates.JSONRenderer(), routers.SwaggerV1Json) - } - - var handlers []macaron.Handler - if setting.CORSConfig.Enabled { - handlers = append(handlers, cors.CORS(cors.Options{ - Scheme: setting.CORSConfig.Scheme, - AllowDomain: setting.CORSConfig.AllowDomain, - AllowSubdomain: setting.CORSConfig.AllowSubdomain, - Methods: setting.CORSConfig.Methods, - MaxAgeSeconds: int(setting.CORSConfig.MaxAge.Seconds()), - AllowCredentials: setting.CORSConfig.AllowCredentials, - })) + m.Get("/swagger.v1.json", routers.SwaggerV1Json) } - handlers = append(handlers, ignSignIn) - m.Group("/api", func() { - apiv1.RegisterRoutes(m) - }, handlers...) - - 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) - }) // Not found handler. - m.NotFound(routers.NotFound) + m.NotFound(web.Wrap(routers.NotFound)) } diff --git a/routers/swagger_json.go b/routers/swagger_json.go index 58c4ec50d9..3ff1674f04 100644 --- a/routers/swagger_json.go +++ b/routers/swagger_json.go @@ -7,6 +7,7 @@ package routers import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" ) // tplSwaggerV1Json swagger v1 json template @@ -14,5 +15,10 @@ const tplSwaggerV1Json base.TplName = "swagger/v1_json" // SwaggerV1Json render swagger v1 json func SwaggerV1Json(ctx *context.Context) { - ctx.HTML(200, tplSwaggerV1Json) + t := ctx.Render.TemplateLookup(string(tplSwaggerV1Json)) + ctx.Resp.Header().Set("Content-Type", "application/json") + if err := t.Execute(ctx.Resp, ctx.Data); err != nil { + log.Error("%v", err) + ctx.Error(500) + } } diff --git a/routers/user/auth.go b/routers/user/auth.go index bce801847d..909d0a2ee5 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -12,22 +12,22 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth/oauth2" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/eventsource" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/hcaptcha" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/recaptcha" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" "code.gitea.io/gitea/services/externalaccount" "code.gitea.io/gitea/services/mailer" - "gitea.com/macaron/captcha" "github.com/markbates/goth" "github.com/tstranex/u2f" ) @@ -149,7 +149,7 @@ func SignIn(ctx *context.Context) { } // SignInPost response for sign in request -func SignInPost(ctx *context.Context, form auth.SignInForm) { +func SignInPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("sign_in") orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers() @@ -170,6 +170,7 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) { return } + form := web.GetForm(ctx).(*auth.SignInForm) u, err := models.UserSignIn(form.UserName, form.Password) if err != nil { if models.IsErrUserNotExist(err) { @@ -250,7 +251,8 @@ func TwoFactor(ctx *context.Context) { } // TwoFactorPost validates a user's two-factor authentication token. -func TwoFactorPost(ctx *context.Context, form auth.TwoFactorAuthForm) { +func TwoFactorPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.TwoFactorAuthForm) ctx.Data["Title"] = ctx.Tr("twofa") // Ensure user is in a 2FA session. @@ -328,7 +330,8 @@ func TwoFactorScratch(ctx *context.Context) { } // TwoFactorScratchPost validates and invalidates a user's two-factor scratch token. -func TwoFactorScratchPost(ctx *context.Context, form auth.TwoFactorScratchAuthForm) { +func TwoFactorScratchPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.TwoFactorScratchAuthForm) ctx.Data["Title"] = ctx.Tr("twofa_scratch") // Ensure user is in a 2FA session. @@ -427,7 +430,8 @@ func U2FChallenge(ctx *context.Context) { } // U2FSign authenticates the user by signResp -func U2FSign(ctx *context.Context, signResp u2f.SignResponse) { +func U2FSign(ctx *context.Context) { + signResp := web.GetForm(ctx).(*u2f.SignResponse) challSess := ctx.Session.Get("u2fChallenge") idSess := ctx.Session.Get("twofaUid") if challSess == nil || idSess == nil { @@ -447,7 +451,7 @@ func U2FSign(ctx *context.Context, signResp u2f.SignResponse) { log.Fatal("parsing u2f registration: %v", err) continue } - newCounter, authErr := r.Authenticate(signResp, *challenge, reg.Counter) + newCounter, authErr := r.Authenticate(*signResp, *challenge, reg.Counter) if authErr == nil { reg.Counter = newCounter user, err := models.GetUserByID(id) @@ -563,20 +567,20 @@ func SignInOAuth(ctx *context.Context) { } // try to do a direct callback flow, so we don't authenticate the user again but use the valid accesstoken to get the user - user, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req.Request, ctx.Resp) + user, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req, ctx.Resp) if err == nil && user != nil { // we got the user without going through the whole OAuth2 authentication flow again handleOAuth2SignIn(user, gothUser, ctx, err) return } - if err = oauth2.Auth(loginSource.Name, ctx.Req.Request, ctx.Resp); err != nil { + if err = oauth2.Auth(loginSource.Name, ctx.Req, ctx.Resp); err != nil { if strings.Contains(err.Error(), "no provider for ") { if err = models.ResetOAuth2(); err != nil { ctx.ServerError("SignIn", err) return } - if err = oauth2.Auth(loginSource.Name, ctx.Req.Request, ctx.Resp); err != nil { + if err = oauth2.Auth(loginSource.Name, ctx.Req, ctx.Resp); err != nil { ctx.ServerError("SignIn", err) } return @@ -602,7 +606,7 @@ func SignInOAuthCallback(ctx *context.Context) { return } - u, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req.Request, ctx.Resp) + u, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req, ctx.Resp) handleOAuth2SignIn(u, gothUser, ctx, err) } @@ -788,7 +792,8 @@ func LinkAccount(ctx *context.Context) { } // LinkAccountPostSignIn handle the coupling of external account with another account using signIn -func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) { +func LinkAccountPostSignIn(ctx *context.Context) { + signInForm := web.GetForm(ctx).(*auth.SignInForm) ctx.Data["DisablePassword"] = !setting.Service.RequireExternalRegistrationPassword || setting.Service.AllowOnlyExternalRegistration ctx.Data["Title"] = ctx.Tr("link_account") ctx.Data["LinkAccountMode"] = true @@ -870,7 +875,8 @@ func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) { } // LinkAccountPostRegister handle the creation of a new account for an external account using signUp -func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) { +func LinkAccountPostRegister(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.RegisterForm) // TODO Make insecure passwords optional for local accounts also, // once email-based Second-Factor Auth is available ctx.Data["DisablePassword"] = !setting.Service.RequireExternalRegistrationPassword || setting.Service.AllowOnlyExternalRegistration @@ -909,7 +915,7 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au var err error switch setting.Service.CaptchaType { case setting.ImageCaptcha: - valid = cpt.VerifyReq(ctx.Req) + valid = context.GetImageCaptcha().VerifyReq(ctx.Req) case setting.ReCaptcha: valid, err = recaptcha.Verify(ctx.Req.Context(), form.GRecaptchaResponse) case setting.HCaptcha: @@ -1029,7 +1035,7 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au // HandleSignOut resets the session and sets the cookies func HandleSignOut(ctx *context.Context) { _ = ctx.Session.Flush() - _ = ctx.Session.Destroy(ctx.Context) + _ = ctx.Session.Destroy(ctx.Resp, ctx.Req) ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) @@ -1069,7 +1075,8 @@ func SignUp(ctx *context.Context) { } // SignUpPost response for sign up information submission -func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) { +func SignUpPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.RegisterForm) ctx.Data["Title"] = ctx.Tr("sign_up") ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up" @@ -1097,7 +1104,7 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo var err error switch setting.Service.CaptchaType { case setting.ImageCaptcha: - valid = cpt.VerifyReq(ctx.Req) + valid = context.GetImageCaptcha().VerifyReq(ctx.Req) case setting.ReCaptcha: valid, err = recaptcha.Verify(ctx.Req.Context(), form.GRecaptchaResponse) case setting.HCaptcha: @@ -1562,7 +1569,8 @@ func MustChangePassword(ctx *context.Context) { // MustChangePasswordPost response for updating a user's password after his/her // account was created by an admin -func MustChangePasswordPost(ctx *context.Context, cpt *captcha.Captcha, form auth.MustChangePasswordForm) { +func MustChangePasswordPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.MustChangePasswordForm) ctx.Data["Title"] = ctx.Tr("auth.must_change_password") ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/settings/change_password" if ctx.HasError() { diff --git a/routers/user/auth_openid.go b/routers/user/auth_openid.go index 39e75f202d..1efcc7eda8 100644 --- a/routers/user/auth_openid.go +++ b/routers/user/auth_openid.go @@ -9,19 +9,18 @@ import ( "net/url" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth/openid" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/hcaptcha" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/recaptcha" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/mailer" - - "gitea.com/macaron/captcha" ) const ( @@ -90,7 +89,8 @@ func allowedOpenIDURI(uri string) (err error) { } // SignInOpenIDPost response for openid sign in request -func SignInOpenIDPost(ctx *context.Context, form auth.SignInOpenIDForm) { +func SignInOpenIDPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.SignInOpenIDForm) ctx.Data["Title"] = ctx.Tr("sign_in") ctx.Data["PageIsSignIn"] = true ctx.Data["PageIsLoginOpenID"] = true @@ -143,9 +143,9 @@ func SignInOpenIDPost(ctx *context.Context, form auth.SignInOpenIDForm) { // signInOpenIDVerify handles response from OpenID provider func signInOpenIDVerify(ctx *context.Context) { - log.Trace("Incoming call to: " + ctx.Req.Request.URL.String()) + log.Trace("Incoming call to: " + ctx.Req.URL.String()) - fullURL := setting.AppURL + ctx.Req.Request.URL.String()[1:] + fullURL := setting.AppURL + ctx.Req.URL.String()[1:] log.Trace("Full URL: " + fullURL) var id, err = openid.Verify(fullURL) @@ -276,8 +276,8 @@ func ConnectOpenID(ctx *context.Context) { } // ConnectOpenIDPost handles submission of a form to connect an OpenID URI to an existing account -func ConnectOpenIDPost(ctx *context.Context, form auth.ConnectOpenIDForm) { - +func ConnectOpenIDPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.ConnectOpenIDForm) oid, _ := ctx.Session.Get("openid_verified_uri").(string) if oid == "" { ctx.Redirect(setting.AppSubURL + "/user/login/openid") @@ -346,7 +346,8 @@ func RegisterOpenID(ctx *context.Context) { } // RegisterOpenIDPost handles submission of a form to create a new user authenticated via an OpenID URI -func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.SignUpOpenIDForm) { +func RegisterOpenIDPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.SignUpOpenIDForm) oid, _ := ctx.Session.Get("openid_verified_uri").(string) if oid == "" { ctx.Redirect(setting.AppSubURL + "/user/login/openid") @@ -369,7 +370,7 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si var err error switch setting.Service.CaptchaType { case setting.ImageCaptcha: - valid = cpt.VerifyReq(ctx.Req) + valid = context.GetImageCaptcha().VerifyReq(ctx.Req) case setting.ReCaptcha: if err := ctx.Req.ParseForm(); err != nil { ctx.ServerError("", err) diff --git a/routers/user/oauth.go b/routers/user/oauth.go index dda1268f8a..d943ec4200 100644 --- a/routers/user/oauth.go +++ b/routers/user/oauth.go @@ -12,14 +12,15 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" - "gitea.com/macaron/binding" + "gitea.com/go-chi/binding" "github.com/dgrijalva/jwt-go" ) @@ -192,9 +193,10 @@ func newAccessTokenResponse(grant *models.OAuth2Grant, clientSecret string) (*Ac } // AuthorizeOAuth manages authorize requests -func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { +func AuthorizeOAuth(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AuthorizationForm) errs := binding.Errors{} - errs = form.Validate(ctx.Context, errs) + errs = form.Validate(ctx.Req, errs) if len(errs) > 0 { errstring := "" for _, e := range errs { @@ -341,7 +343,8 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { } // GrantApplicationOAuth manages the post request submitted when a user grants access to an application -func GrantApplicationOAuth(ctx *context.Context, form auth.GrantApplicationForm) { +func GrantApplicationOAuth(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.GrantApplicationForm) if ctx.Session.Get("client_id") != form.ClientID || ctx.Session.Get("state") != form.State || ctx.Session.Get("redirect_uri") != form.RedirectURI { ctx.Error(400) @@ -386,7 +389,8 @@ func GrantApplicationOAuth(ctx *context.Context, form auth.GrantApplicationForm) } // AccessTokenOAuth manages all access token requests by the client -func AccessTokenOAuth(ctx *context.Context, form auth.AccessTokenForm) { +func AccessTokenOAuth(ctx *context.Context) { + form := *web.GetForm(ctx).(*auth.AccessTokenForm) if form.ClientID == "" { authHeader := ctx.Req.Header.Get("Authorization") authContent := strings.SplitN(authHeader, " ", 2) diff --git a/routers/user/setting/account.go b/routers/user/setting/account.go index 42c2c59b7e..4900bba14a 100644 --- a/routers/user/setting/account.go +++ b/routers/user/setting/account.go @@ -10,13 +10,14 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/mailer" ) @@ -36,7 +37,8 @@ func Account(ctx *context.Context) { } // AccountPost response for change user's password -func AccountPost(ctx *context.Context, form auth.ChangePasswordForm) { +func AccountPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.ChangePasswordForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsAccount"] = true @@ -80,7 +82,8 @@ func AccountPost(ctx *context.Context, form auth.ChangePasswordForm) { } // EmailPost response for change user's email -func EmailPost(ctx *context.Context, form auth.AddEmailForm) { +func EmailPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AddEmailForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsAccount"] = true @@ -252,8 +255,8 @@ func DeleteAccount(ctx *context.Context) { } // UpdateUIThemePost is used to update users' specific theme -func UpdateUIThemePost(ctx *context.Context, form auth.UpdateThemeForm) { - +func UpdateUIThemePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.UpdateThemeForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsAccount"] = true diff --git a/routers/user/setting/account_test.go b/routers/user/setting/account_test.go index 841ecb8ac2..0e7e147b8b 100644 --- a/routers/user/setting/account_test.go +++ b/routers/user/setting/account_test.go @@ -9,9 +9,10 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/web" "github.com/stretchr/testify/assert" ) @@ -85,11 +86,12 @@ func TestChangePassword(t *testing.T) { test.LoadUser(t, ctx, 2) test.LoadRepo(t, ctx, 1) - AccountPost(ctx, auth.ChangePasswordForm{ + web.SetForm(ctx, &auth.ChangePasswordForm{ OldPassword: req.OldPassword, Password: req.NewPassword, Retype: req.Retype, }) + AccountPost(ctx) assert.Contains(t, ctx.Flash.ErrorMsg, req.Message) assert.EqualValues(t, http.StatusFound, ctx.Resp.Status()) diff --git a/routers/user/setting/applications.go b/routers/user/setting/applications.go index 04f9d9f7f9..8da36dc6cf 100644 --- a/routers/user/setting/applications.go +++ b/routers/user/setting/applications.go @@ -7,10 +7,11 @@ package setting import ( "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" ) const ( @@ -28,7 +29,8 @@ func Applications(ctx *context.Context) { } // ApplicationsPost response for add user's access token -func ApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) { +func ApplicationsPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.NewAccessTokenForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsApplications"] = true diff --git a/routers/user/setting/keys.go b/routers/user/setting/keys.go index 76c7ef9da4..a52ffd667b 100644 --- a/routers/user/setting/keys.go +++ b/routers/user/setting/keys.go @@ -7,10 +7,11 @@ package setting import ( "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" ) const ( @@ -31,7 +32,8 @@ func Keys(ctx *context.Context) { } // KeysPost response for change user's SSH/GPG keys -func KeysPost(ctx *context.Context, form auth.AddKeyForm) { +func KeysPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AddKeyForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled diff --git a/routers/user/setting/oauth2.go b/routers/user/setting/oauth2.go index f42c1123e1..7f0f8db1c8 100644 --- a/routers/user/setting/oauth2.go +++ b/routers/user/setting/oauth2.go @@ -8,11 +8,12 @@ import ( "fmt" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" ) const ( @@ -20,7 +21,8 @@ const ( ) // OAuthApplicationsPost response for adding a oauth2 application -func OAuthApplicationsPost(ctx *context.Context, form auth.EditOAuth2ApplicationForm) { +func OAuthApplicationsPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditOAuth2ApplicationForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsApplications"] = true @@ -51,7 +53,8 @@ func OAuthApplicationsPost(ctx *context.Context, form auth.EditOAuth2Application } // OAuthApplicationsEdit response for editing oauth2 application -func OAuthApplicationsEdit(ctx *context.Context, form auth.EditOAuth2ApplicationForm) { +func OAuthApplicationsEdit(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditOAuth2ApplicationForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsApplications"] = true diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index c935b56230..7e90a7ccec 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -14,12 +14,13 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" "github.com/unknwon/i18n" ) @@ -71,7 +72,8 @@ func HandleUsernameChange(ctx *context.Context, user *models.User, newName strin } // ProfilePost response for change user's profile -func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { +func ProfilePost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.UpdateProfileForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsProfile"] = true @@ -123,7 +125,7 @@ func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { // UpdateAvatarSetting update user's avatar // FIXME: limit size. -func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *models.User) error { +func UpdateAvatarSetting(ctx *context.Context, form *auth.AvatarForm, ctxUser *models.User) error { ctxUser.UseCustomAvatar = form.Source == auth.AvatarLocal if len(form.Gravatar) > 0 { if form.Avatar != nil { @@ -171,7 +173,8 @@ func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *mo } // AvatarPost response for change user's avatar request -func AvatarPost(ctx *context.Context, form auth.AvatarForm) { +func AvatarPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AvatarForm) if err := UpdateAvatarSetting(ctx, form, ctx.User); err != nil { ctx.Flash.Error(err.Error()) } else { diff --git a/routers/user/setting/security_openid.go b/routers/user/setting/security_openid.go index 6813765f6f..401705608a 100644 --- a/routers/user/setting/security_openid.go +++ b/routers/user/setting/security_openid.go @@ -6,15 +6,17 @@ package setting import ( "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth/openid" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" ) // OpenIDPost response for change user's openid -func OpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { +func OpenIDPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.AddOpenIDForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsSecurity"] = true @@ -70,9 +72,9 @@ func OpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { } func settingsOpenIDVerify(ctx *context.Context) { - log.Trace("Incoming call to: " + ctx.Req.Request.URL.String()) + log.Trace("Incoming call to: " + ctx.Req.URL.String()) - fullURL := setting.AppURL + ctx.Req.Request.URL.String()[1:] + fullURL := setting.AppURL + ctx.Req.URL.String()[1:] log.Trace("Full URL: " + fullURL) id, err := openid.Verify(fullURL) diff --git a/routers/user/setting/security_twofa.go b/routers/user/setting/security_twofa.go index 3f4c8f6c3f..0dee827cab 100644 --- a/routers/user/setting/security_twofa.go +++ b/routers/user/setting/security_twofa.go @@ -13,10 +13,11 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" "github.com/pquerna/otp" "github.com/pquerna/otp/totp" @@ -165,7 +166,8 @@ func EnrollTwoFactor(ctx *context.Context) { } // EnrollTwoFactorPost handles enrolling the user into 2FA. -func EnrollTwoFactorPost(ctx *context.Context, form auth.TwoFactorAuthForm) { +func EnrollTwoFactorPost(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.TwoFactorAuthForm) ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsSecurity"] = true diff --git a/routers/user/setting/security_u2f.go b/routers/user/setting/security_u2f.go index 7e32b4aaec..8140c3c04a 100644 --- a/routers/user/setting/security_u2f.go +++ b/routers/user/setting/security_u2f.go @@ -8,16 +8,18 @@ import ( "errors" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" + auth "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/web" "github.com/tstranex/u2f" ) // U2FRegister initializes the u2f registration procedure -func U2FRegister(ctx *context.Context, form auth.U2FRegistrationForm) { +func U2FRegister(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.U2FRegistrationForm) if form.Name == "" { ctx.Error(409) return @@ -55,7 +57,8 @@ func U2FRegister(ctx *context.Context, form auth.U2FRegistrationForm) { } // U2FRegisterPost receives the response of the security key -func U2FRegisterPost(ctx *context.Context, response u2f.RegisterResponse) { +func U2FRegisterPost(ctx *context.Context) { + response := web.GetForm(ctx).(*u2f.RegisterResponse) challSess := ctx.Session.Get("u2fChallenge") u2fName := ctx.Session.Get("u2fName") if challSess == nil || u2fName == nil { @@ -69,7 +72,7 @@ func U2FRegisterPost(ctx *context.Context, response u2f.RegisterResponse) { // certificate by default. SkipAttestationVerify: true, } - reg, err := u2f.Register(response, *challenge, config) + reg, err := u2f.Register(*response, *challenge, config) if err != nil { ctx.ServerError("u2f.Register", err) return @@ -82,7 +85,8 @@ func U2FRegisterPost(ctx *context.Context, response u2f.RegisterResponse) { } // U2FDelete deletes an security key by id -func U2FDelete(ctx *context.Context, form auth.U2FDeleteForm) { +func U2FDelete(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.U2FDeleteForm) reg, err := models.GetU2FRegistrationByID(form.ID) if err != nil { if models.IsErrU2FRegistrationNotExist(err) { |