mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2024-11-22 05:06:04 +03:00
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:
parent
2eb1b78871
commit
d15ed7ffec
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -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
197
.golangci.yml
Normal 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
|
@ -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 (
|
||||||
|
@ -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
|
||||||
|
30
core/csrf.go
30
core/csrf.go
@ -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:
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -164,7 +164,7 @@ func (l *LocalizerTest) Test_Clone() {
|
|||||||
|
|
||||||
localizer := l.localizer.Clone()
|
localizer := l.localizer.Clone()
|
||||||
localizer.SetLanguage(language.Russian)
|
localizer.SetLanguage(language.Russian)
|
||||||
|
|
||||||
assert.NotEqual(l.T(), l.localizer.LanguageTag, localizer.LanguageTag)
|
assert.NotEqual(l.T(), l.localizer.LanguageTag, localizer.LanguageTag)
|
||||||
assert.Equal(l.T(), "Test message", l.localizer.GetLocalizedMessage("message"))
|
assert.Equal(l.T(), "Test message", l.localizer.GetLocalizedMessage("message"))
|
||||||
assert.Equal(l.T(), "Тестовое сообщение", localizer.GetLocalizedMessage("message"))
|
assert.Equal(l.T(), "Тестовое сообщение", localizer.GetLocalizedMessage("message"))
|
||||||
@ -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{}
|
||||||
|
@ -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()
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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{}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user