mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2024-11-21 20:56: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
|
||||
|
||||
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:
|
||||
name: Tests
|
||||
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"
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
|
||||
"github.com/retailcrm/mg-transport-core/core"
|
||||
)
|
||||
|
||||
// Options for tool command
|
||||
// Options for tool command.
|
||||
type Options struct{}
|
||||
|
||||
var (
|
||||
|
@ -21,7 +21,7 @@ var (
|
||||
slashRegex = regexp.MustCompile(`/+$`)
|
||||
)
|
||||
|
||||
// ConfigInterface settings data structure
|
||||
// ConfigInterface settings data structure.
|
||||
type ConfigInterface interface {
|
||||
GetVersion() string
|
||||
GetSentryDSN() string
|
||||
@ -35,14 +35,14 @@ type ConfigInterface interface {
|
||||
IsDebug() bool
|
||||
}
|
||||
|
||||
// InfoInterface transport settings data structure
|
||||
// InfoInterface transport settings data structure.
|
||||
type InfoInterface interface {
|
||||
GetName() string
|
||||
GetCode() string
|
||||
GetLogoPath() string
|
||||
}
|
||||
|
||||
// Config struct
|
||||
// Config struct.
|
||||
type Config struct {
|
||||
Version string `yaml:"version"`
|
||||
LogLevel logging.Level `yaml:"log_level"`
|
||||
@ -56,14 +56,14 @@ type Config struct {
|
||||
HTTPClientConfig *HTTPClientConfig `yaml:"http_client"`
|
||||
}
|
||||
|
||||
// Info struct
|
||||
// Info struct.
|
||||
type Info struct {
|
||||
Name string `yaml:"name"`
|
||||
Code string `yaml:"code"`
|
||||
LogoPath string `yaml:"logo_path"`
|
||||
}
|
||||
|
||||
// ConfigAWS struct
|
||||
// ConfigAWS struct.
|
||||
type ConfigAWS struct {
|
||||
AccessKeyID string `yaml:"access_key_id"`
|
||||
SecretAccessKey string `yaml:"secret_access_key"`
|
||||
@ -73,7 +73,7 @@ type ConfigAWS struct {
|
||||
ContentType string `yaml:"content_type"`
|
||||
}
|
||||
|
||||
// DatabaseConfig struct
|
||||
// DatabaseConfig struct.
|
||||
type DatabaseConfig struct {
|
||||
Connection interface{} `yaml:"connection"`
|
||||
Logging bool `yaml:"logging"`
|
||||
@ -83,7 +83,7 @@ type DatabaseConfig struct {
|
||||
ConnectionLifetime int `yaml:"connection_lifetime"`
|
||||
}
|
||||
|
||||
// HTTPClientConfig struct
|
||||
// HTTPClientConfig struct.
|
||||
type HTTPClientConfig struct {
|
||||
Timeout time.Duration `yaml:"timeout"`
|
||||
SSLVerification *bool `yaml:"ssl_verification"`
|
||||
@ -91,7 +91,7 @@ type HTTPClientConfig struct {
|
||||
MockedDomains []string `yaml:"mocked_domains"`
|
||||
}
|
||||
|
||||
// HTTPServerConfig struct
|
||||
// HTTPServerConfig struct.
|
||||
type HTTPServerConfig struct {
|
||||
Host string `yaml:"host"`
|
||||
Listen string `yaml:"listen"`
|
||||
@ -104,12 +104,12 @@ func NewConfig(path string) *Config {
|
||||
return (&Config{}).LoadConfig(path)
|
||||
}
|
||||
|
||||
// LoadConfig read & load configuration file
|
||||
// LoadConfig read & load configuration file.
|
||||
func (c *Config) LoadConfig(path string) *Config {
|
||||
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 {
|
||||
if err := yaml.Unmarshal(data, c); err != nil {
|
||||
panic(err)
|
||||
@ -118,7 +118,7 @@ func (c *Config) LoadConfigFromData(data []byte) *Config {
|
||||
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 {
|
||||
var err error
|
||||
|
||||
@ -135,72 +135,72 @@ func (c *Config) GetConfigData(path string) []byte {
|
||||
return source
|
||||
}
|
||||
|
||||
// GetSentryDSN sentry connection dsn
|
||||
// GetSentryDSN sentry connection dsn.
|
||||
func (c Config) GetSentryDSN() string {
|
||||
return c.SentryDSN
|
||||
}
|
||||
|
||||
// GetVersion transport version
|
||||
// GetVersion transport version.
|
||||
func (c Config) GetVersion() string {
|
||||
return c.Version
|
||||
}
|
||||
|
||||
// GetLogLevel log level
|
||||
// GetLogLevel log level.
|
||||
func (c Config) GetLogLevel() logging.Level {
|
||||
return c.LogLevel
|
||||
}
|
||||
|
||||
// GetTransportInfo transport basic data
|
||||
// GetTransportInfo transport basic data.
|
||||
func (c Config) GetTransportInfo() InfoInterface {
|
||||
return c.TransportInfo
|
||||
}
|
||||
|
||||
// IsDebug debug flag
|
||||
// IsDebug debug flag.
|
||||
func (c Config) IsDebug() bool {
|
||||
return c.Debug
|
||||
}
|
||||
|
||||
// GetAWSConfig AWS configuration
|
||||
// GetAWSConfig AWS configuration.
|
||||
func (c Config) GetAWSConfig() ConfigAWS {
|
||||
return c.ConfigAWS
|
||||
}
|
||||
|
||||
// GetDBConfig database configuration
|
||||
// GetDBConfig database configuration.
|
||||
func (c Config) GetDBConfig() DatabaseConfig {
|
||||
return c.Database
|
||||
}
|
||||
|
||||
// GetHTTPConfig server configuration
|
||||
// GetHTTPConfig server configuration.
|
||||
func (c Config) GetHTTPConfig() HTTPServerConfig {
|
||||
return c.HTTPServer
|
||||
}
|
||||
|
||||
// GetUpdateInterval user data update interval
|
||||
// GetUpdateInterval user data update interval.
|
||||
func (c Config) GetUpdateInterval() int {
|
||||
return c.UpdateInterval
|
||||
}
|
||||
|
||||
// GetHTTPClientConfig returns http client config
|
||||
// GetHTTPClientConfig returns http client config.
|
||||
func (c Config) GetHTTPClientConfig() *HTTPClientConfig {
|
||||
return c.HTTPClientConfig
|
||||
}
|
||||
|
||||
// GetName transport name
|
||||
// GetName transport name.
|
||||
func (t Info) GetName() string {
|
||||
return t.Name
|
||||
}
|
||||
|
||||
// GetCode transport code
|
||||
// GetCode transport code.
|
||||
func (t Info) GetCode() string {
|
||||
return t.Code
|
||||
}
|
||||
|
||||
// GetLogoPath transport logo
|
||||
// GetLogoPath transport logo.
|
||||
func (t Info) GetLogoPath() string {
|
||||
return t.LogoPath
|
||||
}
|
||||
|
||||
// IsSSLVerificationEnabled returns SSL verification flag (default is true)
|
||||
// IsSSLVerificationEnabled returns SSL verification flag (default is true).
|
||||
func (h *HTTPClientConfig) IsSSLVerificationEnabled() bool {
|
||||
if h.SSLVerification == nil {
|
||||
return true
|
||||
|
30
core/csrf.go
30
core/csrf.go
@ -15,33 +15,33 @@ import (
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
// CSRFErrorReason is a error reason type
|
||||
// CSRFErrorReason is a error reason type.
|
||||
type CSRFErrorReason uint8
|
||||
|
||||
// CSRFTokenGetter func type
|
||||
// CSRFTokenGetter func type.
|
||||
type CSRFTokenGetter func(*gin.Context) string
|
||||
|
||||
// CSRFAbortFunc is a callback which
|
||||
// CSRFAbortFunc is a callback which.
|
||||
type CSRFAbortFunc func(*gin.Context, CSRFErrorReason)
|
||||
|
||||
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
|
||||
|
||||
// CSRFErrorCannotStoreTokenInSession will be returned if middleware cannot store token in session
|
||||
// CSRFErrorCannotStoreTokenInSession will be returned if middleware cannot store token in session.
|
||||
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
|
||||
|
||||
// CSRFErrorEmptyToken will be returned if token in session is empty
|
||||
// CSRFErrorEmptyToken will be returned if token in session is empty.
|
||||
CSRFErrorEmptyToken
|
||||
|
||||
// CSRFErrorTokenMismatch will be returned in case of invalid token
|
||||
// CSRFErrorTokenMismatch will be returned in case of invalid token.
|
||||
CSRFErrorTokenMismatch
|
||||
)
|
||||
|
||||
// DefaultCSRFTokenGetter default getter
|
||||
// DefaultCSRFTokenGetter default getter.
|
||||
var DefaultCSRFTokenGetter = func(c *gin.Context) string {
|
||||
r := c.Request
|
||||
|
||||
@ -65,7 +65,7 @@ var DefaultCSRFTokenGetter = func(c *gin.Context) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// DefaultIgnoredMethods ignored methods for CSRF verifier middleware
|
||||
// DefaultIgnoredMethods ignored methods for CSRF verifier middleware.
|
||||
var DefaultIgnoredMethods = []string{"GET", "HEAD", "OPTIONS"}
|
||||
|
||||
// CSRF struct. Provides CSRF token verification.
|
||||
@ -124,7 +124,7 @@ func NewCSRF(salt, secret, sessionName string, store sessions.Store, abortFunc C
|
||||
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 {
|
||||
exists := false
|
||||
|
||||
@ -138,7 +138,7 @@ func (x *CSRF) strInSlice(slice []string, v string) bool {
|
||||
return exists
|
||||
}
|
||||
|
||||
// generateCSRFToken generates new CSRF token
|
||||
// generateCSRFToken generates new CSRF token.
|
||||
func (x *CSRF) generateCSRFToken() string {
|
||||
// nolint:gosec
|
||||
h := sha1.New()
|
||||
@ -166,7 +166,7 @@ func (x *CSRF) generateSalt() string {
|
||||
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 {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
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 {
|
||||
s.Values["csrf_token"] = x.generateCSRFToken()
|
||||
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 {
|
||||
switch r {
|
||||
case CSRFErrorNoTokenInSession:
|
||||
|
@ -23,7 +23,7 @@ var DefaultHTTPClientConfig = &HTTPClientConfig{
|
||||
SSLVerification: &boolTrue,
|
||||
}
|
||||
|
||||
// Engine struct
|
||||
// Engine struct.
|
||||
type Engine struct {
|
||||
Localizer
|
||||
ORM
|
||||
@ -42,7 +42,8 @@ type Engine struct {
|
||||
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 {
|
||||
return &Engine{
|
||||
Config: nil,
|
||||
@ -77,7 +78,7 @@ func (e *Engine) initGin() {
|
||||
e.ginEngine = r
|
||||
}
|
||||
|
||||
// Prepare engine for start
|
||||
// Prepare engine for start.
|
||||
func (e *Engine) Prepare() *Engine {
|
||||
if e.prepared {
|
||||
panic("engine already initialized")
|
||||
@ -119,7 +120,7 @@ func (e *Engine) Prepare() *Engine {
|
||||
return e
|
||||
}
|
||||
|
||||
// TemplateFuncMap combines func map for templates
|
||||
// TemplateFuncMap combines func map for templates.
|
||||
func (e *Engine) TemplateFuncMap(functions template.FuncMap) template.FuncMap {
|
||||
funcMap := e.LocalizationFuncMap()
|
||||
|
||||
@ -134,14 +135,14 @@ func (e *Engine) TemplateFuncMap(functions template.FuncMap) template.FuncMap {
|
||||
return funcMap
|
||||
}
|
||||
|
||||
// CreateRenderer with translation function
|
||||
// CreateRenderer with translation function.
|
||||
func (e *Engine) CreateRenderer(callback func(*Renderer), funcs template.FuncMap) Renderer {
|
||||
renderer := NewRenderer(e.TemplateFuncMap(funcs))
|
||||
callback(&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 {
|
||||
renderer := NewRenderer(e.TemplateFuncMap(funcs))
|
||||
renderer.TemplatesBox = box
|
||||
@ -149,7 +150,7 @@ func (e *Engine) CreateRendererFS(box *packr.Box, callback func(*Renderer), func
|
||||
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 {
|
||||
if !e.prepared {
|
||||
panic("prepare engine first")
|
||||
@ -161,7 +162,7 @@ func (e *Engine) Router() *gin.Engine {
|
||||
return e.ginEngine
|
||||
}
|
||||
|
||||
// JobManager will return singleton JobManager from Engine
|
||||
// JobManager will return singleton JobManager from Engine.
|
||||
func (e *Engine) JobManager() *JobManager {
|
||||
if e.jobManager == nil {
|
||||
e.jobManager = NewJobManager().SetLogger(e.Logger()).SetLogging(e.Config.IsDebug())
|
||||
@ -170,12 +171,12 @@ func (e *Engine) JobManager() *JobManager {
|
||||
return e.jobManager
|
||||
}
|
||||
|
||||
// Logger returns current logger
|
||||
// Logger returns current logger.
|
||||
func (e *Engine) Logger() LoggerInterface {
|
||||
return e.logger
|
||||
}
|
||||
|
||||
// SetLogger sets provided logger instance to engine
|
||||
// SetLogger sets provided logger instance to engine.
|
||||
func (e *Engine) SetLogger(l LoggerInterface) *Engine {
|
||||
if l == nil {
|
||||
return e
|
||||
@ -187,7 +188,7 @@ func (e *Engine) SetLogger(l LoggerInterface) *Engine {
|
||||
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 {
|
||||
client, err := NewHTTPClientBuilder().
|
||||
WithLogger(e.Logger()).
|
||||
@ -205,7 +206,7 @@ func (e *Engine) BuildHTTPClient(certs *x509.CertPool, replaceDefault ...bool) *
|
||||
return e
|
||||
}
|
||||
|
||||
// GetHTTPClientConfig returns configuration for HTTP client
|
||||
// GetHTTPClientConfig returns configuration for HTTP client.
|
||||
func (e *Engine) GetHTTPClientConfig() *HTTPClientConfig {
|
||||
if e.Config.GetHTTPClientConfig() != nil {
|
||||
return e.Config.GetHTTPClientConfig()
|
||||
@ -214,7 +215,7 @@ func (e *Engine) GetHTTPClientConfig() *HTTPClientConfig {
|
||||
return DefaultHTTPClientConfig
|
||||
}
|
||||
|
||||
// SetHTTPClient sets HTTP client to engine
|
||||
// SetHTTPClient sets HTTP client to engine.
|
||||
func (e *Engine) SetHTTPClient(client *http.Client) *Engine {
|
||||
if client != nil {
|
||||
e.httpClient = client
|
||||
@ -223,7 +224,7 @@ func (e *Engine) SetHTTPClient(client *http.Client) *Engine {
|
||||
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 {
|
||||
if e.httpClient == nil {
|
||||
return http.DefaultClient
|
||||
@ -292,7 +293,7 @@ func (e *Engine) GenerateCSRFMiddleware() gin.HandlerFunc {
|
||||
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 {
|
||||
if e.csrf == nil {
|
||||
panic("csrf is not initialized")
|
||||
@ -301,13 +302,13 @@ func (e *Engine) GetCSRFToken(c *gin.Context) string {
|
||||
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 {
|
||||
callback(e.Router())
|
||||
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 {
|
||||
return e.Router().Run(e.Config.GetHTTPConfig().Listen)
|
||||
}
|
||||
|
@ -2,12 +2,12 @@ package core
|
||||
|
||||
import "net/http"
|
||||
|
||||
// ErrorResponse struct
|
||||
// ErrorResponse struct.
|
||||
type ErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// ErrorsResponse struct
|
||||
// ErrorsResponse struct.
|
||||
type ErrorsResponse struct {
|
||||
Error []string `json:"error"`
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DefaultClient stores original http.DefaultClient
|
||||
// DefaultClient stores original http.DefaultClient.
|
||||
var DefaultClient = http.DefaultClient
|
||||
|
||||
// DefaultTransport stores original http.DefaultTransport
|
||||
// DefaultTransport stores original http.DefaultTransport.
|
||||
var DefaultTransport = http.DefaultTransport
|
||||
|
||||
// HTTPClientBuilder builds http client with mocks (if necessary) and timeout.
|
||||
@ -57,7 +57,7 @@ type HTTPClientBuilder struct {
|
||||
mockedDomains []string
|
||||
}
|
||||
|
||||
// NewHTTPClientBuilder returns HTTPClientBuilder with default values
|
||||
// NewHTTPClientBuilder returns HTTPClientBuilder with default values.
|
||||
func NewHTTPClientBuilder() *HTTPClientBuilder {
|
||||
return &HTTPClientBuilder{
|
||||
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 {
|
||||
if logger != nil {
|
||||
b.logger = logger
|
||||
@ -79,7 +79,7 @@ func (b *HTTPClientBuilder) WithLogger(logger LoggerInterface) *HTTPClientBuilde
|
||||
return b
|
||||
}
|
||||
|
||||
// SetTimeout sets timeout for http client
|
||||
// SetTimeout sets timeout for http client.
|
||||
func (b *HTTPClientBuilder) SetTimeout(seconds time.Duration) *HTTPClientBuilder {
|
||||
seconds = seconds * time.Second
|
||||
b.timeout = seconds
|
||||
@ -87,25 +87,25 @@ func (b *HTTPClientBuilder) SetTimeout(seconds time.Duration) *HTTPClientBuilder
|
||||
return b
|
||||
}
|
||||
|
||||
// SetMockAddress sets mock address
|
||||
// SetMockAddress sets mock address.
|
||||
func (b *HTTPClientBuilder) SetMockAddress(address string) *HTTPClientBuilder {
|
||||
b.mockAddress = address
|
||||
return b
|
||||
}
|
||||
|
||||
// AddMockedDomain adds new mocked domain
|
||||
// AddMockedDomain adds new mocked domain.
|
||||
func (b *HTTPClientBuilder) AddMockedDomain(domain string) *HTTPClientBuilder {
|
||||
b.mockedDomains = append(b.mockedDomains, domain)
|
||||
return b
|
||||
}
|
||||
|
||||
// SetMockedDomains sets mocked domains from slice
|
||||
// SetMockedDomains sets mocked domains from slice.
|
||||
func (b *HTTPClientBuilder) SetMockedDomains(domains []string) *HTTPClientBuilder {
|
||||
b.mockedDomains = domains
|
||||
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 {
|
||||
if b.httpTransport.TLSClientConfig == nil {
|
||||
b.httpTransport.TLSClientConfig = &tls.Config{}
|
||||
@ -116,7 +116,7 @@ func (b *HTTPClientBuilder) SetSSLVerification(enabled bool) *HTTPClientBuilder
|
||||
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 {
|
||||
if b.httpTransport.TLSClientConfig == nil {
|
||||
b.httpTransport.TLSClientConfig = &tls.Config{}
|
||||
@ -127,13 +127,13 @@ func (b *HTTPClientBuilder) SetCertPool(pool *x509.CertPool) *HTTPClientBuilder
|
||||
return b
|
||||
}
|
||||
|
||||
// SetLogging enables or disables logging in mocks
|
||||
// SetLogging enables or disables logging in mocks.
|
||||
func (b *HTTPClientBuilder) SetLogging(flag bool) *HTTPClientBuilder {
|
||||
b.logging = flag
|
||||
return b
|
||||
}
|
||||
|
||||
// FromConfig fulfills mock configuration from HTTPClientConfig
|
||||
// FromConfig fulfills mock configuration from HTTPClientConfig.
|
||||
func (b *HTTPClientBuilder) FromConfig(config *HTTPClientConfig) *HTTPClientBuilder {
|
||||
if config == nil {
|
||||
return b
|
||||
@ -153,12 +153,12 @@ func (b *HTTPClientBuilder) FromConfig(config *HTTPClientConfig) *HTTPClientBuil
|
||||
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 {
|
||||
return b.FromConfig(engine.GetHTTPClientConfig())
|
||||
}
|
||||
|
||||
// buildDialer initializes dialer with provided timeout
|
||||
// buildDialer initializes dialer with provided timeout.
|
||||
func (b *HTTPClientBuilder) buildDialer() *HTTPClientBuilder {
|
||||
b.dialer = &net.Dialer{
|
||||
Timeout: b.timeout,
|
||||
@ -168,7 +168,7 @@ func (b *HTTPClientBuilder) buildDialer() *HTTPClientBuilder {
|
||||
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 {
|
||||
if b.mockAddress == "" {
|
||||
return nil
|
||||
@ -184,7 +184,7 @@ func (b *HTTPClientBuilder) parseAddress() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildMocks builds mocks for http client
|
||||
// buildMocks builds mocks for http client.
|
||||
func (b *HTTPClientBuilder) buildMocks() error {
|
||||
if b.dialer == nil {
|
||||
return errors.New("dialer must be built first")
|
||||
@ -229,7 +229,7 @@ func (b *HTTPClientBuilder) buildMocks() error {
|
||||
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{}) {
|
||||
if b.logging {
|
||||
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 {
|
||||
if b.built {
|
||||
http.DefaultClient = b.httpClient
|
||||
@ -250,7 +250,7 @@ func (b *HTTPClientBuilder) ReplaceDefault() *HTTPClientBuilder {
|
||||
return b
|
||||
}
|
||||
|
||||
// RestoreDefault restores default client and transport after replacement
|
||||
// RestoreDefault restores default client and transport after replacement.
|
||||
func (b *HTTPClientBuilder) RestoreDefault() *HTTPClientBuilder {
|
||||
http.DefaultClient = DefaultClient
|
||||
http.DefaultTransport = DefaultTransport
|
||||
@ -258,7 +258,7 @@ func (b *HTTPClientBuilder) RestoreDefault() *HTTPClientBuilder {
|
||||
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) {
|
||||
if err := b.buildDialer().parseAddress(); err != nil {
|
||||
return nil, err
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"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
|
||||
|
||||
// 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{})
|
||||
|
||||
// JobErrorHandler is a function to handle jobs errors. First argument is a job name.
|
||||
@ -56,7 +56,7 @@ type JobManager struct {
|
||||
logger LoggerInterface
|
||||
}
|
||||
|
||||
// getWrappedFunc wraps job into function
|
||||
// getWrappedFunc wraps job into function.
|
||||
func (j *Job) getWrappedFunc(name string, log JobLogFunc) func() {
|
||||
return 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) {
|
||||
return func(stopChannel chan bool) {
|
||||
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 {
|
||||
j.writeLock.RLock()
|
||||
|
||||
@ -104,7 +104,7 @@ func (j *Job) run(name string, log JobLogFunc) *Job {
|
||||
return j
|
||||
}
|
||||
|
||||
// stop running job
|
||||
// stop running job.
|
||||
func (j *Job) stop() *Job {
|
||||
j.writeLock.RLock()
|
||||
|
||||
@ -123,24 +123,24 @@ func (j *Job) stop() *Job {
|
||||
return j
|
||||
}
|
||||
|
||||
// runOnce run job once
|
||||
// runOnce run job once.
|
||||
func (j *Job) runOnce(name string, log JobLogFunc) *Job {
|
||||
go j.getWrappedFunc(name, log)()
|
||||
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 {
|
||||
j.getWrappedFunc(name, log)()
|
||||
return j
|
||||
}
|
||||
|
||||
// NewJobManager is a JobManager constructor
|
||||
// NewJobManager is a JobManager constructor.
|
||||
func NewJobManager() *JobManager {
|
||||
return &JobManager{jobs: &sync.Map{}}
|
||||
}
|
||||
|
||||
// DefaultJobErrorHandler returns default error handler for a job
|
||||
// DefaultJobErrorHandler returns default error handler for a job.
|
||||
func DefaultJobErrorHandler() JobErrorHandler {
|
||||
return func(name string, err error, log JobLogFunc) {
|
||||
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 {
|
||||
return func(name string, recoverValue interface{}, log JobLogFunc) {
|
||||
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 {
|
||||
if logger != nil {
|
||||
j.logger = logger
|
||||
@ -167,13 +167,13 @@ func (j *JobManager) SetLogger(logger LoggerInterface) *JobManager {
|
||||
return j
|
||||
}
|
||||
|
||||
// SetLogging enables or disables JobManager logging
|
||||
// SetLogging enables or disables JobManager logging.
|
||||
func (j *JobManager) SetLogging(enableLogging bool) *JobManager {
|
||||
j.enableLogging = enableLogging
|
||||
return j
|
||||
}
|
||||
|
||||
// RegisterJob registers new job
|
||||
// RegisterJob registers new job.
|
||||
func (j *JobManager) RegisterJob(name string, job *Job) error {
|
||||
if job == 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)
|
||||
}
|
||||
|
||||
// FetchJob fetches already exist job
|
||||
// FetchJob fetches already exist job.
|
||||
func (j *JobManager) FetchJob(name string) (value *Job, ok bool) {
|
||||
if i, ok := j.jobs.Load(name); ok {
|
||||
if job, ok := i.(*Job); ok {
|
||||
@ -209,7 +209,7 @@ func (j *JobManager) FetchJob(name string) (value *Job, ok bool) {
|
||||
return &Job{}, false
|
||||
}
|
||||
|
||||
// UpdateJob updates job
|
||||
// UpdateJob updates job.
|
||||
func (j *JobManager) UpdateJob(name string, job *Job) error {
|
||||
if job, ok := j.FetchJob(name); ok {
|
||||
_ = j.UnregisterJob(name)
|
||||
@ -259,7 +259,7 @@ func (j *JobManager) RunJobOnceSync(name string) error {
|
||||
return fmt.Errorf("cannot find job `%s`", name)
|
||||
}
|
||||
|
||||
// Start all jobs in the manager
|
||||
// Start all jobs in the manager.
|
||||
func (j *JobManager) Start() {
|
||||
j.jobs.Range(func(key, value interface{}) bool {
|
||||
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{}) {
|
||||
if !j.enableLogging {
|
||||
return
|
||||
|
@ -14,20 +14,20 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// DefaultLanguages for transports
|
||||
// DefaultLanguages for transports.
|
||||
var DefaultLanguages = []language.Tag{
|
||||
language.English,
|
||||
language.Russian,
|
||||
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
|
||||
|
||||
// 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"
|
||||
|
||||
// Localizer struct
|
||||
// Localizer struct.
|
||||
type Localizer struct {
|
||||
i18nStorage *sync.Map
|
||||
TranslationsBox *packr.Box
|
||||
@ -70,17 +70,17 @@ func NewLocalizerFS(locale language.Tag, matcher language.Matcher, translationsB
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
bundle := i18n.NewBundle(tag)
|
||||
bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal)
|
||||
@ -151,14 +151,14 @@ func (l *Localizer) createLocaleBundleByTag(tag language.Tag) *i18n.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() {
|
||||
defer l.loadMutex.Unlock()
|
||||
l.loadMutex.Lock()
|
||||
l.getCurrentLocalizer()
|
||||
}
|
||||
|
||||
// loadTranslationsToBundle loads translations to provided bundle
|
||||
// loadTranslationsToBundle loads translations to provided bundle.
|
||||
func (l *Localizer) loadTranslationsToBundle(i18nBundle *i18n.Bundle) {
|
||||
switch {
|
||||
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 {
|
||||
files, err := ioutil.ReadDir(l.TranslationsPath)
|
||||
if err != nil {
|
||||
@ -190,7 +190,7 @@ func (l *Localizer) loadFromDirectory(i18nBundle *i18n.Bundle) error {
|
||||
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 {
|
||||
err := l.TranslationsBox.Walk(func(s string, file packd.File) error {
|
||||
if fileInfo, err := file.FileInfo(); err == nil {
|
||||
@ -217,7 +217,7 @@ func (l *Localizer) loadFromFS(i18nBundle *i18n.Bundle) error {
|
||||
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 {
|
||||
var localizer *i18n.Localizer
|
||||
|
||||
@ -247,24 +247,24 @@ func (l *Localizer) isUnd(tag language.Tag) bool {
|
||||
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 {
|
||||
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) {
|
||||
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) {
|
||||
for _, tag := range tags {
|
||||
l.getLocalizer(tag)
|
||||
}
|
||||
}
|
||||
|
||||
// SetLanguage will change language using language tag
|
||||
// SetLanguage will change language using language tag.
|
||||
func (l *Localizer) SetLanguage(tag language.Tag) {
|
||||
if l.isUnd(tag) {
|
||||
tag = DefaultLanguage
|
||||
@ -276,7 +276,7 @@ func (l *Localizer) SetLanguage(tag language.Tag) {
|
||||
|
||||
// FetchLanguage will load language from tag
|
||||
//
|
||||
// Deprecated: Use `(*core.Localizer).LoadTranslations()` instead
|
||||
// Deprecated: Use `(*core.Localizer).LoadTranslations()` instead.
|
||||
func (l *Localizer) FetchLanguage() {
|
||||
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) {
|
||||
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{}) {
|
||||
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) {
|
||||
if c == nil {
|
||||
return nil, false
|
||||
|
@ -164,7 +164,7 @@ func (l *LocalizerTest) Test_Clone() {
|
||||
|
||||
localizer := l.localizer.Clone()
|
||||
localizer.SetLanguage(language.Russian)
|
||||
|
||||
|
||||
assert.NotEqual(l.T(), l.localizer.LanguageTag, localizer.LanguageTag)
|
||||
assert.Equal(l.T(), "Test message", l.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)
|
||||
}
|
||||
|
||||
// getContextWithLang generates context with Accept-Language header
|
||||
// getContextWithLang generates context with Accept-Language header.
|
||||
func (l *LocalizerTest) getContextWithLang(tag language.Tag) *gin.Context {
|
||||
urlInstance, _ := url.Parse("https://example.com")
|
||||
headers := http.Header{}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"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 {
|
||||
Fatal(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.
|
||||
// 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 {
|
||||
logger *logging.Logger
|
||||
mutex *sync.RWMutex
|
||||
@ -55,14 +55,14 @@ func newInheritedLogger(transportCode string, logLevel logging.Level, logFormat
|
||||
return logger
|
||||
}
|
||||
|
||||
// DefaultLogFormatter will return default formatter for logs
|
||||
// DefaultLogFormatter will return default formatter for logs.
|
||||
func DefaultLogFormatter() logging.Formatter {
|
||||
return logging.MustStringFormatter(
|
||||
`%{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 {
|
||||
if l.mutex == nil {
|
||||
l.mutex = &sync.RWMutex{}
|
||||
@ -71,14 +71,14 @@ func (l *Logger) Exclusive() *Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
// lock locks logger
|
||||
// lock locks logger.
|
||||
func (l *Logger) lock() {
|
||||
if l.mutex != nil {
|
||||
l.mutex.Lock()
|
||||
}
|
||||
}
|
||||
|
||||
// unlock unlocks logger
|
||||
// unlock unlocks logger.
|
||||
func (l *Logger) unlock() {
|
||||
if l.mutex != nil {
|
||||
l.mutex.Unlock()
|
||||
|
@ -2,7 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
// "os"
|
||||
// "os/exec"
|
||||
// "os/exec".
|
||||
"testing"
|
||||
|
||||
"github.com/op/go-logging"
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"gopkg.in/gormigrate.v1"
|
||||
)
|
||||
|
||||
// migrations default GORMigrate tool
|
||||
// migrations default GORMigrate tool.
|
||||
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 {
|
||||
db *gorm.DB
|
||||
first *gormigrate.Migration
|
||||
@ -22,17 +22,17 @@ type Migrate struct {
|
||||
prepared bool
|
||||
}
|
||||
|
||||
// MigrationInfo with migration info
|
||||
// MigrationInfo with migration info.
|
||||
type MigrationInfo struct {
|
||||
ID string `gorm:"column:id; type:varchar(255)"`
|
||||
}
|
||||
|
||||
// TableName for MigrationInfo
|
||||
// TableName for MigrationInfo.
|
||||
func (MigrationInfo) TableName() string {
|
||||
return "migrations"
|
||||
}
|
||||
|
||||
// Migrations returns default migrate
|
||||
// Migrations returns default migrate.
|
||||
func Migrations() *Migrate {
|
||||
if migrations == nil {
|
||||
migrations = &Migrate{
|
||||
@ -45,7 +45,7 @@ func Migrations() *Migrate {
|
||||
return migrations
|
||||
}
|
||||
|
||||
// Add GORMigrate to migrate
|
||||
// Add GORMigrate to migrate.
|
||||
func (m *Migrate) Add(migration *gormigrate.Migration) {
|
||||
if migration == nil {
|
||||
return
|
||||
@ -54,13 +54,13 @@ func (m *Migrate) Add(migration *gormigrate.Migration) {
|
||||
m.migrations[migration.ID] = migration
|
||||
}
|
||||
|
||||
// SetDB to migrate
|
||||
// SetDB to migrate.
|
||||
func (m *Migrate) SetDB(db *gorm.DB) *Migrate {
|
||||
m.db = db
|
||||
return m
|
||||
}
|
||||
|
||||
// Migrate all, including schema initialization
|
||||
// Migrate all, including schema initialization.
|
||||
func (m *Migrate) Migrate() error {
|
||||
if err := m.prepareMigrations(); err != nil {
|
||||
return err
|
||||
@ -73,7 +73,7 @@ func (m *Migrate) Migrate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rollback all migrations
|
||||
// Rollback all migrations.
|
||||
func (m *Migrate) Rollback() error {
|
||||
if err := m.prepareMigrations(); err != nil {
|
||||
return err
|
||||
@ -94,7 +94,7 @@ func (m *Migrate) Rollback() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MigrateTo specified version
|
||||
// MigrateTo specified version.
|
||||
func (m *Migrate) MigrateTo(version string) error {
|
||||
if err := m.prepareMigrations(); err != nil {
|
||||
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 {
|
||||
if err := m.prepareMigrations(); err != nil {
|
||||
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 {
|
||||
if err := m.prepareMigrations(); err != nil {
|
||||
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 {
|
||||
if err := m.prepareMigrations(); err != nil {
|
||||
return err
|
||||
@ -164,7 +164,7 @@ func (m *Migrate) RollbackTo(version string) error {
|
||||
return m.GORMigrate.RollbackTo(version)
|
||||
}
|
||||
|
||||
// Current migration version
|
||||
// Current migration version.
|
||||
func (m *Migrate) Current() string {
|
||||
var migrationInfo MigrationInfo
|
||||
|
||||
@ -191,7 +191,7 @@ func (m *Migrate) Current() string {
|
||||
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) {
|
||||
for key, ver := range m.versions {
|
||||
if ver == version {
|
||||
@ -206,7 +206,7 @@ func (m *Migrate) NextFrom(version string) (string, error) {
|
||||
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) {
|
||||
for key, ver := range m.versions {
|
||||
if ver == version {
|
||||
@ -221,12 +221,12 @@ func (m *Migrate) PreviousFrom(version string) (string, error) {
|
||||
return "", errors.New("cannot find specified migration")
|
||||
}
|
||||
|
||||
// Close db connection
|
||||
// Close db connection.
|
||||
func (m *Migrate) Close() error {
|
||||
return m.db.Close()
|
||||
}
|
||||
|
||||
// prepareMigrations prepare migrate
|
||||
// prepareMigrations prepare migrate.
|
||||
func (m *Migrate) prepareMigrations() error {
|
||||
var (
|
||||
keys []string
|
||||
|
@ -30,12 +30,12 @@ func init() {
|
||||
}
|
||||
`
|
||||
|
||||
// NewMigrationCommand struct
|
||||
// NewMigrationCommand struct.
|
||||
type NewMigrationCommand struct {
|
||||
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 {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
@ -44,7 +44,7 @@ func (x *NewMigrationCommand) FileExists(filename string) bool {
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
// Execute migration generator command
|
||||
// Execute migration generator command.
|
||||
func (x *NewMigrationCommand) Execute(args []string) error {
|
||||
version := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
directory := path.Clean(x.Directory)
|
||||
|
@ -2,7 +2,7 @@ package core
|
||||
|
||||
import "time"
|
||||
|
||||
// Connection model
|
||||
// Connection model.
|
||||
type Connection struct {
|
||||
ID int `gorm:"primary_key"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// Account model
|
||||
// Account model.
|
||||
type Account struct {
|
||||
ID int `gorm:"primary_key"`
|
||||
ConnectionID int `gorm:"column:connection_id" json:"connectionId,omitempty"`
|
||||
@ -28,7 +28,7 @@ type Account struct {
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// User model
|
||||
// User model.
|
||||
type User struct {
|
||||
ID int `gorm:"primary_key"`
|
||||
ExternalID string `gorm:"column:external_id; type:varchar(255); not null; unique"`
|
||||
@ -49,5 +49,5 @@ func (User) TableName() string {
|
||||
return "mg_user"
|
||||
}
|
||||
|
||||
// Accounts list
|
||||
// Accounts list.
|
||||
type Accounts []Account
|
||||
|
@ -4,16 +4,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
// PostgreSQL is an default
|
||||
// PostgreSQL is an default.
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
)
|
||||
|
||||
// ORM struct
|
||||
// ORM struct.
|
||||
type ORM struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
// NewORM will init new database connection
|
||||
// NewORM will init new database connection.
|
||||
func NewORM(config DatabaseConfig) *ORM {
|
||||
orm := &ORM{}
|
||||
orm.createDB(config)
|
||||
@ -36,7 +36,7 @@ func (orm *ORM) createDB(config DatabaseConfig) {
|
||||
orm.DB = db
|
||||
}
|
||||
|
||||
// CloseDB close database connection
|
||||
// CloseDB close database connection.
|
||||
func (orm *ORM) CloseDB() {
|
||||
_ = orm.DB.Close()
|
||||
}
|
||||
|
@ -8,22 +8,23 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/retailcrm/mg-transport-core/core/stacktrace"
|
||||
|
||||
"github.com/getsentry/raven-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ErrorHandlerFunc will handle errors
|
||||
// ErrorHandlerFunc will handle errors.
|
||||
type ErrorHandlerFunc func(recovery interface{}, c *gin.Context)
|
||||
|
||||
// SentryTaggedTypes list
|
||||
// SentryTaggedTypes list.
|
||||
type SentryTaggedTypes []SentryTagged
|
||||
|
||||
// SentryTags list for SentryTaggedStruct. Format: name => property name
|
||||
// SentryTags list for SentryTaggedStruct. Format: name => property name.
|
||||
type SentryTags map[string]string
|
||||
|
||||
// SentryTagged interface for both tagged scalar and struct
|
||||
// SentryTagged interface for both tagged scalar and struct.
|
||||
type SentryTagged interface {
|
||||
BuildTags(interface{}) (map[string]string, error)
|
||||
GetContextKey() string
|
||||
@ -31,7 +32,7 @@ type SentryTagged interface {
|
||||
GetName() string
|
||||
}
|
||||
|
||||
// Sentry struct. Holds SentryTaggedStruct list
|
||||
// Sentry struct. Holds SentryTaggedStruct list.
|
||||
type Sentry struct {
|
||||
TaggedTypes SentryTaggedTypes
|
||||
Stacktrace bool
|
||||
@ -41,20 +42,20 @@ type Sentry struct {
|
||||
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 reflect.Type
|
||||
GinContextKey string
|
||||
Tags SentryTags
|
||||
}
|
||||
|
||||
// SentryTaggedScalar variable from context
|
||||
// SentryTaggedScalar variable from context.
|
||||
type SentryTaggedScalar struct {
|
||||
SentryTaggedStruct
|
||||
Name string
|
||||
}
|
||||
|
||||
// NewSentry constructor
|
||||
// NewSentry constructor.
|
||||
func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTypes, logger LoggerInterface, localizer *Localizer) *Sentry {
|
||||
sentry := &Sentry{
|
||||
DefaultError: defaultError,
|
||||
@ -67,7 +68,7 @@ func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTy
|
||||
return sentry
|
||||
}
|
||||
|
||||
// NewTaggedStruct constructor
|
||||
// NewTaggedStruct constructor.
|
||||
func NewTaggedStruct(sample interface{}, ginCtxKey string, tags map[string]string) *SentryTaggedStruct {
|
||||
n := make(map[string]string)
|
||||
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 {
|
||||
return &SentryTaggedScalar{
|
||||
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) {
|
||||
client, _ := raven.New(sentryDSN)
|
||||
s.Client = client
|
||||
}
|
||||
|
||||
// combineGinErrorHandlers calls several error handlers simultaneously
|
||||
// combineGinErrorHandlers calls several error handlers simultaneously.
|
||||
func (s *Sentry) combineGinErrorHandlers(handlers ...ErrorHandlerFunc) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
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 {
|
||||
defaultHandlers := []ErrorHandlerFunc{
|
||||
s.ErrorResponseHandler(),
|
||||
@ -132,7 +133,7 @@ func (s *Sentry) ErrorMiddleware() gin.HandlerFunc {
|
||||
return s.combineGinErrorHandlers(defaultHandlers...)
|
||||
}
|
||||
|
||||
// PanicLogger logs panic
|
||||
// PanicLogger logs panic.
|
||||
func (s *Sentry) PanicLogger() ErrorHandlerFunc {
|
||||
return func(recovery interface{}, c *gin.Context) {
|
||||
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 {
|
||||
return func(recovery interface{}, c *gin.Context) {
|
||||
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 {
|
||||
return func(recovery interface{}, c *gin.Context) {
|
||||
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 {
|
||||
return func(recovery interface{}, c *gin.Context) {
|
||||
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 {
|
||||
t.Tags[property] = name
|
||||
return t
|
||||
}
|
||||
|
||||
// GetTags is Tags getter
|
||||
// GetTags is Tags getter.
|
||||
func (t *SentryTaggedStruct) GetTags() SentryTags {
|
||||
return t.Tags
|
||||
}
|
||||
|
||||
// GetContextKey is GinContextKey getter
|
||||
// GetContextKey is GinContextKey getter.
|
||||
func (t *SentryTaggedStruct) GetContextKey() string {
|
||||
return t.GinContextKey
|
||||
}
|
||||
|
||||
// GetName is useless for SentryTaggedStruct
|
||||
// GetName is useless for SentryTaggedStruct.
|
||||
func (t *SentryTaggedStruct) GetName() string {
|
||||
return ""
|
||||
}
|
||||
@ -303,7 +304,7 @@ func (t *SentryTaggedStruct) GetProperty(v interface{}, property string) (name s
|
||||
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) {
|
||||
items := make(map[string]string)
|
||||
for prop, name := range t.Tags {
|
||||
@ -319,7 +320,7 @@ func (t *SentryTaggedStruct) BuildTags(v interface{}) (tags map[string]string, e
|
||||
return
|
||||
}
|
||||
|
||||
// valueToString convert reflect.Value to string representation
|
||||
// valueToString convert reflect.Value to string representation.
|
||||
func (t *SentryTaggedStruct) valueToString(field reflect.Value) string {
|
||||
k := field.Kind()
|
||||
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 {
|
||||
return SentryTags{}
|
||||
}
|
||||
|
||||
// GetContextKey is getter for GinContextKey
|
||||
// GetContextKey is getter for GinContextKey.
|
||||
func (t *SentryTaggedScalar) GetContextKey() string {
|
||||
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 {
|
||||
return t.Name
|
||||
}
|
||||
@ -377,7 +378,7 @@ func (t *SentryTaggedScalar) Get(v interface{}) (value string, err error) {
|
||||
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) {
|
||||
items = make(map[string]string)
|
||||
if value, e := t.Get(v); e == nil {
|
||||
|
@ -125,7 +125,7 @@ func (n *simpleError) Error() string {
|
||||
return n.msg
|
||||
}
|
||||
|
||||
// wrappableError is a simple implementation of wrappable error
|
||||
// wrappableError is a simple implementation of wrappable error.
|
||||
type wrappableError struct {
|
||||
msg string
|
||||
err error
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
"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")
|
||||
|
||||
// StackBuilderInterface is an interface for every stacktrace builder
|
||||
// StackBuilderInterface is an interface for every stacktrace builder.
|
||||
type StackBuilderInterface interface {
|
||||
SetClient(RavenClientInterface) StackBuilderInterface
|
||||
SetError(error) StackBuilderInterface
|
||||
@ -16,7 +16,7 @@ type StackBuilderInterface interface {
|
||||
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 {
|
||||
err error
|
||||
buildErr error
|
||||
@ -30,7 +30,7 @@ func (a *AbstractStackBuilder) SetClient(client RavenClientInterface) StackBuild
|
||||
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 {
|
||||
a.err = err
|
||||
return a
|
||||
@ -46,7 +46,7 @@ func (a *AbstractStackBuilder) GetResult() (*raven.Stacktrace, error) {
|
||||
return a.stack, a.buildErr
|
||||
}
|
||||
|
||||
// FallbackToGeneric fallbacks to GenericStackBuilder method
|
||||
// FallbackToGeneric fallbacks to GenericStackBuilder method.
|
||||
func (a *AbstractStackBuilder) FallbackToGeneric() {
|
||||
a.stack, a.err = GenericStack(a.client), nil
|
||||
}
|
||||
|
@ -4,27 +4,27 @@ import (
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
stack pkgErrors.StackTrace
|
||||
}
|
||||
|
||||
// NewPkgErrorsStackTransformer is a PkgErrorsStackTransformer constructor
|
||||
// NewPkgErrorsStackTransformer is a PkgErrorsStackTransformer constructor.
|
||||
func NewPkgErrorsStackTransformer(stack pkgErrors.StackTrace) *PkgErrorsStackTransformer {
|
||||
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 {
|
||||
if p.stack == nil {
|
||||
return Stacktrace{}
|
||||
@ -37,12 +37,12 @@ func (p *PkgErrorsStackTransformer) Stack() Stacktrace {
|
||||
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 {
|
||||
AbstractStackBuilder
|
||||
}
|
||||
|
||||
// Build stacktrace
|
||||
// Build stacktrace.
|
||||
func (b *PkgErrorsBuilder) Build() StackBuilderInterface {
|
||||
if !isPkgErrors(b.err) {
|
||||
b.buildErr = ErrUnfeasibleBuilder
|
||||
@ -69,7 +69,7 @@ func (b *PkgErrorsBuilder) Build() StackBuilderInterface {
|
||||
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 {
|
||||
causeable, ok := err.(PkgErrorCauseable)
|
||||
if !ok {
|
||||
@ -78,7 +78,8 @@ func (b *PkgErrorsBuilder) getErrorCause(err error) error {
|
||||
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 {
|
||||
traceable, ok := err.(PkgErrorTraceable)
|
||||
if !ok {
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"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 {
|
||||
msg string
|
||||
cause error
|
||||
|
@ -10,31 +10,32 @@ import (
|
||||
// Frame is a program counter inside a stack frame.
|
||||
type Frame uintptr
|
||||
|
||||
// Stacktrace is stack of Frames
|
||||
// Stacktrace is stack of Frames.
|
||||
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 {
|
||||
Stack() Stacktrace
|
||||
}
|
||||
|
||||
// RavenStacktraceBuilder builds *raven.Stacktrace for any generic stack data
|
||||
// RavenStacktraceBuilder builds *raven.Stacktrace for any generic stack data.
|
||||
type RavenStacktraceBuilder struct {
|
||||
transformer RavenStackTransformer
|
||||
}
|
||||
|
||||
// NewRavenStacktraceBuilder is a RavenStacktraceBuilder constructor
|
||||
// NewRavenStacktraceBuilder is a RavenStacktraceBuilder constructor.
|
||||
func NewRavenStacktraceBuilder(p RavenStackTransformer) *RavenStacktraceBuilder {
|
||||
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 {
|
||||
b.transformer = p
|
||||
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 {
|
||||
// This code is borrowed from github.com/getsentry/raven-go.NewStacktrace().
|
||||
var frames []*raven.StacktraceFrame
|
||||
@ -53,7 +54,7 @@ func (b *RavenStacktraceBuilder) Build(context int, appPackagePrefixes []string)
|
||||
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 {
|
||||
// This code is borrowed from github.com/pkg/errors.Frame.
|
||||
pc := uintptr(f) - 1
|
||||
|
@ -14,7 +14,7 @@ func GetStackBuilderByErrorType(err error) StackBuilderInterface {
|
||||
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 {
|
||||
_, okTraceable := err.(PkgErrorTraceable)
|
||||
_, okCauseable := err.(PkgErrorCauseable)
|
||||
|
@ -4,17 +4,17 @@ import (
|
||||
"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 {
|
||||
Unwrap() error
|
||||
}
|
||||
|
||||
// UnwrapBuilder builds stacktrace from the chain of wrapped errors
|
||||
// UnwrapBuilder builds stacktrace from the chain of wrapped errors.
|
||||
type UnwrapBuilder struct {
|
||||
AbstractStackBuilder
|
||||
}
|
||||
|
||||
// Build stacktrace
|
||||
// Build stacktrace.
|
||||
func (b *UnwrapBuilder) Build() StackBuilderInterface {
|
||||
if _, ok := b.err.(Unwrappable); !ok {
|
||||
b.buildErr = ErrUnfeasibleBuilder
|
||||
|
@ -23,7 +23,7 @@ func (n *simpleError) Error() string {
|
||||
return n.msg
|
||||
}
|
||||
|
||||
// wrappableError is a simple implementation of wrappable error
|
||||
// wrappableError is a simple implementation of wrappable error.
|
||||
type wrappableError struct {
|
||||
msg string
|
||||
err error
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"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 {
|
||||
multitemplate.Renderer
|
||||
TemplatesBox *packr.Box
|
||||
@ -15,22 +15,22 @@ type Renderer struct {
|
||||
alreadyAdded map[string]*template.Template
|
||||
}
|
||||
|
||||
// NewRenderer is a Renderer constructor
|
||||
// NewRenderer is a Renderer constructor.
|
||||
func NewRenderer(funcMap template.FuncMap) Renderer {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
return 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 {
|
||||
if tpl := r.getTemplate(name); tpl != nil {
|
||||
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...))
|
||||
}
|
||||
|
||||
// addFromBox adds embedded template
|
||||
// addFromBox adds embedded template.
|
||||
func (r *Renderer) addFromBox(name string, funcMap template.FuncMap, files ...string) *template.Template {
|
||||
var filesData []string
|
||||
|
||||
@ -76,7 +76,7 @@ func (r *Renderer) storeTemplate(name string, tpl *template.Template) *template.
|
||||
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 {
|
||||
if renderer, ok := r.Renderer.(multitemplate.Render); ok {
|
||||
if i, ok := renderer[name]; ok {
|
||||
|
@ -23,12 +23,13 @@ type TranslationsExtractor struct {
|
||||
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 {
|
||||
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) {
|
||||
var dataMap map[string]interface{}
|
||||
|
||||
@ -39,7 +40,7 @@ func (t *TranslationsExtractor) unmarshalToMap(in []byte) (map[string]interface{
|
||||
return dataMap, nil
|
||||
}
|
||||
|
||||
// loadYAMLBox loads YAML from box
|
||||
// loadYAMLBox loads YAML from box.
|
||||
func (t *TranslationsExtractor) loadYAMLBox(fileName string) (map[string]interface{}, error) {
|
||||
var (
|
||||
dataMap map[string]interface{}
|
||||
@ -54,7 +55,7 @@ func (t *TranslationsExtractor) loadYAMLBox(fileName string) (map[string]interfa
|
||||
return t.unmarshalToMap(data)
|
||||
}
|
||||
|
||||
// loadYAMLFile loads YAML from file
|
||||
// loadYAMLFile loads YAML from file.
|
||||
func (t *TranslationsExtractor) loadYAMLFile(fileName string) (map[string]interface{}, error) {
|
||||
var (
|
||||
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 {
|
||||
keys := make([]string, len(data))
|
||||
|
||||
@ -113,12 +114,12 @@ func (t *TranslationsExtractor) GetMapKeys(data map[string]interface{}) []string
|
||||
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) {
|
||||
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) {
|
||||
var (
|
||||
data map[string]interface{}
|
||||
|
@ -73,7 +73,7 @@ var defaultCurrencies = map[string]string{
|
||||
"gbp": "£",
|
||||
}
|
||||
|
||||
// Utils service object
|
||||
// Utils service object.
|
||||
type Utils struct {
|
||||
IsDebug bool
|
||||
TokenCounter uint32
|
||||
@ -82,7 +82,7 @@ type Utils struct {
|
||||
slashRegex *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewUtils will create new Utils instance
|
||||
// NewUtils will create new Utils instance.
|
||||
func NewUtils(awsConfig ConfigAWS, logger LoggerInterface, debug bool) *Utils {
|
||||
return &Utils{
|
||||
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) {
|
||||
u.TokenCounter = tokenCounter
|
||||
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))))
|
||||
}
|
||||
|
||||
// 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) {
|
||||
client := v5.New(url, key)
|
||||
client.Debug = u.IsDebug
|
||||
@ -117,7 +117,6 @@ func (u *Utils) GetAPIClient(url, key string) (*v5.Client, int, error) {
|
||||
if e != nil && e.Error() != "" {
|
||||
u.Logger.Error(url, status, e.Error(), cr)
|
||||
return nil, http.StatusInternalServerError, errors.New(e.Error())
|
||||
|
||||
}
|
||||
|
||||
if !cr.Success {
|
||||
@ -166,7 +165,7 @@ func (u *Utils) checkCredentials(credential []string) []string {
|
||||
return rc
|
||||
}
|
||||
|
||||
// UploadUserAvatar will upload avatar for user
|
||||
// UploadUserAvatar will upload avatar for user.
|
||||
func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) {
|
||||
s3Config := &aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials(
|
||||
@ -206,12 +205,12 @@ func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) {
|
||||
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 {
|
||||
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) {
|
||||
item := v1.Item{}
|
||||
|
||||
@ -230,7 +229,7 @@ func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, in
|
||||
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) {
|
||||
res, _ := json.Marshal(v)
|
||||
|
||||
@ -242,7 +241,7 @@ func GetEntitySHA1(v interface{}) (hash string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReplaceMarkdownSymbols will remove markdown symbols from text
|
||||
// ReplaceMarkdownSymbols will remove markdown symbols from text.
|
||||
func ReplaceMarkdownSymbols(s string) string {
|
||||
for _, v := range markdownSymbols {
|
||||
s = strings.Replace(s, v, "\\"+v, -1)
|
||||
@ -251,13 +250,13 @@ func ReplaceMarkdownSymbols(s string) string {
|
||||
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 {
|
||||
return defaultCurrencies
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if i, ok := DefaultCurrencies()[strings.ToLower(code)]; ok {
|
||||
return i
|
||||
|
@ -243,7 +243,7 @@ func TestUtils_GetEntitySHA1(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUtils_GetCurrencySymbol(t *testing.T) {
|
||||
for code, _ := range DefaultCurrencies() {
|
||||
for code := range DefaultCurrencies() {
|
||||
if strings.ToUpper(code) == defaultCurrencies[code] {
|
||||
continue
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"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() {
|
||||
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||
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 {
|
||||
return regCommandName.Match([]byte(fl.Field().String()))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user