From ba072ae43c8c9211168135801a5b0aff09a60462 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 16 Jul 2021 10:31:30 +0800 Subject: [PATCH 01/10] refactor context to add a BaseContext and reduce private context struct size --- modules/context/api.go | 7 +- modules/context/base.go | 165 +++++++++++++++++++++++++++++++++++++ modules/context/context.go | 93 ++------------------- modules/context/private.go | 11 +-- routers/install/install.go | 13 ++- 5 files changed, 184 insertions(+), 105 deletions(-) create mode 100644 modules/context/base.go diff --git a/modules/context/api.go b/modules/context/api.go index 4a2d5d1665d3e..983f60a34a413 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -272,10 +272,9 @@ func APIContexter() func(http.Handler) http.Handler { var locale = middleware.Locale(w, req) var ctx = APIContext{ Context: &Context{ - Resp: NewResponse(w), - Data: map[string]interface{}{}, - Locale: locale, - Session: session.GetSession(req), + BaseContext: NewBaseContext(w, req, map[string]interface{}{}), + Locale: locale, + Session: session.GetSession(req), Repo: &Repository{ PullRequest: &PullRequest{}, }, diff --git a/modules/context/base.go b/modules/context/base.go new file mode 100644 index 0000000000000..376430699187d --- /dev/null +++ b/modules/context/base.go @@ -0,0 +1,165 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package context + +import ( + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" + + chi "github.com/go-chi/chi/v5" +) + +type BaseContext struct { + Resp ResponseWriter + Req *http.Request + Data map[string]interface{} +} + +func NewBaseContext(resp http.ResponseWriter, req *http.Request, data map[string]interface{}) *BaseContext { + return &BaseContext{ + Resp: NewResponse(resp), + Req: req, + Data: data, + } +} + +// GetData returns the data +func (ctx *BaseContext) GetData() map[string]interface{} { + return ctx.Data +} + +// HasValue returns true if value of given name exists. +func (ctx *BaseContext) HasValue(name string) bool { + _, ok := ctx.Data[name] + return ok +} + +// Header returns a header +func (ctx *BaseContext) Header() http.Header { + return ctx.Resp.Header() +} + +// RemoteAddr returns the client machie ip address +func (ctx *BaseContext) RemoteAddr() string { + return ctx.Req.RemoteAddr +} + +// Params returns the param on route +func (ctx *BaseContext) Params(p string) string { + s, _ := url.PathUnescape(chi.URLParam(ctx.Req, strings.TrimPrefix(p, ":"))) + return s +} + +// ParamsInt64 returns the param on route as int64 +func (ctx *BaseContext) ParamsInt64(p string) int64 { + v, _ := strconv.ParseInt(ctx.Params(p), 10, 64) + return v +} + +// SetParams set params into routes +func (ctx *BaseContext) SetParams(k, v string) { + chiCtx := chi.RouteContext(ctx) + chiCtx.URLParams.Add(strings.TrimPrefix(k, ":"), url.PathEscape(v)) +} + +// Write writes data to webbrowser +func (ctx *BaseContext) Write(bs []byte) (int, error) { + return ctx.Resp.Write(bs) +} + +// Written returns true if there are something sent to web browser +func (ctx *BaseContext) Written() bool { + return ctx.Resp.Status() > 0 +} + +// Status writes status code +func (ctx *BaseContext) Status(status int) { + ctx.Resp.WriteHeader(status) +} + +// Deadline is part of the interface for context.Context and we pass this to the request context +func (ctx *BaseContext) Deadline() (deadline time.Time, ok bool) { + return ctx.Req.Context().Deadline() +} + +// Done is part of the interface for context.Context and we pass this to the request context +func (ctx *BaseContext) Done() <-chan struct{} { + return ctx.Req.Context().Done() +} + +// Err is part of the interface for context.Context and we pass this to the request context +func (ctx *BaseContext) Err() error { + return ctx.Req.Context().Err() +} + +// Value is part of the interface for context.Context and we pass this to the request context +func (ctx *BaseContext) Value(key interface{}) interface{} { + return ctx.Req.Context().Value(key) +} + +// FIXME: We should differ Query and Form, currently we just use form as query +// Currently to be compatible with macaron, we keep it. + +// Query returns request form as string with default +func (ctx *BaseContext) Query(key string, defaults ...string) string { + return (*Forms)(ctx.Req).MustString(key, defaults...) +} + +// QueryTrim returns request form as string with default and trimmed spaces +func (ctx *BaseContext) QueryTrim(key string, defaults ...string) string { + return (*Forms)(ctx.Req).MustTrimmed(key, defaults...) +} + +// QueryStrings returns request form as strings with default +func (ctx *BaseContext) QueryStrings(key string, defaults ...[]string) []string { + return (*Forms)(ctx.Req).MustStrings(key, defaults...) +} + +// QueryInt returns request form as int with default +func (ctx *BaseContext) QueryInt(key string, defaults ...int) int { + return (*Forms)(ctx.Req).MustInt(key, defaults...) +} + +// QueryInt64 returns request form as int64 with default +func (ctx *BaseContext) QueryInt64(key string, defaults ...int64) int64 { + return (*Forms)(ctx.Req).MustInt64(key, defaults...) +} + +// QueryBool returns request form as bool with default +func (ctx *BaseContext) QueryBool(key string, defaults ...bool) bool { + return (*Forms)(ctx.Req).MustBool(key, defaults...) +} + +// QueryOptionalBool returns request form as OptionalBool with default +func (ctx *BaseContext) QueryOptionalBool(key string, defaults ...util.OptionalBool) util.OptionalBool { + return (*Forms)(ctx.Req).MustOptionalBool(key, defaults...) +} + +// JSON render content as JSON +func (ctx *BaseContext) JSON(status int, content interface{}) { + ctx.Resp.Header().Set("Content-Type", "application/json;charset=utf-8") + ctx.Resp.WriteHeader(status) + if err := json.NewEncoder(ctx.Resp).Encode(content); err != nil { + log.Error("Render JSON failed: %v", err) + ctx.Status(500) + } +} + +// PlainText render content as plain text +func (ctx *BaseContext) PlainText(status int, bs []byte) { + ctx.Resp.WriteHeader(status) + ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") + if _, err := ctx.Resp.Write(bs); err != nil { + log.Error("Render PlainText failed: %v", err) + ctx.Status(500) + } +} diff --git a/modules/context/context.go b/modules/context/context.go index 5a37f8b0bf2a9..2efd420ccab12 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -24,7 +24,6 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" mc "code.gitea.io/gitea/modules/cache" - "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" @@ -49,11 +48,9 @@ type Render interface { // Context represents context of a request. type Context struct { - Resp ResponseWriter - Req *http.Request - Data map[string]interface{} // data used by MVC templates + *BaseContext PageData map[string]interface{} // data used by JavaScript modules in one page, it's `window.config.pageData` - Render Render + Render Render translation.Locale Cache cache.Cache csrf CSRF @@ -166,12 +163,6 @@ func (ctx *Context) HasError() bool { return hasErr.(bool) } -// HasValue returns true if value of given name exists. -func (ctx *Context) HasValue(name string) bool { - _, ok := ctx.Data[name] - return ok -} - // RedirectToFirst redirects to first not empty URL func (ctx *Context) RedirectToFirst(location ...string) { for _, loc := range location { @@ -377,15 +368,6 @@ func (ctx *Context) Error(status int, contents ...string) { http.Error(ctx.Resp, v, status) } -// JSON render content as JSON -func (ctx *Context) JSON(status int, content interface{}) { - ctx.Resp.Header().Set("Content-Type", "application/json;charset=utf-8") - ctx.Resp.WriteHeader(status) - if err := json.NewEncoder(ctx.Resp).Encode(content); err != nil { - ctx.ServerError("Render JSON failed", err) - } -} - // Redirect redirect the request func (ctx *Context) Redirect(location string, status ...int) { code := http.StatusFound @@ -483,64 +465,6 @@ func (ctx *Context) GetCookieFloat64(name string) float64 { return v } -// RemoteAddr returns the client machie ip address -func (ctx *Context) RemoteAddr() string { - return ctx.Req.RemoteAddr -} - -// Params returns the param on route -func (ctx *Context) Params(p string) string { - s, _ := url.PathUnescape(chi.URLParam(ctx.Req, strings.TrimPrefix(p, ":"))) - return s -} - -// ParamsInt64 returns the param on route as int64 -func (ctx *Context) ParamsInt64(p string) int64 { - v, _ := strconv.ParseInt(ctx.Params(p), 10, 64) - return v -} - -// SetParams set params into routes -func (ctx *Context) SetParams(k, v string) { - chiCtx := chi.RouteContext(ctx) - chiCtx.URLParams.Add(strings.TrimPrefix(k, ":"), url.PathEscape(v)) -} - -// Write writes data to webbrowser -func (ctx *Context) Write(bs []byte) (int, error) { - return ctx.Resp.Write(bs) -} - -// Written returns true if there are something sent to web browser -func (ctx *Context) Written() bool { - return ctx.Resp.Status() > 0 -} - -// Status writes status code -func (ctx *Context) Status(status int) { - ctx.Resp.WriteHeader(status) -} - -// Deadline is part of the interface for context.Context and we pass this to the request context -func (ctx *Context) Deadline() (deadline time.Time, ok bool) { - return ctx.Req.Context().Deadline() -} - -// Done is part of the interface for context.Context and we pass this to the request context -func (ctx *Context) Done() <-chan struct{} { - return ctx.Req.Context().Done() -} - -// Err is part of the interface for context.Context and we pass this to the request context -func (ctx *Context) Err() error { - return ctx.Req.Context().Err() -} - -// Value is part of the interface for context.Context and we pass this to the request context -func (ctx *Context) Value(key interface{}) interface{} { - return ctx.Req.Context().Value(key) -} - // Handler represents a custom handler type Handler func(*Context) @@ -645,7 +569,12 @@ func Contexter() func(next http.Handler) http.Handler { var startTime = time.Now() var link = setting.AppSubURL + strings.TrimSuffix(req.URL.EscapedPath(), "/") var ctx = Context{ - Resp: NewResponse(resp), + BaseContext: NewBaseContext(resp, req, map[string]interface{}{ + "CurrentURL": setting.AppSubURL + req.URL.RequestURI(), + "PageStartTime": startTime, + "Link": link, + "RunModeIsProd": setting.IsProd, + }), Cache: mc.GetCache(), Locale: locale, Link: link, @@ -655,12 +584,6 @@ func Contexter() func(next http.Handler) http.Handler { PullRequest: &PullRequest{}, }, Org: &Organization{}, - Data: map[string]interface{}{ - "CurrentURL": setting.AppSubURL + req.URL.RequestURI(), - "PageStartTime": startTime, - "Link": link, - "RunModeIsProd": setting.IsProd, - }, } // PageData is passed by reference, and it will be rendered to `window.config.pageData` in `head.tmpl` for JavaScript modules ctx.PageData = map[string]interface{}{} diff --git a/modules/context/private.go b/modules/context/private.go index dfefa1d2f0192..af15c45925c29 100644 --- a/modules/context/private.go +++ b/modules/context/private.go @@ -10,9 +10,7 @@ import ( ) // PrivateContext represents a context for private routes -type PrivateContext struct { - *Context -} +type PrivateContext = BaseContext var ( privateContextKey interface{} = "default_private_context" @@ -32,12 +30,7 @@ func GetPrivateContext(req *http.Request) *PrivateContext { func PrivateContexter() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx := &PrivateContext{ - Context: &Context{ - Resp: NewResponse(w), - Data: map[string]interface{}{}, - }, - } + ctx := NewBaseContext(w, req, map[string]interface{}{}) ctx.Req = WithPrivateContext(req, ctx) next.ServeHTTP(ctx.Resp, ctx.Req) }) diff --git a/routers/install/install.go b/routers/install/install.go index 45804acf3b5ab..751bde979d736 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -65,12 +65,7 @@ func Init(next http.Handler) http.Handler { var locale = middleware.Locale(resp, req) var startTime = time.Now() var ctx = context.Context{ - Resp: context.NewResponse(resp), - Flash: &middleware.Flash{}, - Locale: locale, - Render: rnd, - Session: session.GetSession(req), - Data: map[string]interface{}{ + BaseContext: context.NewBaseContext(resp, req, map[string]interface{}{ "Title": locale.Tr("install.install"), "PageIsInstall": true, "DbTypeNames": getDbTypeNames(), @@ -84,7 +79,11 @@ func Init(next http.Handler) http.Handler { return time.Since(startTime).String() }, "PasswordHashAlgorithms": user_model.AvailableHashAlgorithms, - }, + }), + Flash: &middleware.Flash{}, + Locale: locale, + Render: rnd, + Session: session.GetSession(req), } for _, lang := range translation.AllLangs() { if lang.Lang == locale.Language() { From 4704057f64c7f92022fc5e464b23526021aa7bcd Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 16 Jul 2021 10:39:14 +0800 Subject: [PATCH 02/10] Fix lint and move some methods to base context from context --- modules/context/base.go | 40 ++++++++++++++++++++++++++++++++++++++ modules/context/context.go | 40 ++------------------------------------ 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/modules/context/base.go b/modules/context/base.go index 376430699187d..5ccb54e0eefb6 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -7,6 +7,7 @@ package context import ( "net/http" "net/url" + "path" "strconv" "strings" "time" @@ -18,12 +19,14 @@ import ( chi "github.com/go-chi/chi/v5" ) +// BaseContext represents a general context for some simple routes type BaseContext struct { Resp ResponseWriter Req *http.Request Data map[string]interface{} } +// NewBaseContext creates a new base context func NewBaseContext(resp http.ResponseWriter, req *http.Request, data map[string]interface{}) *BaseContext { return &BaseContext{ Resp: NewResponse(resp), @@ -144,6 +147,25 @@ func (ctx *BaseContext) QueryOptionalBool(key string, defaults ...util.OptionalB return (*Forms)(ctx.Req).MustOptionalBool(key, defaults...) } +// Error returned an error to web browser +func (ctx *BaseContext) Error(status int, contents ...string) { + var v = http.StatusText(status) + if len(contents) > 0 { + v = contents[0] + } + http.Error(ctx.Resp, v, status) +} + +// Redirect redirect the request +func (ctx *BaseContext) Redirect(location string, status ...int) { + code := http.StatusFound + if len(status) == 1 { + code = status[0] + } + + http.Redirect(ctx.Resp, ctx.Req, location, code) +} + // JSON render content as JSON func (ctx *BaseContext) JSON(status int, content interface{}) { ctx.Resp.Header().Set("Content-Type", "application/json;charset=utf-8") @@ -163,3 +185,21 @@ func (ctx *BaseContext) PlainText(status int, bs []byte) { ctx.Status(500) } } + +// ServeFile serves given file to response. +func (ctx *BaseContext) ServeFile(file string, names ...string) { + var name string + if len(names) > 0 { + name = names[0] + } else { + name = path.Base(file) + } + ctx.Resp.Header().Set("Content-Description", "File Transfer") + ctx.Resp.Header().Set("Content-Type", "application/octet-stream") + ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name) + ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary") + ctx.Resp.Header().Set("Expires", "0") + ctx.Resp.Header().Set("Cache-Control", "must-revalidate") + ctx.Resp.Header().Set("Pragma", "public") + http.ServeFile(ctx.Resp, ctx.Req, file) +} diff --git a/modules/context/context.go b/modules/context/context.go index 2efd420ccab12..a1c68287da95e 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -317,7 +317,8 @@ func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interfa http.ServeContent(ctx.Resp, ctx.Req, name, modtime, r) } -// PlainText render content as plain text +// PlainText render content as plain text, this will override basecontext's method +// because we need a beautiful failed page func (ctx *Context) PlainText(status int, bs []byte) { ctx.Resp.WriteHeader(status) ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") @@ -326,24 +327,6 @@ func (ctx *Context) PlainText(status int, bs []byte) { } } -// ServeFile serves given file to response. -func (ctx *Context) ServeFile(file string, names ...string) { - var name string - if len(names) > 0 { - name = names[0] - } else { - name = path.Base(file) - } - ctx.Resp.Header().Set("Content-Description", "File Transfer") - ctx.Resp.Header().Set("Content-Type", "application/octet-stream") - ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name) - ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary") - ctx.Resp.Header().Set("Expires", "0") - ctx.Resp.Header().Set("Cache-Control", "must-revalidate") - ctx.Resp.Header().Set("Pragma", "public") - http.ServeFile(ctx.Resp, ctx.Req, file) -} - // ServeStream serves file via io stream func (ctx *Context) ServeStream(rd io.Reader, name string) { ctx.Resp.Header().Set("Content-Description", "File Transfer") @@ -359,25 +342,6 @@ func (ctx *Context) ServeStream(rd io.Reader, name string) { } } -// Error returned an error to web browser -func (ctx *Context) Error(status int, contents ...string) { - var v = http.StatusText(status) - if len(contents) > 0 { - v = contents[0] - } - http.Error(ctx.Resp, v, status) -} - -// Redirect redirect the request -func (ctx *Context) Redirect(location string, status ...int) { - code := http.StatusFound - if len(status) == 1 { - code = status[0] - } - - http.Redirect(ctx.Resp, ctx.Req, location, code) -} - // SetCookie convenience function to set most cookies consistently // CSRF and a few others are the exception here func (ctx *Context) SetCookie(name, value string, expiry int) { From 8a32e50bc5fa6dff33ca77f53387d12e912d8343 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 16 Jul 2021 10:51:32 +0800 Subject: [PATCH 03/10] Fix lint --- modules/test/context_tests.go | 19 +++++++++---------- routers/api/v1/misc/markdown_test.go | 6 ++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go index 548e454c8eafc..9d3c1f297bf21 100644 --- a/modules/test/context_tests.go +++ b/modules/test/context_tests.go @@ -27,24 +27,23 @@ import ( // MockContext mock context for unit tests func MockContext(t *testing.T, path string) *context.Context { + requestURL, err := url.Parse(path) + assert.NoError(t, err) + var resp = &mockResponseWriter{} + var req = &http.Request{ + URL: requestURL, + Form: url.Values{}, + } var ctx = context.Context{ - Render: &mockRender{}, - Data: make(map[string]interface{}), + BaseContext: context.NewBaseContext(resp, req, map[string]interface{}{}), + Render: &mockRender{}, Flash: &middleware.Flash{ Values: make(url.Values), }, - Resp: context.NewResponse(resp), Locale: &mockLocale{}, } - requestURL, err := url.Parse(path) - assert.NoError(t, err) - var req = &http.Request{ - URL: requestURL, - Form: url.Values{}, - } - chiCtx := chi.NewRouteContext() req = req.WithContext(scontext.WithValue(req.Context(), chi.RouteCtxKey, chiCtx)) ctx.Req = context.WithContext(req, &ctx) diff --git a/routers/api/v1/misc/markdown_test.go b/routers/api/v1/misc/markdown_test.go index dc6762c4cf239..6a1a67d4599f2 100644 --- a/routers/api/v1/misc/markdown_test.go +++ b/routers/api/v1/misc/markdown_test.go @@ -30,10 +30,8 @@ func createContext(req *http.Request) (*context.Context, *httptest.ResponseRecor var rnd = templates.HTMLRenderer() resp := httptest.NewRecorder() c := &context.Context{ - Req: req, - Resp: context.NewResponse(resp), - Render: rnd, - Data: make(map[string]interface{}), + BaseContext: context.NewBaseContext(resp, req, map[string]interface{}{}), + Render: rnd, } return c, resp } From 1cc485970081f492945a345102d3312367a2eacd Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 18 Jul 2021 12:27:16 +0800 Subject: [PATCH 04/10] use http.StatusXXX constants --- modules/context/base.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/context/base.go b/modules/context/base.go index 5ccb54e0eefb6..017e380a05948 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -172,7 +172,7 @@ func (ctx *BaseContext) JSON(status int, content interface{}) { ctx.Resp.WriteHeader(status) if err := json.NewEncoder(ctx.Resp).Encode(content); err != nil { log.Error("Render JSON failed: %v", err) - ctx.Status(500) + ctx.Status(http.StatusInternalServerError) } } @@ -182,7 +182,7 @@ func (ctx *BaseContext) PlainText(status int, bs []byte) { ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") if _, err := ctx.Resp.Write(bs); err != nil { log.Error("Render PlainText failed: %v", err) - ctx.Status(500) + ctx.Status(http.StatusInternalServerError) } } From 8dfd55ffcc7e5e59c58fbf79aaa2b30767e2249c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 24 Jul 2021 11:43:00 +0800 Subject: [PATCH 05/10] Remove unnecessary PlainText --- modules/context/context.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index a1c68287da95e..aacb1e23f4902 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -33,7 +33,6 @@ import ( "gitea.com/go-chi/cache" "gitea.com/go-chi/session" - chi "github.com/go-chi/chi/v5" "github.com/unknwon/com" "github.com/unknwon/i18n" "github.com/unrolled/render" @@ -50,7 +49,7 @@ type Render interface { type Context struct { *BaseContext PageData map[string]interface{} // data used by JavaScript modules in one page, it's `window.config.pageData` - Render Render + Render Render translation.Locale Cache cache.Cache csrf CSRF @@ -317,16 +316,6 @@ func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interfa http.ServeContent(ctx.Resp, ctx.Req, name, modtime, r) } -// PlainText render content as plain text, this will override basecontext's method -// because we need a beautiful failed page -func (ctx *Context) PlainText(status int, bs []byte) { - ctx.Resp.WriteHeader(status) - ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") - if _, err := ctx.Resp.Write(bs); err != nil { - ctx.ServerError("Write bytes failed", err) - } -} - // ServeStream serves file via io stream func (ctx *Context) ServeStream(rd io.Reader, name string) { ctx.Resp.Header().Set("Content-Description", "File Transfer") From e59b1b9b60769cba73188261fb77955f537cb60a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 29 Jul 2021 22:30:59 +0800 Subject: [PATCH 06/10] services should not depends on context --- modules/context/base.go | 31 ++++++++--------- services/agit/agit.go | 74 ++++++++--------------------------------- 2 files changed, 28 insertions(+), 77 deletions(-) diff --git a/modules/context/base.go b/modules/context/base.go index 017e380a05948..8299ba31220bb 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -109,41 +109,38 @@ func (ctx *BaseContext) Value(key interface{}) interface{} { return ctx.Req.Context().Value(key) } -// FIXME: We should differ Query and Form, currently we just use form as query -// Currently to be compatible with macaron, we keep it. - -// Query returns request form as string with default -func (ctx *BaseContext) Query(key string, defaults ...string) string { +// Form returns request form as string with default +func (ctx *BaseContext) Form(key string, defaults ...string) string { return (*Forms)(ctx.Req).MustString(key, defaults...) } -// QueryTrim returns request form as string with default and trimmed spaces -func (ctx *BaseContext) QueryTrim(key string, defaults ...string) string { +// FormTrim returns request form as string with default and trimmed spaces +func (ctx *BaseContext) FormTrim(key string, defaults ...string) string { return (*Forms)(ctx.Req).MustTrimmed(key, defaults...) } -// QueryStrings returns request form as strings with default -func (ctx *BaseContext) QueryStrings(key string, defaults ...[]string) []string { +// FormStrings returns request form as strings with default +func (ctx *BaseContext) FormStrings(key string, defaults ...[]string) []string { return (*Forms)(ctx.Req).MustStrings(key, defaults...) } -// QueryInt returns request form as int with default -func (ctx *BaseContext) QueryInt(key string, defaults ...int) int { +// FormInt returns request form as int with default +func (ctx *BaseContext) FormInt(key string, defaults ...int) int { return (*Forms)(ctx.Req).MustInt(key, defaults...) } -// QueryInt64 returns request form as int64 with default -func (ctx *BaseContext) QueryInt64(key string, defaults ...int64) int64 { +// FormInt64 returns request form as int64 with default +func (ctx *BaseContext) FormInt64(key string, defaults ...int64) int64 { return (*Forms)(ctx.Req).MustInt64(key, defaults...) } -// QueryBool returns request form as bool with default -func (ctx *BaseContext) QueryBool(key string, defaults ...bool) bool { +// FormBool returns request form as bool with default +func (ctx *BaseContext) FormBool(key string, defaults ...bool) bool { return (*Forms)(ctx.Req).MustBool(key, defaults...) } -// QueryOptionalBool returns request form as OptionalBool with default -func (ctx *BaseContext) QueryOptionalBool(key string, defaults ...util.OptionalBool) util.OptionalBool { +// FormOptionalBool returns request form as OptionalBool with default +func (ctx *BaseContext) FormOptionalBool(key string, defaults ...util.OptionalBool) util.OptionalBool { return (*Forms)(ctx.Req).MustOptionalBool(key, defaults...) } diff --git a/services/agit/agit.go b/services/agit/agit.go index beb21940b0cd1..3392d5ef05e4d 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -6,13 +6,11 @@ package agit import ( "fmt" - "net/http" "os" "strings" "code.gitea.io/gitea/models" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" @@ -21,7 +19,7 @@ import ( ) // ProcRecive handle proc receive work -func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []private.HookProcReceiveRefResult { +func ProcRecive(repo *models.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) { // TODO: Add more options? var ( topicBranch string @@ -31,10 +29,8 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat ) results := make([]private.HookProcReceiveRefResult, 0, len(opts.OldCommitIDs)) - repo := ctx.Repo.Repository - gitRepo := ctx.Repo.GitRepo - ownerName := ctx.Repo.Repository.OwnerName - repoName := ctx.Repo.Repository.Name + ownerName := repo.OwnerName + repoName := repo.Name topicBranch = opts.GitPushOptions["topic"] _, forcePush = opts.GitPushOptions["force-push"] @@ -100,11 +96,7 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat pr, err := models.GetUnmergedPullRequest(repo.ID, repo.ID, headBranch, baseBranchName, models.PullRequestFlowAGit) if err != nil { if !models.IsErrPullRequestNotExist(err) { - log.Error("Failed to get unmerged agit flow pull request in repository: %s/%s Error: %v", ownerName, repoName, err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Failed to get unmerged agit flow pull request in repository: %s/%s Error: %v", ownerName, repoName, err), - }) - return nil + return nil, fmt.Errorf("Failed to get unmerged agit flow pull request in repository: %s/%s Error: %v", ownerName, repoName, err) } // create a new pull request @@ -114,24 +106,15 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat if !has || len(title) == 0 { commit, err := gitRepo.GetCommit(opts.NewCommitIDs[i]) if err != nil { - log.Error("Failed to get commit %s in repository: %s/%s Error: %v", opts.NewCommitIDs[i], ownerName, repoName, err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Failed to get commit %s in repository: %s/%s Error: %v", opts.NewCommitIDs[i], ownerName, repoName, err), - }) - return nil + return nil, fmt.Errorf("Failed to get commit %s in repository: %s/%s Error: %v", opts.NewCommitIDs[i], ownerName, repoName, err) } title = strings.Split(commit.CommitMessage, "\n")[0] } description = opts.GitPushOptions["description"] } - pusher, err := user_model.GetUserByID(opts.UserID) if err != nil { - log.Error("Failed to get user. Error: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Failed to get user. Error: %v", err), - }) - return nil + return nil, fmt.Errorf("Failed to get user. Error: %v", err) } prIssue := &models.Issue{ @@ -157,12 +140,7 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat } if err := pull_service.NewPullRequest(repo, prIssue, []int64{}, []string{}, pr, []int64{}); err != nil { - if models.IsErrUserDoesNotHaveAccessToRepo(err) { - ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err.Error()) - return nil - } - ctx.Error(http.StatusInternalServerError, "NewPullRequest", err.Error()) - return nil + return nil, err } log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID) @@ -178,20 +156,12 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat // update exist pull request if err := pr.LoadBaseRepo(); err != nil { - log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Unable to load base repository for PR[%d] Error: %v", pr.ID, err), - }) - return nil + return nil, fmt.Errorf("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) } oldCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName()) if err != nil { - log.Error("Unable to get ref commit id in base repository for PR[%d] Error: %v", pr.ID, err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Unable to get ref commit id in base repository for PR[%d] Error: %v", pr.ID, err), - }) - return nil + return nil, fmt.Errorf("Unable to get ref commit id in base repository for PR[%d] Error: %v", pr.ID, err) } if oldCommitID == opts.NewCommitIDs[i] { @@ -207,11 +177,7 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat if !forcePush { output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+opts.NewCommitIDs[i]).RunInDirWithEnv(repo.RepoPath(), os.Environ()) if err != nil { - log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, opts.NewCommitIDs[i], repo, err) - ctx.JSON(http.StatusInternalServerError, private.Response{ - Err: fmt.Sprintf("Fail to detect force push: %v", err), - }) - return nil + return nil, fmt.Errorf("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, opts.NewCommitIDs[i], repo, err) } else if len(output) > 0 { results = append(results, private.HookProcReceiveRefResult{ OriginalRef: opts.RefFullNames[i], @@ -225,29 +191,17 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat pr.HeadCommitID = opts.NewCommitIDs[i] if err = pull_service.UpdateRef(pr); err != nil { - log.Error("Failed to update pull ref. Error: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Failed to update pull ref. Error: %v", err), - }) - return nil + return nil, fmt.Errorf("Failed to update pull ref. Error: %v", err) } pull_service.AddToTaskQueue(pr) pusher, err := user_model.GetUserByID(opts.UserID) if err != nil { - log.Error("Failed to get user. Error: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Failed to get user. Error: %v", err), - }) - return nil + return nil, fmt.Errorf("Failed to get user. Error: %v", err) } err = pr.LoadIssue() if err != nil { - log.Error("Failed to load pull issue. Error: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ - "Err": fmt.Sprintf("Failed to load pull issue. Error: %v", err), - }) - return nil + return nil, fmt.Errorf("Failed to load pull issue. Error: %v", err) } comment, err := models.CreatePushPullComment(pusher, pr, oldCommitID, opts.NewCommitIDs[i]) if err == nil && comment != nil { @@ -265,7 +219,7 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat }) } - return results + return results, nil } // UserNameChanged hanle user name change for agit flow pull From 924fa81389584cff8c3aeab652fc779b90354280 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 19 Aug 2021 00:22:28 +0800 Subject: [PATCH 07/10] Merge --- modules/context/base.go | 36 ------------------------------------ modules/context/form.go | 14 +++++++------- 2 files changed, 7 insertions(+), 43 deletions(-) diff --git a/modules/context/base.go b/modules/context/base.go index 8299ba31220bb..183227fd24bb2 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -14,7 +14,6 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/util" chi "github.com/go-chi/chi/v5" ) @@ -109,41 +108,6 @@ func (ctx *BaseContext) Value(key interface{}) interface{} { return ctx.Req.Context().Value(key) } -// Form returns request form as string with default -func (ctx *BaseContext) Form(key string, defaults ...string) string { - return (*Forms)(ctx.Req).MustString(key, defaults...) -} - -// FormTrim returns request form as string with default and trimmed spaces -func (ctx *BaseContext) FormTrim(key string, defaults ...string) string { - return (*Forms)(ctx.Req).MustTrimmed(key, defaults...) -} - -// FormStrings returns request form as strings with default -func (ctx *BaseContext) FormStrings(key string, defaults ...[]string) []string { - return (*Forms)(ctx.Req).MustStrings(key, defaults...) -} - -// FormInt returns request form as int with default -func (ctx *BaseContext) FormInt(key string, defaults ...int) int { - return (*Forms)(ctx.Req).MustInt(key, defaults...) -} - -// FormInt64 returns request form as int64 with default -func (ctx *BaseContext) FormInt64(key string, defaults ...int64) int64 { - return (*Forms)(ctx.Req).MustInt64(key, defaults...) -} - -// FormBool returns request form as bool with default -func (ctx *BaseContext) FormBool(key string, defaults ...bool) bool { - return (*Forms)(ctx.Req).MustBool(key, defaults...) -} - -// FormOptionalBool returns request form as OptionalBool with default -func (ctx *BaseContext) FormOptionalBool(key string, defaults ...util.OptionalBool) util.OptionalBool { - return (*Forms)(ctx.Req).MustOptionalBool(key, defaults...) -} - // Error returned an error to web browser func (ctx *BaseContext) Error(status int, contents ...string) { var v = http.StatusText(status) diff --git a/modules/context/form.go b/modules/context/form.go index 8d185909737c7..f06755458857a 100644 --- a/modules/context/form.go +++ b/modules/context/form.go @@ -12,12 +12,12 @@ import ( ) // FormString returns the first value matching the provided key in the form as a string -func (ctx *Context) FormString(key string) string { +func (ctx *BaseContext) FormString(key string) string { return ctx.Req.FormValue(key) } // FormStrings returns a string slice for the provided key from the form -func (ctx *Context) FormStrings(key string) []string { +func (ctx *BaseContext) FormStrings(key string) []string { if ctx.Req.Form == nil { if err := ctx.Req.ParseMultipartForm(32 << 20); err != nil { return nil @@ -30,31 +30,31 @@ func (ctx *Context) FormStrings(key string) []string { } // FormTrim returns the first value for the provided key in the form as a space trimmed string -func (ctx *Context) FormTrim(key string) string { +func (ctx *BaseContext) FormTrim(key string) string { return strings.TrimSpace(ctx.Req.FormValue(key)) } // FormInt returns the first value for the provided key in the form as an int -func (ctx *Context) FormInt(key string) int { +func (ctx *BaseContext) FormInt(key string) int { v, _ := strconv.Atoi(ctx.Req.FormValue(key)) return v } // FormInt64 returns the first value for the provided key in the form as an int64 -func (ctx *Context) FormInt64(key string) int64 { +func (ctx *BaseContext) FormInt64(key string) int64 { v, _ := strconv.ParseInt(ctx.Req.FormValue(key), 10, 64) return v } // FormBool returns true if the value for the provided key in the form is "1" or "true" -func (ctx *Context) FormBool(key string) bool { +func (ctx *BaseContext) FormBool(key string) bool { v, _ := strconv.ParseBool(ctx.Req.FormValue(key)) return v } // FormOptionalBool returns an OptionalBoolTrue or OptionalBoolFalse if the value // for the provided key exists in the form else it returns OptionalBoolNone -func (ctx *Context) FormOptionalBool(key string) util.OptionalBool { +func (ctx *BaseContext) FormOptionalBool(key string) util.OptionalBool { value := ctx.Req.FormValue(key) if len(value) == 0 { return util.OptionalBoolNone From 207d5835c6b5a0922526555f02fbe5db47eb289f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Dec 2021 17:05:12 +0800 Subject: [PATCH 08/10] Merge --- modules/context/private.go | 18 ++++++++++++++++-- routers/private/hook_pre_receive.go | 22 +++++++++++----------- routers/private/hook_proc_receive.go | 8 +++++++- routers/private/internal_repo.go | 10 ++++------ services/agit/agit.go | 4 ++-- 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/modules/context/private.go b/modules/context/private.go index af15c45925c29..25faeb51eda72 100644 --- a/modules/context/private.go +++ b/modules/context/private.go @@ -7,15 +7,29 @@ package context import ( "context" "net/http" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" ) // PrivateContext represents a context for private routes -type PrivateContext = BaseContext +type PrivateContext struct { + *BaseContext + Repository *models.Repository + GitRepo *git.Repository +} var ( privateContextKey interface{} = "default_private_context" ) +// NewPrivateContext creates a new private context +func NewPrivateContext(resp http.ResponseWriter, req *http.Request, data map[string]interface{}) *PrivateContext { + return &PrivateContext{ + BaseContext: NewBaseContext(resp, req, map[string]interface{}{}), + } +} + // WithPrivateContext set up private context in request func WithPrivateContext(req *http.Request, ctx *PrivateContext) *http.Request { return req.WithContext(context.WithValue(req.Context(), privateContextKey, ctx)) @@ -30,7 +44,7 @@ func GetPrivateContext(req *http.Request) *PrivateContext { func PrivateContexter() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx := NewBaseContext(w, req, map[string]interface{}{}) + ctx := NewPrivateContext(w, req, map[string]interface{}{}) ctx.Req = WithPrivateContext(req, ctx) next.ServeHTTP(ctx.Resp, ctx.Req) }) diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index 5ab21d525b975..8665244a2698c 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -142,8 +142,8 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID, refFullN return } - repo := ctx.Repo.Repository - gitRepo := ctx.Repo.GitRepo + repo := ctx.Repository + gitRepo := ctx.GitRepo branchName := strings.TrimPrefix(refFullName, git.BranchPrefix) if branchName == repo.DefaultBranch && newCommitID == git.EmptySHA { @@ -363,9 +363,9 @@ func preReceiveTag(ctx *preReceiveContext, oldCommitID, newCommitID, refFullName if !ctx.gotProtectedTags { var err error - ctx.protectedTags, err = ctx.Repo.Repository.GetProtectedTags() + ctx.protectedTags, err = ctx.Repository.GetProtectedTags() if err != nil { - log.Error("Unable to get protected tags for %-v Error: %v", ctx.Repo.Repository, err) + log.Error("Unable to get protected tags for %-v Error: %v", ctx.Repository, err) ctx.JSON(http.StatusInternalServerError, private.Response{ Err: err.Error(), }) @@ -382,7 +382,7 @@ func preReceiveTag(ctx *preReceiveContext, oldCommitID, newCommitID, refFullName return } if !isAllowed { - log.Warn("Forbidden: Tag %s in %-v is protected", tagName, ctx.Repo.Repository) + log.Warn("Forbidden: Tag %s in %-v is protected", tagName, ctx.Repository) ctx.JSON(http.StatusForbidden, private.Response{ Err: fmt.Sprintf("Tag %s is protected", tagName), }) @@ -395,7 +395,7 @@ func preReceivePullRequest(ctx *preReceiveContext, oldCommitID, newCommitID, ref return } - if ctx.Repo.Repository.IsEmpty { + if ctx.Repository.IsEmpty { ctx.JSON(http.StatusForbidden, map[string]interface{}{ "err": "Can't create pull request for an empty repository.", }) @@ -412,13 +412,13 @@ func preReceivePullRequest(ctx *preReceiveContext, oldCommitID, newCommitID, ref baseBranchName := refFullName[len(git.PullRequestPrefix):] baseBranchExist := false - if ctx.Repo.GitRepo.IsBranchExist(baseBranchName) { + if ctx.GitRepo.IsBranchExist(baseBranchName) { baseBranchExist = true } if !baseBranchExist { for p, v := range baseBranchName { - if v == '/' && ctx.Repo.GitRepo.IsBranchExist(baseBranchName[:p]) && p != len(baseBranchName)-1 { + if v == '/' && ctx.GitRepo.IsBranchExist(baseBranchName[:p]) && p != len(baseBranchName)-1 { baseBranchExist = true break } @@ -460,11 +460,11 @@ func loadUserAndPermission(ctx *gitea_context.PrivateContext, id int64) (user *u return } - perm, err = models.GetUserRepoPermission(ctx.Repo.Repository, user) + perm, err = models.GetUserRepoPermission(ctx.Repository, user) if err != nil { - log.Error("Unable to get Repo permission of repo %s/%s of User %s", ctx.Repo.Repository.OwnerName, ctx.Repo.Repository.Name, user.Name, err) + log.Error("Unable to get Repo permission of repo %s/%s of User %s", ctx.Repository.OwnerName, ctx.Repository.Name, user.Name, err) ctx.JSON(http.StatusInternalServerError, private.Response{ - Err: fmt.Sprintf("Unable to get Repo permission of repo %s/%s of User %s: %v", ctx.Repo.Repository.OwnerName, ctx.Repo.Repository.Name, user.Name, err), + Err: fmt.Sprintf("Unable to get Repo permission of repo %s/%s of User %s: %v", ctx.Repository.OwnerName, ctx.Repository.Name, user.Name, err), }) return } diff --git a/routers/private/hook_proc_receive.go b/routers/private/hook_proc_receive.go index e427a55c56161..8aceff9f4bae9 100644 --- a/routers/private/hook_proc_receive.go +++ b/routers/private/hook_proc_receive.go @@ -10,6 +10,7 @@ import ( 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" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/agit" @@ -23,7 +24,12 @@ func HookProcReceive(ctx *gitea_context.PrivateContext) { return } - results := agit.ProcRecive(ctx, opts) + results, err := agit.ProcReceive(ctx.Repository, ctx.GitRepo, opts) + if err != nil { + log.Error("agit.ProcReceive failed: %v", err) + ctx.Status(http.StatusInternalServerError) + return + } if ctx.Written() { return } diff --git a/routers/private/internal_repo.go b/routers/private/internal_repo.go index 60daa1dbeaae2..f15799918a8a6 100644 --- a/routers/private/internal_repo.go +++ b/routers/private/internal_repo.go @@ -52,16 +52,14 @@ func RepoAssignment(ctx *gitea_context.PrivateContext) context.CancelFunc { return nil } - ctx.Repo = &gitea_context.Repository{ - Repository: repo, - GitRepo: gitRepo, - } + ctx.Repository = repo + ctx.GitRepo = gitRepo // We opened it, we should close it cancel := func() { // If it's been set to nil then assume someone else has closed it. - if ctx.Repo.GitRepo != nil { - ctx.Repo.GitRepo.Close() + if ctx.GitRepo != nil { + ctx.GitRepo.Close() } } diff --git a/services/agit/agit.go b/services/agit/agit.go index 3392d5ef05e4d..9cc453a50a080 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -18,8 +18,8 @@ import ( pull_service "code.gitea.io/gitea/services/pull" ) -// ProcRecive handle proc receive work -func ProcRecive(repo *models.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) { +// ProcReceive handle proc receive work +func ProcReceive(repo *models.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) { // TODO: Add more options? var ( topicBranch string From 34c01536b368cf380866baa5371e01a662fa3586 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Dec 2021 17:10:33 +0800 Subject: [PATCH 09/10] Rename HasValue -> HasDataKey --- modules/context/base.go | 2 +- routers/install/install.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/context/base.go b/modules/context/base.go index 183227fd24bb2..9902400dd3ace 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -40,7 +40,7 @@ func (ctx *BaseContext) GetData() map[string]interface{} { } // HasValue returns true if value of given name exists. -func (ctx *BaseContext) HasValue(name string) bool { +func (ctx *BaseContext) HasDataKey(name string) bool { _, ok := ctx.Data[name] return ok } diff --git a/routers/install/install.go b/routers/install/install.go index 751bde979d736..82511eff29aba 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -248,12 +248,12 @@ func SubmitInstall(ctx *context.Context) { ctx.Data["CurDbType"] = form.DbType if ctx.HasError() { - if ctx.HasValue("Err_SMTPUser") { + if ctx.HasDataKey("Err_SMTPUser") { ctx.Data["Err_SMTP"] = true } - if ctx.HasValue("Err_AdminName") || - ctx.HasValue("Err_AdminPasswd") || - ctx.HasValue("Err_AdminEmail") { + if ctx.HasDataKey("Err_AdminName") || + ctx.HasDataKey("Err_AdminPasswd") || + ctx.HasDataKey("Err_AdminEmail") { ctx.Data["Err_Admin"] = true } From f497ec66a8f3e6f70c60130ab6eae0dd7a0d8ef6 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Dec 2021 21:39:00 +0800 Subject: [PATCH 10/10] Fix lint --- modules/context/base.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/context/base.go b/modules/context/base.go index 9902400dd3ace..0614fa1fd3023 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -39,7 +39,7 @@ func (ctx *BaseContext) GetData() map[string]interface{} { return ctx.Data } -// HasValue returns true if value of given name exists. +// HasDataKey returns true if value of given name exists. func (ctx *BaseContext) HasDataKey(name string) bool { _, ok := ctx.Data[name] return ok