From 2b44a60ee7bc25c726e29481fe737cc6458e16e4 Mon Sep 17 00:00:00 2001 From: "Stanislav N. aka pztrn" Date: Sat, 20 Nov 2021 22:19:58 +0500 Subject: [PATCH] The Great Linting Fixes, Drone configuration fix (again) and flatfile changes. Great linting fixes has been applied, thanks to golangci-lint for extensive reporting. Fixed Drone configuration to use array for when-branch statement in Docker plugin. Flatfile storage from now will write files with 0600 permission for greater security. --- .drone.yml | 2 +- cmd/fastpastebin/fastpastebin.go | 28 +++--- domains/indexpage/indexpage.go | 8 +- domains/pastes/paste_get.go | 86 +++++++++---------- domains/pastes/paste_post.go | 38 ++++---- domains/pastes/pastes_get.go | 28 +++--- internal/context/http_server.go | 14 +-- internal/context/logger.go | 30 +++---- .../database/dialects/flatfiles/flatfiles.go | 14 ++- .../mysql/migrations/4_passworded_pastes.go | 12 +-- .../database/dialects/mysql/mysqldatabase.go | 10 +-- .../migrations/4_passworded_pastes.go | 12 +-- .../dialects/postgresql/postgresqldatabase.go | 14 +-- internal/templater/exported.go | 14 +-- 14 files changed, 154 insertions(+), 156 deletions(-) diff --git a/.drone.yml b/.drone.yml index 6075d41..55a81fd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -21,7 +21,7 @@ steps: - name: docker image: plugins/docker when: - branch: master + branch: ["master"] settings: username: from_secret: dockerhub_user diff --git a/cmd/fastpastebin/fastpastebin.go b/cmd/fastpastebin/fastpastebin.go index 2855948..7501536 100644 --- a/cmd/fastpastebin/fastpastebin.go +++ b/cmd/fastpastebin/fastpastebin.go @@ -39,29 +39,29 @@ import ( ) func main() { - c := context.New() - c.Initialize() + appCtx := context.New() + appCtx.Initialize() - c.Logger.Info().Msg("Starting Fast Pastebin...") + appCtx.Logger.Info().Msg("Starting Fast Pastebin...") // Here goes initial initialization for packages that want CLI flags // to be added. // Parse flags. - c.Flagger.Parse() + appCtx.Flagger.Parse() // Continue loading. - c.LoadConfiguration() - c.InitializePost() - database.New(c) - c.Database.Initialize() - templater.Initialize(c) + appCtx.LoadConfiguration() + appCtx.InitializePost() + database.New(appCtx) + appCtx.Database.Initialize() + templater.Initialize(appCtx) - captcha.New(c) + captcha.New(appCtx) - dbnotavailable.New(c) - indexpage.New(c) - pastes.New(c) + dbnotavailable.New(appCtx) + indexpage.New(appCtx) + pastes.New(appCtx) // CTRL+C handler. signalHandler := make(chan os.Signal, 1) @@ -71,7 +71,7 @@ func main() { go func() { <-signalHandler - c.Shutdown() + appCtx.Shutdown() shutdownDone <- true }() diff --git a/domains/indexpage/indexpage.go b/domains/indexpage/indexpage.go index b13606d..ade4a5d 100644 --- a/domains/indexpage/indexpage.go +++ b/domains/indexpage/indexpage.go @@ -35,12 +35,12 @@ import ( ) // Index of this site. -func indexGet(ec echo.Context) error { +func indexGet(ectx echo.Context) error { // We should check if database connection available. dbConn := c.Database.GetDatabaseConnection() if c.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil { // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/database_not_available") + return ectx.Redirect(http.StatusFound, "/database_not_available") } // Generate list of available languages to highlight. @@ -54,8 +54,8 @@ func indexGet(ec echo.Context) error { // Captcha. captchaString := captcha.NewCaptcha() - htmlData := templater.GetTemplate(ec, "index.html", map[string]string{"lexers": availableLexersSelectOpts, "captchaString": captchaString}) + htmlData := templater.GetTemplate(ectx, "index.html", map[string]string{"lexers": availableLexersSelectOpts, "captchaString": captchaString}) // nolint:wrapcheck - return ec.HTML(http.StatusOK, htmlData) + return ectx.HTML(http.StatusOK, htmlData) } diff --git a/domains/pastes/paste_get.go b/domains/pastes/paste_get.go index e4ff0ab..de32324 100644 --- a/domains/pastes/paste_get.go +++ b/domains/pastes/paste_get.go @@ -72,8 +72,8 @@ func pasteGetData(pasteID int, timestamp int64, cookieValue string) (*structs.Pa // GET for "/paste/PASTE_ID" and "/paste/PASTE_ID/TIMESTAMP" (private pastes). // Web interface version. -func pasteGETWebInterface(ec echo.Context) error { - pasteIDRaw := ec.Param("id") +func pasteGETWebInterface(ectx echo.Context) error { + pasteIDRaw := ectx.Param("id") // We already get numbers from string, so we will not check strconv.Atoi() // error. pasteID, _ := strconv.Atoi(regexInts.FindAllString(pasteIDRaw, 1)[0]) @@ -85,16 +85,16 @@ func pasteGETWebInterface(ec echo.Context) error { // will show 404 Not Found error and spam about that in logs. var timestamp int64 - tsProvidedStr := ec.Param("timestamp") + tsProvidedStr := ectx.Param("timestamp") if tsProvidedStr != "" { tsProvided, err := strconv.ParseInt(tsProvidedStr, 10, 64) if err != nil { c.Logger.Error().Err(err).Int("paste ID", pasteID).Int64("provided timestamp", tsProvided).Msg("Invalid timestamp provided for getting private paste") - errtpl := templater.GetErrorTemplate(ec, "Paste #"+pasteIDStr+" not found") + errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDStr+" not found") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } timestamp = tsProvided @@ -104,7 +104,7 @@ func pasteGETWebInterface(ec echo.Context) error { // for private pastes. var cookieValue string - cookie, err1 := ec.Cookie("PASTE-" + pasteIDStr) + cookie, err1 := ectx.Cookie("PASTE-" + pasteIDStr) if err1 == nil { cookieValue = cookie.Value } @@ -113,10 +113,10 @@ func pasteGETWebInterface(ec echo.Context) error { // For these cases we should return 404 Not Found page. if err == pasteExpired || err == pasteNotFound || err == pasteTimestampInvalid { - errtpl := templater.GetErrorTemplate(ec, "Paste #"+pasteIDRaw+" not found") + errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found") // nolint:wrapcheck - return ec.HTML(http.StatusNotFound, errtpl) + return ectx.HTML(http.StatusNotFound, errtpl) } // If passed cookie value was invalid - go to paste authorization @@ -125,7 +125,7 @@ func pasteGETWebInterface(ec echo.Context) error { c.Logger.Info().Int("paste ID", pasteID).Msg("Invalid cookie, redirecting to auth page") // nolint:wrapcheck - return ec.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDStr+"/"+ec.Param("timestamp")+"/verify") + return ectx.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDStr+"/"+ectx.Param("timestamp")+"/verify") } // Format paste data map. @@ -180,16 +180,16 @@ func pasteGETWebInterface(ec echo.Context) error { pasteData["pastedata"] = buf.String() // Get template and format it. - pasteHTML := templater.GetTemplate(ec, "paste.html", pasteData) + pasteHTML := templater.GetTemplate(ectx, "paste.html", pasteData) // nolint:wrapcheck - return ec.HTML(http.StatusOK, pasteHTML) + return ectx.HTML(http.StatusOK, pasteHTML) } // GET for "/paste/PASTE_ID/TIMESTAMP/verify" - a password verify page. -func pastePasswordedVerifyGet(ec echo.Context) error { - pasteIDRaw := ec.Param("id") - timestampRaw := ec.Param("timestamp") +func pastePasswordedVerifyGet(ectx echo.Context) error { + pasteIDRaw := ectx.Param("id") + timestampRaw := ectx.Param("timestamp") // We already get numbers from string, so we will not check strconv.Atoi() // error. pasteID, _ := strconv.Atoi(regexInts.FindAllString(pasteIDRaw, 1)[0]) @@ -199,14 +199,14 @@ func pastePasswordedVerifyGet(ec echo.Context) error { if err1 != nil { c.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste data") - errtpl := templater.GetErrorTemplate(ec, "Paste #"+pasteIDRaw+" not found") + errtpl := templater.GetErrorTemplate(ectx, "Paste #"+pasteIDRaw+" not found") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } // Check for auth cookie. If present - redirect to paste. - cookie, err := ec.Cookie("PASTE-" + strconv.Itoa(pasteID)) + cookie, err := ectx.Cookie("PASTE-" + strconv.Itoa(pasteID)) if err == nil { // No cookie, redirect to auth page. c.Logger.Debug().Msg("Paste cookie found, checking it...") @@ -218,7 +218,7 @@ func pastePasswordedVerifyGet(ec echo.Context) error { c.Logger.Info().Msg("Valid cookie, redirecting to paste page...") // nolint:wrapcheck - return ec.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDRaw+"/"+ec.Param("timestamp")) + return ectx.Redirect(http.StatusMovedPermanently, "/paste/"+pasteIDRaw+"/"+ectx.Param("timestamp")) } c.Logger.Debug().Msg("Invalid cookie, showing auth page") @@ -229,24 +229,24 @@ func pastePasswordedVerifyGet(ec echo.Context) error { htmlData["pasteID"] = strconv.Itoa(pasteID) htmlData["pasteTimestamp"] = timestampRaw - verifyHTML := templater.GetTemplate(ec, "passworded_paste_verify.html", htmlData) + verifyHTML := templater.GetTemplate(ectx, "passworded_paste_verify.html", htmlData) // nolint:wrapcheck - return ec.HTML(http.StatusOK, verifyHTML) + return ectx.HTML(http.StatusOK, verifyHTML) } // POST for "/paste/PASTE_ID/TIMESTAMP/verify" - a password verify page. -func pastePasswordedVerifyPost(ec echo.Context) error { +func pastePasswordedVerifyPost(ectx echo.Context) error { // We should check if database connection available. dbConn := c.Database.GetDatabaseConnection() if c.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil { // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/database_not_available") + return ectx.Redirect(http.StatusFound, "/database_not_available") } - pasteIDRaw := ec.Param("id") - timestampRaw := ec.Param("timestamp") + pasteIDRaw := ectx.Param("id") + timestampRaw := ectx.Param("timestamp") // We already get numbers from string, so we will not check strconv.Atoi() // error. pasteID, _ := strconv.Atoi(regexInts.FindAllString(pasteIDRaw, 1)[0]) @@ -256,20 +256,20 @@ func pastePasswordedVerifyPost(ec echo.Context) error { paste, err1 := c.Database.GetPaste(pasteID) if err1 != nil { c.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste") - errtpl := templater.GetErrorTemplate(ec, "Paste #"+strconv.Itoa(pasteID)+" not found") + errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } - params, err2 := ec.FormParams() + params, err2 := ectx.FormParams() if err2 != nil { c.Logger.Debug().Msg("No form parameters passed") - errtpl := templater.GetErrorTemplate(ec, "Paste #"+strconv.Itoa(pasteID)+" not found") + errtpl := templater.GetErrorTemplate(ectx, "Paste #"+strconv.Itoa(pasteID)+" not found") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } if paste.VerifyPassword(params["paste-password"][0]) { @@ -279,29 +279,29 @@ func pastePasswordedVerifyPost(ec echo.Context) error { cookie.Name = "PASTE-" + strconv.Itoa(pasteID) cookie.Value = paste.GenerateCryptedCookieValue() cookie.Expires = time.Now().Add(24 * time.Hour) - ec.SetCookie(cookie) + ectx.SetCookie(cookie) // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/paste/"+strconv.Itoa(pasteID)+"/"+timestampRaw) + return ectx.Redirect(http.StatusFound, "/paste/"+strconv.Itoa(pasteID)+"/"+timestampRaw) } - errtpl := templater.GetErrorTemplate(ec, "Invalid password. Please, try again.") + errtpl := templater.GetErrorTemplate(ectx, "Invalid password. Please, try again.") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } // GET for "/pastes/:id/raw", raw paste output. // Web interface version. -func pasteRawGETWebInterface(ec echo.Context) error { +func pasteRawGETWebInterface(ectx echo.Context) error { // We should check if database connection available. dbConn := c.Database.GetDatabaseConnection() if c.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil { // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/database_not_available/raw") + return ectx.Redirect(http.StatusFound, "/database_not_available/raw") } - pasteIDRaw := ec.Param("id") + pasteIDRaw := ectx.Param("id") // We already get numbers from string, so we will not check strconv.Atoi() // error. pasteID, _ := strconv.Atoi(regexInts.FindAllString(pasteIDRaw, 1)[0]) @@ -313,26 +313,26 @@ func pasteRawGETWebInterface(ec echo.Context) error { c.Logger.Error().Err(err1).Int("paste ID", pasteID).Msg("Failed to get paste from database") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.") + return ectx.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.") } if paste.IsExpired() { c.Logger.Error().Int("paste ID", pasteID).Msg("Paste is expired") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.") + return ectx.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.") } // Check if we have a private paste and it's parameters are correct. if paste.Private { - tsProvidedStr := ec.Param("timestamp") + tsProvidedStr := ectx.Param("timestamp") tsProvided, err2 := strconv.ParseInt(tsProvidedStr, 10, 64) if err2 != nil { c.Logger.Error().Err(err2).Int("paste ID", pasteID).Str("provided timestamp", tsProvidedStr).Msg("Invalid timestamp provided for getting private paste") // nolint:wrapcheck - return ec.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") + return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") } pasteTS := paste.CreatedAt.Unix() @@ -340,7 +340,7 @@ func pasteRawGETWebInterface(ec echo.Context) error { c.Logger.Error().Int("paste ID", pasteID).Int64("provided timestamp", tsProvided).Int64("paste timestamp", pasteTS).Msg("Incorrect timestamp provided for private paste") // nolint:wrapcheck - return ec.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") + return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") } } @@ -349,9 +349,9 @@ func pasteRawGETWebInterface(ec echo.Context) error { // Return error for now. if paste.Password != "" { c.Logger.Error().Int("paste ID", pasteID).Msg("Cannot render paste as raw: passworded paste. Patches welcome!") - return ec.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") + return ectx.String(http.StatusBadRequest, "Paste #"+pasteIDRaw+" not found") } // nolint:wrapcheck - return ec.String(http.StatusOK, paste.Data) + return ectx.String(http.StatusOK, paste.Data) } diff --git a/domains/pastes/paste_post.go b/domains/pastes/paste_post.go index 49a33c0..db27fe4 100644 --- a/domains/pastes/paste_post.go +++ b/domains/pastes/paste_post.go @@ -20,22 +20,22 @@ const KeepPastesForever = "forever" // POST for "/paste/" which will create new paste and redirect to // "/pastes/CREATED_PASTE_ID". This handler will do all the job for // requests comes from browsers via web interface. -func pastePOSTWebInterface(ec echo.Context) error { +func pastePOSTWebInterface(ectx echo.Context) error { // We should check if database connection available. dbConn := c.Database.GetDatabaseConnection() if c.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil { // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/database_not_available") + return ectx.Redirect(http.StatusFound, "/database_not_available") } - params, err := ec.FormParams() + params, err := ectx.FormParams() if err != nil { c.Logger.Error().Msg("Passed paste form is empty") - errtpl := templater.GetErrorTemplate(ec, "Cannot create empty paste") + errtpl := templater.GetErrorTemplate(ectx, "Cannot create empty paste") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } c.Logger.Debug().Msgf("Received parameters: %+v", params) @@ -44,29 +44,29 @@ func pastePOSTWebInterface(ec echo.Context) error { if len(params["paste-contents"][0]) == 0 { c.Logger.Debug().Msg("Empty paste submitted, ignoring") - errtpl := templater.GetErrorTemplate(ec, "Empty pastes aren't allowed.") + errtpl := templater.GetErrorTemplate(ectx, "Empty pastes aren't allowed.") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } if !strings.ContainsAny(params["paste-keep-for"][0], "Mmhd") && params["paste-keep-for"][0] != KeepPastesForever { c.Logger.Debug().Str("field value", params["paste-keep-for"][0]).Msg("'Keep paste for' field have invalid value") - errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") + errtpl := templater.GetErrorTemplate(ectx, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } // Verify captcha. if !captcha.Verify(params["paste-captcha-id"][0], params["paste-captcha-solution"][0]) { c.Logger.Debug().Str("captcha ID", params["paste-captcha-id"][0]).Str("captcha solution", params["paste-captcha-solution"][0]).Msg("Invalid captcha solution") - errtpl := templater.GetErrorTemplate(ec, "Invalid captcha solution.") + errtpl := templater.GetErrorTemplate(ectx, "Invalid captcha solution.") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } // nolint:exhaustivestruct @@ -101,10 +101,10 @@ func pastePOSTWebInterface(ec echo.Context) error { } else { c.Logger.Debug().Err(err).Msg("Failed to parse 'Keep for' integer") - errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") + errtpl := templater.GetErrorTemplate(ectx, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } } @@ -138,25 +138,25 @@ func pastePOSTWebInterface(ec echo.Context) error { _ = paste.CreatePassword(pastePassword[0]) } - id, err2 := c.Database.SavePaste(paste) + pasteID, err2 := c.Database.SavePaste(paste) if err2 != nil { c.Logger.Error().Err(err2).Msg("Failed to save paste") - errtpl := templater.GetErrorTemplate(ec, "Failed to save paste. Please, try again later.") + errtpl := templater.GetErrorTemplate(ectx, "Failed to save paste. Please, try again later.") // nolint:wrapcheck - return ec.HTML(http.StatusBadRequest, errtpl) + return ectx.HTML(http.StatusBadRequest, errtpl) } - newPasteIDAsString := strconv.FormatInt(id, 10) + newPasteIDAsString := strconv.FormatInt(pasteID, 10) c.Logger.Debug().Msg("Paste saved, URL: /paste/" + newPasteIDAsString) // Private pastes have it's timestamp in URL. if paste.Private { // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString+"/"+strconv.FormatInt(paste.CreatedAt.Unix(), 10)) + return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString+"/"+strconv.FormatInt(paste.CreatedAt.Unix(), 10)) } // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString) + return ectx.Redirect(http.StatusFound, "/paste/"+newPasteIDAsString) } diff --git a/domains/pastes/pastes_get.go b/domains/pastes/pastes_get.go index e29ac75..e7f983c 100644 --- a/domains/pastes/pastes_get.go +++ b/domains/pastes/pastes_get.go @@ -37,15 +37,15 @@ import ( // GET for "/pastes/", a list of publicly available pastes. // Web interface version. -func pastesGET(ec echo.Context) error { +func pastesGET(ectx echo.Context) error { // We should check if database connection available. dbConn := c.Database.GetDatabaseConnection() if c.Config.Database.Type != flatfiles.FlatFileDialect && dbConn == nil { // nolint:wrapcheck - return ec.Redirect(http.StatusFound, "/database_not_available") + return ectx.Redirect(http.StatusFound, "/database_not_available") } - pageFromParamRaw := ec.Param("page") + pageFromParamRaw := ectx.Param("page") page := 1 @@ -66,34 +66,34 @@ func pastesGET(ec echo.Context) error { if err3 != nil { c.Logger.Error().Err(err3).Msg("Failed to get pastes list from database") - noPastesToShowTpl := templater.GetErrorTemplate(ec, "No pastes to show.") + noPastesToShowTpl := templater.GetErrorTemplate(ectx, "No pastes to show.") // nolint:wrapcheck - return ec.HTML(http.StatusOK, noPastesToShowTpl) + return ectx.HTML(http.StatusOK, noPastesToShowTpl) } if len(pastes) > 0 { pastesString = "" - for i := range pastes { + for _, paste := range pastes { pasteDataMap := make(map[string]string) - pasteDataMap["pasteID"] = strconv.Itoa(pastes[i].ID) - pasteDataMap["pasteTitle"] = pastes[i].Title - pasteDataMap["pasteDate"] = pastes[i].CreatedAt.Format("2006-01-02 @ 15:04:05") + " UTC" + pasteDataMap["pasteID"] = strconv.Itoa(paste.ID) + pasteDataMap["pasteTitle"] = paste.Title + pasteDataMap["pasteDate"] = paste.CreatedAt.Format("2006-01-02 @ 15:04:05") + " UTC" // Get max 4 lines of each paste. - pasteDataSplitted := strings.Split(pastes[i].Data, "\n") + pasteDataSplitted := strings.Split(paste.Data, "\n") var pasteData string if len(pasteDataSplitted) < 4 { - pasteData = pastes[i].Data + pasteData = paste.Data } else { pasteData = strings.Join(pasteDataSplitted[0:4], "\n") } pasteDataMap["pasteData"] = pasteData - pasteTpl := templater.GetRawTemplate(ec, "pastelist_paste.html", pasteDataMap) + pasteTpl := templater.GetRawTemplate(ectx, "pastelist_paste.html", pasteDataMap) pastesString += pasteTpl } @@ -104,8 +104,8 @@ func pastesGET(ec echo.Context) error { c.Logger.Debug().Int("total pages", pages).Int("current page", page).Msg("Paging data") paginationHTML := pagination.CreateHTML(page, pages, "/pastes/") - pasteListTpl := templater.GetTemplate(ec, "pastelist_list.html", map[string]string{"pastes": pastesString, "pagination": paginationHTML}) + pasteListTpl := templater.GetTemplate(ectx, "pastelist_list.html", map[string]string{"pastes": pastesString, "pagination": paginationHTML}) // nolint:wrapcheck - return ec.HTML(http.StatusOK, pasteListTpl) + return ectx.HTML(http.StatusOK, pasteListTpl) } diff --git a/internal/context/http_server.go b/internal/context/http_server.go index 57f48c6..42113ad 100644 --- a/internal/context/http_server.go +++ b/internal/context/http_server.go @@ -31,16 +31,16 @@ func (c *Context) initializeHTTPServer() { // Wrapper around previous function. func (c *Context) echoReqLogger() echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(ec echo.Context) error { + return func(ectx echo.Context) error { c.Logger.Info(). - Str("IP", ec.RealIP()). - Str("Host", ec.Request().Host). - Str("Method", ec.Request().Method). - Str("Path", ec.Request().URL.Path). - Str("UA", ec.Request().UserAgent()). + Str("IP", ectx.RealIP()). + Str("Host", ectx.Request().Host). + Str("Method", ectx.Request().Method). + Str("Path", ectx.Request().URL.Path). + Str("UA", ectx.Request().UserAgent()). Msg("HTTP request") - return next(ec) + return next(ectx) } } } diff --git a/internal/context/logger.go b/internal/context/logger.go index b1e65df..b4695bc 100644 --- a/internal/context/logger.go +++ b/internal/context/logger.go @@ -11,14 +11,14 @@ import ( ) // Puts memory usage into log lines. -func (c *Context) getMemoryUsage(e *zerolog.Event, level zerolog.Level, message string) { +func (c *Context) getMemoryUsage(event *zerolog.Event, level zerolog.Level, message string) { var m runtime.MemStats runtime.ReadMemStats(&m) - e.Str("memalloc", fmt.Sprintf("%dMB", m.Alloc/1024/1024)) - e.Str("memsys", fmt.Sprintf("%dMB", m.Sys/1024/1024)) - e.Str("numgc", fmt.Sprintf("%d", m.NumGC)) + event.Str("memalloc", fmt.Sprintf("%dMB", m.Alloc/1024/1024)) + event.Str("memsys", fmt.Sprintf("%dMB", m.Sys/1024/1024)) + event.Str("numgc", fmt.Sprintf("%d", m.NumGC)) } // Initializes logger. @@ -26,26 +26,26 @@ func (c *Context) initializeLogger() { // Устанавливаем форматирование логгера. // nolint:exhaustivestruct output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339} - output.FormatLevel = func(i interface{}) string { + output.FormatLevel = func(lvlRaw interface{}) string { var v string - if ii, ok := i.(string); ok { - ii = strings.ToUpper(ii) - switch ii { + if lvl, ok := lvlRaw.(string); ok { + lvl = strings.ToUpper(lvl) + switch lvl { case "DEBUG": - v = fmt.Sprintf("\x1b[30m%-5s\x1b[0m", ii) + v = fmt.Sprintf("\x1b[30m%-5s\x1b[0m", lvl) case "ERROR": - v = fmt.Sprintf("\x1b[31m%-5s\x1b[0m", ii) + v = fmt.Sprintf("\x1b[31m%-5s\x1b[0m", lvl) case "FATAL": - v = fmt.Sprintf("\x1b[35m%-5s\x1b[0m", ii) + v = fmt.Sprintf("\x1b[35m%-5s\x1b[0m", lvl) case "INFO": - v = fmt.Sprintf("\x1b[32m%-5s\x1b[0m", ii) + v = fmt.Sprintf("\x1b[32m%-5s\x1b[0m", lvl) case "PANIC": - v = fmt.Sprintf("\x1b[36m%-5s\x1b[0m", ii) + v = fmt.Sprintf("\x1b[36m%-5s\x1b[0m", lvl) case "WARN": - v = fmt.Sprintf("\x1b[33m%-5s\x1b[0m", ii) + v = fmt.Sprintf("\x1b[33m%-5s\x1b[0m", lvl) default: - v = ii + v = lvl } } diff --git a/internal/database/dialects/flatfiles/flatfiles.go b/internal/database/dialects/flatfiles/flatfiles.go index 106a6e2..d6226d3 100644 --- a/internal/database/dialects/flatfiles/flatfiles.go +++ b/internal/database/dialects/flatfiles/flatfiles.go @@ -250,16 +250,16 @@ func (ff *FlatFiles) Initialize() { } } -func (ff *FlatFiles) SavePaste(p *structs.Paste) (int64, error) { +func (ff *FlatFiles) SavePaste(paste *structs.Paste) (int64, error) { ff.writeMutex.Lock() // Write paste data on disk. filesOnDisk, _ := ioutil.ReadDir(filepath.Join(ff.path, "pastes")) pasteID := len(filesOnDisk) + 1 - p.ID = pasteID + paste.ID = pasteID c.Logger.Debug().Int("new paste ID", pasteID).Msg("Writing paste to disk") - data, err := json.Marshal(p) + data, err := json.Marshal(paste) if err != nil { ff.writeMutex.Unlock() @@ -267,8 +267,7 @@ func (ff *FlatFiles) SavePaste(p *structs.Paste) (int64, error) { return 0, err } - // nolint:gosec - err = ioutil.WriteFile(filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json"), data, 0644) + err = ioutil.WriteFile(filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json"), data, 0o600) if err != nil { ff.writeMutex.Unlock() @@ -280,7 +279,7 @@ func (ff *FlatFiles) SavePaste(p *structs.Paste) (int64, error) { // nolint:exhaustivestruct indexData := Index{} indexData.ID = pasteID - indexData.Private = p.Private + indexData.Private = paste.Private ff.pastesIndex = append(ff.pastesIndex, indexData) ff.writeMutex.Unlock() @@ -297,8 +296,7 @@ func (ff *FlatFiles) Shutdown() { return } - // nolint:gosec - err1 := ioutil.WriteFile(filepath.Join(ff.path, "pastes", "index.json"), indexData, 0644) + err1 := ioutil.WriteFile(filepath.Join(ff.path, "pastes", "index.json"), indexData, 0o600) if err1 != nil { c.Logger.Error().Err(err1).Msg("Failed to write index data to file. Pretty sure that you've lost your pastes.") diff --git a/internal/database/dialects/mysql/migrations/4_passworded_pastes.go b/internal/database/dialects/mysql/migrations/4_passworded_pastes.go index d3510fd..38d145c 100644 --- a/internal/database/dialects/mysql/migrations/4_passworded_pastes.go +++ b/internal/database/dialects/mysql/migrations/4_passworded_pastes.go @@ -28,14 +28,14 @@ import ( "database/sql" ) -func PasswordedPastesUp(tx *sql.Tx) error { - _, err := tx.Exec("ALTER TABLE `pastes` ADD `password` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password for paste (scrypted and sha256ed).'") +func PasswordedPastesUp(txn *sql.Tx) error { + _, err := txn.Exec("ALTER TABLE `pastes` ADD `password` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password for paste (scrypted and sha256ed).'") if err != nil { // nolint:wrapcheck return err } - _, err1 := tx.Exec("ALTER TABLE `pastes` ADD `password_salt` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password salt (sha256ed).'") + _, err1 := txn.Exec("ALTER TABLE `pastes` ADD `password_salt` varchar(64) NOT NULL DEFAULT '' COMMENT 'Password salt (sha256ed).'") if err1 != nil { // nolint:wrapcheck return err1 @@ -44,14 +44,14 @@ func PasswordedPastesUp(tx *sql.Tx) error { return nil } -func PasswordedPastesDown(tx *sql.Tx) error { - _, err := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `password`") +func PasswordedPastesDown(txn *sql.Tx) error { + _, err := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password`") if err != nil { // nolint:wrapcheck return err } - _, err1 := tx.Exec("ALTER TABLE `pastes` DROP COLUMN `password_salt`") + _, err1 := txn.Exec("ALTER TABLE `pastes` DROP COLUMN `password_salt`") if err1 != nil { // nolint:wrapcheck return err1 diff --git a/internal/database/dialects/mysql/mysqldatabase.go b/internal/database/dialects/mysql/mysqldatabase.go index 4a6ce58..9ae1113 100644 --- a/internal/database/dialects/mysql/mysqldatabase.go +++ b/internal/database/dialects/mysql/mysqldatabase.go @@ -81,15 +81,15 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { db.check() // nolint:exhaustivestruct - p := &structs.Paste{} + paste := &structs.Paste{} - err := db.db.Get(p, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID) + err := db.db.Get(paste, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID) if err != nil { // nolint:wrapcheck return nil, err } - return p, nil + return paste, nil } func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) { @@ -195,13 +195,13 @@ func (db *Database) SavePaste(p *structs.Paste) (int64, error) { return 0, err } - ID, err1 := result.LastInsertId() + lastInsertID, err1 := result.LastInsertId() if err1 != nil { // nolint:wrapcheck return 0, err } - return ID, nil + return lastInsertID, nil } func (db *Database) Shutdown() { diff --git a/internal/database/dialects/postgresql/migrations/4_passworded_pastes.go b/internal/database/dialects/postgresql/migrations/4_passworded_pastes.go index 05808c0..6aca4cf 100644 --- a/internal/database/dialects/postgresql/migrations/4_passworded_pastes.go +++ b/internal/database/dialects/postgresql/migrations/4_passworded_pastes.go @@ -28,14 +28,14 @@ import ( "database/sql" ) -func PasswordedPastesUp(tx *sql.Tx) error { - _, err := tx.Exec("ALTER TABLE pastes ADD COLUMN password VARCHAR(64) NOT NULL DEFAULT ''; COMMENT ON COLUMN pastes.password IS 'Password for paste (scrypted and sha256ed).';") +func PasswordedPastesUp(txn *sql.Tx) error { + _, err := txn.Exec("ALTER TABLE pastes ADD COLUMN password VARCHAR(64) NOT NULL DEFAULT ''; COMMENT ON COLUMN pastes.password IS 'Password for paste (scrypted and sha256ed).';") if err != nil { // nolint:wrapcheck return err } - _, err1 := tx.Exec("ALTER TABLE pastes ADD COLUMN password_salt VARCHAR(64) NOT NULL DEFAULT ''; COMMENT ON COLUMN pastes.password_salt IS 'Password salt (sha256ed).';") + _, err1 := txn.Exec("ALTER TABLE pastes ADD COLUMN password_salt VARCHAR(64) NOT NULL DEFAULT ''; COMMENT ON COLUMN pastes.password_salt IS 'Password salt (sha256ed).';") if err1 != nil { // nolint:wrapcheck return err1 @@ -44,14 +44,14 @@ func PasswordedPastesUp(tx *sql.Tx) error { return nil } -func PasswordedPastesDown(tx *sql.Tx) error { - _, err := tx.Exec("ALTER TABLE pastes DROP COLUMN password") +func PasswordedPastesDown(txn *sql.Tx) error { + _, err := txn.Exec("ALTER TABLE pastes DROP COLUMN password") if err != nil { // nolint:wrapcheck return err } - _, err1 := tx.Exec("ALTER TABLE pastes DROP COLUMN password_salt") + _, err1 := txn.Exec("ALTER TABLE pastes DROP COLUMN password_salt") if err1 != nil { // nolint:wrapcheck return err1 diff --git a/internal/database/dialects/postgresql/postgresqldatabase.go b/internal/database/dialects/postgresql/postgresqldatabase.go index 17102c6..92b4069 100644 --- a/internal/database/dialects/postgresql/postgresqldatabase.go +++ b/internal/database/dialects/postgresql/postgresqldatabase.go @@ -84,9 +84,9 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { db.check() // nolint:exhaustivestruct - p := &structs.Paste{} + paste := &structs.Paste{} - err := db.db.Get(p, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID) + err := db.db.Get(paste, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID) if err != nil { // nolint:wrapcheck return nil, err @@ -96,10 +96,10 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) { // timestamps in server's local timezone. We should convert them. loc, _ := time.LoadLocation("UTC") - utcCreatedAt := p.CreatedAt.In(loc) - p.CreatedAt = &utcCreatedAt + utcCreatedAt := paste.CreatedAt.In(loc) + paste.CreatedAt = &utcCreatedAt - return p, nil + return paste, nil } func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) { @@ -197,7 +197,7 @@ func (db *Database) Initialize() { migrations.Migrate() } -func (db *Database) SavePaste(p *structs.Paste) (int64, error) { +func (db *Database) SavePaste(paste *structs.Paste) (int64, error) { db.check() stmt, err := db.db.PrepareNamed("INSERT INTO pastes (title, data, created_at, keep_for, keep_for_unit_type, language, private, password, password_salt) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type, :language, :private, :password, :password_salt) RETURNING id") @@ -208,7 +208,7 @@ func (db *Database) SavePaste(p *structs.Paste) (int64, error) { var id int64 - err = stmt.Get(&id, p) + err = stmt.Get(&id, paste) if err != nil { // nolint:wrapcheck return 0, err diff --git a/internal/templater/exported.go b/internal/templater/exported.go index 5d6b154..ef384fa 100644 --- a/internal/templater/exported.go +++ b/internal/templater/exported.go @@ -50,11 +50,11 @@ func GetErrorTemplate(ec echo.Context, errorText string) string { } // GetRawTemplate returns only raw template data. -func GetRawTemplate(ec echo.Context, templateName string, data map[string]string) string { +func GetRawTemplate(ectx echo.Context, templateName string, data map[string]string) string { // Getting main template. tplRaw, err := assets.Data.ReadFile(templateName) if err != nil { - _ = ec.String(http.StatusBadRequest, templateName+" not found.") + _ = ectx.String(http.StatusBadRequest, templateName+" not found.") return "" } @@ -69,13 +69,13 @@ func GetRawTemplate(ec echo.Context, templateName string, data map[string]string } // GetTemplate returns formatted template that can be outputted to client. -func GetTemplate(ec echo.Context, name string, data map[string]string) string { +func GetTemplate(ectx echo.Context, name string, data map[string]string) string { log.Debug().Str("name", name).Msg("Requested template") // Getting main template. mainhtml, err := assets.Data.ReadFile("main.html") if err != nil { - _ = ec.String(http.StatusBadRequest, "main.html not found.") + _ = ectx.String(http.StatusBadRequest, "main.html not found.") return "" } @@ -83,7 +83,7 @@ func GetTemplate(ec echo.Context, name string, data map[string]string) string { // Getting navigation. navhtml, err1 := assets.Data.ReadFile("navigation.html") if err1 != nil { - _ = ec.String(http.StatusBadRequest, "navigation.html not found.") + _ = ectx.String(http.StatusBadRequest, "navigation.html not found.") return "" } @@ -91,7 +91,7 @@ func GetTemplate(ec echo.Context, name string, data map[string]string) string { // Getting footer. footerhtml, err2 := assets.Data.ReadFile("footer.html") if err2 != nil { - _ = ec.String(http.StatusBadRequest, "footer.html not found.") + _ = ectx.String(http.StatusBadRequest, "footer.html not found.") return "" } @@ -105,7 +105,7 @@ func GetTemplate(ec echo.Context, name string, data map[string]string) string { // Get requested template. reqhtml, err3 := assets.Data.ReadFile(name) if err3 != nil { - _ = ec.String(http.StatusBadRequest, name+" not found.") + _ = ectx.String(http.StatusBadRequest, name+" not found.") return "" }