linter fixes

This commit is contained in:
Pavel 2024-06-14 18:10:48 +03:00
parent 983dbe7229
commit 90e9de051a
49 changed files with 251 additions and 199 deletions

View File

@ -32,8 +32,7 @@ func main() {
if _, err := parser.Parse(); err != nil {
if flagsErr, ok := err.(*flags.Error); ok && flagsErr.Type == flags.ErrHelp { // nolint:errorlint
os.Exit(0)
} else {
os.Exit(1)
}
os.Exit(1)
}
}

View File

@ -1,7 +1,7 @@
package config
import (
"io/ioutil"
"os"
"path/filepath"
"time"
@ -132,7 +132,7 @@ func (c *Config) GetConfigData(path string) []byte {
panic(err)
}
source, err := ioutil.ReadFile(path)
source, err := os.ReadFile(path)
if err != nil {
panic(err)
}

View File

@ -1,7 +1,6 @@
package config
import (
"io/ioutil"
"os"
"path"
"testing"
@ -54,7 +53,7 @@ config_aws:
bucket: bucket
folder_name: folder
content_type: image/jpeg`)
err := ioutil.WriteFile(testConfigFile, c.data, os.ModePerm)
err := os.WriteFile(testConfigFile, c.data, os.ModePerm)
require.Nil(c.T(), err)
c.config = NewConfig(testConfigFile)

View File

@ -51,7 +51,7 @@ func (x *NewMigrationCommand) FileExists(filename string) bool {
}
// Execute migration generator command.
func (x *NewMigrationCommand) Execute(args []string) error {
func (x *NewMigrationCommand) Execute(_ []string) error {
tpl, err := template.New("migration").Parse(migrationTemplate)
if err != nil {
return fmt.Errorf("fatal: cannot parse base migration template: %w", err)

View File

@ -2,7 +2,6 @@ package db
import (
"fmt"
"io/ioutil"
"log"
"math/rand"
"os"
@ -36,7 +35,7 @@ func (s *MigrationGeneratorSuite) Test_FileExists() {
func (s *MigrationGeneratorSuite) Test_Execute() {
found := false
assert.NoError(s.T(), s.command.Execute([]string{}))
files, err := ioutil.ReadDir(s.command.Directory)
files, err := os.ReadDir(s.command.Directory)
if err != nil {
log.Fatal(err)
}

View File

@ -14,11 +14,14 @@ type User struct {
// TableName will return table name for User
// It will not work if User is not embedded, but mapped as another type
// type MyUser User // will not work
//
// type MyUser User // will not work
//
// but
// type MyUser struct { // will work
// User
// }
//
// type MyUser struct { // will work
// User
// }
func (User) TableName() string {
return "mg_user"
}

View File

@ -2,6 +2,7 @@
Package core provides different functions like error-reporting, logging, localization, etc.
to make it easier to create transports.
Usage:
package main
import (
@ -36,14 +37,19 @@ Usage:
}
}
Resource embedding
# Resource embedding
packr can be used to provide resource embedding, see:
https://github.com/gobuffalo/packr/tree/master/v2
In order to use packr you must follow instruction, and provide boxes with templates, translations and assets to library.
You can find instruction here:
https://github.com/gobuffalo/packr/tree/master/v2#library-installation
Example of usage:
package main
import (
@ -104,10 +110,12 @@ Example of usage:
}
}
Migration generator
# Migration generator
This library contains helper tool for transports. You can install it via go:
$ go get -u github.com/retailcrm/mg-transport-core/cmd/transport-core-tool
Currently, it only can generate new migrations for your transport.
Copyright (c) 2019 RetailDriver LLC. Usage of this source code is governed by a MIT license.

View File

@ -2,7 +2,7 @@ package core
import (
"encoding/json"
"io/ioutil"
"io"
"net/http"
)
@ -40,7 +40,7 @@ func getDomainsByStore(store string) []Domain {
return nil
}
respBody, readErr := ioutil.ReadAll(resp.Body)
respBody, readErr := io.ReadAll(resp.Body)
if readErr != nil {
return nil

View File

@ -7,6 +7,7 @@ import (
"io/fs"
"net/http"
"sync"
"time"
"github.com/blacked/go-zabbix"
"github.com/getsentry/sentry-go"
@ -26,12 +27,14 @@ import (
"github.com/retailcrm/mg-transport-core/v2/core/logger"
)
const DefaultHTTPClientTimeout time.Duration = 30
var boolTrue = true
// DefaultHTTPClientConfig is a default config for HTTP client. It will be used by Engine for building HTTP client
// if HTTP client config is not present in the configuration.
var DefaultHTTPClientConfig = &config.HTTPClientConfig{
Timeout: 30,
Timeout: DefaultHTTPClientTimeout,
SSLVerification: &boolTrue,
}
@ -279,10 +282,9 @@ func (e *Engine) BuildHTTPClient(certs *x509.CertPool, replaceDefault ...bool) *
if err != nil {
panic(err)
} else {
e.httpClient = client
}
e.httpClient = client
return e
}

View File

@ -6,7 +6,7 @@ import (
"database/sql"
"fmt"
"html/template"
"io/ioutil"
"io"
"net/http"
"net/url"
"os"
@ -365,7 +365,7 @@ func (e *EngineTest) Test_GetCSRFToken() {
URL: &url.URL{
RawQuery: "",
},
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
Body: io.NopCloser(bytes.NewReader([]byte{})),
Header: http.Header{"X-CSRF-Token": []string{"token"}},
}}
c.Set("csrf_token", "token")

View File

@ -10,7 +10,7 @@ import (
const DefaultResetPeriod = time.Minute * 15
// AtomicCounter is a default Counter implementation.
// It uses atomics under the hood (hence the name) and can be configured with custom reset timeout and
// It uses atomics under the hood (hence the name) and can be configured with custom reset timeout and.
type AtomicCounter struct {
name atomic.String
msg atomic.String

View File

@ -1,7 +1,7 @@
package healthcheck
var (
// compile-time checks to ensure that implementations are compatible with the interface
// compile-time checks to ensure that implementations are compatible with the interface.
_ = Storage(&SyncMapStorage{})
_ = Counter(&AtomicCounter{})
_ = Processor(CounterProcessor{})

View File

@ -44,7 +44,7 @@ type callbackLogger struct {
fn callbackLoggerFunc
}
func (n *callbackLogger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
func (n *callbackLogger) Check(_ zapcore.Level, _ string) *zapcore.CheckedEntry {
return &zapcore.CheckedEntry{}
}
@ -75,7 +75,7 @@ func (n *callbackLogger) cloneWithFields(fields []zap.Field) *callbackLogger {
cl.fields = fields
return cl
}
cl.fields = append(existing, fields...)
cl.fields = append(existing, fields...) // nolint:gocritic
return cl
}
@ -91,19 +91,19 @@ func (n *callbackLogger) WithLazy(args ...zap.Field) logger.Logger {
return n.cloneWithFields(args)
}
func (n *callbackLogger) WithGroup(name string) logger.Logger {
func (n *callbackLogger) WithGroup(_ string) logger.Logger {
return n
}
func (n *callbackLogger) ForHandler(handler any) logger.Logger {
func (n *callbackLogger) ForHandler(_ any) logger.Logger {
return n
}
func (n *callbackLogger) ForConnection(conn any) logger.Logger {
func (n *callbackLogger) ForConnection(_ any) logger.Logger {
return n
}
func (n *callbackLogger) ForAccount(acc any) logger.Logger {
func (n *callbackLogger) ForAccount(_ any) logger.Logger {
return n
}
@ -288,11 +288,11 @@ func (t *JobTest) oncePanicJob() {
}
func (t *JobTest) regularJob() {
rand.Seed(time.Now().UnixNano())
r := rand.New(rand.NewSource(time.Now().UnixNano())) // nolint:gosec
t.job = &Job{
Command: func(log logger.Logger) error {
t.executedChan <- true
t.randomNumber <- rand.Int() // nolint:gosec
t.randomNumber <- r.Int() // nolint:gosec
return nil
},
ErrorHandler: t.testErrorHandler(),
@ -303,7 +303,6 @@ func (t *JobTest) regularJob() {
}
func (t *JobTest) regularSyncJob() {
rand.Seed(time.Now().UnixNano())
t.job = &Job{
Command: func(log logger.Logger) error {
t.syncBool = true

View File

@ -3,7 +3,7 @@ package core
import (
"html/template"
"io/fs"
"io/ioutil"
"os"
"path"
"sync"
@ -90,7 +90,8 @@ type CloneableLocalizer interface {
// NewLocalizer returns localizer instance with specified parameters.
// Usage:
// NewLocalizer(language.English, DefaultLocalizerMatcher(), "translations")
//
// NewLocalizer(language.English, DefaultLocalizerMatcher(), "translations")
func NewLocalizer(locale language.Tag, matcher language.Matcher, translationsPath string) LocalizerInterface {
localizer := &Localizer{
i18nStorage: &sync.Map{},
@ -106,7 +107,9 @@ func NewLocalizer(locale language.Tag, matcher language.Matcher, translationsPat
// NewLocalizerFS returns localizer instance with specified parameters.
// Usage:
// NewLocalizerFS(language.English, DefaultLocalizerMatcher(), translationsFS)
//
// NewLocalizerFS(language.English, DefaultLocalizerMatcher(), translationsFS)
//
// TODO This code should be covered with tests.
func NewLocalizerFS(
locale language.Tag, matcher language.Matcher, translationsFS fs.FS,
@ -161,9 +164,10 @@ func (l *Localizer) Clone() CloneableLocalizer {
// Because of that all Localizer instances from this middleware will share *same* mutex. This mutex is used to wrap
// i18n.Bundle methods (those aren't goroutine-safe to use).
// Usage:
// engine := gin.New()
// localizer := NewLocalizer("en", DefaultLocalizerMatcher(), "translations")
// engine.Use(localizer.LocalizationMiddleware())
//
// engine := gin.New()
// localizer := NewLocalizer("en", DefaultLocalizerMatcher(), "translations")
// engine.Use(localizer.LocalizationMiddleware())
func (l *Localizer) LocalizationMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
clone := l.Clone().(LocaleControls)
@ -174,15 +178,21 @@ func (l *Localizer) LocalizationMiddleware() gin.HandlerFunc {
// LocalizationFuncMap returns template.FuncMap (html template is used) with one method - trans
// Usage in code:
// engine := gin.New()
// engine.FuncMap = localizer.LocalizationFuncMap()
//
// engine := gin.New()
// engine.FuncMap = localizer.LocalizationFuncMap()
//
// or (with multitemplate)
// renderer := multitemplate.NewRenderer()
// funcMap := localizer.LocalizationFuncMap()
// renderer.AddFromFilesFuncs("index", funcMap, "template/index.html")
//
// renderer := multitemplate.NewRenderer()
// funcMap := localizer.LocalizationFuncMap()
// renderer.AddFromFilesFuncs("index", funcMap, "template/index.html")
//
// funcMap must be passed for every .AddFromFilesFuncs call
// Usage in templates:
// <p class="info">{{"need_login_msg" | trans}}
//
// <p class="info">{{"need_login_msg" | trans}}
//
// You can borrow FuncMap from this method and add your functions to it.
func (l *Localizer) LocalizationFuncMap() template.FuncMap {
return template.FuncMap{
@ -196,7 +206,7 @@ func (l *Localizer) LocalizationFuncMap() template.FuncMap {
parts = append(parts, "")
}
partsMap := make(map[string]interface{}, len(parts)/2)
partsMap := make(map[string]interface{}, len(parts)/2) // nolint:gomnd
for i := 0; i < len(parts)-1; i += 2 {
partsMap[parts[i]] = parts[i+1]
@ -239,7 +249,7 @@ func (l *Localizer) loadTranslationsToBundle(i18nBundle *i18n.Bundle) {
// LoadTranslations will load all translation files from translations directory.
func (l *Localizer) loadFromDirectory(i18nBundle *i18n.Bundle) error {
files, err := ioutil.ReadDir(l.TranslationsPath)
files, err := os.ReadDir(l.TranslationsPath)
if err != nil {
return err
}

View File

@ -1,7 +1,6 @@
package core
import (
"io/ioutil"
"math/rand"
"net/http"
"net/http/httptest"
@ -40,7 +39,7 @@ func createTestLangFiles(t *testing.T) {
}
if _, err := os.Stat(fileName); err != nil && os.IsNotExist(err) {
err = ioutil.WriteFile(fileName, data, os.ModePerm)
err = os.WriteFile(fileName, data, os.ModePerm)
require.Nil(t, err)
}
}
@ -103,7 +102,7 @@ func (l *LocalizerTest) Test_LocalizationMiddleware_Context() {
func (l *LocalizerTest) Test_LocalizationMiddleware_Httptest() {
var wg sync.WaitGroup
rand.Seed(time.Now().UnixNano())
r := rand.New(rand.NewSource(time.Now().UnixNano())) // nolint:gosec
l.localizer.Preload(DefaultLanguages)
langMsgMap := map[language.Tag]string{
language.English: "Test message",
@ -122,7 +121,7 @@ func (l *LocalizerTest) Test_LocalizationMiddleware_Httptest() {
wg.Add(1)
go func(m map[language.Tag]string, wg *sync.WaitGroup) {
var tag language.Tag
switch rand.Intn(3-1) + 1 { // nolint:gosec
switch r.Intn(3-1) + 1 { // nolint:gosec
case 1:
tag = language.English
case 2:

View File

@ -2,6 +2,7 @@ package logger
import (
"fmt"
"go.uber.org/zap"
retailcrm "github.com/retailcrm/api-client-go/v2"

View File

@ -1,12 +1,13 @@
package logger
import (
"net/http"
"testing"
"github.com/h2non/gock"
retailcrm "github.com/retailcrm/api-client-go/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net/http"
"testing"
)
func TestAPIClientAdapter(t *testing.T) {

View File

@ -2,10 +2,11 @@ package logger
import (
"fmt"
json "github.com/goccy/go-json"
"io"
"net/http"
json "github.com/goccy/go-json"
"go.uber.org/zap"
)

View File

@ -4,11 +4,12 @@ import (
"bytes"
"errors"
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestErr(t *testing.T) {

View File

@ -4,11 +4,12 @@ import (
"bufio"
"bytes"
"encoding/json"
"github.com/guregu/null/v5"
"io"
"os"
"sync"
"github.com/guregu/null/v5"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

View File

@ -27,7 +27,8 @@ type Logger interface {
Warn(msg string, fields ...zap.Field)
// Error logs an error-level message with the given fields.
Error(msg string, fields ...zap.Field)
// DPanic logs a debug-panic-level message with the given fields and panics if the logger's panic level is set to a non-zero value.
// DPanic logs a debug-panic-level message with the given fields and panics
// if the logger's panic level is set to a non-zero value.
DPanic(msg string, fields ...zap.Field)
// Panic logs a panic-level message with the given fields and panics immediately.
Panic(msg string, fields ...zap.Field)

View File

@ -1,11 +1,12 @@
package logger
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
"testing"
)
type TestDefaultSuite struct {

View File

@ -1,12 +1,13 @@
package logger
import (
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGinMiddleware(t *testing.T) {

View File

@ -18,19 +18,21 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// nolint
package logger
import (
"encoding/base64"
"encoding/json"
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"io"
"math"
"time"
"unicode/utf8"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/buffer"
)

View File

@ -2,8 +2,10 @@ package logger
import (
"fmt"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
"go.uber.org/zap"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
)
const (
@ -36,10 +38,10 @@ func (m *mgTransportClientAdapter) Debugf(msg string, args ...interface{}) {
if len(args) > 1 {
uri = fmt.Sprint(args[1])
}
if len(args) > 2 {
if len(args) > 2 { // nolint:gomnd
token = fmt.Sprint(args[2])
}
if len(args) > 3 {
if len(args) > 3 { // nolint:gomnd
body = args[3]
}
m.log.Debug("MG TRANSPORT API Request",

View File

@ -1,12 +1,14 @@
package logger
import (
"github.com/h2non/gock"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net/http"
"testing"
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
)
func TestMGTransportClientAdapter(t *testing.T) {

View File

@ -13,11 +13,11 @@ func NewNil() Logger {
return &Nil{}
}
func (l *Nil) With(fields ...zap.Field) Logger {
func (l *Nil) With(_ ...zap.Field) Logger {
return l
}
func (l *Nil) WithLazy(fields ...zap.Field) Logger {
func (l *Nil) WithLazy(_ ...zap.Field) Logger {
return l
}
@ -25,35 +25,35 @@ func (l *Nil) Level() zapcore.Level {
return zapcore.DebugLevel
}
func (l *Nil) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
func (l *Nil) Check(_ zapcore.Level, _ string) *zapcore.CheckedEntry {
return &zapcore.CheckedEntry{}
}
func (l *Nil) Log(lvl zapcore.Level, msg string, fields ...zap.Field) {}
func (l *Nil) Log(_ zapcore.Level, _ string, _ ...zap.Field) {}
func (l *Nil) Debug(msg string, fields ...zap.Field) {}
func (l *Nil) Debug(_ string, _ ...zap.Field) {}
func (l *Nil) Info(msg string, fields ...zap.Field) {}
func (l *Nil) Info(_ string, _ ...zap.Field) {}
func (l *Nil) Warn(msg string, fields ...zap.Field) {}
func (l *Nil) Warn(_ string, _ ...zap.Field) {}
func (l *Nil) Error(msg string, fields ...zap.Field) {}
func (l *Nil) Error(_ string, _ ...zap.Field) {}
func (l *Nil) DPanic(msg string, fields ...zap.Field) {}
func (l *Nil) DPanic(_ string, _ ...zap.Field) {}
func (l *Nil) Panic(msg string, fields ...zap.Field) {}
func (l *Nil) Panic(_ string, _ ...zap.Field) {}
func (l *Nil) Fatal(msg string, fields ...zap.Field) {}
func (l *Nil) Fatal(_ string, _ ...zap.Field) {}
func (l *Nil) ForHandler(handler any) Logger {
func (l *Nil) ForHandler(_ any) Logger {
return l
}
func (l *Nil) ForConnection(conn any) Logger {
func (l *Nil) ForConnection(_ any) Logger {
return l
}
func (l *Nil) ForAccount(acc any) Logger {
func (l *Nil) ForAccount(_ any) Logger {
return l
}

View File

@ -1,8 +1,9 @@
package logger
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPool(t *testing.T) {

View File

@ -1,10 +1,11 @@
package logger
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"testing"
)
func TestWriterAdapter(t *testing.T) {

View File

@ -2,9 +2,10 @@ package logger
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
func TestZabbixCollectorAdapter(t *testing.T) {

View File

@ -6,7 +6,6 @@ import (
"crypto/sha1"
"encoding/base64"
"io"
"io/ioutil"
"math/rand"
"time"
@ -57,10 +56,10 @@ var DefaultCSRFTokenGetter = func(c *gin.Context) string {
} else if t := r.Header.Get("X-XSRF-Token"); len(t) > 0 {
return t
} else if c.Request.Body != nil {
data, _ := ioutil.ReadAll(c.Request.Body)
c.Request.Body = ioutil.NopCloser(bytes.NewReader(data))
data, _ := io.ReadAll(c.Request.Body)
c.Request.Body = io.NopCloser(bytes.NewReader(data))
t := r.FormValue("csrf_token")
c.Request.Body = ioutil.NopCloser(bytes.NewReader(data))
c.Request.Body = io.NopCloser(bytes.NewReader(data))
if len(t) > 0 {
return t
@ -91,17 +90,20 @@ type CSRF struct {
// csrfTokenGetter will be used to obtain token.
//
// Usage (with random salt):
// core.NewCSRF("", "super secret", "csrf_session", store, func (c *gin.Context, reason core.CSRFErrorReason) {
// c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid CSRF token"})
// }, core.DefaultCSRFTokenGetter)
//
// core.NewCSRF("", "super secret", "csrf_session", store, func (c *gin.Context, reason core.CSRFErrorReason) {
// c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid CSRF token"})
// }, core.DefaultCSRFTokenGetter)
//
// Note for csrfTokenGetter: if you want to read token from request body (for example, from form field)
// - don't forget to restore Body data!
//
// Body in http.Request is io.ReadCloser instance. Reading CSRF token from form like that:
// if t := r.FormValue("csrf_token"); len(t) > 0 {
// return t
// }
//
// if t := r.FormValue("csrf_token"); len(t) > 0 {
// return t
// }
//
// will close body - and all next middlewares won't be able to read body at all!
//
// Use DefaultCSRFTokenGetter as example to implement your own token getter.
@ -185,11 +187,11 @@ func (x *CSRF) generateSalt() string {
// pseudoRandomString generates pseudo-random string with specified length.
func (x *CSRF) pseudoRandomString(length int) string {
rand.Seed(time.Now().UnixNano())
r := rand.New(rand.NewSource(time.Now().UnixNano())) // nolint:gosec
data := make([]byte, length)
for i := 0; i < length; i++ { // it is supposed to use pseudo-random data.
data[i] = byte(65 + rand.Intn(90-65)) // nolint:gosec,gomnd
data[i] = byte(65 + r.Intn(90-65)) // nolint:gosec,gomnd
}
return string(data)
@ -209,15 +211,16 @@ func (x *CSRF) CSRFFromContext(c *gin.Context) string {
// GenerateCSRFMiddleware returns gin.HandlerFunc which will generate CSRF token
// Usage:
// engine := gin.New()
// csrf := NewCSRF("salt", "secret", "not_found", "incorrect", localizer)
// engine.Use(csrf.GenerateCSRFMiddleware())
//
// engine := gin.New()
// csrf := NewCSRF("salt", "secret", "not_found", "incorrect", localizer)
// engine.Use(csrf.GenerateCSRFMiddleware())
func (x *CSRF) GenerateCSRFMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
session, _ := x.store.Get(c.Request, x.sessionName)
if i, ok := session.Values["csrf_token"]; ok {
if i, ok := i.(string); !ok || i == "" {
if i, ok := session.Values["csrf_token"]; ok { // nolint:nestif
if i, ok := i.(string); !ok || i == "" { // nolint:nestif
if x.fillToken(session, c) != nil {
x.abortFunc(c, CSRFErrorCannotStoreTokenInSession)
c.Abort()
@ -243,8 +246,9 @@ func (x *CSRF) fillToken(s *sessions.Session, c *gin.Context) error {
// VerifyCSRFMiddleware verifies CSRF token
// Usage:
// engine := gin.New()
// engine.Use(csrf.VerifyCSRFMiddleware())
//
// engine := gin.New()
// engine.Use(csrf.VerifyCSRFMiddleware())
func (x *CSRF) VerifyCSRFMiddleware(ignoredMethods []string) gin.HandlerFunc {
return func(c *gin.Context) {
if x.strInSlice(ignoredMethods, c.Request.Method) {
@ -254,9 +258,9 @@ func (x *CSRF) VerifyCSRFMiddleware(ignoredMethods []string) gin.HandlerFunc {
var token string
session, _ := x.store.Get(c.Request, x.sessionName)
if i, ok := session.Values["csrf_token"]; ok {
if i, ok := session.Values["csrf_token"]; ok { // nolint:nestif
var v string
if v, ok = i.(string); !ok || v == "" {
if v, ok = i.(string); !ok || v == "" { // nolint:nestif
if !ok {
x.abortFunc(c, CSRFErrorIncorrectTokenType)
} else if v == "" {

View File

@ -3,7 +3,6 @@ package middleware
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@ -32,7 +31,7 @@ func TestCSRF_DefaultCSRFTokenGetter_Empty(t *testing.T) {
URL: &url.URL{
RawQuery: "",
},
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
Body: io.NopCloser(bytes.NewReader([]byte(""))),
}}
assert.Empty(t, DefaultCSRFTokenGetter(c))
@ -85,14 +84,14 @@ func TestCSRF_DefaultCSRFTokenGetter_Form(t *testing.T) {
RawQuery: "",
},
Header: headers,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
Body: io.NopCloser(bytes.NewReader([]byte(""))),
}}
c.Request.PostForm = url.Values{"csrf_token": {"token"}}
assert.NotEmpty(t, DefaultCSRFTokenGetter(c))
assert.Equal(t, "token", DefaultCSRFTokenGetter(c))
_, err := ioutil.ReadAll(c.Request.Body)
_, err := io.ReadAll(c.Request.Body)
assert.NoError(t, err)
}

View File

@ -23,6 +23,8 @@ import (
"github.com/gin-gonic/gin"
)
const recoveryMiddlewareSkipFrames = 3
// ErrorHandlerFunc will handle errors.
type ErrorHandlerFunc func(recovery interface{}, c *gin.Context)
@ -249,7 +251,7 @@ func (s *Sentry) recoveryMiddleware() gin.HandlerFunc { // nolint
}
if l != nil {
// TODO: Check if we can output stacktraces with prefix data like before if we really need it.
stack := stacktrace.FormattedStack(3, "trace: ")
stack := stacktrace.FormattedStack(recoveryMiddlewareSkipFrames, "trace: ")
formattedErr := logger.Err(err)
httpRequest, _ := httputil.DumpRequest(c.Request, false)
headers := strings.Split(string(httpRequest), "\r\n")

View File

@ -31,12 +31,12 @@ type sentryMockTransport struct {
sending sync.RWMutex
}
func (s *sentryMockTransport) Flush(timeout time.Duration) bool {
func (s *sentryMockTransport) Flush(_ time.Duration) bool {
// noop
return true
}
func (s *sentryMockTransport) Configure(options sentry.ClientOptions) {
func (s *sentryMockTransport) Configure(_ sentry.ClientOptions) {
// noop
}

View File

@ -18,7 +18,7 @@ func TestError(t *testing.T) {
func (t *ErrorTest) TestAppendToError() {
err := errors.New("test error")
_, ok := err.(StackTraced)
_, ok := err.(StackTraced) // nolint:errorlint
t.Assert().False(ok)
@ -28,16 +28,16 @@ func (t *ErrorTest) TestAppendToError() {
t.Assert().Nil(AppendToError(nil))
t.Assert().Implements((*StackTraced)(nil), withTrace)
t.Assert().Implements((*StackTraced)(nil), twiceTrace)
t.Assert().Equal(withTrace.(StackTraced).StackTrace(), twiceTrace.(StackTraced).StackTrace())
t.Assert().Equal(withTrace.(StackTraced).StackTrace(), twiceTrace.(StackTraced).StackTrace()) // nolint:errorlint
}
func (t *ErrorTest) TestCauseUnwrap() {
err := errors.New("test error")
wrapped := AppendToError(err)
t.Assert().Equal(err, wrapped.(*withStack).Cause())
t.Assert().Equal(err, wrapped.(*withStack).Cause()) // nolint:errorlint
t.Assert().Equal(err, errors.Unwrap(wrapped))
t.Assert().Equal(wrapped.(*withStack).Cause(), errors.Unwrap(wrapped))
t.Assert().Equal(wrapped.(*withStack).Cause(), errors.Unwrap(wrapped)) // nolint:errorlint
}
func (t *ErrorTest) TestFormat() {

View File

@ -5,7 +5,7 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"runtime"
"strconv"
@ -63,34 +63,34 @@ func (f Frame) name() string {
// Format formats the frame according to the fmt.Formatter interface.
//
// %s source file
// %d source line
// %n function name
// %v equivalent to %s:%d
// %s source file
// %d source line
// %n function name
// %v equivalent to %s:%d
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d
// %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
switch verb {
case 's':
switch {
case s.Flag('+'):
io.WriteString(s, f.name())
io.WriteString(s, "\n\t")
io.WriteString(s, f.file())
_, _ = io.WriteString(s, f.name())
_, _ = io.WriteString(s, "\n\t")
_, _ = io.WriteString(s, f.file())
default:
io.WriteString(s, path.Base(f.file()))
_, _ = io.WriteString(s, path.Base(f.file()))
}
case 'd':
io.WriteString(s, strconv.Itoa(f.line()))
_, _ = io.WriteString(s, strconv.Itoa(f.line()))
case 'n':
io.WriteString(s, funcname(f.name()))
_, _ = io.WriteString(s, funcname(f.name()))
case 'v':
f.Format(s, 's')
io.WriteString(s, ":")
_, _ = io.WriteString(s, ":")
f.Format(s, 'd')
}
}
@ -110,23 +110,23 @@ type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case s.Flag('+'):
for _, f := range st {
io.WriteString(s, "\n")
_, _ = io.WriteString(s, "\n")
f.Format(s, verb)
}
case s.Flag('#'):
fmt.Fprintf(s, "%#v", []Frame(st))
_, _ = fmt.Fprintf(s, "%#v", []Frame(st))
default:
st.formatSlice(s, verb)
}
@ -138,14 +138,14 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
// formatSlice will format this StackTrace into the given buffer as a slice of
// Frame, only valid when called with '%s' or '%v'.
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
io.WriteString(s, "[")
_, _ = io.WriteString(s, "[")
for i, f := range st {
if i > 0 {
io.WriteString(s, " ")
_, _ = io.WriteString(s, " ")
}
f.Format(s, verb)
}
io.WriteString(s, "]")
_, _ = io.WriteString(s, "]")
}
// stack represents a stack of program counters.
@ -159,7 +159,7 @@ func (s *stack) Format(st fmt.State, verb rune) {
if verb == 'v' && st.Flag('+') {
for _, pc := range *s {
f := Frame(pc)
fmt.Fprintf(st, "\n%+v", f)
_, _ = fmt.Fprintf(st, "\n%+v", f)
}
}
}
@ -185,16 +185,16 @@ func FormattedStack(skip int, prefix string) []byte {
break
}
// Print this much at least. If we can't find the source, it won't show.
fmt.Fprintf(buf, "%s%s:%d (0x%x)\n", prefix, file, line, pc)
_, _ = fmt.Fprintf(buf, "%s%s:%d (0x%x)\n", prefix, file, line, pc)
if file != lastFile {
data, err := ioutil.ReadFile(file)
data, err := os.ReadFile(file)
if err != nil {
continue
}
lines = bytes.Split(data, []byte{'\n'})
lastFile = file
}
fmt.Fprintf(buf, "%s\t%s: %s\n", prefix, function(pc), source(lines, line))
_, _ = fmt.Fprintf(buf, "%s\t%s: %s\n", prefix, function(pc), source(lines, line))
}
return buf.Bytes()
}

View File

@ -3,7 +3,6 @@ package core
import (
"fmt"
"html/template"
"io/ioutil"
"os"
"path"
"testing"
@ -37,8 +36,8 @@ func (t *TemplateTest) initTestData() {
require.Nil(t.T(), err)
data1 := []byte(`data {{template "body" .}}`)
data2 := []byte(`{{define "body"}}test {{"test" | trans}}{{end}}`)
err1 := ioutil.WriteFile(fmt.Sprintf(testTemplatesFile, 1), data1, os.ModePerm)
err2 := ioutil.WriteFile(fmt.Sprintf(testTemplatesFile, 2), data2, os.ModePerm)
err1 := os.WriteFile(fmt.Sprintf(testTemplatesFile, 1), data1, os.ModePerm)
err2 := os.WriteFile(fmt.Sprintf(testTemplatesFile, 2), data2, os.ModePerm)
require.Nil(t.T(), err1)
require.Nil(t.T(), err2)
}

View File

@ -18,36 +18,41 @@ import (
// because AsError() returns nil if there are no errors in the list.
//
// Example:
// err := errorutil.NewCollector().
// Do(errors.New("error 1")).
// Do(errors.New("error 2"), errors.New("error 3"))
// // Will print error message.
// fmt.Println(err)
//
// err := errorutil.NewCollector().
// Do(errors.New("error 1")).
// Do(errors.New("error 2"), errors.New("error 3"))
// // Will print error message.
// fmt.Println(err)
//
// This code will produce something like this:
// #1 err at /home/user/main.go:62: error 1
// #2 err at /home/user/main.go:63: error 2
// #3 err at /home/user/main.go:64: error 3
//
// #1 err at /home/user/main.go:62: error 1
// #2 err at /home/user/main.go:63: error 2
// #3 err at /home/user/main.go:64: error 3
//
// You can also iterate over the error to use their data instead of using predefined message:
// err := errorutil.NewCollector().
// Do(errors.New("error 1")).
// Do(errors.New("error 2"), errors.New("error 3"))
//
// for err := range c.Iterate() {
// fmt.Printf("Error at %s:%d: %v\n", err.File, err.Line, err)
// }
// err := errorutil.NewCollector().
// Do(errors.New("error 1")).
// Do(errors.New("error 2"), errors.New("error 3"))
//
// for err := range c.Iterate() {
// fmt.Printf("Error at %s:%d: %v\n", err.File, err.Line, err)
// }
//
// This code will produce output that looks like this:
// Error at /home/user/main.go:164: error 0
// Error at /home/user/main.go:164: error 1
// Error at /home/user/main.go:164: error 2
//
// Error at /home/user/main.go:164: error 0
// Error at /home/user/main.go:164: error 1
// Error at /home/user/main.go:164: error 2
//
// Example with GORM migration (Collector is returned as an error here).
// return errorutil.NewCollector().Do(
// db.CreateTable(models.Account{}, models.Connection{}).Error,
// db.Table("account").AddUniqueIndex("account_key", "channel").Error,
// ).AsError()
//
// return errorutil.NewCollector().Do(
// db.CreateTable(models.Account{}, models.Connection{}).Error,
// db.Table("account").AddUniqueIndex("account_key", "channel").Error,
// ).AsError()
type Collector struct {
errors *errList
}

View File

@ -14,7 +14,8 @@ type ListResponse struct {
// GetErrorResponse returns ErrorResponse with specified status code
// Usage (with gin):
// context.JSON(GetErrorResponse(http.StatusPaymentRequired, "Not enough money"))
//
// context.JSON(GetErrorResponse(http.StatusPaymentRequired, "Not enough money"))
func GetErrorResponse(statusCode int, err string) (int, interface{}) {
return statusCode, Response{
Error: err,
@ -23,28 +24,32 @@ func GetErrorResponse(statusCode int, err string) (int, interface{}) {
// BadRequest returns ErrorResponse with code 400
// Usage (with gin):
// context.JSON(BadRequest("invalid data"))
//
// context.JSON(BadRequest("invalid data"))
func BadRequest(err string) (int, interface{}) {
return GetErrorResponse(http.StatusBadRequest, err)
}
// Unauthorized returns ErrorResponse with code 401
// Usage (with gin):
// context.JSON(Unauthorized("invalid credentials"))
//
// context.JSON(Unauthorized("invalid credentials"))
func Unauthorized(err string) (int, interface{}) {
return GetErrorResponse(http.StatusUnauthorized, err)
}
// Forbidden returns ErrorResponse with code 403
// Usage (with gin):
// context.JSON(Forbidden("forbidden"))
//
// context.JSON(Forbidden("forbidden"))
func Forbidden(err string) (int, interface{}) {
return GetErrorResponse(http.StatusForbidden, err)
}
// InternalServerError returns ErrorResponse with code 500
// Usage (with gin):
// context.JSON(BadRequest("invalid data"))
//
// context.JSON(BadRequest("invalid data"))
func InternalServerError(err string) (int, interface{}) {
return GetErrorResponse(http.StatusInternalServerError, err)
}

View File

@ -5,12 +5,13 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"go.uber.org/zap"
"net"
"net/http"
"net/url"
"time"
"go.uber.org/zap"
"github.com/pkg/errors"
"github.com/retailcrm/mg-transport-core/v2/core/config"
"github.com/retailcrm/mg-transport-core/v2/core/logger"
@ -229,7 +230,7 @@ func (b *HTTPClientBuilder) buildMocks() error {
return errors.New("dialer must be built first")
}
if b.mockHost != "" && b.mockPort != "" && len(b.mockedDomains) > 0 {
if b.mockHost != "" && b.mockPort != "" && len(b.mockedDomains) > 0 { // nolint:nestif
b.log("Mock address has been set", zap.String("address", net.JoinHostPort(b.mockHost, b.mockPort)))
b.log("Mocked domains: ")

View File

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
@ -209,6 +208,7 @@ x5porosgI2RgOTTwmiYOcYQTS2650jYydHhK16Gu2b3UKernO16mAWXNDWfvS2bk
nAI2GL2ACEdOCyRvgq16AycJJYU7nYQ+t9aveefx0uhbYYIVeYub9NxmCfD3MojI
saG/63vo0ng851n90DVoMRWx9n1CjEvss/vvz+jXIl9njaCtizN3WUf1NwUB
-----END CERTIFICATE-----`
// nolint:gosec
keyFileData := `-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEArcVIOmlAXGS4xGBIM8xPgfMALMiunU/X22w3zv+Z/T4R48UC
5402K7PcQAJe0Qmo/J1INEc319/Iw9UxsJBawtbtaYzn++DlTF7MNsWu4JmZZyXn
@ -237,9 +237,9 @@ weywTxDl/OD5ybNkZIRKsIXciFYG1VCGO2HNGN9qJcV+nJ63kyrIBauwUkuEhiN5
uf/TQPpjrGW5nxOf94qn6FzV2WSype9BcM5MD7z7rk202Fs7Zqc=
-----END RSA PRIVATE KEY-----`
certFile, err := ioutil.TempFile("/tmp", "cert_")
certFile, err := os.CreateTemp("/tmp", "cert_")
require.NoError(t.T(), err, "cannot create temp cert file")
keyFile, err := ioutil.TempFile("/tmp", "key_")
keyFile, err := os.CreateTemp("/tmp", "key_")
require.NoError(t.T(), err, "cannot create temp key file")
_, err = certFile.WriteString(certFileData)
@ -252,7 +252,7 @@ uf/TQPpjrGW5nxOf94qn6FzV2WSype9BcM5MD7z7rk202Fs7Zqc=
errorutil.Collect(keyFile.Sync(), keyFile.Close()), "cannot sync and close temp key file")
mux := &http.ServeMux{}
srv := &http.Server{Addr: mockServerAddr, Handler: mux}
srv := &http.Server{Addr: mockServerAddr, Handler: mux, ReadHeaderTimeout: defaultDialerTimeout}
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
_, _ = io.WriteString(w, "ok")
@ -307,7 +307,7 @@ uf/TQPpjrGW5nxOf94qn6FzV2WSype9BcM5MD7z7rk202Fs7Zqc=
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
require.NoError(t.T(), err, "error while reading body")
assert.Equal(t.T(), http.StatusCreated, resp.StatusCode, "invalid status code")

View File

@ -46,7 +46,7 @@ func printRequestData(t UnmatchedRequestsTestingT, r *http.Request) {
}
}
if r.Body == nil {
if r.Body == nil { // nolint:nestif
t.Log("No body is present.")
} else {
data, err := io.ReadAll(r.Body)

View File

@ -11,11 +11,11 @@ import (
// remove all the entities created after the hook was set up.
// You can use it like this:
//
// func TestSomething(t *testing.T){
// db, _ := gorm.Open(...)
// cleaner := DeleteCreatedEntities(db)
// defer cleaner()
// }.
// func TestSomething(t *testing.T){
// db, _ := gorm.Open(...)
// cleaner := DeleteCreatedEntities(db)
// defer cleaner()
// }.
func DeleteCreatedEntities(db *gorm.DB) func() { // nolint
type entity struct {
key interface{}

View File

@ -3,8 +3,9 @@ package testutil
import (
"bufio"
"encoding/json"
"github.com/guregu/null/v5"
"io"
"github.com/guregu/null/v5"
)
type LogRecord struct {

View File

@ -2,11 +2,12 @@ package testutil
import (
"bytes"
"github.com/stretchr/testify/suite"
"io"
"strings"
"testing"
"time"
"github.com/stretchr/testify/suite"
)
type JSONRecordScannerTest struct {

View File

@ -3,7 +3,6 @@ package testutil
import (
"errors"
"io/fs"
"io/ioutil"
"os"
"path/filepath"
"sort"
@ -63,8 +62,8 @@ func (t *TranslationsExtractor) loadYAMLFile(fileName string) (map[string]interf
err error
)
if info, err = os.Stat(fileName); err == nil {
if !info.IsDir() {
if info, err = os.Stat(fileName); err == nil { // nolint:nestif
if !info.IsDir() { // nolint:nestif
var (
path string
source []byte
@ -75,7 +74,7 @@ func (t *TranslationsExtractor) loadYAMLFile(fileName string) (map[string]interf
return dataMap, err
}
if source, err = ioutil.ReadFile(path); err != nil {
if source, err = os.ReadFile(path); err != nil {
return dataMap, err
}

View File

@ -1,7 +1,6 @@
package testutil
import (
"io/ioutil"
"os"
"reflect"
"sort"
@ -40,7 +39,7 @@ func (t *TranslationsExtractorTest) SetupSuite() {
data, _ := yaml.Marshal(translation)
// It's not regular temporary file. Little hack in order to test translations extractor.
// nolint:gosec
errWrite := ioutil.WriteFile("/tmp/translate.en.yml", data, os.ModePerm)
errWrite := os.WriteFile("/tmp/translate.en.yml", data, os.ModePerm)
require.NoError(t.T(), errWrite)
t.extractor = NewTranslationsExtractor("translate.{}.yml")

View File

@ -20,9 +20,10 @@ import (
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/gin-gonic/gin"
retailcrm "github.com/retailcrm/api-client-go/v2"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
"github.com/retailcrm/mg-transport-core/v2/core/config"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
"github.com/retailcrm/mg-transport-core/v2/core/logger"
"github.com/retailcrm/mg-transport-core/v2/core/util/errorutil"

View File

@ -11,11 +11,12 @@ import (
"github.com/h2non/gock"
retailcrm "github.com/retailcrm/api-client-go/v2"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
"github.com/retailcrm/mg-transport-core/v2/core/config"
"github.com/retailcrm/mg-transport-core/v2/core/logger"