Static analysis (#23)

* lint stage for a workflow
* golangci-lint config
* lint only new code or last commit
* run lint only for pull requests
This commit is contained in:
Pavel 2021-02-09 14:57:14 +03:00 committed by GitHub
parent 2eb1b78871
commit d15ed7ffec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 457 additions and 243 deletions

View File

@ -12,6 +12,18 @@ env:
GO111MODULE: on GO111MODULE: on
jobs: jobs:
golangci:
name: lint
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Lint code with golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.36
only-new-issues: true
tests: tests:
name: Tests name: Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest

197
.golangci.yml Normal file
View File

@ -0,0 +1,197 @@
run:
skip-dirs-use-default: true
allow-parallel-runners: true
output:
format: colored-line-number
sort-results: true
linters:
disable-all: true
enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- unused
- unparam
- varcheck
- bodyclose
- dogsled
- dupl
- errorlint
- exhaustive
- exportloopref
- funlen
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- goimports
- golint
- gomnd
- gosec
- ifshort
- interfacer
- lll
- makezero
- maligned
- misspell
- nestif
- prealloc
- predeclared
- scopelint
- sqlclosecheck
- unconvert
- whitespace
linters-settings:
govet:
check-shadowing: false
disable-all: true
enable:
- assign
- atomic
- bools
- buildtag
- copylocks
- httpresponse
- loopclosure
- lostcancel
- printf
- shift
- stdmethods
- structtag
- tests
- unmarshal
- unreachable
- unsafeptr
- unused
settings:
printf:
funcs:
- (*log.Logger).Fatal
- (*log.Logger).Fatalf
- (*log.Logger).Fatalln
- (*log.Logger).Panic
- (*log.Logger).Panicf
- (*log.Logger).Panicln
- (*log.Logger).Print
- (*log.Logger).Printf
- (*log.Logger).Println
- (*testing.common).Error
- (*testing.common).Errorf
- (*testing.common).Fatal
- (*testing.common).Fatalf
- (*testing.common).Log
- (*testing.common).Logf
- (*testing.common).Skip
- (*testing.common).Skipf
- (testing.TB).Error
- (testing.TB).Errorf
- (testing.TB).Fatal
- (testing.TB).Fatalf
- (testing.TB).Log
- (testing.TB).Logf
- (testing.TB).Skip
- (testing.TB).Skipf
- fmt.Errorf
- fmt.Fprint
- fmt.Fprintf
- fmt.Fprintln
- fmt.Print
- fmt.Printf
- fmt.Println
- fmt.Sprint
- fmt.Sprintf
- fmt.Sprintln
- log.Fatal
- log.Fatalf
- log.Fatalln
- log.Panic
- log.Panicf
- log.Panicln
- log.Print
- log.Printf
- log.Println
- runtime/trace.Logf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Fatalf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Panicf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Panicf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Criticalf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Errorf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Warningf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Noticef
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Infof
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Debugf
unused:
check-exported: false
unparam:
check-exported: false
dogsled:
max-blank-identifiers: 3
dupl:
threshold: 200
errorlint:
errorf: true
exhaustive:
check-generated: false
default-signifies-exhaustive: false
funlen:
lines: 60
statements: 40
gocognit:
min-complexity: 25
gocyclo:
min-complexity: 25
goimports:
local-prefixes: github.com/retailcrm/mg-transport-core
lll:
line-length: 120
maligned:
suggest-new: true
misspell:
locale: US
nestif:
min-complexity: 4
whitespace:
multi-if: false
multi-func: false
issues:
exclude-rules:
- path: _test\.go
linters:
- gomnd
- lll
- bodyclose
- errcheck
- sqlclosecheck
- misspell
- ineffassign
- whitespace
- makezero
- maligned
- ifshort
- errcheck
- funlen
- goconst
- gocognit
- gocyclo
- godot
exclude-use-default: true
exclude-case-sensitive: false
max-issues-per-linter: 0
max-same-issues: 0
fix: true
severity:
default-severity: error
case-sensitive: false
service:
golangci-lint-version: 1.36.x

View File

@ -4,10 +4,11 @@ import (
"os" "os"
"github.com/jessevdk/go-flags" "github.com/jessevdk/go-flags"
"github.com/retailcrm/mg-transport-core/core" "github.com/retailcrm/mg-transport-core/core"
) )
// Options for tool command // Options for tool command.
type Options struct{} type Options struct{}
var ( var (

View File

@ -21,7 +21,7 @@ var (
slashRegex = regexp.MustCompile(`/+$`) slashRegex = regexp.MustCompile(`/+$`)
) )
// ConfigInterface settings data structure // ConfigInterface settings data structure.
type ConfigInterface interface { type ConfigInterface interface {
GetVersion() string GetVersion() string
GetSentryDSN() string GetSentryDSN() string
@ -35,14 +35,14 @@ type ConfigInterface interface {
IsDebug() bool IsDebug() bool
} }
// InfoInterface transport settings data structure // InfoInterface transport settings data structure.
type InfoInterface interface { type InfoInterface interface {
GetName() string GetName() string
GetCode() string GetCode() string
GetLogoPath() string GetLogoPath() string
} }
// Config struct // Config struct.
type Config struct { type Config struct {
Version string `yaml:"version"` Version string `yaml:"version"`
LogLevel logging.Level `yaml:"log_level"` LogLevel logging.Level `yaml:"log_level"`
@ -56,14 +56,14 @@ type Config struct {
HTTPClientConfig *HTTPClientConfig `yaml:"http_client"` HTTPClientConfig *HTTPClientConfig `yaml:"http_client"`
} }
// Info struct // Info struct.
type Info struct { type Info struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Code string `yaml:"code"` Code string `yaml:"code"`
LogoPath string `yaml:"logo_path"` LogoPath string `yaml:"logo_path"`
} }
// ConfigAWS struct // ConfigAWS struct.
type ConfigAWS struct { type ConfigAWS struct {
AccessKeyID string `yaml:"access_key_id"` AccessKeyID string `yaml:"access_key_id"`
SecretAccessKey string `yaml:"secret_access_key"` SecretAccessKey string `yaml:"secret_access_key"`
@ -73,7 +73,7 @@ type ConfigAWS struct {
ContentType string `yaml:"content_type"` ContentType string `yaml:"content_type"`
} }
// DatabaseConfig struct // DatabaseConfig struct.
type DatabaseConfig struct { type DatabaseConfig struct {
Connection interface{} `yaml:"connection"` Connection interface{} `yaml:"connection"`
Logging bool `yaml:"logging"` Logging bool `yaml:"logging"`
@ -83,7 +83,7 @@ type DatabaseConfig struct {
ConnectionLifetime int `yaml:"connection_lifetime"` ConnectionLifetime int `yaml:"connection_lifetime"`
} }
// HTTPClientConfig struct // HTTPClientConfig struct.
type HTTPClientConfig struct { type HTTPClientConfig struct {
Timeout time.Duration `yaml:"timeout"` Timeout time.Duration `yaml:"timeout"`
SSLVerification *bool `yaml:"ssl_verification"` SSLVerification *bool `yaml:"ssl_verification"`
@ -91,7 +91,7 @@ type HTTPClientConfig struct {
MockedDomains []string `yaml:"mocked_domains"` MockedDomains []string `yaml:"mocked_domains"`
} }
// HTTPServerConfig struct // HTTPServerConfig struct.
type HTTPServerConfig struct { type HTTPServerConfig struct {
Host string `yaml:"host"` Host string `yaml:"host"`
Listen string `yaml:"listen"` Listen string `yaml:"listen"`
@ -104,12 +104,12 @@ func NewConfig(path string) *Config {
return (&Config{}).LoadConfig(path) return (&Config{}).LoadConfig(path)
} }
// LoadConfig read & load configuration file // LoadConfig read & load configuration file.
func (c *Config) LoadConfig(path string) *Config { func (c *Config) LoadConfig(path string) *Config {
return c.LoadConfigFromData(c.GetConfigData(path)) return c.LoadConfigFromData(c.GetConfigData(path))
} }
// LoadConfigFromData loads config from byte sequence // LoadConfigFromData loads config from byte sequence.
func (c *Config) LoadConfigFromData(data []byte) *Config { func (c *Config) LoadConfigFromData(data []byte) *Config {
if err := yaml.Unmarshal(data, c); err != nil { if err := yaml.Unmarshal(data, c); err != nil {
panic(err) panic(err)
@ -118,7 +118,7 @@ func (c *Config) LoadConfigFromData(data []byte) *Config {
return c return c
} }
// GetConfigData returns config file data in form of byte sequence // GetConfigData returns config file data in form of byte sequence.
func (c *Config) GetConfigData(path string) []byte { func (c *Config) GetConfigData(path string) []byte {
var err error var err error
@ -135,72 +135,72 @@ func (c *Config) GetConfigData(path string) []byte {
return source return source
} }
// GetSentryDSN sentry connection dsn // GetSentryDSN sentry connection dsn.
func (c Config) GetSentryDSN() string { func (c Config) GetSentryDSN() string {
return c.SentryDSN return c.SentryDSN
} }
// GetVersion transport version // GetVersion transport version.
func (c Config) GetVersion() string { func (c Config) GetVersion() string {
return c.Version return c.Version
} }
// GetLogLevel log level // GetLogLevel log level.
func (c Config) GetLogLevel() logging.Level { func (c Config) GetLogLevel() logging.Level {
return c.LogLevel return c.LogLevel
} }
// GetTransportInfo transport basic data // GetTransportInfo transport basic data.
func (c Config) GetTransportInfo() InfoInterface { func (c Config) GetTransportInfo() InfoInterface {
return c.TransportInfo return c.TransportInfo
} }
// IsDebug debug flag // IsDebug debug flag.
func (c Config) IsDebug() bool { func (c Config) IsDebug() bool {
return c.Debug return c.Debug
} }
// GetAWSConfig AWS configuration // GetAWSConfig AWS configuration.
func (c Config) GetAWSConfig() ConfigAWS { func (c Config) GetAWSConfig() ConfigAWS {
return c.ConfigAWS return c.ConfigAWS
} }
// GetDBConfig database configuration // GetDBConfig database configuration.
func (c Config) GetDBConfig() DatabaseConfig { func (c Config) GetDBConfig() DatabaseConfig {
return c.Database return c.Database
} }
// GetHTTPConfig server configuration // GetHTTPConfig server configuration.
func (c Config) GetHTTPConfig() HTTPServerConfig { func (c Config) GetHTTPConfig() HTTPServerConfig {
return c.HTTPServer return c.HTTPServer
} }
// GetUpdateInterval user data update interval // GetUpdateInterval user data update interval.
func (c Config) GetUpdateInterval() int { func (c Config) GetUpdateInterval() int {
return c.UpdateInterval return c.UpdateInterval
} }
// GetHTTPClientConfig returns http client config // GetHTTPClientConfig returns http client config.
func (c Config) GetHTTPClientConfig() *HTTPClientConfig { func (c Config) GetHTTPClientConfig() *HTTPClientConfig {
return c.HTTPClientConfig return c.HTTPClientConfig
} }
// GetName transport name // GetName transport name.
func (t Info) GetName() string { func (t Info) GetName() string {
return t.Name return t.Name
} }
// GetCode transport code // GetCode transport code.
func (t Info) GetCode() string { func (t Info) GetCode() string {
return t.Code return t.Code
} }
// GetLogoPath transport logo // GetLogoPath transport logo.
func (t Info) GetLogoPath() string { func (t Info) GetLogoPath() string {
return t.LogoPath return t.LogoPath
} }
// IsSSLVerificationEnabled returns SSL verification flag (default is true) // IsSSLVerificationEnabled returns SSL verification flag (default is true).
func (h *HTTPClientConfig) IsSSLVerificationEnabled() bool { func (h *HTTPClientConfig) IsSSLVerificationEnabled() bool {
if h.SSLVerification == nil { if h.SSLVerification == nil {
return true return true

View File

@ -15,33 +15,33 @@ import (
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
) )
// CSRFErrorReason is a error reason type // CSRFErrorReason is a error reason type.
type CSRFErrorReason uint8 type CSRFErrorReason uint8
// CSRFTokenGetter func type // CSRFTokenGetter func type.
type CSRFTokenGetter func(*gin.Context) string type CSRFTokenGetter func(*gin.Context) string
// CSRFAbortFunc is a callback which // CSRFAbortFunc is a callback which.
type CSRFAbortFunc func(*gin.Context, CSRFErrorReason) type CSRFAbortFunc func(*gin.Context, CSRFErrorReason)
const ( const (
// CSRFErrorNoTokenInSession will be returned if token is not present in session // CSRFErrorNoTokenInSession will be returned if token is not present in session.
CSRFErrorNoTokenInSession CSRFErrorReason = iota CSRFErrorNoTokenInSession CSRFErrorReason = iota
// CSRFErrorCannotStoreTokenInSession will be returned if middleware cannot store token in session // CSRFErrorCannotStoreTokenInSession will be returned if middleware cannot store token in session.
CSRFErrorCannotStoreTokenInSession CSRFErrorCannotStoreTokenInSession
// CSRFErrorIncorrectTokenType will be returned if data type of token in session is not string // CSRFErrorIncorrectTokenType will be returned if data type of token in session is not string.
CSRFErrorIncorrectTokenType CSRFErrorIncorrectTokenType
// CSRFErrorEmptyToken will be returned if token in session is empty // CSRFErrorEmptyToken will be returned if token in session is empty.
CSRFErrorEmptyToken CSRFErrorEmptyToken
// CSRFErrorTokenMismatch will be returned in case of invalid token // CSRFErrorTokenMismatch will be returned in case of invalid token.
CSRFErrorTokenMismatch CSRFErrorTokenMismatch
) )
// DefaultCSRFTokenGetter default getter // DefaultCSRFTokenGetter default getter.
var DefaultCSRFTokenGetter = func(c *gin.Context) string { var DefaultCSRFTokenGetter = func(c *gin.Context) string {
r := c.Request r := c.Request
@ -65,7 +65,7 @@ var DefaultCSRFTokenGetter = func(c *gin.Context) string {
return "" return ""
} }
// DefaultIgnoredMethods ignored methods for CSRF verifier middleware // DefaultIgnoredMethods ignored methods for CSRF verifier middleware.
var DefaultIgnoredMethods = []string{"GET", "HEAD", "OPTIONS"} var DefaultIgnoredMethods = []string{"GET", "HEAD", "OPTIONS"}
// CSRF struct. Provides CSRF token verification. // CSRF struct. Provides CSRF token verification.
@ -124,7 +124,7 @@ func NewCSRF(salt, secret, sessionName string, store sessions.Store, abortFunc C
return csrf return csrf
} }
// strInSlice checks whether string exists in slice // strInSlice checks whether string exists in slice.
func (x *CSRF) strInSlice(slice []string, v string) bool { func (x *CSRF) strInSlice(slice []string, v string) bool {
exists := false exists := false
@ -138,7 +138,7 @@ func (x *CSRF) strInSlice(slice []string, v string) bool {
return exists return exists
} }
// generateCSRFToken generates new CSRF token // generateCSRFToken generates new CSRF token.
func (x *CSRF) generateCSRFToken() string { func (x *CSRF) generateCSRFToken() string {
// nolint:gosec // nolint:gosec
h := sha1.New() h := sha1.New()
@ -166,7 +166,7 @@ func (x *CSRF) generateSalt() string {
return string(salt) return string(salt)
} }
// pseudoRandomString generates pseudo-random string with specified length // pseudoRandomString generates pseudo-random string with specified length.
func (x *CSRF) pseudoRandomString(length int) string { func (x *CSRF) pseudoRandomString(length int) string {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
data := make([]byte, length) data := make([]byte, length)
@ -217,7 +217,7 @@ func (x *CSRF) GenerateCSRFMiddleware() gin.HandlerFunc {
} }
} }
// fillToken stores token in session and context // fillToken stores token in session and context.
func (x *CSRF) fillToken(s *sessions.Session, c *gin.Context) error { func (x *CSRF) fillToken(s *sessions.Session, c *gin.Context) error {
s.Values["csrf_token"] = x.generateCSRFToken() s.Values["csrf_token"] = x.generateCSRFToken()
c.Set("csrf_token", s.Values["csrf_token"]) c.Set("csrf_token", s.Values["csrf_token"])
@ -265,7 +265,7 @@ func (x *CSRF) VerifyCSRFMiddleware(ignoredMethods []string) gin.HandlerFunc {
} }
} }
// GetCSRFErrorMessage returns generic error message for CSRFErrorReason in English (useful for logs) // GetCSRFErrorMessage returns generic error message for CSRFErrorReason in English (useful for logs).
func GetCSRFErrorMessage(r CSRFErrorReason) string { func GetCSRFErrorMessage(r CSRFErrorReason) string {
switch r { switch r {
case CSRFErrorNoTokenInSession: case CSRFErrorNoTokenInSession:

View File

@ -23,7 +23,7 @@ var DefaultHTTPClientConfig = &HTTPClientConfig{
SSLVerification: &boolTrue, SSLVerification: &boolTrue,
} }
// Engine struct // Engine struct.
type Engine struct { type Engine struct {
Localizer Localizer
ORM ORM
@ -42,7 +42,8 @@ type Engine struct {
prepared bool prepared bool
} }
// New Engine instance (must be configured manually, gin can be accessed via engine.Router() directly or engine.ConfigureRouter(...) with callback) // New Engine instance (must be configured manually, gin can be accessed via engine.Router() directly or
// engine.ConfigureRouter(...) with callback).
func New() *Engine { func New() *Engine {
return &Engine{ return &Engine{
Config: nil, Config: nil,
@ -77,7 +78,7 @@ func (e *Engine) initGin() {
e.ginEngine = r e.ginEngine = r
} }
// Prepare engine for start // Prepare engine for start.
func (e *Engine) Prepare() *Engine { func (e *Engine) Prepare() *Engine {
if e.prepared { if e.prepared {
panic("engine already initialized") panic("engine already initialized")
@ -119,7 +120,7 @@ func (e *Engine) Prepare() *Engine {
return e return e
} }
// TemplateFuncMap combines func map for templates // TemplateFuncMap combines func map for templates.
func (e *Engine) TemplateFuncMap(functions template.FuncMap) template.FuncMap { func (e *Engine) TemplateFuncMap(functions template.FuncMap) template.FuncMap {
funcMap := e.LocalizationFuncMap() funcMap := e.LocalizationFuncMap()
@ -134,14 +135,14 @@ func (e *Engine) TemplateFuncMap(functions template.FuncMap) template.FuncMap {
return funcMap return funcMap
} }
// CreateRenderer with translation function // CreateRenderer with translation function.
func (e *Engine) CreateRenderer(callback func(*Renderer), funcs template.FuncMap) Renderer { func (e *Engine) CreateRenderer(callback func(*Renderer), funcs template.FuncMap) Renderer {
renderer := NewRenderer(e.TemplateFuncMap(funcs)) renderer := NewRenderer(e.TemplateFuncMap(funcs))
callback(&renderer) callback(&renderer)
return renderer return renderer
} }
// CreateRendererFS with translation function and packr box with templates data // CreateRendererFS with translation function and packr box with templates data.
func (e *Engine) CreateRendererFS(box *packr.Box, callback func(*Renderer), funcs template.FuncMap) Renderer { func (e *Engine) CreateRendererFS(box *packr.Box, callback func(*Renderer), funcs template.FuncMap) Renderer {
renderer := NewRenderer(e.TemplateFuncMap(funcs)) renderer := NewRenderer(e.TemplateFuncMap(funcs))
renderer.TemplatesBox = box renderer.TemplatesBox = box
@ -149,7 +150,7 @@ func (e *Engine) CreateRendererFS(box *packr.Box, callback func(*Renderer), func
return renderer return renderer
} }
// Router will return current gin.Engine or panic if it's not present // Router will return current gin.Engine or panic if it's not present.
func (e *Engine) Router() *gin.Engine { func (e *Engine) Router() *gin.Engine {
if !e.prepared { if !e.prepared {
panic("prepare engine first") panic("prepare engine first")
@ -161,7 +162,7 @@ func (e *Engine) Router() *gin.Engine {
return e.ginEngine return e.ginEngine
} }
// JobManager will return singleton JobManager from Engine // JobManager will return singleton JobManager from Engine.
func (e *Engine) JobManager() *JobManager { func (e *Engine) JobManager() *JobManager {
if e.jobManager == nil { if e.jobManager == nil {
e.jobManager = NewJobManager().SetLogger(e.Logger()).SetLogging(e.Config.IsDebug()) e.jobManager = NewJobManager().SetLogger(e.Logger()).SetLogging(e.Config.IsDebug())
@ -170,12 +171,12 @@ func (e *Engine) JobManager() *JobManager {
return e.jobManager return e.jobManager
} }
// Logger returns current logger // Logger returns current logger.
func (e *Engine) Logger() LoggerInterface { func (e *Engine) Logger() LoggerInterface {
return e.logger return e.logger
} }
// SetLogger sets provided logger instance to engine // SetLogger sets provided logger instance to engine.
func (e *Engine) SetLogger(l LoggerInterface) *Engine { func (e *Engine) SetLogger(l LoggerInterface) *Engine {
if l == nil { if l == nil {
return e return e
@ -187,7 +188,7 @@ func (e *Engine) SetLogger(l LoggerInterface) *Engine {
return e return e
} }
// BuildHTTPClient builds HTTP client with provided configuration // BuildHTTPClient builds HTTP client with provided configuration.
func (e *Engine) BuildHTTPClient(certs *x509.CertPool, replaceDefault ...bool) *Engine { func (e *Engine) BuildHTTPClient(certs *x509.CertPool, replaceDefault ...bool) *Engine {
client, err := NewHTTPClientBuilder(). client, err := NewHTTPClientBuilder().
WithLogger(e.Logger()). WithLogger(e.Logger()).
@ -205,7 +206,7 @@ func (e *Engine) BuildHTTPClient(certs *x509.CertPool, replaceDefault ...bool) *
return e return e
} }
// GetHTTPClientConfig returns configuration for HTTP client // GetHTTPClientConfig returns configuration for HTTP client.
func (e *Engine) GetHTTPClientConfig() *HTTPClientConfig { func (e *Engine) GetHTTPClientConfig() *HTTPClientConfig {
if e.Config.GetHTTPClientConfig() != nil { if e.Config.GetHTTPClientConfig() != nil {
return e.Config.GetHTTPClientConfig() return e.Config.GetHTTPClientConfig()
@ -214,7 +215,7 @@ func (e *Engine) GetHTTPClientConfig() *HTTPClientConfig {
return DefaultHTTPClientConfig return DefaultHTTPClientConfig
} }
// SetHTTPClient sets HTTP client to engine // SetHTTPClient sets HTTP client to engine.
func (e *Engine) SetHTTPClient(client *http.Client) *Engine { func (e *Engine) SetHTTPClient(client *http.Client) *Engine {
if client != nil { if client != nil {
e.httpClient = client e.httpClient = client
@ -223,7 +224,7 @@ func (e *Engine) SetHTTPClient(client *http.Client) *Engine {
return e return e
} }
// HTTPClient returns inner http client or default http client // HTTPClient returns inner http client or default http client.
func (e *Engine) HTTPClient() *http.Client { func (e *Engine) HTTPClient() *http.Client {
if e.httpClient == nil { if e.httpClient == nil {
return http.DefaultClient return http.DefaultClient
@ -292,7 +293,7 @@ func (e *Engine) GenerateCSRFMiddleware() gin.HandlerFunc {
return e.csrf.GenerateCSRFMiddleware() return e.csrf.GenerateCSRFMiddleware()
} }
// GetCSRFToken returns CSRF token from provided context // GetCSRFToken returns CSRF token from provided context.
func (e *Engine) GetCSRFToken(c *gin.Context) string { func (e *Engine) GetCSRFToken(c *gin.Context) string {
if e.csrf == nil { if e.csrf == nil {
panic("csrf is not initialized") panic("csrf is not initialized")
@ -301,13 +302,13 @@ func (e *Engine) GetCSRFToken(c *gin.Context) string {
return e.csrf.CSRFFromContext(c) return e.csrf.CSRFFromContext(c)
} }
// ConfigureRouter will call provided callback with current gin.Engine, or panic if engine is not present // ConfigureRouter will call provided callback with current gin.Engine, or panic if engine is not present.
func (e *Engine) ConfigureRouter(callback func(*gin.Engine)) *Engine { func (e *Engine) ConfigureRouter(callback func(*gin.Engine)) *Engine {
callback(e.Router()) callback(e.Router())
return e return e
} }
// Run gin.Engine loop, or panic if engine is not present // Run gin.Engine loop, or panic if engine is not present.
func (e *Engine) Run() error { func (e *Engine) Run() error {
return e.Router().Run(e.Config.GetHTTPConfig().Listen) return e.Router().Run(e.Config.GetHTTPConfig().Listen)
} }

View File

@ -2,12 +2,12 @@ package core
import "net/http" import "net/http"
// ErrorResponse struct // ErrorResponse struct.
type ErrorResponse struct { type ErrorResponse struct {
Error string `json:"error"` Error string `json:"error"`
} }
// ErrorsResponse struct // ErrorsResponse struct.
type ErrorsResponse struct { type ErrorsResponse struct {
Error []string `json:"error"` Error []string `json:"error"`
} }

View File

@ -12,10 +12,10 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// DefaultClient stores original http.DefaultClient // DefaultClient stores original http.DefaultClient.
var DefaultClient = http.DefaultClient var DefaultClient = http.DefaultClient
// DefaultTransport stores original http.DefaultTransport // DefaultTransport stores original http.DefaultTransport.
var DefaultTransport = http.DefaultTransport var DefaultTransport = http.DefaultTransport
// HTTPClientBuilder builds http client with mocks (if necessary) and timeout. // HTTPClientBuilder builds http client with mocks (if necessary) and timeout.
@ -57,7 +57,7 @@ type HTTPClientBuilder struct {
mockedDomains []string mockedDomains []string
} }
// NewHTTPClientBuilder returns HTTPClientBuilder with default values // NewHTTPClientBuilder returns HTTPClientBuilder with default values.
func NewHTTPClientBuilder() *HTTPClientBuilder { func NewHTTPClientBuilder() *HTTPClientBuilder {
return &HTTPClientBuilder{ return &HTTPClientBuilder{
built: false, built: false,
@ -70,7 +70,7 @@ func NewHTTPClientBuilder() *HTTPClientBuilder {
} }
} }
// WithLogger sets provided logger into HTTPClientBuilder // WithLogger sets provided logger into HTTPClientBuilder.
func (b *HTTPClientBuilder) WithLogger(logger LoggerInterface) *HTTPClientBuilder { func (b *HTTPClientBuilder) WithLogger(logger LoggerInterface) *HTTPClientBuilder {
if logger != nil { if logger != nil {
b.logger = logger b.logger = logger
@ -79,7 +79,7 @@ func (b *HTTPClientBuilder) WithLogger(logger LoggerInterface) *HTTPClientBuilde
return b return b
} }
// SetTimeout sets timeout for http client // SetTimeout sets timeout for http client.
func (b *HTTPClientBuilder) SetTimeout(seconds time.Duration) *HTTPClientBuilder { func (b *HTTPClientBuilder) SetTimeout(seconds time.Duration) *HTTPClientBuilder {
seconds = seconds * time.Second seconds = seconds * time.Second
b.timeout = seconds b.timeout = seconds
@ -87,25 +87,25 @@ func (b *HTTPClientBuilder) SetTimeout(seconds time.Duration) *HTTPClientBuilder
return b return b
} }
// SetMockAddress sets mock address // SetMockAddress sets mock address.
func (b *HTTPClientBuilder) SetMockAddress(address string) *HTTPClientBuilder { func (b *HTTPClientBuilder) SetMockAddress(address string) *HTTPClientBuilder {
b.mockAddress = address b.mockAddress = address
return b return b
} }
// AddMockedDomain adds new mocked domain // AddMockedDomain adds new mocked domain.
func (b *HTTPClientBuilder) AddMockedDomain(domain string) *HTTPClientBuilder { func (b *HTTPClientBuilder) AddMockedDomain(domain string) *HTTPClientBuilder {
b.mockedDomains = append(b.mockedDomains, domain) b.mockedDomains = append(b.mockedDomains, domain)
return b return b
} }
// SetMockedDomains sets mocked domains from slice // SetMockedDomains sets mocked domains from slice.
func (b *HTTPClientBuilder) SetMockedDomains(domains []string) *HTTPClientBuilder { func (b *HTTPClientBuilder) SetMockedDomains(domains []string) *HTTPClientBuilder {
b.mockedDomains = domains b.mockedDomains = domains
return b return b
} }
// SetSSLVerification enables or disables SSL certificates verification in client // SetSSLVerification enables or disables SSL certificates verification in client.
func (b *HTTPClientBuilder) SetSSLVerification(enabled bool) *HTTPClientBuilder { func (b *HTTPClientBuilder) SetSSLVerification(enabled bool) *HTTPClientBuilder {
if b.httpTransport.TLSClientConfig == nil { if b.httpTransport.TLSClientConfig == nil {
b.httpTransport.TLSClientConfig = &tls.Config{} b.httpTransport.TLSClientConfig = &tls.Config{}
@ -116,7 +116,7 @@ func (b *HTTPClientBuilder) SetSSLVerification(enabled bool) *HTTPClientBuilder
return b return b
} }
// SetSSLVerification enables or disables SSL certificates verification in client // SetSSLVerification enables or disables SSL certificates verification in client.
func (b *HTTPClientBuilder) SetCertPool(pool *x509.CertPool) *HTTPClientBuilder { func (b *HTTPClientBuilder) SetCertPool(pool *x509.CertPool) *HTTPClientBuilder {
if b.httpTransport.TLSClientConfig == nil { if b.httpTransport.TLSClientConfig == nil {
b.httpTransport.TLSClientConfig = &tls.Config{} b.httpTransport.TLSClientConfig = &tls.Config{}
@ -127,13 +127,13 @@ func (b *HTTPClientBuilder) SetCertPool(pool *x509.CertPool) *HTTPClientBuilder
return b return b
} }
// SetLogging enables or disables logging in mocks // SetLogging enables or disables logging in mocks.
func (b *HTTPClientBuilder) SetLogging(flag bool) *HTTPClientBuilder { func (b *HTTPClientBuilder) SetLogging(flag bool) *HTTPClientBuilder {
b.logging = flag b.logging = flag
return b return b
} }
// FromConfig fulfills mock configuration from HTTPClientConfig // FromConfig fulfills mock configuration from HTTPClientConfig.
func (b *HTTPClientBuilder) FromConfig(config *HTTPClientConfig) *HTTPClientBuilder { func (b *HTTPClientBuilder) FromConfig(config *HTTPClientConfig) *HTTPClientBuilder {
if config == nil { if config == nil {
return b return b
@ -153,12 +153,12 @@ func (b *HTTPClientBuilder) FromConfig(config *HTTPClientConfig) *HTTPClientBuil
return b return b
} }
// FromEngine fulfills mock configuration from ConfigInterface inside Engine // FromEngine fulfills mock configuration from ConfigInterface inside Engine.
func (b *HTTPClientBuilder) FromEngine(engine *Engine) *HTTPClientBuilder { func (b *HTTPClientBuilder) FromEngine(engine *Engine) *HTTPClientBuilder {
return b.FromConfig(engine.GetHTTPClientConfig()) return b.FromConfig(engine.GetHTTPClientConfig())
} }
// buildDialer initializes dialer with provided timeout // buildDialer initializes dialer with provided timeout.
func (b *HTTPClientBuilder) buildDialer() *HTTPClientBuilder { func (b *HTTPClientBuilder) buildDialer() *HTTPClientBuilder {
b.dialer = &net.Dialer{ b.dialer = &net.Dialer{
Timeout: b.timeout, Timeout: b.timeout,
@ -168,7 +168,7 @@ func (b *HTTPClientBuilder) buildDialer() *HTTPClientBuilder {
return b return b
} }
// parseAddress parses address and returns error in case of error (port is necessary) // parseAddress parses address and returns error in case of error (port is necessary).
func (b *HTTPClientBuilder) parseAddress() error { func (b *HTTPClientBuilder) parseAddress() error {
if b.mockAddress == "" { if b.mockAddress == "" {
return nil return nil
@ -184,7 +184,7 @@ func (b *HTTPClientBuilder) parseAddress() error {
return nil return nil
} }
// buildMocks builds mocks for http client // buildMocks builds mocks for http client.
func (b *HTTPClientBuilder) buildMocks() error { func (b *HTTPClientBuilder) buildMocks() error {
if b.dialer == nil { if b.dialer == nil {
return errors.New("dialer must be built first") return errors.New("dialer must be built first")
@ -229,7 +229,7 @@ func (b *HTTPClientBuilder) buildMocks() error {
return nil return nil
} }
// logf prints logs via Engine or via fmt.Printf // logf prints logs via Engine or via fmt.Printf.
func (b *HTTPClientBuilder) logf(format string, args ...interface{}) { func (b *HTTPClientBuilder) logf(format string, args ...interface{}) {
if b.logging { if b.logging {
if b.logger != nil { if b.logger != nil {
@ -240,7 +240,7 @@ func (b *HTTPClientBuilder) logf(format string, args ...interface{}) {
} }
} }
// ReplaceDefault replaces default client and transport with generated ones // ReplaceDefault replaces default client and transport with generated ones.
func (b *HTTPClientBuilder) ReplaceDefault() *HTTPClientBuilder { func (b *HTTPClientBuilder) ReplaceDefault() *HTTPClientBuilder {
if b.built { if b.built {
http.DefaultClient = b.httpClient http.DefaultClient = b.httpClient
@ -250,7 +250,7 @@ func (b *HTTPClientBuilder) ReplaceDefault() *HTTPClientBuilder {
return b return b
} }
// RestoreDefault restores default client and transport after replacement // RestoreDefault restores default client and transport after replacement.
func (b *HTTPClientBuilder) RestoreDefault() *HTTPClientBuilder { func (b *HTTPClientBuilder) RestoreDefault() *HTTPClientBuilder {
http.DefaultClient = DefaultClient http.DefaultClient = DefaultClient
http.DefaultTransport = DefaultTransport http.DefaultTransport = DefaultTransport
@ -258,7 +258,7 @@ func (b *HTTPClientBuilder) RestoreDefault() *HTTPClientBuilder {
return b return b
} }
// Build builds client, pass true to replace http.DefaultClient with generated one // Build builds client, pass true to replace http.DefaultClient with generated one.
func (b *HTTPClientBuilder) Build(replaceDefault ...bool) (*http.Client, error) { func (b *HTTPClientBuilder) Build(replaceDefault ...bool) (*http.Client, error) {
if err := b.buildDialer().parseAddress(); err != nil { if err := b.buildDialer().parseAddress(); err != nil {
return nil, err return nil, err

View File

@ -9,10 +9,10 @@ import (
"github.com/op/go-logging" "github.com/op/go-logging"
) )
// JobFunc is empty func which should be executed in a parallel goroutine // JobFunc is empty func which should be executed in a parallel goroutine.
type JobFunc func(JobLogFunc) error type JobFunc func(JobLogFunc) error
// JobLogFunc is a function which logs data from job // JobLogFunc is a function which logs data from job.
type JobLogFunc func(string, logging.Level, ...interface{}) type JobLogFunc func(string, logging.Level, ...interface{})
// JobErrorHandler is a function to handle jobs errors. First argument is a job name. // JobErrorHandler is a function to handle jobs errors. First argument is a job name.
@ -56,7 +56,7 @@ type JobManager struct {
logger LoggerInterface logger LoggerInterface
} }
// getWrappedFunc wraps job into function // getWrappedFunc wraps job into function.
func (j *Job) getWrappedFunc(name string, log JobLogFunc) func() { func (j *Job) getWrappedFunc(name string, log JobLogFunc) func() {
return func() { return func() {
defer func() { defer func() {
@ -71,7 +71,7 @@ func (j *Job) getWrappedFunc(name string, log JobLogFunc) func() {
} }
} }
// getWrappedTimerFunc returns job timer func to run in the separate goroutine // getWrappedTimerFunc returns job timer func to run in the separate goroutine.
func (j *Job) getWrappedTimerFunc(name string, log JobLogFunc) func(chan bool) { func (j *Job) getWrappedTimerFunc(name string, log JobLogFunc) func(chan bool) {
return func(stopChannel chan bool) { return func(stopChannel chan bool) {
for range time.NewTicker(j.Interval).C { for range time.NewTicker(j.Interval).C {
@ -85,7 +85,7 @@ func (j *Job) getWrappedTimerFunc(name string, log JobLogFunc) func(chan bool) {
} }
} }
// run job // run job.
func (j *Job) run(name string, log JobLogFunc) *Job { func (j *Job) run(name string, log JobLogFunc) *Job {
j.writeLock.RLock() j.writeLock.RLock()
@ -104,7 +104,7 @@ func (j *Job) run(name string, log JobLogFunc) *Job {
return j return j
} }
// stop running job // stop running job.
func (j *Job) stop() *Job { func (j *Job) stop() *Job {
j.writeLock.RLock() j.writeLock.RLock()
@ -123,24 +123,24 @@ func (j *Job) stop() *Job {
return j return j
} }
// runOnce run job once // runOnce run job once.
func (j *Job) runOnce(name string, log JobLogFunc) *Job { func (j *Job) runOnce(name string, log JobLogFunc) *Job {
go j.getWrappedFunc(name, log)() go j.getWrappedFunc(name, log)()
return j return j
} }
// runOnceSync run job once in current goroutine // runOnceSync run job once in current goroutine.
func (j *Job) runOnceSync(name string, log JobLogFunc) *Job { func (j *Job) runOnceSync(name string, log JobLogFunc) *Job {
j.getWrappedFunc(name, log)() j.getWrappedFunc(name, log)()
return j return j
} }
// NewJobManager is a JobManager constructor // NewJobManager is a JobManager constructor.
func NewJobManager() *JobManager { func NewJobManager() *JobManager {
return &JobManager{jobs: &sync.Map{}} return &JobManager{jobs: &sync.Map{}}
} }
// DefaultJobErrorHandler returns default error handler for a job // DefaultJobErrorHandler returns default error handler for a job.
func DefaultJobErrorHandler() JobErrorHandler { func DefaultJobErrorHandler() JobErrorHandler {
return func(name string, err error, log JobLogFunc) { return func(name string, err error, log JobLogFunc) {
if err != nil && name != "" { if err != nil && name != "" {
@ -149,7 +149,7 @@ func DefaultJobErrorHandler() JobErrorHandler {
} }
} }
// DefaultJobPanicHandler returns default panic handler for a job // DefaultJobPanicHandler returns default panic handler for a job.
func DefaultJobPanicHandler() JobPanicHandler { func DefaultJobPanicHandler() JobPanicHandler {
return func(name string, recoverValue interface{}, log JobLogFunc) { return func(name string, recoverValue interface{}, log JobLogFunc) {
if recoverValue != nil && name != "" { if recoverValue != nil && name != "" {
@ -158,7 +158,7 @@ func DefaultJobPanicHandler() JobPanicHandler {
} }
} }
// SetLogger sets logger into JobManager // SetLogger sets logger into JobManager.
func (j *JobManager) SetLogger(logger LoggerInterface) *JobManager { func (j *JobManager) SetLogger(logger LoggerInterface) *JobManager {
if logger != nil { if logger != nil {
j.logger = logger j.logger = logger
@ -167,13 +167,13 @@ func (j *JobManager) SetLogger(logger LoggerInterface) *JobManager {
return j return j
} }
// SetLogging enables or disables JobManager logging // SetLogging enables or disables JobManager logging.
func (j *JobManager) SetLogging(enableLogging bool) *JobManager { func (j *JobManager) SetLogging(enableLogging bool) *JobManager {
j.enableLogging = enableLogging j.enableLogging = enableLogging
return j return j
} }
// RegisterJob registers new job // RegisterJob registers new job.
func (j *JobManager) RegisterJob(name string, job *Job) error { func (j *JobManager) RegisterJob(name string, job *Job) error {
if job == nil { if job == nil {
return errors.New("job shouldn't be nil") return errors.New("job shouldn't be nil")
@ -198,7 +198,7 @@ func (j *JobManager) UnregisterJob(name string) error {
return fmt.Errorf("cannot find job `%s`", name) return fmt.Errorf("cannot find job `%s`", name)
} }
// FetchJob fetches already exist job // FetchJob fetches already exist job.
func (j *JobManager) FetchJob(name string) (value *Job, ok bool) { func (j *JobManager) FetchJob(name string) (value *Job, ok bool) {
if i, ok := j.jobs.Load(name); ok { if i, ok := j.jobs.Load(name); ok {
if job, ok := i.(*Job); ok { if job, ok := i.(*Job); ok {
@ -209,7 +209,7 @@ func (j *JobManager) FetchJob(name string) (value *Job, ok bool) {
return &Job{}, false return &Job{}, false
} }
// UpdateJob updates job // UpdateJob updates job.
func (j *JobManager) UpdateJob(name string, job *Job) error { func (j *JobManager) UpdateJob(name string, job *Job) error {
if job, ok := j.FetchJob(name); ok { if job, ok := j.FetchJob(name); ok {
_ = j.UnregisterJob(name) _ = j.UnregisterJob(name)
@ -259,7 +259,7 @@ func (j *JobManager) RunJobOnceSync(name string) error {
return fmt.Errorf("cannot find job `%s`", name) return fmt.Errorf("cannot find job `%s`", name)
} }
// Start all jobs in the manager // Start all jobs in the manager.
func (j *JobManager) Start() { func (j *JobManager) Start() {
j.jobs.Range(func(key, value interface{}) bool { j.jobs.Range(func(key, value interface{}) bool {
name := key.(string) name := key.(string)
@ -269,7 +269,7 @@ func (j *JobManager) Start() {
}) })
} }
// log logs via logger or as plaintext // log logs via logger or as plaintext.
func (j *JobManager) log(format string, severity logging.Level, args ...interface{}) { func (j *JobManager) log(format string, severity logging.Level, args ...interface{}) {
if !j.enableLogging { if !j.enableLogging {
return return

View File

@ -14,20 +14,20 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
// DefaultLanguages for transports // DefaultLanguages for transports.
var DefaultLanguages = []language.Tag{ var DefaultLanguages = []language.Tag{
language.English, language.English,
language.Russian, language.Russian,
language.Spanish, language.Spanish,
} }
// DefaultLanguage is a base language which will be chosen if current language is unspecified // DefaultLanguage is a base language which will be chosen if current language is unspecified.
var DefaultLanguage = language.English var DefaultLanguage = language.English
// LocalizerContextKey is a key which is used to store localizer in gin.Context key-value storage // LocalizerContextKey is a key which is used to store localizer in gin.Context key-value storage.
const LocalizerContextKey = "localizer" const LocalizerContextKey = "localizer"
// Localizer struct // Localizer struct.
type Localizer struct { type Localizer struct {
i18nStorage *sync.Map i18nStorage *sync.Map
TranslationsBox *packr.Box TranslationsBox *packr.Box
@ -70,17 +70,17 @@ func NewLocalizerFS(locale language.Tag, matcher language.Matcher, translationsB
return localizer return localizer
} }
// DefaultLocalizerBundle returns new localizer bundle with English as default language // DefaultLocalizerBundle returns new localizer bundle with English as default language.
func DefaultLocalizerBundle() *i18n.Bundle { func DefaultLocalizerBundle() *i18n.Bundle {
return i18n.NewBundle(DefaultLanguage) return i18n.NewBundle(DefaultLanguage)
} }
// LocalizerBundle returns new localizer bundle provided language as default // LocalizerBundle returns new localizer bundle provided language as default.
func LocalizerBundle(tag language.Tag) *i18n.Bundle { func LocalizerBundle(tag language.Tag) *i18n.Bundle {
return i18n.NewBundle(tag) return i18n.NewBundle(tag)
} }
// DefaultLocalizerMatcher returns matcher with English, Russian and Spanish tags // DefaultLocalizerMatcher returns matcher with English, Russian and Spanish tags.
func DefaultLocalizerMatcher() language.Matcher { func DefaultLocalizerMatcher() language.Matcher {
return language.NewMatcher(DefaultLanguages) return language.NewMatcher(DefaultLanguages)
} }
@ -137,12 +137,12 @@ func (l *Localizer) LocalizationFuncMap() template.FuncMap {
} }
} }
// getLocaleBundle returns current locale bundle and creates it if needed // getLocaleBundle returns current locale bundle and creates it if needed.
func (l *Localizer) getLocaleBundle() *i18n.Bundle { func (l *Localizer) getLocaleBundle() *i18n.Bundle {
return l.createLocaleBundleByTag(l.LanguageTag) return l.createLocaleBundleByTag(l.LanguageTag)
} }
// createLocaleBundleByTag creates locale bundle by language tag // createLocaleBundleByTag creates locale bundle by language tag.
func (l *Localizer) createLocaleBundleByTag(tag language.Tag) *i18n.Bundle { func (l *Localizer) createLocaleBundleByTag(tag language.Tag) *i18n.Bundle {
bundle := i18n.NewBundle(tag) bundle := i18n.NewBundle(tag)
bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal) bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal)
@ -151,14 +151,14 @@ func (l *Localizer) createLocaleBundleByTag(tag language.Tag) *i18n.Bundle {
return bundle return bundle
} }
// LoadTranslations will load all translation files from translations directory or from embedded box // LoadTranslations will load all translation files from translations directory or from embedded box.
func (l *Localizer) LoadTranslations() { func (l *Localizer) LoadTranslations() {
defer l.loadMutex.Unlock() defer l.loadMutex.Unlock()
l.loadMutex.Lock() l.loadMutex.Lock()
l.getCurrentLocalizer() l.getCurrentLocalizer()
} }
// loadTranslationsToBundle loads translations to provided bundle // loadTranslationsToBundle loads translations to provided bundle.
func (l *Localizer) loadTranslationsToBundle(i18nBundle *i18n.Bundle) { func (l *Localizer) loadTranslationsToBundle(i18nBundle *i18n.Bundle) {
switch { switch {
case l.TranslationsPath != "": case l.TranslationsPath != "":
@ -174,7 +174,7 @@ func (l *Localizer) loadTranslationsToBundle(i18nBundle *i18n.Bundle) {
} }
} }
// LoadTranslations will load all translation files from translations directory // LoadTranslations will load all translation files from translations directory.
func (l *Localizer) loadFromDirectory(i18nBundle *i18n.Bundle) error { func (l *Localizer) loadFromDirectory(i18nBundle *i18n.Bundle) error {
files, err := ioutil.ReadDir(l.TranslationsPath) files, err := ioutil.ReadDir(l.TranslationsPath)
if err != nil { if err != nil {
@ -190,7 +190,7 @@ func (l *Localizer) loadFromDirectory(i18nBundle *i18n.Bundle) error {
return nil return nil
} }
// LoadTranslations will load all translation files from embedded box // LoadTranslations will load all translation files from embedded box.
func (l *Localizer) loadFromFS(i18nBundle *i18n.Bundle) error { func (l *Localizer) loadFromFS(i18nBundle *i18n.Bundle) error {
err := l.TranslationsBox.Walk(func(s string, file packd.File) error { err := l.TranslationsBox.Walk(func(s string, file packd.File) error {
if fileInfo, err := file.FileInfo(); err == nil { if fileInfo, err := file.FileInfo(); err == nil {
@ -217,7 +217,7 @@ func (l *Localizer) loadFromFS(i18nBundle *i18n.Bundle) error {
return nil return nil
} }
// getLocalizer returns *i18n.Localizer with provided language tag. It will be created if not exist // getLocalizer returns *i18n.Localizer with provided language tag. It will be created if not exist.
func (l *Localizer) getLocalizer(tag language.Tag) *i18n.Localizer { func (l *Localizer) getLocalizer(tag language.Tag) *i18n.Localizer {
var localizer *i18n.Localizer var localizer *i18n.Localizer
@ -247,24 +247,24 @@ func (l *Localizer) isUnd(tag language.Tag) bool {
return tag == language.Und || tag.IsRoot() return tag == language.Und || tag.IsRoot()
} }
// getCurrentLocalizer returns *i18n.Localizer with current language tag // getCurrentLocalizer returns *i18n.Localizer with current language tag.
func (l *Localizer) getCurrentLocalizer() *i18n.Localizer { func (l *Localizer) getCurrentLocalizer() *i18n.Localizer {
return l.getLocalizer(l.LanguageTag) return l.getLocalizer(l.LanguageTag)
} }
// SetLocale will change language for current localizer // SetLocale will change language for current localizer.
func (l *Localizer) SetLocale(al string) { func (l *Localizer) SetLocale(al string) {
l.SetLanguage(l.matchByString(al)) l.SetLanguage(l.matchByString(al))
} }
// Preload provided languages (so they will not be loaded every time in middleware) // Preload provided languages (so they will not be loaded every time in middleware).
func (l *Localizer) Preload(tags []language.Tag) { func (l *Localizer) Preload(tags []language.Tag) {
for _, tag := range tags { for _, tag := range tags {
l.getLocalizer(tag) l.getLocalizer(tag)
} }
} }
// SetLanguage will change language using language tag // SetLanguage will change language using language tag.
func (l *Localizer) SetLanguage(tag language.Tag) { func (l *Localizer) SetLanguage(tag language.Tag) {
if l.isUnd(tag) { if l.isUnd(tag) {
tag = DefaultLanguage tag = DefaultLanguage
@ -276,7 +276,7 @@ func (l *Localizer) SetLanguage(tag language.Tag) {
// FetchLanguage will load language from tag // FetchLanguage will load language from tag
// //
// Deprecated: Use `(*core.Localizer).LoadTranslations()` instead // Deprecated: Use `(*core.Localizer).LoadTranslations()` instead.
func (l *Localizer) FetchLanguage() { func (l *Localizer) FetchLanguage() {
l.LoadTranslations() l.LoadTranslations()
} }
@ -295,7 +295,7 @@ func (l *Localizer) GetLocalizedTemplateMessage(messageID string, templateData m
}) })
} }
// Localize will return localized message by it's ID, or error if message wasn't found // Localize will return localized message by it's ID, or error if message wasn't found.
func (l *Localizer) Localize(messageID string) (string, error) { func (l *Localizer) Localize(messageID string) (string, error) {
return l.getCurrentLocalizer().Localize(&i18n.LocalizeConfig{MessageID: messageID}) return l.getCurrentLocalizer().Localize(&i18n.LocalizeConfig{MessageID: messageID})
} }
@ -309,12 +309,12 @@ func (l *Localizer) LocalizeTemplateMessage(messageID string, templateData map[s
}) })
} }
// BadRequestLocalized is same as BadRequest(string), but passed string will be localized // BadRequestLocalized is same as BadRequest(string), but passed string will be localized.
func (l *Localizer) BadRequestLocalized(err string) (int, interface{}) { func (l *Localizer) BadRequestLocalized(err string) (int, interface{}) {
return BadRequest(l.GetLocalizedMessage(err)) return BadRequest(l.GetLocalizedMessage(err))
} }
// GetContextLocalizer returns localizer from context if it exist there // GetContextLocalizer returns localizer from context if it exist there.
func GetContextLocalizer(c *gin.Context) (*Localizer, bool) { func GetContextLocalizer(c *gin.Context) (*Localizer, bool) {
if c == nil { if c == nil {
return nil, false return nil, false

View File

@ -186,7 +186,7 @@ func (l *LocalizerTest) Test_BadRequestLocalized() {
assert.Equal(l.T(), "Test message", resp.(ErrorResponse).Error) assert.Equal(l.T(), "Test message", resp.(ErrorResponse).Error)
} }
// getContextWithLang generates context with Accept-Language header // getContextWithLang generates context with Accept-Language header.
func (l *LocalizerTest) getContextWithLang(tag language.Tag) *gin.Context { func (l *LocalizerTest) getContextWithLang(tag language.Tag) *gin.Context {
urlInstance, _ := url.Parse("https://example.com") urlInstance, _ := url.Parse("https://example.com")
headers := http.Header{} headers := http.Header{}

View File

@ -7,7 +7,7 @@ import (
"github.com/op/go-logging" "github.com/op/go-logging"
) )
// LoggerInterface contains methods which should be present in logger implementation // LoggerInterface contains methods which should be present in logger implementation.
type LoggerInterface interface { type LoggerInterface interface {
Fatal(args ...interface{}) Fatal(args ...interface{})
Fatalf(format string, args ...interface{}) Fatalf(format string, args ...interface{})
@ -28,7 +28,7 @@ type LoggerInterface interface {
} }
// Logger component. Uses github.com/op/go-logging under the hood. // Logger component. Uses github.com/op/go-logging under the hood.
// This logger can prevent any write operations (disabled by default, use .Exclusive() method to enable) // This logger can prevent any write operations (disabled by default, use .Exclusive() method to enable).
type Logger struct { type Logger struct {
logger *logging.Logger logger *logging.Logger
mutex *sync.RWMutex mutex *sync.RWMutex
@ -55,14 +55,14 @@ func newInheritedLogger(transportCode string, logLevel logging.Level, logFormat
return logger return logger
} }
// DefaultLogFormatter will return default formatter for logs // DefaultLogFormatter will return default formatter for logs.
func DefaultLogFormatter() logging.Formatter { func DefaultLogFormatter() logging.Formatter {
return logging.MustStringFormatter( return logging.MustStringFormatter(
`%{time:2006-01-02 15:04:05.000} %{level:.4s} => %{message}`, `%{time:2006-01-02 15:04:05.000} %{level:.4s} => %{message}`,
) )
} }
// Exclusive makes logger goroutine-safe // Exclusive makes logger goroutine-safe.
func (l *Logger) Exclusive() *Logger { func (l *Logger) Exclusive() *Logger {
if l.mutex == nil { if l.mutex == nil {
l.mutex = &sync.RWMutex{} l.mutex = &sync.RWMutex{}
@ -71,14 +71,14 @@ func (l *Logger) Exclusive() *Logger {
return l return l
} }
// lock locks logger // lock locks logger.
func (l *Logger) lock() { func (l *Logger) lock() {
if l.mutex != nil { if l.mutex != nil {
l.mutex.Lock() l.mutex.Lock()
} }
} }
// unlock unlocks logger // unlock unlocks logger.
func (l *Logger) unlock() { func (l *Logger) unlock() {
if l.mutex != nil { if l.mutex != nil {
l.mutex.Unlock() l.mutex.Unlock()

View File

@ -2,7 +2,7 @@ package core
import ( import (
// "os" // "os"
// "os/exec" // "os/exec".
"testing" "testing"
"github.com/op/go-logging" "github.com/op/go-logging"

View File

@ -9,10 +9,10 @@ import (
"gopkg.in/gormigrate.v1" "gopkg.in/gormigrate.v1"
) )
// migrations default GORMigrate tool // migrations default GORMigrate tool.
var migrations *Migrate var migrations *Migrate
// Migrate tool, decorates gormigrate.Migration in order to provide better interface & versioning // Migrate tool, decorates gormigrate.Migration in order to provide better interface & versioning.
type Migrate struct { type Migrate struct {
db *gorm.DB db *gorm.DB
first *gormigrate.Migration first *gormigrate.Migration
@ -22,17 +22,17 @@ type Migrate struct {
prepared bool prepared bool
} }
// MigrationInfo with migration info // MigrationInfo with migration info.
type MigrationInfo struct { type MigrationInfo struct {
ID string `gorm:"column:id; type:varchar(255)"` ID string `gorm:"column:id; type:varchar(255)"`
} }
// TableName for MigrationInfo // TableName for MigrationInfo.
func (MigrationInfo) TableName() string { func (MigrationInfo) TableName() string {
return "migrations" return "migrations"
} }
// Migrations returns default migrate // Migrations returns default migrate.
func Migrations() *Migrate { func Migrations() *Migrate {
if migrations == nil { if migrations == nil {
migrations = &Migrate{ migrations = &Migrate{
@ -45,7 +45,7 @@ func Migrations() *Migrate {
return migrations return migrations
} }
// Add GORMigrate to migrate // Add GORMigrate to migrate.
func (m *Migrate) Add(migration *gormigrate.Migration) { func (m *Migrate) Add(migration *gormigrate.Migration) {
if migration == nil { if migration == nil {
return return
@ -54,13 +54,13 @@ func (m *Migrate) Add(migration *gormigrate.Migration) {
m.migrations[migration.ID] = migration m.migrations[migration.ID] = migration
} }
// SetDB to migrate // SetDB to migrate.
func (m *Migrate) SetDB(db *gorm.DB) *Migrate { func (m *Migrate) SetDB(db *gorm.DB) *Migrate {
m.db = db m.db = db
return m return m
} }
// Migrate all, including schema initialization // Migrate all, including schema initialization.
func (m *Migrate) Migrate() error { func (m *Migrate) Migrate() error {
if err := m.prepareMigrations(); err != nil { if err := m.prepareMigrations(); err != nil {
return err return err
@ -73,7 +73,7 @@ func (m *Migrate) Migrate() error {
return nil return nil
} }
// Rollback all migrations // Rollback all migrations.
func (m *Migrate) Rollback() error { func (m *Migrate) Rollback() error {
if err := m.prepareMigrations(); err != nil { if err := m.prepareMigrations(); err != nil {
return err return err
@ -94,7 +94,7 @@ func (m *Migrate) Rollback() error {
return nil return nil
} }
// MigrateTo specified version // MigrateTo specified version.
func (m *Migrate) MigrateTo(version string) error { func (m *Migrate) MigrateTo(version string) error {
if err := m.prepareMigrations(); err != nil { if err := m.prepareMigrations(); err != nil {
return err return err
@ -111,7 +111,7 @@ func (m *Migrate) MigrateTo(version string) error {
} }
} }
// MigrateNextTo migrate to next version from specified version // MigrateNextTo migrate to next version from specified version.
func (m *Migrate) MigrateNextTo(version string) error { func (m *Migrate) MigrateNextTo(version string) error {
if err := m.prepareMigrations(); err != nil { if err := m.prepareMigrations(); err != nil {
return err return err
@ -132,7 +132,7 @@ func (m *Migrate) MigrateNextTo(version string) error {
} }
} }
// MigratePreviousTo migrate to previous version from specified version // MigratePreviousTo migrate to previous version from specified version.
func (m *Migrate) MigratePreviousTo(version string) error { func (m *Migrate) MigratePreviousTo(version string) error {
if err := m.prepareMigrations(); err != nil { if err := m.prepareMigrations(); err != nil {
return err return err
@ -155,7 +155,7 @@ func (m *Migrate) MigratePreviousTo(version string) error {
} }
} }
// RollbackTo specified version // RollbackTo specified version.
func (m *Migrate) RollbackTo(version string) error { func (m *Migrate) RollbackTo(version string) error {
if err := m.prepareMigrations(); err != nil { if err := m.prepareMigrations(); err != nil {
return err return err
@ -164,7 +164,7 @@ func (m *Migrate) RollbackTo(version string) error {
return m.GORMigrate.RollbackTo(version) return m.GORMigrate.RollbackTo(version)
} }
// Current migration version // Current migration version.
func (m *Migrate) Current() string { func (m *Migrate) Current() string {
var migrationInfo MigrationInfo var migrationInfo MigrationInfo
@ -191,7 +191,7 @@ func (m *Migrate) Current() string {
return migrationInfo.ID return migrationInfo.ID
} }
// NextFrom returns next version from passed version // NextFrom returns next version from passed version.
func (m *Migrate) NextFrom(version string) (string, error) { func (m *Migrate) NextFrom(version string) (string, error) {
for key, ver := range m.versions { for key, ver := range m.versions {
if ver == version { if ver == version {
@ -206,7 +206,7 @@ func (m *Migrate) NextFrom(version string) (string, error) {
return "", errors.New("cannot find specified migration") return "", errors.New("cannot find specified migration")
} }
// PreviousFrom returns previous version from passed version // PreviousFrom returns previous version from passed version.
func (m *Migrate) PreviousFrom(version string) (string, error) { func (m *Migrate) PreviousFrom(version string) (string, error) {
for key, ver := range m.versions { for key, ver := range m.versions {
if ver == version { if ver == version {
@ -221,12 +221,12 @@ func (m *Migrate) PreviousFrom(version string) (string, error) {
return "", errors.New("cannot find specified migration") return "", errors.New("cannot find specified migration")
} }
// Close db connection // Close db connection.
func (m *Migrate) Close() error { func (m *Migrate) Close() error {
return m.db.Close() return m.db.Close()
} }
// prepareMigrations prepare migrate // prepareMigrations prepare migrate.
func (m *Migrate) prepareMigrations() error { func (m *Migrate) prepareMigrations() error {
var ( var (
keys []string keys []string

View File

@ -30,12 +30,12 @@ func init() {
} }
` `
// NewMigrationCommand struct // NewMigrationCommand struct.
type NewMigrationCommand struct { type NewMigrationCommand struct {
Directory string `short:"d" long:"directory" default:"./migrations" description:"Directory where migration will be created"` Directory string `short:"d" long:"directory" default:"./migrations" description:"Directory where migration will be created"`
} }
// FileExists returns true if provided file exist and it's not directory // FileExists returns true if provided file exist and it's not directory.
func (x *NewMigrationCommand) FileExists(filename string) bool { func (x *NewMigrationCommand) FileExists(filename string) bool {
info, err := os.Stat(filename) info, err := os.Stat(filename)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -44,7 +44,7 @@ func (x *NewMigrationCommand) FileExists(filename string) bool {
return !info.IsDir() return !info.IsDir()
} }
// Execute migration generator command // Execute migration generator command.
func (x *NewMigrationCommand) Execute(args []string) error { func (x *NewMigrationCommand) Execute(args []string) error {
version := strconv.FormatInt(time.Now().Unix(), 10) version := strconv.FormatInt(time.Now().Unix(), 10)
directory := path.Clean(x.Directory) directory := path.Clean(x.Directory)

View File

@ -2,7 +2,7 @@ package core
import "time" import "time"
// Connection model // Connection model.
type Connection struct { type Connection struct {
ID int `gorm:"primary_key"` ID int `gorm:"primary_key"`
ClientID string `gorm:"column:client_id; type:varchar(70); not null; unique" json:"clientId,omitempty"` ClientID string `gorm:"column:client_id; type:varchar(70); not null; unique" json:"clientId,omitempty"`
@ -16,7 +16,7 @@ type Connection struct {
Accounts []Account `gorm:"foreignkey:ConnectionID"` Accounts []Account `gorm:"foreignkey:ConnectionID"`
} }
// Account model // Account model.
type Account struct { type Account struct {
ID int `gorm:"primary_key"` ID int `gorm:"primary_key"`
ConnectionID int `gorm:"column:connection_id" json:"connectionId,omitempty"` ConnectionID int `gorm:"column:connection_id" json:"connectionId,omitempty"`
@ -28,7 +28,7 @@ type Account struct {
UpdatedAt time.Time UpdatedAt time.Time
} }
// User model // User model.
type User struct { type User struct {
ID int `gorm:"primary_key"` ID int `gorm:"primary_key"`
ExternalID string `gorm:"column:external_id; type:varchar(255); not null; unique"` ExternalID string `gorm:"column:external_id; type:varchar(255); not null; unique"`
@ -49,5 +49,5 @@ func (User) TableName() string {
return "mg_user" return "mg_user"
} }
// Accounts list // Accounts list.
type Accounts []Account type Accounts []Account

View File

@ -4,16 +4,16 @@ import (
"time" "time"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
// PostgreSQL is an default // PostgreSQL is an default.
_ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/postgres"
) )
// ORM struct // ORM struct.
type ORM struct { type ORM struct {
DB *gorm.DB DB *gorm.DB
} }
// NewORM will init new database connection // NewORM will init new database connection.
func NewORM(config DatabaseConfig) *ORM { func NewORM(config DatabaseConfig) *ORM {
orm := &ORM{} orm := &ORM{}
orm.createDB(config) orm.createDB(config)
@ -36,7 +36,7 @@ func (orm *ORM) createDB(config DatabaseConfig) {
orm.DB = db orm.DB = db
} }
// CloseDB close database connection // CloseDB close database connection.
func (orm *ORM) CloseDB() { func (orm *ORM) CloseDB() {
_ = orm.DB.Close() _ = orm.DB.Close()
} }

View File

@ -8,22 +8,23 @@ import (
"strconv" "strconv"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/retailcrm/mg-transport-core/core/stacktrace" "github.com/retailcrm/mg-transport-core/core/stacktrace"
"github.com/getsentry/raven-go" "github.com/getsentry/raven-go"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// ErrorHandlerFunc will handle errors // ErrorHandlerFunc will handle errors.
type ErrorHandlerFunc func(recovery interface{}, c *gin.Context) type ErrorHandlerFunc func(recovery interface{}, c *gin.Context)
// SentryTaggedTypes list // SentryTaggedTypes list.
type SentryTaggedTypes []SentryTagged type SentryTaggedTypes []SentryTagged
// SentryTags list for SentryTaggedStruct. Format: name => property name // SentryTags list for SentryTaggedStruct. Format: name => property name.
type SentryTags map[string]string type SentryTags map[string]string
// SentryTagged interface for both tagged scalar and struct // SentryTagged interface for both tagged scalar and struct.
type SentryTagged interface { type SentryTagged interface {
BuildTags(interface{}) (map[string]string, error) BuildTags(interface{}) (map[string]string, error)
GetContextKey() string GetContextKey() string
@ -31,7 +32,7 @@ type SentryTagged interface {
GetName() string GetName() string
} }
// Sentry struct. Holds SentryTaggedStruct list // Sentry struct. Holds SentryTaggedStruct list.
type Sentry struct { type Sentry struct {
TaggedTypes SentryTaggedTypes TaggedTypes SentryTaggedTypes
Stacktrace bool Stacktrace bool
@ -41,20 +42,20 @@ type Sentry struct {
Client stacktrace.RavenClientInterface Client stacktrace.RavenClientInterface
} }
// SentryTaggedStruct holds information about type, it's key in gin.Context (for middleware), and it's properties // SentryTaggedStruct holds information about type, it's key in gin.Context (for middleware), and it's properties.
type SentryTaggedStruct struct { type SentryTaggedStruct struct {
Type reflect.Type Type reflect.Type
GinContextKey string GinContextKey string
Tags SentryTags Tags SentryTags
} }
// SentryTaggedScalar variable from context // SentryTaggedScalar variable from context.
type SentryTaggedScalar struct { type SentryTaggedScalar struct {
SentryTaggedStruct SentryTaggedStruct
Name string Name string
} }
// NewSentry constructor // NewSentry constructor.
func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTypes, logger LoggerInterface, localizer *Localizer) *Sentry { func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTypes, logger LoggerInterface, localizer *Localizer) *Sentry {
sentry := &Sentry{ sentry := &Sentry{
DefaultError: defaultError, DefaultError: defaultError,
@ -67,7 +68,7 @@ func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTy
return sentry return sentry
} }
// NewTaggedStruct constructor // NewTaggedStruct constructor.
func NewTaggedStruct(sample interface{}, ginCtxKey string, tags map[string]string) *SentryTaggedStruct { func NewTaggedStruct(sample interface{}, ginCtxKey string, tags map[string]string) *SentryTaggedStruct {
n := make(map[string]string) n := make(map[string]string)
for k, v := range tags { for k, v := range tags {
@ -81,7 +82,7 @@ func NewTaggedStruct(sample interface{}, ginCtxKey string, tags map[string]strin
} }
} }
// NewTaggedScalar constructor // NewTaggedScalar constructor.
func NewTaggedScalar(sample interface{}, ginCtxKey string, name string) *SentryTaggedScalar { func NewTaggedScalar(sample interface{}, ginCtxKey string, name string) *SentryTaggedScalar {
return &SentryTaggedScalar{ return &SentryTaggedScalar{
SentryTaggedStruct: SentryTaggedStruct{ SentryTaggedStruct: SentryTaggedStruct{
@ -93,13 +94,13 @@ func NewTaggedScalar(sample interface{}, ginCtxKey string, name string) *SentryT
} }
} }
// createRavenClient will init raven.Client // createRavenClient will init raven.Client.
func (s *Sentry) createRavenClient(sentryDSN string) { func (s *Sentry) createRavenClient(sentryDSN string) {
client, _ := raven.New(sentryDSN) client, _ := raven.New(sentryDSN)
s.Client = client s.Client = client
} }
// combineGinErrorHandlers calls several error handlers simultaneously // combineGinErrorHandlers calls several error handlers simultaneously.
func (s *Sentry) combineGinErrorHandlers(handlers ...ErrorHandlerFunc) gin.HandlerFunc { func (s *Sentry) combineGinErrorHandlers(handlers ...ErrorHandlerFunc) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
defer func() { defer func() {
@ -117,7 +118,7 @@ func (s *Sentry) combineGinErrorHandlers(handlers ...ErrorHandlerFunc) gin.Handl
} }
} }
// ErrorMiddleware returns error handlers, attachable to gin.Engine // ErrorMiddleware returns error handlers, attachable to gin.Engine.
func (s *Sentry) ErrorMiddleware() gin.HandlerFunc { func (s *Sentry) ErrorMiddleware() gin.HandlerFunc {
defaultHandlers := []ErrorHandlerFunc{ defaultHandlers := []ErrorHandlerFunc{
s.ErrorResponseHandler(), s.ErrorResponseHandler(),
@ -132,7 +133,7 @@ func (s *Sentry) ErrorMiddleware() gin.HandlerFunc {
return s.combineGinErrorHandlers(defaultHandlers...) return s.combineGinErrorHandlers(defaultHandlers...)
} }
// PanicLogger logs panic // PanicLogger logs panic.
func (s *Sentry) PanicLogger() ErrorHandlerFunc { func (s *Sentry) PanicLogger() ErrorHandlerFunc {
return func(recovery interface{}, c *gin.Context) { return func(recovery interface{}, c *gin.Context) {
if recovery != nil { if recovery != nil {
@ -146,7 +147,7 @@ func (s *Sentry) PanicLogger() ErrorHandlerFunc {
} }
} }
// ErrorLogger logs basic errors // ErrorLogger logs basic errors.
func (s *Sentry) ErrorLogger() ErrorHandlerFunc { func (s *Sentry) ErrorLogger() ErrorHandlerFunc {
return func(recovery interface{}, c *gin.Context) { return func(recovery interface{}, c *gin.Context) {
for _, err := range c.Errors { for _, err := range c.Errors {
@ -159,7 +160,7 @@ func (s *Sentry) ErrorLogger() ErrorHandlerFunc {
} }
} }
// ErrorResponseHandler will be executed in case of any unexpected error // ErrorResponseHandler will be executed in case of any unexpected error.
func (s *Sentry) ErrorResponseHandler() ErrorHandlerFunc { func (s *Sentry) ErrorResponseHandler() ErrorHandlerFunc {
return func(recovery interface{}, c *gin.Context) { return func(recovery interface{}, c *gin.Context) {
publicErrors := c.Errors.ByType(gin.ErrorTypePublic) publicErrors := c.Errors.ByType(gin.ErrorTypePublic)
@ -194,7 +195,7 @@ func (s *Sentry) ErrorResponseHandler() ErrorHandlerFunc {
} }
} }
// ErrorCaptureHandler will generate error data and send it to sentry // ErrorCaptureHandler will generate error data and send it to sentry.
func (s *Sentry) ErrorCaptureHandler() ErrorHandlerFunc { func (s *Sentry) ErrorCaptureHandler() ErrorHandlerFunc {
return func(recovery interface{}, c *gin.Context) { return func(recovery interface{}, c *gin.Context) {
tags := map[string]string{ tags := map[string]string{
@ -248,23 +249,23 @@ func (s *Sentry) ErrorCaptureHandler() ErrorHandlerFunc {
} }
} }
// AddTag will add tag with property name which holds tag in object // AddTag will add tag with property name which holds tag in object.
func (t *SentryTaggedStruct) AddTag(name string, property string) *SentryTaggedStruct { func (t *SentryTaggedStruct) AddTag(name string, property string) *SentryTaggedStruct {
t.Tags[property] = name t.Tags[property] = name
return t return t
} }
// GetTags is Tags getter // GetTags is Tags getter.
func (t *SentryTaggedStruct) GetTags() SentryTags { func (t *SentryTaggedStruct) GetTags() SentryTags {
return t.Tags return t.Tags
} }
// GetContextKey is GinContextKey getter // GetContextKey is GinContextKey getter.
func (t *SentryTaggedStruct) GetContextKey() string { func (t *SentryTaggedStruct) GetContextKey() string {
return t.GinContextKey return t.GinContextKey
} }
// GetName is useless for SentryTaggedStruct // GetName is useless for SentryTaggedStruct.
func (t *SentryTaggedStruct) GetName() string { func (t *SentryTaggedStruct) GetName() string {
return "" return ""
} }
@ -303,7 +304,7 @@ func (t *SentryTaggedStruct) GetProperty(v interface{}, property string) (name s
return return
} }
// BuildTags will extract tags for Sentry from specified object // BuildTags will extract tags for Sentry from specified object.
func (t *SentryTaggedStruct) BuildTags(v interface{}) (tags map[string]string, err error) { func (t *SentryTaggedStruct) BuildTags(v interface{}) (tags map[string]string, err error) {
items := make(map[string]string) items := make(map[string]string)
for prop, name := range t.Tags { for prop, name := range t.Tags {
@ -319,7 +320,7 @@ func (t *SentryTaggedStruct) BuildTags(v interface{}) (tags map[string]string, e
return return
} }
// valueToString convert reflect.Value to string representation // valueToString convert reflect.Value to string representation.
func (t *SentryTaggedStruct) valueToString(field reflect.Value) string { func (t *SentryTaggedStruct) valueToString(field reflect.Value) string {
k := field.Kind() k := field.Kind()
switch { switch {
@ -340,17 +341,17 @@ func (t *SentryTaggedStruct) valueToString(field reflect.Value) string {
} }
} }
// GetTags is useless for SentryTaggedScalar // GetTags is useless for SentryTaggedScalar.
func (t *SentryTaggedScalar) GetTags() SentryTags { func (t *SentryTaggedScalar) GetTags() SentryTags {
return SentryTags{} return SentryTags{}
} }
// GetContextKey is getter for GinContextKey // GetContextKey is getter for GinContextKey.
func (t *SentryTaggedScalar) GetContextKey() string { func (t *SentryTaggedScalar) GetContextKey() string {
return t.GinContextKey return t.GinContextKey
} }
// GetName is getter for Name (tag name for scalar) // GetName is getter for Name (tag name for scalar).
func (t *SentryTaggedScalar) GetName() string { func (t *SentryTaggedScalar) GetName() string {
return t.Name return t.Name
} }
@ -377,7 +378,7 @@ func (t *SentryTaggedScalar) Get(v interface{}) (value string, err error) {
return return
} }
// BuildTags returns map with single item in this format: <tag name> => <scalar value> // BuildTags returns map with single item in this format: <tag name> => <scalar value>.
func (t *SentryTaggedScalar) BuildTags(v interface{}) (items map[string]string, err error) { func (t *SentryTaggedScalar) BuildTags(v interface{}) (items map[string]string, err error) {
items = make(map[string]string) items = make(map[string]string)
if value, e := t.Get(v); e == nil { if value, e := t.Get(v); e == nil {

View File

@ -125,7 +125,7 @@ func (n *simpleError) Error() string {
return n.msg return n.msg
} }
// wrappableError is a simple implementation of wrappable error // wrappableError is a simple implementation of wrappable error.
type wrappableError struct { type wrappableError struct {
msg string msg string
err error err error

View File

@ -5,10 +5,10 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// ErrUnfeasibleBuilder will be returned if builder for stacktrace was chosen incorrectly // ErrUnfeasibleBuilder will be returned if builder for stacktrace was chosen incorrectly.
var ErrUnfeasibleBuilder = errors.New("unfeasible builder for this error type") var ErrUnfeasibleBuilder = errors.New("unfeasible builder for this error type")
// StackBuilderInterface is an interface for every stacktrace builder // StackBuilderInterface is an interface for every stacktrace builder.
type StackBuilderInterface interface { type StackBuilderInterface interface {
SetClient(RavenClientInterface) StackBuilderInterface SetClient(RavenClientInterface) StackBuilderInterface
SetError(error) StackBuilderInterface SetError(error) StackBuilderInterface
@ -16,7 +16,7 @@ type StackBuilderInterface interface {
GetResult() (*raven.Stacktrace, error) GetResult() (*raven.Stacktrace, error)
} }
// AbstractStackBuilder contains methods, which would be implemented in every builder anyway // AbstractStackBuilder contains methods, which would be implemented in every builder anyway.
type AbstractStackBuilder struct { type AbstractStackBuilder struct {
err error err error
buildErr error buildErr error
@ -30,7 +30,7 @@ func (a *AbstractStackBuilder) SetClient(client RavenClientInterface) StackBuild
return a return a
} }
// SetError sets error in builder, which will be processed // SetError sets error in builder, which will be processed.
func (a *AbstractStackBuilder) SetError(err error) StackBuilderInterface { func (a *AbstractStackBuilder) SetError(err error) StackBuilderInterface {
a.err = err a.err = err
return a return a
@ -46,7 +46,7 @@ func (a *AbstractStackBuilder) GetResult() (*raven.Stacktrace, error) {
return a.stack, a.buildErr return a.stack, a.buildErr
} }
// FallbackToGeneric fallbacks to GenericStackBuilder method // FallbackToGeneric fallbacks to GenericStackBuilder method.
func (a *AbstractStackBuilder) FallbackToGeneric() { func (a *AbstractStackBuilder) FallbackToGeneric() {
a.stack, a.err = GenericStack(a.client), nil a.stack, a.err = GenericStack(a.client), nil
} }

View File

@ -4,27 +4,27 @@ import (
pkgErrors "github.com/pkg/errors" pkgErrors "github.com/pkg/errors"
) )
// PkgErrorCauseable is an interface for checking Cause() method existence in the error // PkgErrorCauseable is an interface for checking Cause() method existence in the error.
type PkgErrorCauseable interface { type PkgErrorCauseable interface {
Cause() error Cause() error
} }
// PkgErrorTraceable is an interface for checking StackTrace() method existence in the error // PkgErrorTraceable is an interface for checking StackTrace() method existence in the error.
type PkgErrorTraceable interface { type PkgErrorTraceable interface {
StackTrace() pkgErrors.StackTrace StackTrace() pkgErrors.StackTrace
} }
// PkgErrorsStackTransformer transforms stack data from github.com/pkg/errors error to stacktrace.Stacktrace // PkgErrorsStackTransformer transforms stack data from github.com/pkg/errors error to stacktrace.Stacktrace.
type PkgErrorsStackTransformer struct { type PkgErrorsStackTransformer struct {
stack pkgErrors.StackTrace stack pkgErrors.StackTrace
} }
// NewPkgErrorsStackTransformer is a PkgErrorsStackTransformer constructor // NewPkgErrorsStackTransformer is a PkgErrorsStackTransformer constructor.
func NewPkgErrorsStackTransformer(stack pkgErrors.StackTrace) *PkgErrorsStackTransformer { func NewPkgErrorsStackTransformer(stack pkgErrors.StackTrace) *PkgErrorsStackTransformer {
return &PkgErrorsStackTransformer{stack: stack} return &PkgErrorsStackTransformer{stack: stack}
} }
// Stack returns stacktrace (which is []uintptr internally, each uintptc is a pc) // Stack returns stacktrace (which is []uintptr internally, each uintptc is a pc).
func (p *PkgErrorsStackTransformer) Stack() Stacktrace { func (p *PkgErrorsStackTransformer) Stack() Stacktrace {
if p.stack == nil { if p.stack == nil {
return Stacktrace{} return Stacktrace{}
@ -37,12 +37,12 @@ func (p *PkgErrorsStackTransformer) Stack() Stacktrace {
return result return result
} }
// PkgErrorsBuilder builds stacktrace with data from github.com/pkg/errors error // PkgErrorsBuilder builds stacktrace with data from github.com/pkg/errors error.
type PkgErrorsBuilder struct { type PkgErrorsBuilder struct {
AbstractStackBuilder AbstractStackBuilder
} }
// Build stacktrace // Build stacktrace.
func (b *PkgErrorsBuilder) Build() StackBuilderInterface { func (b *PkgErrorsBuilder) Build() StackBuilderInterface {
if !isPkgErrors(b.err) { if !isPkgErrors(b.err) {
b.buildErr = ErrUnfeasibleBuilder b.buildErr = ErrUnfeasibleBuilder
@ -69,7 +69,7 @@ func (b *PkgErrorsBuilder) Build() StackBuilderInterface {
return b return b
} }
// getErrorCause will try to extract original error from wrapper - it is used only if stacktrace is not present // getErrorCause will try to extract original error from wrapper - it is used only if stacktrace is not present.
func (b *PkgErrorsBuilder) getErrorCause(err error) error { func (b *PkgErrorsBuilder) getErrorCause(err error) error {
causeable, ok := err.(PkgErrorCauseable) causeable, ok := err.(PkgErrorCauseable)
if !ok { if !ok {
@ -78,7 +78,8 @@ func (b *PkgErrorsBuilder) getErrorCause(err error) error {
return causeable.Cause() return causeable.Cause()
} }
// getErrorStackTrace will try to extract stacktrace from error using StackTrace method (default errors doesn't have it) // getErrorStackTrace will try to extract stacktrace from error using StackTrace method
// (default errors doesn't have it).
func (b *PkgErrorsBuilder) getErrorStack(err error) pkgErrors.StackTrace { func (b *PkgErrorsBuilder) getErrorStack(err error) pkgErrors.StackTrace {
traceable, ok := err.(PkgErrorTraceable) traceable, ok := err.(PkgErrorTraceable)
if !ok { if !ok {

View File

@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
) )
// errorWithCause has Cause() method, but doesn't have StackTrace() method // errorWithCause has Cause() method, but doesn't have StackTrace() method.
type errorWithCause struct { type errorWithCause struct {
msg string msg string
cause error cause error

View File

@ -10,31 +10,32 @@ import (
// Frame is a program counter inside a stack frame. // Frame is a program counter inside a stack frame.
type Frame uintptr type Frame uintptr
// Stacktrace is stack of Frames // Stacktrace is stack of Frames.
type Stacktrace []Frame type Stacktrace []Frame
// RavenStackTransformer is an interface for any component, which will transform some unknown stacktrace data to stacktrace.Stacktrace // RavenStackTransformer is an interface for any component, which will transform some
// unknown stacktrace data to stacktrace.Stacktrace.
type RavenStackTransformer interface { type RavenStackTransformer interface {
Stack() Stacktrace Stack() Stacktrace
} }
// RavenStacktraceBuilder builds *raven.Stacktrace for any generic stack data // RavenStacktraceBuilder builds *raven.Stacktrace for any generic stack data.
type RavenStacktraceBuilder struct { type RavenStacktraceBuilder struct {
transformer RavenStackTransformer transformer RavenStackTransformer
} }
// NewRavenStacktraceBuilder is a RavenStacktraceBuilder constructor // NewRavenStacktraceBuilder is a RavenStacktraceBuilder constructor.
func NewRavenStacktraceBuilder(p RavenStackTransformer) *RavenStacktraceBuilder { func NewRavenStacktraceBuilder(p RavenStackTransformer) *RavenStacktraceBuilder {
return (&RavenStacktraceBuilder{}).SetTransformer(p) return (&RavenStacktraceBuilder{}).SetTransformer(p)
} }
// SetTransformer sets stack transformer into stacktrace builder // SetTransformer sets stack transformer into stacktrace builder.
func (b *RavenStacktraceBuilder) SetTransformer(p RavenStackTransformer) *RavenStacktraceBuilder { func (b *RavenStacktraceBuilder) SetTransformer(p RavenStackTransformer) *RavenStacktraceBuilder {
b.transformer = p b.transformer = p
return b return b
} }
// Build converts generic stacktrace to to github.com/getsentry/raven-go.Stacktrace // Build converts generic stacktrace to to github.com/getsentry/raven-go.Stacktrace.
func (b *RavenStacktraceBuilder) Build(context int, appPackagePrefixes []string) *raven.Stacktrace { func (b *RavenStacktraceBuilder) Build(context int, appPackagePrefixes []string) *raven.Stacktrace {
// This code is borrowed from github.com/getsentry/raven-go.NewStacktrace(). // This code is borrowed from github.com/getsentry/raven-go.NewStacktrace().
var frames []*raven.StacktraceFrame var frames []*raven.StacktraceFrame
@ -53,7 +54,7 @@ func (b *RavenStacktraceBuilder) Build(context int, appPackagePrefixes []string)
return &raven.Stacktrace{Frames: frames} return &raven.Stacktrace{Frames: frames}
} }
// convertFrame converts single generic stacktrace frame to github.com/pkg/errors.Frame // convertFrame converts single generic stacktrace frame to github.com/pkg/errors.Frame.
func (b *RavenStacktraceBuilder) convertFrame(f Frame, context int, appPackagePrefixes []string) *raven.StacktraceFrame { func (b *RavenStacktraceBuilder) convertFrame(f Frame, context int, appPackagePrefixes []string) *raven.StacktraceFrame {
// This code is borrowed from github.com/pkg/errors.Frame. // This code is borrowed from github.com/pkg/errors.Frame.
pc := uintptr(f) - 1 pc := uintptr(f) - 1

View File

@ -14,7 +14,7 @@ func GetStackBuilderByErrorType(err error) StackBuilderInterface {
return &GenericStackBuilder{AbstractStackBuilder{err: err}} return &GenericStackBuilder{AbstractStackBuilder{err: err}}
} }
// isPkgErrors returns true if passed error might be github.com/pkg/errors error // isPkgErrors returns true if passed error might be github.com/pkg/errors error.
func isPkgErrors(err error) bool { func isPkgErrors(err error) bool {
_, okTraceable := err.(PkgErrorTraceable) _, okTraceable := err.(PkgErrorTraceable)
_, okCauseable := err.(PkgErrorCauseable) _, okCauseable := err.(PkgErrorCauseable)

View File

@ -4,17 +4,17 @@ import (
"github.com/getsentry/raven-go" "github.com/getsentry/raven-go"
) )
// Unwrappable is the interface for errors with Unwrap() method // Unwrappable is the interface for errors with Unwrap() method.
type Unwrappable interface { type Unwrappable interface {
Unwrap() error Unwrap() error
} }
// UnwrapBuilder builds stacktrace from the chain of wrapped errors // UnwrapBuilder builds stacktrace from the chain of wrapped errors.
type UnwrapBuilder struct { type UnwrapBuilder struct {
AbstractStackBuilder AbstractStackBuilder
} }
// Build stacktrace // Build stacktrace.
func (b *UnwrapBuilder) Build() StackBuilderInterface { func (b *UnwrapBuilder) Build() StackBuilderInterface {
if _, ok := b.err.(Unwrappable); !ok { if _, ok := b.err.(Unwrappable); !ok {
b.buildErr = ErrUnfeasibleBuilder b.buildErr = ErrUnfeasibleBuilder

View File

@ -23,7 +23,7 @@ func (n *simpleError) Error() string {
return n.msg return n.msg
} }
// wrappableError is a simple implementation of wrappable error // wrappableError is a simple implementation of wrappable error.
type wrappableError struct { type wrappableError struct {
msg string msg string
err error err error

View File

@ -7,7 +7,7 @@ import (
"github.com/gobuffalo/packr/v2" "github.com/gobuffalo/packr/v2"
) )
// Renderer wraps multitemplate.Renderer in order to make it easier to use // Renderer wraps multitemplate.Renderer in order to make it easier to use.
type Renderer struct { type Renderer struct {
multitemplate.Renderer multitemplate.Renderer
TemplatesBox *packr.Box TemplatesBox *packr.Box
@ -15,22 +15,22 @@ type Renderer struct {
alreadyAdded map[string]*template.Template alreadyAdded map[string]*template.Template
} }
// NewRenderer is a Renderer constructor // NewRenderer is a Renderer constructor.
func NewRenderer(funcMap template.FuncMap) Renderer { func NewRenderer(funcMap template.FuncMap) Renderer {
return newRendererWithMultitemplate(funcMap, multitemplate.NewRenderer()) return newRendererWithMultitemplate(funcMap, multitemplate.NewRenderer())
} }
// NewStaticRenderer is a Renderer constructor with multitemplate.Render // NewStaticRenderer is a Renderer constructor with multitemplate.Render.
func NewStaticRenderer(funcMap template.FuncMap) Renderer { func NewStaticRenderer(funcMap template.FuncMap) Renderer {
return newRendererWithMultitemplate(funcMap, multitemplate.New()) return newRendererWithMultitemplate(funcMap, multitemplate.New())
} }
// NewDynamicRenderer is a Renderer constructor with multitemplate.DynamicRender // NewDynamicRenderer is a Renderer constructor with multitemplate.DynamicRender.
func NewDynamicRenderer(funcMap template.FuncMap) Renderer { func NewDynamicRenderer(funcMap template.FuncMap) Renderer {
return newRendererWithMultitemplate(funcMap, multitemplate.NewDynamic()) return newRendererWithMultitemplate(funcMap, multitemplate.NewDynamic())
} }
// newRendererWithMultitemplate initializes Renderer with provided multitemplate.Renderer instance // newRendererWithMultitemplate initializes Renderer with provided multitemplate.Renderer instance.
func newRendererWithMultitemplate(funcMap template.FuncMap, renderer multitemplate.Renderer) Renderer { func newRendererWithMultitemplate(funcMap template.FuncMap, renderer multitemplate.Renderer) Renderer {
return Renderer{ return Renderer{
Renderer: renderer, Renderer: renderer,
@ -39,7 +39,7 @@ func newRendererWithMultitemplate(funcMap template.FuncMap, renderer multitempla
} }
} }
// Push is an AddFromFilesFuncs wrapper // Push is an AddFromFilesFuncs wrapper.
func (r *Renderer) Push(name string, files ...string) *template.Template { func (r *Renderer) Push(name string, files ...string) *template.Template {
if tpl := r.getTemplate(name); tpl != nil { if tpl := r.getTemplate(name); tpl != nil {
return tpl return tpl
@ -52,7 +52,7 @@ func (r *Renderer) Push(name string, files ...string) *template.Template {
return r.storeTemplate(name, r.addFromBox(name, r.FuncMap, files...)) return r.storeTemplate(name, r.addFromBox(name, r.FuncMap, files...))
} }
// addFromBox adds embedded template // addFromBox adds embedded template.
func (r *Renderer) addFromBox(name string, funcMap template.FuncMap, files ...string) *template.Template { func (r *Renderer) addFromBox(name string, funcMap template.FuncMap, files ...string) *template.Template {
var filesData []string var filesData []string
@ -76,7 +76,7 @@ func (r *Renderer) storeTemplate(name string, tpl *template.Template) *template.
return tpl return tpl
} }
// getTemplate returns template from render or from storage // getTemplate returns template from render or from storage.
func (r *Renderer) getTemplate(name string) *template.Template { func (r *Renderer) getTemplate(name string) *template.Template {
if renderer, ok := r.Renderer.(multitemplate.Render); ok { if renderer, ok := r.Renderer.(multitemplate.Render); ok {
if i, ok := renderer[name]; ok { if i, ok := renderer[name]; ok {

View File

@ -23,12 +23,13 @@ type TranslationsExtractor struct {
TranslationsPath string TranslationsPath string
} }
// NewTranslationsExtractor constructor. Use "translate.{}.yml" as template if your translations are named like "translate.en.yml" // NewTranslationsExtractor constructor. Use "translate.{}.yml" as template
// if your translations are named like "translate.en.yml".
func NewTranslationsExtractor(fileNameTemplate string) *TranslationsExtractor { func NewTranslationsExtractor(fileNameTemplate string) *TranslationsExtractor {
return &TranslationsExtractor{fileNameTemplate: fileNameTemplate} return &TranslationsExtractor{fileNameTemplate: fileNameTemplate}
} }
// unmarshalToMap returns map with unmarshaled data or error // unmarshalToMap returns map with unmarshaled data or error.
func (t *TranslationsExtractor) unmarshalToMap(in []byte) (map[string]interface{}, error) { func (t *TranslationsExtractor) unmarshalToMap(in []byte) (map[string]interface{}, error) {
var dataMap map[string]interface{} var dataMap map[string]interface{}
@ -39,7 +40,7 @@ func (t *TranslationsExtractor) unmarshalToMap(in []byte) (map[string]interface{
return dataMap, nil return dataMap, nil
} }
// loadYAMLBox loads YAML from box // loadYAMLBox loads YAML from box.
func (t *TranslationsExtractor) loadYAMLBox(fileName string) (map[string]interface{}, error) { func (t *TranslationsExtractor) loadYAMLBox(fileName string) (map[string]interface{}, error) {
var ( var (
dataMap map[string]interface{} dataMap map[string]interface{}
@ -54,7 +55,7 @@ func (t *TranslationsExtractor) loadYAMLBox(fileName string) (map[string]interfa
return t.unmarshalToMap(data) return t.unmarshalToMap(data)
} }
// loadYAMLFile loads YAML from file // loadYAMLFile loads YAML from file.
func (t *TranslationsExtractor) loadYAMLFile(fileName string) (map[string]interface{}, error) { func (t *TranslationsExtractor) loadYAMLFile(fileName string) (map[string]interface{}, error) {
var ( var (
dataMap map[string]interface{} dataMap map[string]interface{}
@ -98,7 +99,7 @@ func (t *TranslationsExtractor) loadYAML(fileName string) (map[string]interface{
} }
} }
// GetMapKeys returns sorted map keys from map[string]interface{} - useful to check keys in several translation files // GetMapKeys returns sorted map keys from map[string]interface{} - useful to check keys in several translation files.
func (t *TranslationsExtractor) GetMapKeys(data map[string]interface{}) []string { func (t *TranslationsExtractor) GetMapKeys(data map[string]interface{}) []string {
keys := make([]string, len(data)) keys := make([]string, len(data))
@ -113,12 +114,12 @@ func (t *TranslationsExtractor) GetMapKeys(data map[string]interface{}) []string
return keys return keys
} }
// LoadLocale returns translation file data with provided locale // LoadLocale returns translation file data with provided locale.
func (t *TranslationsExtractor) LoadLocale(locale string) (map[string]interface{}, error) { func (t *TranslationsExtractor) LoadLocale(locale string) (map[string]interface{}, error) {
return t.loadYAML(strings.Replace(t.fileNameTemplate, "{}", locale, 1)) return t.loadYAML(strings.Replace(t.fileNameTemplate, "{}", locale, 1))
} }
// LoadLocaleKeys returns only sorted keys from translation file // LoadLocaleKeys returns only sorted keys from translation file.
func (t *TranslationsExtractor) LoadLocaleKeys(locale string) ([]string, error) { func (t *TranslationsExtractor) LoadLocaleKeys(locale string) ([]string, error) {
var ( var (
data map[string]interface{} data map[string]interface{}

View File

@ -73,7 +73,7 @@ var defaultCurrencies = map[string]string{
"gbp": "£", "gbp": "£",
} }
// Utils service object // Utils service object.
type Utils struct { type Utils struct {
IsDebug bool IsDebug bool
TokenCounter uint32 TokenCounter uint32
@ -82,7 +82,7 @@ type Utils struct {
slashRegex *regexp.Regexp slashRegex *regexp.Regexp
} }
// NewUtils will create new Utils instance // NewUtils will create new Utils instance.
func NewUtils(awsConfig ConfigAWS, logger LoggerInterface, debug bool) *Utils { func NewUtils(awsConfig ConfigAWS, logger LoggerInterface, debug bool) *Utils {
return &Utils{ return &Utils{
IsDebug: debug, IsDebug: debug,
@ -93,7 +93,7 @@ func NewUtils(awsConfig ConfigAWS, logger LoggerInterface, debug bool) *Utils {
} }
} }
// resetUtils // resetUtils.
func (u *Utils) resetUtils(awsConfig ConfigAWS, debug bool, tokenCounter uint32) { func (u *Utils) resetUtils(awsConfig ConfigAWS, debug bool, tokenCounter uint32) {
u.TokenCounter = tokenCounter u.TokenCounter = tokenCounter
u.ConfigAWS = awsConfig u.ConfigAWS = awsConfig
@ -108,7 +108,7 @@ func (u *Utils) GenerateToken() string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%d%d", time.Now().UnixNano(), c)))) return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%d%d", time.Now().UnixNano(), c))))
} }
// GetAPIClient will initialize RetailCRM api client from url and key // GetAPIClient will initialize RetailCRM api client from url and key.
func (u *Utils) GetAPIClient(url, key string) (*v5.Client, int, error) { func (u *Utils) GetAPIClient(url, key string) (*v5.Client, int, error) {
client := v5.New(url, key) client := v5.New(url, key)
client.Debug = u.IsDebug client.Debug = u.IsDebug
@ -117,7 +117,6 @@ func (u *Utils) GetAPIClient(url, key string) (*v5.Client, int, error) {
if e != nil && e.Error() != "" { if e != nil && e.Error() != "" {
u.Logger.Error(url, status, e.Error(), cr) u.Logger.Error(url, status, e.Error(), cr)
return nil, http.StatusInternalServerError, errors.New(e.Error()) return nil, http.StatusInternalServerError, errors.New(e.Error())
} }
if !cr.Success { if !cr.Success {
@ -166,7 +165,7 @@ func (u *Utils) checkCredentials(credential []string) []string {
return rc return rc
} }
// UploadUserAvatar will upload avatar for user // UploadUserAvatar will upload avatar for user.
func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) { func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) {
s3Config := &aws.Config{ s3Config := &aws.Config{
Credentials: credentials.NewStaticCredentials( Credentials: credentials.NewStaticCredentials(
@ -206,12 +205,12 @@ func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) {
return return
} }
// RemoveTrailingSlash will remove slash at the end of any string // RemoveTrailingSlash will remove slash at the end of any string.
func (u *Utils) RemoveTrailingSlash(crmURL string) string { func (u *Utils) RemoveTrailingSlash(crmURL string) string {
return u.slashRegex.ReplaceAllString(crmURL, ``) return u.slashRegex.ReplaceAllString(crmURL, ``)
} }
// GetMGItemData will upload file to MG by URL and return information about attachable item // GetMGItemData will upload file to MG by URL and return information about attachable item.
func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, int, error) { func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, int, error) {
item := v1.Item{} item := v1.Item{}
@ -230,7 +229,7 @@ func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, in
return item, st, err return item, st, err
} }
// GetEntitySHA1 will serialize any value to JSON and return SHA1 hash of this JSON // GetEntitySHA1 will serialize any value to JSON and return SHA1 hash of this JSON.
func GetEntitySHA1(v interface{}) (hash string, err error) { func GetEntitySHA1(v interface{}) (hash string, err error) {
res, _ := json.Marshal(v) res, _ := json.Marshal(v)
@ -242,7 +241,7 @@ func GetEntitySHA1(v interface{}) (hash string, err error) {
return return
} }
// ReplaceMarkdownSymbols will remove markdown symbols from text // ReplaceMarkdownSymbols will remove markdown symbols from text.
func ReplaceMarkdownSymbols(s string) string { func ReplaceMarkdownSymbols(s string) string {
for _, v := range markdownSymbols { for _, v := range markdownSymbols {
s = strings.Replace(s, v, "\\"+v, -1) s = strings.Replace(s, v, "\\"+v, -1)
@ -251,13 +250,13 @@ func ReplaceMarkdownSymbols(s string) string {
return s return s
} }
// DefaultCurrencies will return default currencies list for all bots // DefaultCurrencies will return default currencies list for all bots.
func DefaultCurrencies() map[string]string { func DefaultCurrencies() map[string]string {
return defaultCurrencies return defaultCurrencies
} }
// GetCurrencySymbol returns currency symbol by it's ISO 4127 code. // GetCurrencySymbol returns currency symbol by it's ISO 4127 code.
// It returns provided currency code in uppercase if currency symbol cannot be found // It returns provided currency code in uppercase if currency symbol cannot be found.
func GetCurrencySymbol(code string) string { func GetCurrencySymbol(code string) string {
if i, ok := DefaultCurrencies()[strings.ToLower(code)]; ok { if i, ok := DefaultCurrencies()[strings.ToLower(code)]; ok {
return i return i

View File

@ -243,7 +243,7 @@ func TestUtils_GetEntitySHA1(t *testing.T) {
} }
func TestUtils_GetCurrencySymbol(t *testing.T) { func TestUtils_GetCurrencySymbol(t *testing.T) {
for code, _ := range DefaultCurrencies() { for code := range DefaultCurrencies() {
if strings.ToUpper(code) == defaultCurrencies[code] { if strings.ToUpper(code) == defaultCurrencies[code] {
continue continue
} }

View File

@ -5,7 +5,7 @@ import (
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
) )
// init here will register `validatecrmurl` function for gin validator // init here will register `validatecrmurl` function for gin validator.
func init() { func init() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok { if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
if err := v.RegisterValidation("validatecrmurl", validateCrmURL); err != nil { if err := v.RegisterValidation("validatecrmurl", validateCrmURL); err != nil {
@ -14,7 +14,7 @@ func init() {
} }
} }
// validateCrmURL will validate CRM URL // validateCrmURL will validate CRM URL.
func validateCrmURL(fl validator.FieldLevel) bool { func validateCrmURL(fl validator.FieldLevel) bool {
return regCommandName.Match([]byte(fl.Field().String())) return regCommandName.Match([]byte(fl.Field().String()))
} }