mirror of
https://github.com/nabbar/golib.git
synced 2025-10-05 15:56:50 +08:00
11
.github/workflows/go.yml
vendored
11
.github/workflows/go.yml
vendored
@@ -20,13 +20,14 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ^1.14
|
||||
go-version: ^1.16
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Link workspace with GOPATH
|
||||
continue-on-error: false
|
||||
run: |
|
||||
sudo mkdir -vp $(dirname ${GOPATH}/src/github.com/${GITHUB_REPOSITORY})
|
||||
sudo chown -R ${USER}:users $(dirname ${GOPATH}/src/github.com/${GITHUB_REPOSITORY})
|
||||
@@ -34,17 +35,19 @@ jobs:
|
||||
sudo ln -svf $(pwd) ${GOPATH}/src/github.com/${GITHUB_REPOSITORY}
|
||||
|
||||
- name: Check out tools into the Go module directory
|
||||
continue-on-error: false
|
||||
run: |
|
||||
git clone https://github.com/nabbar/gotools.git scripts
|
||||
./scripts/prepare
|
||||
|
||||
- name: Update vendor or dependancies
|
||||
continue-on-error: false
|
||||
run: ./scripts/ci_depend
|
||||
|
||||
- name: Check goFmt & goImport
|
||||
continue-on-error: false
|
||||
run: ./scripts/ci_format
|
||||
|
||||
- name: Update vendor or dependancies
|
||||
run: ./scripts/ci_depend
|
||||
|
||||
- name: Check Missing License
|
||||
continue-on-error: false
|
||||
run: ./scripts/ci_license
|
||||
|
491
.golangci.yml
491
.golangci.yml
@@ -1,23 +1,88 @@
|
||||
# This file contains all available configuration options
|
||||
# with their default values.
|
||||
linters-settings:
|
||||
dupl:
|
||||
threshold: 100
|
||||
funlen:
|
||||
lines: 250
|
||||
statements: 200
|
||||
gci:
|
||||
local-prefixes: github.com/golangci/golangci-lint
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 2
|
||||
gocyclo:
|
||||
min-complexity: 50
|
||||
goimports:
|
||||
local-prefixes: github.com/golangci/golangci-lint
|
||||
gomnd:
|
||||
settings:
|
||||
mnd:
|
||||
# don't include the "operation" and "assign"
|
||||
checks: argument,case,condition,return
|
||||
govet:
|
||||
check-shadowing: true
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
lll:
|
||||
line-length: 140
|
||||
maligned:
|
||||
suggest-new: true
|
||||
misspell:
|
||||
locale: US
|
||||
|
||||
linters:
|
||||
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- exhaustive
|
||||
- funlen
|
||||
- goconst
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- gomnd
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
|
||||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 4
|
||||
|
||||
#concurrency: 4
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
timeout: 30m
|
||||
|
||||
timeout: 10m
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 0
|
||||
|
||||
issues-exit-code: 1
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
tests: false
|
||||
# list of build tags, all linters use it. Default is empty list.
|
||||
build-tags: []
|
||||
|
||||
#build-tags:
|
||||
# - mytag
|
||||
# which dirs to skip: issues from them won't be reported;
|
||||
# can use regexp here: generated.*, regexp is applied on full path;
|
||||
# default value is empty list, but default dirs are skipped independently
|
||||
@@ -25,22 +90,21 @@ run:
|
||||
# "/" will be replaced by current OS file path separator to properly work
|
||||
# on Windows.
|
||||
skip-dirs:
|
||||
- vendor
|
||||
- test
|
||||
|
||||
- test/
|
||||
- vendor/
|
||||
- .*
|
||||
# default is true. Enables skipping of directories:
|
||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs-use-default: true
|
||||
|
||||
#skip-dirs-use-default: true
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
# "/" will be replaced by current OS file path separator to properly work
|
||||
# on Windows.
|
||||
skip-files:
|
||||
- ".*\\.my\\.go$"
|
||||
|
||||
#skip-files:
|
||||
# - ".*\\.my\\.go$"
|
||||
# - lib/bad.go
|
||||
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
|
||||
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
||||
# automatic updating of go.mod described above. Instead, it fails when any changes
|
||||
@@ -49,401 +113,20 @@ run:
|
||||
# If invoked with -mod=vendor, the go command assumes that the vendor
|
||||
# directory holds the correct copies of dependencies and ignores
|
||||
# the dependency descriptions in go.mod.
|
||||
#modules-download-mode: readonly|release|vendor
|
||||
|
||||
modules-download-mode: vendor
|
||||
# Allow multiple parallel golangci-lint instances running.
|
||||
# If false (default) - golangci-lint acquires file lock on start.
|
||||
allow-parallel-runners: false
|
||||
|
||||
allow-parallel-runners: true
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
||||
format: colored-line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
# make issues output unique by line, default is true
|
||||
uniq-by-line: true
|
||||
|
||||
# add a prefix to the output file references; default is no prefix
|
||||
path-prefix: ""
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
dogsled:
|
||||
# checks assignments with too many blank identifiers; default is 2
|
||||
max-blank-identifiers: 2
|
||||
dupl:
|
||||
# tokens count to trigger issue, 150 by default
|
||||
threshold: 100
|
||||
errcheck:
|
||||
# report about not checking of errors in type assertions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: false
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
|
||||
# [deprecated] comma-separated list of pairs of the form pkg:regex
|
||||
# the regex is used to ignore names within pkg. (default "fmt:.*").
|
||||
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
|
||||
# path to a file containing a list of functions to exclude from checking
|
||||
# see https://github.com/kisielk/errcheck#excluding-functions for details
|
||||
# exclude: /path/to/file.txt
|
||||
exhaustive:
|
||||
# indicates that switch statements are to be considered exhaustive if a
|
||||
# 'default' case is present, even if all enum members aren't listed in the
|
||||
# switch
|
||||
default-signifies-exhaustive: false
|
||||
funlen:
|
||||
lines: 1000
|
||||
statements: 100
|
||||
gocognit:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 50
|
||||
nestif:
|
||||
# minimal complexity of if statements to report, 5 by default
|
||||
min-complexity: 4
|
||||
goconst:
|
||||
# minimal length of string constant, 3 by default
|
||||
min-len: 3
|
||||
# minimal occurrences count to trigger, 3 by default
|
||||
min-occurrences: 3
|
||||
gocritic:
|
||||
# Which checks should be enabled; can't be combined with 'disabled-checks';
|
||||
# See https://go-critic.github.io/overview#checks-overview
|
||||
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
|
||||
# By default list of stable checks is used.
|
||||
# enabled-checks:
|
||||
# - rangeValCopy
|
||||
|
||||
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
|
||||
disabled-checks:
|
||||
- regexpMust
|
||||
|
||||
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
|
||||
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
|
||||
enabled-tags:
|
||||
- performance
|
||||
disabled-tags:
|
||||
- experimental
|
||||
|
||||
settings: # settings passed to gocritic
|
||||
captLocal: # must be valid enabled check name
|
||||
paramsOnly: true
|
||||
rangeValCopy:
|
||||
sizeThreshold: 32
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 50
|
||||
godot:
|
||||
# check all top-level comments, not only declarations
|
||||
check-all: false
|
||||
godox:
|
||||
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
|
||||
# might be left in the code accidentally and should be resolved before merging
|
||||
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
|
||||
- NOTE
|
||||
- OPTIMIZE # marks code that should be optimized before merging
|
||||
- HACK # marks hack-arounds that should be removed before merging
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goheader:
|
||||
values:
|
||||
const:
|
||||
# define here const type values in format k:v, for example:
|
||||
# YEAR: 2020
|
||||
# COMPANY: MY COMPANY
|
||||
regexp:
|
||||
# define here regexp type values, for example
|
||||
# AUTHOR: .*@mycompany\.com
|
||||
template:
|
||||
# put here copyright header template for source code files, for example:
|
||||
# {{ AUTHOR }} {{ COMPANY }} {{ YEAR }}
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
template-path:
|
||||
# also as alternative of directive 'template' you may put the path to file with the template source
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
local-prefixes: github.com/org/project
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gomnd:
|
||||
settings:
|
||||
mnd:
|
||||
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
|
||||
checks: argument,case,condition,operation,return,assign
|
||||
gomodguard:
|
||||
allowed:
|
||||
modules: # List of allowed modules
|
||||
# - gopkg.in/yaml.v2
|
||||
domains: # List of allowed module domains
|
||||
# - golang.org
|
||||
blocked:
|
||||
modules: # List of blocked modules
|
||||
# - github.com/uudashr/go-module: # Blocked module
|
||||
# recommendations: # Recommended modules that should be used instead (Optional)
|
||||
# - golang.org/x/mod
|
||||
# reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
|
||||
versions: # List of blocked module version constraints
|
||||
# - github.com/mitchellh/go-homedir: # Blocked module with version constraint
|
||||
# version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons
|
||||
# reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional)
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: true
|
||||
|
||||
# settings per analyzer
|
||||
settings:
|
||||
printf: # analyzer name, run `go tool vet help` to see all analyzers
|
||||
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
|
||||
# enable or disable analyzers by name
|
||||
enable:
|
||||
- atomicalign
|
||||
enable-all: false
|
||||
disable:
|
||||
- shadow
|
||||
disable-all: false
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
include-go-root: false
|
||||
packages:
|
||||
# - github.com/sirupsen/logrus
|
||||
packages-with-error-message:
|
||||
# specify an error message to output when a blacklisted package is used
|
||||
# - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 240
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
ignore-words:
|
||||
- someword
|
||||
nakedret:
|
||||
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
|
||||
max-func-lines: 30
|
||||
prealloc:
|
||||
# XXX: we don't recommend using this linter before doing performance profiling.
|
||||
# For most programs usage of prealloc will be a premature optimization.
|
||||
|
||||
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
|
||||
# True by default.
|
||||
simple: true
|
||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||
nolintlint:
|
||||
# Enable to ensure that nolint directives are all used. Default is true.
|
||||
allow-unused: false
|
||||
# Disable to ensure that nolint directives don't have a leading space. Default is true.
|
||||
allow-leading-space: true
|
||||
# Exclude following linters from requiring an explanation. Default is [].
|
||||
allow-no-explanation: []
|
||||
# Enable to require an explanation of nonzero length after each nolint directive. Default is false.
|
||||
require-explanation: true
|
||||
# Enable to require nolint directives to mention the specific linter being suppressed. Default is false.
|
||||
require-specific: true
|
||||
rowserrcheck:
|
||||
packages:
|
||||
- github.com/jmoiron/sqlx
|
||||
testpackage:
|
||||
# regexp pattern to skip files
|
||||
skip-regexp: (export|internal)_test\.go
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
unused:
|
||||
# treat code as a program (not a library) and report unused exported identifiers; default is false.
|
||||
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
whitespace:
|
||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
||||
wsl:
|
||||
# If true append is only allowed to be cuddled if appending value is
|
||||
# matching variables, fields or types on line above. Default is true.
|
||||
strict-append: true
|
||||
# Allow calls and assignments to be cuddled as long as the lines have any
|
||||
# matching variables, fields or types. Default is true.
|
||||
allow-assign-and-call: true
|
||||
# Allow multiline assignments to be cuddled. Default is true.
|
||||
allow-multiline-assign: true
|
||||
# Allow declarations (var) to be cuddled.
|
||||
allow-cuddle-declarations: true
|
||||
# Allow trailing comments in ending of blocks
|
||||
allow-trailing-comment: false
|
||||
# Force newlines in end of case at this limit (0 = never).
|
||||
force-case-trailing-whitespace: 0
|
||||
# Force cuddling of err checks with err var assignment
|
||||
force-err-cuddling: false
|
||||
# Allow leading comments to be separated with empty liens
|
||||
allow-separated-leading-comment: false
|
||||
gofumpt:
|
||||
# Choose whether or not to use the extra rules that are disabled
|
||||
# by default
|
||||
extra-rules: false
|
||||
|
||||
# The custom section can be used to define linter plugins to be loaded at runtime. See README doc
|
||||
# for more info.
|
||||
#custom:
|
||||
# Each custom linter should have a unique name.
|
||||
#example:
|
||||
# The path to the plugin *.so. Can be absolute or local. Required for each custom linter
|
||||
#path: /path/to/example.so
|
||||
# The description of the linter. Optional, just for documentation purposes.
|
||||
#description: This is an example usage of a plugin linter.
|
||||
# Intended to point to the repo location of the linter. Optional, just for documentation purposes.
|
||||
#original-url: github.com/golangci/example-linter
|
||||
|
||||
linters:
|
||||
fast: false
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoinits
|
||||
- gochecknoglobals
|
||||
- wsl
|
||||
- golint
|
||||
- gocritic
|
||||
- stylecheck
|
||||
- whitespace
|
||||
- gofumpt
|
||||
- nestif
|
||||
- nolintlint
|
||||
- nlreturn
|
||||
|
||||
issues:
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
exclude:
|
||||
- .*test.*\.go
|
||||
|
||||
|
||||
# Excluding configuration per-path, per-linter, per-text and per-source
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
|
||||
# Exclude known linters from partially hard-vendored code,
|
||||
# which is impossible to exclude via "nolint" comments.
|
||||
- path: internal/hmac/
|
||||
text: "weak cryptographic primitive"
|
||||
linters:
|
||||
- gosec
|
||||
|
||||
# Exclude some staticcheck messages
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "SA9003:"
|
||||
|
||||
# Exclude lll issues for long lines with go:generate
|
||||
- linters:
|
||||
- lll
|
||||
source: "^//go:generate "
|
||||
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: false
|
||||
|
||||
# The default value is false. If set to true exclude and exclude-rules
|
||||
# regular expressions become case sensitive.
|
||||
exclude-case-sensitive: false
|
||||
|
||||
# The list of ids of default excludes to include or disable. By default it's empty.
|
||||
include:
|
||||
- EXC0002 # disable excluding of issues about comments from golint
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-issues-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
||||
|
||||
# Show only new issues: if there are unstaged changes or untracked files,
|
||||
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
||||
# It's a super-useful option for integration of golangci-lint into existing
|
||||
# large codebase. It's not practical to fix all existing issues at the moment
|
||||
# of integration: much better don't allow issues in new code.
|
||||
# Default is false.
|
||||
new: false
|
||||
|
||||
# Show only new issues created after git revision `REV`
|
||||
#new-from-rev: REV
|
||||
|
||||
# Show only new issues created in git patch with set file path.
|
||||
#new-from-patch: path/to/patch/file
|
||||
|
||||
severity:
|
||||
# Default value is empty string.
|
||||
# Set the default severity for issues. If severity rules are defined and the issues
|
||||
# do not match or no severity is provided to the rule this will be the default
|
||||
# severity applied. Severities should match the supported severity names of the
|
||||
# selected out format.
|
||||
# - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
|
||||
# - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
|
||||
# - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
|
||||
default-severity: error
|
||||
|
||||
# The default value is false.
|
||||
# If set to true severity-rules regular expressions become case sensitive.
|
||||
case-sensitive: false
|
||||
|
||||
# Default value is empty list.
|
||||
# When a list of severity rules are provided, severity information will be added to lint
|
||||
# issues. Severity rules have the same filtering capability as exclude rules except you
|
||||
# are allowed to specify one matcher per severity rule.
|
||||
# Only affects out formats that support setting severity information.
|
||||
rules:
|
||||
- linters:
|
||||
- dupl
|
||||
severity: info
|
||||
|
@@ -43,11 +43,9 @@ import (
|
||||
type ArchiveType uint8
|
||||
|
||||
const (
|
||||
ArchiveTypeUnknown = iota
|
||||
ArchiveTypeZip
|
||||
ArchiveTypeTar
|
||||
ArchiveTypeTarGzip
|
||||
ArchiveTypeGzip
|
||||
TypeTar = iota + 1
|
||||
TypeTarGzip
|
||||
TypeGzip
|
||||
)
|
||||
|
||||
func ExtractFile(src, dst libiot.FileProgress, fileNameContain, fileNameRegex string) liberr.Error {
|
||||
@@ -204,15 +202,16 @@ func ExtractAll(src libiot.FileProgress, originalName, outputPath string, defaul
|
||||
func CreateArchive(archiveType ArchiveType, archive libiot.FileProgress, pathContent ...string) (created bool, err liberr.Error) {
|
||||
//@TODO: make function
|
||||
if len(pathContent) < 1 {
|
||||
//nolint #goerr113
|
||||
return false, ErrorParamsEmpty.ErrorParent(fmt.Errorf("pathContent is empty"))
|
||||
}
|
||||
|
||||
switch archiveType {
|
||||
case ArchiveTypeGzip:
|
||||
case TypeGzip:
|
||||
return libgzp.Create(archive, pathContent...)
|
||||
case ArchiveTypeTar:
|
||||
case TypeTar:
|
||||
return libtar.Create(archive, pathContent...)
|
||||
case ArchiveTypeTarGzip:
|
||||
case TypeTarGzip:
|
||||
return libtar.CreateGzip(archive, pathContent...)
|
||||
}
|
||||
|
||||
|
@@ -34,10 +34,9 @@ import (
|
||||
"os"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
libiot "github.com/nabbar/golib/ioutils"
|
||||
)
|
||||
|
||||
func Create(archive libiot.FileProgress, content ...string) (bool, liberr.Error) {
|
||||
func Create(archive io.WriteSeeker, content ...string) (bool, liberr.Error) {
|
||||
var (
|
||||
w *gzip.Writer
|
||||
f *os.File
|
||||
@@ -46,6 +45,7 @@ func Create(archive libiot.FileProgress, content ...string) (bool, liberr.Error)
|
||||
)
|
||||
|
||||
if len(content) != 1 {
|
||||
//nolint #goerr113
|
||||
return false, ErrorParamsMismatching.ErrorParent(fmt.Errorf("content path must be limited to strictly one contents"))
|
||||
}
|
||||
|
||||
|
@@ -36,185 +36,125 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
libiot "github.com/nabbar/golib/ioutils"
|
||||
)
|
||||
|
||||
func Create(archive libiot.FileProgress, content ...string) (bool, liberr.Error) {
|
||||
func Create(archive io.WriteSeeker, content ...string) (bool, liberr.Error) {
|
||||
|
||||
var (
|
||||
t *tar.Writer
|
||||
n int64
|
||||
|
||||
err error
|
||||
lEr = ErrorTarCreateAddFile.Error(nil)
|
||||
)
|
||||
|
||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
||||
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||
return false, ErrorFileSeek.ErrorParent(err)
|
||||
}
|
||||
|
||||
t = tar.NewWriter(archive)
|
||||
|
||||
for i := 0; i < len(content); i++ {
|
||||
if content[i] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
err = filepath.Walk(content[i], func(file string, inf os.FileInfo, err error) error {
|
||||
var (
|
||||
e error
|
||||
h *tar.Header
|
||||
f *os.File
|
||||
)
|
||||
|
||||
// generate tar header
|
||||
h, e = tar.FileInfoHeader(inf, file)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
// must provide real name
|
||||
// (see https://golang.org/src/archive/tar/common.go?#L626)
|
||||
h.Name = filepath.ToSlash(file)
|
||||
|
||||
// write header
|
||||
if e = t.WriteHeader(h); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if not a dir, write file content
|
||||
if !inf.IsDir() {
|
||||
f, e = os.Open(file)
|
||||
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
if _, e = io.Copy(t, f); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
n++
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
lEr.AddParent(err)
|
||||
continue
|
||||
}
|
||||
if ok, err := createTar(archive, content...); err != nil || !ok {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
if n < 1 {
|
||||
if lEr.HasParent() {
|
||||
return false, lEr
|
||||
}
|
||||
|
||||
return false, ErrorTarCreate.ErrorParent(fmt.Errorf("no file to add in archive"))
|
||||
} else if !lEr.HasParent() {
|
||||
lEr = nil
|
||||
}
|
||||
|
||||
if err = t.Close(); err != nil {
|
||||
return false, ErrorTarCreate.ErrorParent(err)
|
||||
}
|
||||
|
||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
||||
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||
return false, ErrorFileSeek.ErrorParent(err)
|
||||
}
|
||||
|
||||
return true, lEr
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func CreateGzip(archive libiot.FileProgress, content ...string) (bool, liberr.Error) {
|
||||
func CreateGzip(archive io.WriteSeeker, content ...string) (bool, liberr.Error) {
|
||||
|
||||
var (
|
||||
z *gzip.Writer
|
||||
t *tar.Writer
|
||||
n int64
|
||||
|
||||
err error
|
||||
lEr = ErrorTarCreateAddFile.Error(nil)
|
||||
)
|
||||
|
||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
||||
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||
return false, ErrorFileSeek.ErrorParent(err)
|
||||
}
|
||||
|
||||
z = gzip.NewWriter(archive)
|
||||
t = tar.NewWriter(z)
|
||||
z := gzip.NewWriter(archive)
|
||||
|
||||
for i := 0; i < len(content); i++ {
|
||||
if content[i] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
err = filepath.Walk(content[i], func(file string, inf os.FileInfo, err error) error {
|
||||
var (
|
||||
e error
|
||||
h *tar.Header
|
||||
f *os.File
|
||||
)
|
||||
|
||||
// generate tar header
|
||||
h, e = tar.FileInfoHeader(inf, file)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
// must provide real name
|
||||
// (see https://golang.org/src/archive/tar/common.go?#L626)
|
||||
h.Name = filepath.ToSlash(file)
|
||||
|
||||
// write header
|
||||
if e = t.WriteHeader(h); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if not a dir, write file content
|
||||
if !inf.IsDir() {
|
||||
f, e = os.Open(file)
|
||||
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
if _, e = io.Copy(t, f); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
n++
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
lEr.AddParent(err)
|
||||
continue
|
||||
}
|
||||
if ok, err := createTar(z, content...); err != nil || !ok {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
if n < 1 {
|
||||
if lEr.HasParent() {
|
||||
return false, lEr
|
||||
}
|
||||
|
||||
return false, ErrorTarCreate.ErrorParent(fmt.Errorf("no file to add in archive"))
|
||||
} else if !lEr.HasParent() {
|
||||
lEr = nil
|
||||
}
|
||||
|
||||
if err = t.Close(); err != nil {
|
||||
return false, ErrorTarCreate.ErrorParent(err)
|
||||
}
|
||||
|
||||
if err = z.Close(); err != nil {
|
||||
if err := z.Close(); err != nil {
|
||||
return false, ErrorGzipCreate.ErrorParent(err)
|
||||
}
|
||||
|
||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
||||
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||
return false, ErrorFileSeek.ErrorParent(err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func createTar(w io.Writer, content ...string) (bool, liberr.Error) {
|
||||
var (
|
||||
t *tar.Writer
|
||||
n int64
|
||||
|
||||
err error
|
||||
lEr = ErrorTarCreateAddFile.Error(nil)
|
||||
)
|
||||
|
||||
t = tar.NewWriter(w)
|
||||
|
||||
for i := 0; i < len(content); i++ {
|
||||
if content[i] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
err = filepath.Walk(content[i], func(file string, inf os.FileInfo, err error) error {
|
||||
var (
|
||||
e error
|
||||
h *tar.Header
|
||||
f *os.File
|
||||
)
|
||||
|
||||
// generate tar header
|
||||
h, e = tar.FileInfoHeader(inf, file)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
// must provide real name
|
||||
// (see https://golang.org/src/archive/tar/common.go?#L626)
|
||||
h.Name = filepath.ToSlash(file)
|
||||
|
||||
// write header
|
||||
if e = t.WriteHeader(h); e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
// if not a dir, write file content
|
||||
if !inf.IsDir() {
|
||||
//nolint #gosec
|
||||
/* #nosec */
|
||||
f, e = os.Open(file)
|
||||
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
if _, e = io.Copy(t, f); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
n++
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
lEr.AddParent(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if n < 1 {
|
||||
if lEr.HasParent() {
|
||||
return false, lEr
|
||||
}
|
||||
|
||||
//nolint #goerr113
|
||||
return false, ErrorTarCreate.ErrorParent(fmt.Errorf("no file to add in archive"))
|
||||
} else if !lEr.HasParent() {
|
||||
lEr = nil
|
||||
}
|
||||
|
||||
if err = t.Close(); err != nil {
|
||||
return false, ErrorTarCreate.ErrorParent(err)
|
||||
}
|
||||
|
||||
return true, lEr
|
||||
}
|
||||
|
@@ -107,23 +107,14 @@ func (a *artifactoryModel) request(uri string, bodyResponse interface{}) liberr.
|
||||
u *url.URL
|
||||
)
|
||||
|
||||
//ctx, cnl = context.WithTimeout(a.ctx, libhtc.TIMEOUT_5_SEC)
|
||||
ctx, cnl = context.WithCancel(a.ctx)
|
||||
defer func() {
|
||||
if cnl != nil {
|
||||
cnl()
|
||||
}
|
||||
|
||||
if rsp != nil && rsp.Body != nil {
|
||||
_ = rsp.Body.Close()
|
||||
}
|
||||
|
||||
if req != nil && req.Body != nil {
|
||||
_ = req.Body.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
//ctx, cnl = context.WithTimeout(a.ctx, libhtc.TIMEOUT_5_SEC)
|
||||
ctx, cnl = context.WithCancel(a.ctx)
|
||||
|
||||
u = &url.URL{
|
||||
Scheme: a.endpoint.Scheme,
|
||||
Opaque: a.endpoint.Opaque,
|
||||
@@ -149,15 +140,29 @@ func (a *artifactoryModel) request(uri string, bodyResponse interface{}) liberr.
|
||||
return ErrorRequestInit.ErrorParent(e)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if req != nil && req.Body != nil {
|
||||
_ = req.Body.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if rsp, e = a.Do(req); e != nil {
|
||||
return ErrorRequestDo.ErrorParent(e)
|
||||
}
|
||||
|
||||
if rsp.StatusCode >= 400 {
|
||||
defer func() {
|
||||
if rsp != nil && rsp.Body != nil {
|
||||
_ = rsp.Body.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if rsp.StatusCode >= http.StatusBadRequest {
|
||||
//nolint #goerr113
|
||||
return ErrorRequestResponse.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||
}
|
||||
|
||||
if rsp.Body == nil {
|
||||
//nolint #goerr113
|
||||
return ErrorRequestResponseBodyEmpty.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||
}
|
||||
|
||||
@@ -181,10 +186,12 @@ func (a *artifactoryModel) getStorageList() (sto []ResponseStorage, err liberr.E
|
||||
)
|
||||
|
||||
if a.regex == "" {
|
||||
//nolint #goerr113
|
||||
return nil, ErrorParamsEmpty.ErrorParent(fmt.Errorf("regex is empty: %s", a.regex))
|
||||
}
|
||||
|
||||
if a.group < 1 {
|
||||
//nolint #goerr113
|
||||
return nil, ErrorParamsEmpty.ErrorParent(fmt.Errorf("group extracted from regex is empty: %s - %v", a.regex, a.group))
|
||||
}
|
||||
|
||||
@@ -342,9 +349,11 @@ func (a *artifactoryModel) Download(dst libiot.FileProgress, containName string,
|
||||
return ErrorRequestInit.ErrorParent(e)
|
||||
} else if rsp, e = a.Do(req); e != nil {
|
||||
return ErrorRequestDo.ErrorParent(e)
|
||||
} else if rsp.StatusCode >= 400 {
|
||||
} else if rsp.StatusCode >= http.StatusBadRequest {
|
||||
//nolint #goerr113
|
||||
return ErrorRequestResponse.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||
} else if rsp.Body == nil {
|
||||
//nolint #goerr113
|
||||
return ErrorRequestResponseBodyEmpty.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||
} else if _, e := dst.ReadFrom(rsp.Body); e != nil {
|
||||
return ErrorArtifactoryDownload.ErrorParent(e)
|
||||
|
@@ -71,8 +71,6 @@ func TestGolibAwsHelper(t *testing.T) {
|
||||
RunSpecs(t, "Aws Helper Suite")
|
||||
}
|
||||
|
||||
const testRegion = "us-east-1"
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
var (
|
||||
err error
|
||||
|
@@ -226,7 +226,7 @@ func (c *awsModel) ResolveEndpoint(service, region string) (sdkaws.Endpoint, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
logger.DebugLevel.Logf("Called ResolveEndpoint for service / region '%s' with nil endpoint", service, region)
|
||||
logger.DebugLevel.Logf("Called ResolveEndpoint for service '%s' / region '%s' with nil endpoint", service, region)
|
||||
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
|
||||
}
|
||||
|
||||
|
@@ -26,10 +26,13 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
//nolint #nosec
|
||||
/* #nosec */
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
|
||||
//nolint #gci
|
||||
"os"
|
||||
|
||||
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
|
||||
@@ -101,8 +104,8 @@ func (cli *client) MultipartPutCustom(partSize libhlp.PartSize, object string, b
|
||||
|
||||
/* #nosec */
|
||||
h := md5.New()
|
||||
if _, err := tmp.WriteTo(h); err != nil {
|
||||
return cli.multipartCancel(err, upl.UploadId, object)
|
||||
if _, e := tmp.WriteTo(h); e != nil {
|
||||
return cli.multipartCancel(e, upl.UploadId, object)
|
||||
}
|
||||
|
||||
_, err = tmp.Seek(0, io.SeekStart)
|
||||
|
@@ -42,6 +42,7 @@ const maxItemList int32 = 1000
|
||||
|
||||
func (cli *client) VersionList(arn string, maxItem int32) (map[string]string, liberr.Error) {
|
||||
if arn == "" {
|
||||
//nolint #goerr113
|
||||
return nil, libhlp.ErrorParamsEmpty.ErrorParent(fmt.Errorf("arn is empty"))
|
||||
}
|
||||
|
||||
@@ -51,7 +52,7 @@ func (cli *client) VersionList(arn string, maxItem int32) (map[string]string, li
|
||||
|
||||
var (
|
||||
marker = ""
|
||||
res = make(map[string]string, 0)
|
||||
res = make(map[string]string)
|
||||
)
|
||||
|
||||
for {
|
||||
|
@@ -39,12 +39,6 @@ type Certif struct {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
InheritDefault bool `mapstructure:"inheritDefault" json:"inheritDefault" yaml:"inheritDefault" toml:"inheritDefault"`
|
||||
VersionMin string `mapstructure:"versionMin" json:"versionMin" yaml:"versionMin" toml:"versionMin"`
|
||||
VersionMax string `mapstructure:"versionMax" json:"versionMax" yaml:"versionMax" toml:"versionMax"`
|
||||
DynmaicSizingDisable bool `mapstructure:"dynamicSizingDisable" json:"dynamicSizingDisable" yaml:"dynamicSizingDisable" toml:"dynamicSizingDisable"`
|
||||
SessionTicketDisable bool `mapstructure:"sessionTicketDisable" json:"sessionTicketDisable" yaml:"sessionTicketDisable" toml:"sessionTicketDisable"`
|
||||
AuthClient string `mapstructure:"authClient" json:"authClient" yaml:"authClient" toml:"authClient"`
|
||||
CurveList []string `mapstructure:"curveList" json:"curveList" yaml:"curveList" toml:"curveList"`
|
||||
CipherList []string `mapstructure:"cipherList" json:"cipherList" yaml:"cipherList" toml:"cipherList"`
|
||||
RootCAString []string `mapstructure:"rootCA" json:"rootCA" yaml:"rootCA" toml:"rootCA"`
|
||||
@@ -53,6 +47,12 @@ type Config struct {
|
||||
ClientCAFiles []string `mapstructure:"clientCAFiles" json:"clientCAFiles" yaml:"clientCAFiles" toml:"clientCAFiles"`
|
||||
CertPairString []Certif `mapstructure:"certPair" json:"certPair" yaml:"certPair" toml:"certPair"`
|
||||
CertPairFile []Certif `mapstructure:"certPairFiles" json:"certPairFiles" yaml:"certPairFiles" toml:"certPairFiles"`
|
||||
VersionMin string `mapstructure:"versionMin" json:"versionMin" yaml:"versionMin" toml:"versionMin"`
|
||||
VersionMax string `mapstructure:"versionMax" json:"versionMax" yaml:"versionMax" toml:"versionMax"`
|
||||
AuthClient string `mapstructure:"authClient" json:"authClient" yaml:"authClient" toml:"authClient"`
|
||||
InheritDefault bool `mapstructure:"inheritDefault" json:"inheritDefault" yaml:"inheritDefault" toml:"inheritDefault"`
|
||||
DynamicSizingDisable bool `mapstructure:"dynamicSizingDisable" json:"dynamicSizingDisable" yaml:"dynamicSizingDisable" toml:"dynamicSizingDisable"`
|
||||
SessionTicketDisable bool `mapstructure:"sessionTicketDisable" json:"sessionTicketDisable" yaml:"sessionTicketDisable" toml:"sessionTicketDisable"`
|
||||
}
|
||||
|
||||
func (c *Config) Validate() liberr.Error {
|
||||
@@ -64,6 +64,7 @@ func (c *Config) Validate() liberr.Error {
|
||||
}
|
||||
|
||||
for _, err := range err.(valid.ValidationErrors) {
|
||||
//nolint #goerr113
|
||||
e.AddParent(fmt.Errorf("config field '%s' is not validated by constraint '%s'", err.StructNamespace(), err.ActualTag()))
|
||||
}
|
||||
}
|
||||
@@ -83,6 +84,7 @@ func (c *Config) New() (TLSConfig, liberr.Error) {
|
||||
}
|
||||
}
|
||||
|
||||
//nolint #gocognit
|
||||
func (c *Config) NewFrom(cfg TLSConfig) (TLSConfig, liberr.Error) {
|
||||
var t *config
|
||||
|
||||
@@ -103,7 +105,7 @@ func (c *Config) NewFrom(cfg TLSConfig) (TLSConfig, liberr.Error) {
|
||||
t.tlsMaxVersion = StringToTlsVersion(c.VersionMax)
|
||||
}
|
||||
|
||||
if c.DynmaicSizingDisable {
|
||||
if c.DynamicSizingDisable {
|
||||
t.dynSizingDisabled = true
|
||||
}
|
||||
|
||||
|
@@ -80,47 +80,47 @@ func New() TLSConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddRootCAContents(rootContent string) bool {
|
||||
return Default.AddRootCAString(rootContent)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddRootCAFile(rootFile string) liberr.Error {
|
||||
return Default.AddRootCAFile(rootFile)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddCACertificateContents(caContent string) bool {
|
||||
return Default.AddClientCAString(caContent)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddCACertificateFile(caFile string) liberr.Error {
|
||||
return Default.AddClientCAFile(caFile)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddCertificatePairString(key, crt string) liberr.Error {
|
||||
return Default.AddCertificatePairString(key, crt)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddCertificatePairFile(keyFile, crtFile string) liberr.Error {
|
||||
return Default.AddCertificatePairFile(keyFile, crtFile)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func CheckCertificates() bool {
|
||||
return Default.LenCertificatePair() > 0
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func GetCertificates() []tls.Certificate {
|
||||
return Default.GetCertificatePair()
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AppendCertificates(cert []tls.Certificate) []tls.Certificate {
|
||||
if !CheckCertificates() {
|
||||
return cert
|
||||
@@ -129,67 +129,67 @@ func AppendCertificates(cert []tls.Certificate) []tls.Certificate {
|
||||
return append(cert, GetCertificates()...)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func GetRootCA() *x509.CertPool {
|
||||
return Default.GetRootCA()
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func GetClientCA() *x509.CertPool {
|
||||
return Default.GetClientCA()
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetVersionMin(vers uint16) {
|
||||
Default.SetVersionMin(vers)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetVersionMax(vers uint16) {
|
||||
Default.SetVersionMax(vers)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetClientAuth(auth string) {
|
||||
Default.SetClientAuth(StringToClientAuth(auth))
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetCipherList(cipher []uint16) {
|
||||
Default.SetCipherList(cipher)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetCurve(curves []tls.CurveID) {
|
||||
Default.SetCurveList(curves)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetDynamicSizing(enable bool) {
|
||||
Default.SetDynamicSizingDisabled(!enable)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func SetSessionTicket(enable bool) {
|
||||
Default.SetSessionTicketDisabled(!enable)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func GetTLSConfig(serverName string) *tls.Config {
|
||||
return Default.TlsConfig(serverName)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func GetTlsConfigCertificates() *tls.Config {
|
||||
return Default.TlsConfig("")
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddCertificateContents(keyContents, certContents string) liberr.Error {
|
||||
return Default.AddCertificatePairString(keyContents, certContents)
|
||||
}
|
||||
|
||||
// Deprecated: use local config and no more globals default config
|
||||
// Deprecated: use local config and no more globals default config.
|
||||
func AddCertificateFile(keyFile, certFile string) liberr.Error {
|
||||
return Default.AddCertificatePairFile(keyFile, certFile)
|
||||
}
|
||||
|
@@ -38,20 +38,16 @@ import (
|
||||
)
|
||||
|
||||
type config struct {
|
||||
caRoot *x509.CertPool
|
||||
cert []tls.Certificate
|
||||
|
||||
tlsMinVersion uint16
|
||||
tlsMaxVersion uint16
|
||||
|
||||
cipherList []uint16
|
||||
curveList []tls.CurveID
|
||||
|
||||
cert []tls.Certificate
|
||||
cipherList []uint16
|
||||
curveList []tls.CurveID
|
||||
caRoot *x509.CertPool
|
||||
clientAuth tls.ClientAuthType
|
||||
clientCA *x509.CertPool
|
||||
tlsMinVersion uint16
|
||||
tlsMaxVersion uint16
|
||||
dynSizingDisabled bool
|
||||
ticketSessionDisabled bool
|
||||
|
||||
clientAuth tls.ClientAuthType
|
||||
clientCA *x509.CertPool
|
||||
}
|
||||
|
||||
func (c *config) checkFile(pemFiles ...string) liberr.Error {
|
||||
@@ -248,12 +244,7 @@ func (c *config) cloneCipherList() []uint16 {
|
||||
return nil
|
||||
}
|
||||
|
||||
list := make([]uint16, 0)
|
||||
for _, v := range c.cipherList {
|
||||
list = append(list, v)
|
||||
}
|
||||
|
||||
return list
|
||||
return append(make([]uint16, 0), c.cipherList...)
|
||||
}
|
||||
|
||||
func (c *config) cloneCurveList() []tls.CurveID {
|
||||
@@ -261,12 +252,7 @@ func (c *config) cloneCurveList() []tls.CurveID {
|
||||
return nil
|
||||
}
|
||||
|
||||
list := make([]tls.CurveID, 0)
|
||||
for _, v := range c.curveList {
|
||||
list = append(list, v)
|
||||
}
|
||||
|
||||
return list
|
||||
return append(make([]tls.CurveID, 0), c.curveList...)
|
||||
}
|
||||
|
||||
func (c *config) cloneCertificates() []tls.Certificate {
|
||||
@@ -274,12 +260,7 @@ func (c *config) cloneCertificates() []tls.Certificate {
|
||||
return nil
|
||||
}
|
||||
|
||||
list := make([]tls.Certificate, 0)
|
||||
for _, v := range c.cert {
|
||||
list = append(list, v)
|
||||
}
|
||||
|
||||
return list
|
||||
return append(make([]tls.Certificate, 0), c.cert...)
|
||||
}
|
||||
|
||||
func (c *config) cloneRootCA() *x509.CertPool {
|
||||
|
@@ -33,12 +33,12 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Deprecated: use StringToCipherKey
|
||||
// Deprecated: use StringToCipherKey.
|
||||
func GetCipherKey(cipher string) uint16 {
|
||||
return StringToCipherKey(cipher)
|
||||
}
|
||||
|
||||
// Deprecated: use StringToCurveID
|
||||
// Deprecated: use StringToCurveID.
|
||||
func GetCurveID(curveRef string) tls.CurveID {
|
||||
return StringToCurveID(curveRef)
|
||||
}
|
||||
|
@@ -223,6 +223,7 @@ func (c ConfigCluster) GetDGBConfigCluster() dgbcfg.Config {
|
||||
d.Quiesce = true
|
||||
}
|
||||
|
||||
//nolint #exhaustive
|
||||
switch c.SnapshotCompressionType {
|
||||
case dgbcfg.Snappy:
|
||||
d.SnapshotCompressionType = dgbcfg.Snappy
|
||||
@@ -230,6 +231,7 @@ func (c ConfigCluster) GetDGBConfigCluster() dgbcfg.Config {
|
||||
d.SnapshotCompressionType = dgbcfg.NoCompression
|
||||
}
|
||||
|
||||
//nolint #exhaustive
|
||||
switch c.EntryCompressionType {
|
||||
case dgbcfg.Snappy:
|
||||
d.EntryCompressionType = dgbcfg.Snappy
|
||||
|
@@ -33,7 +33,7 @@ import (
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
func printPrompt(text string) {
|
||||
@@ -87,7 +87,7 @@ func PromptBool(text string) (bool, error) {
|
||||
func PromptPassword(text string) (string, error) {
|
||||
printPrompt(text)
|
||||
//nolint #unconvert
|
||||
res, err := terminal.ReadPassword(int(syscall.Stdin))
|
||||
res, err := term.ReadPassword(int(syscall.Stdin))
|
||||
fmt.Printf("\n")
|
||||
|
||||
return string(res), err
|
||||
|
@@ -36,39 +36,43 @@ type Config interface {
|
||||
|
||||
Store(key string, cfg interface{})
|
||||
Load(key string) interface{}
|
||||
|
||||
ObjectStore(key string, obj interface{})
|
||||
ObjectLoad(key string) interface{}
|
||||
}
|
||||
|
||||
func NewConfig(ctx context.Context) Config {
|
||||
return &configContext{
|
||||
Context: ctx,
|
||||
cfg: &atomic.Value{},
|
||||
obj: &atomic.Value{},
|
||||
cfg: new(atomic.Value),
|
||||
}
|
||||
}
|
||||
|
||||
type configContext struct {
|
||||
context.Context
|
||||
cfg *atomic.Value
|
||||
obj *atomic.Value
|
||||
}
|
||||
|
||||
func (c *configContext) Store(key string, cfg interface{}) {
|
||||
func (c configContext) getMap() map[string]*atomic.Value {
|
||||
var (
|
||||
v interface{}
|
||||
s map[string]*atomic.Value
|
||||
ok bool
|
||||
)
|
||||
|
||||
if v = c.cfg.Load(); v == nil {
|
||||
s = make(map[string]*atomic.Value, 0)
|
||||
if c.cfg == nil {
|
||||
c.cfg = new(atomic.Value)
|
||||
} else if v = c.cfg.Load(); v == nil {
|
||||
s = make(map[string]*atomic.Value)
|
||||
|
||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
||||
s = make(map[string]*atomic.Value, 0)
|
||||
s = make(map[string]*atomic.Value)
|
||||
}
|
||||
|
||||
if _, ok = s[key]; !ok {
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *configContext) Store(key string, cfg interface{}) {
|
||||
s := c.getMap()
|
||||
|
||||
if _, ok := s[key]; !ok {
|
||||
s[key] = &atomic.Value{}
|
||||
}
|
||||
|
||||
@@ -77,17 +81,9 @@ func (c *configContext) Store(key string, cfg interface{}) {
|
||||
}
|
||||
|
||||
func (c *configContext) Load(key string) interface{} {
|
||||
var (
|
||||
v interface{}
|
||||
s map[string]*atomic.Value
|
||||
ok bool
|
||||
)
|
||||
s := c.getMap()
|
||||
|
||||
if v = c.cfg.Load(); v == nil {
|
||||
return nil
|
||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
||||
return nil
|
||||
} else if _, ok = s[key]; !ok {
|
||||
if _, ok := s[key]; !ok {
|
||||
return nil
|
||||
} else {
|
||||
return s[key].Load()
|
||||
@@ -97,10 +93,6 @@ func (c *configContext) Load(key string) interface{} {
|
||||
func (c *configContext) Merge(cfg Config) bool {
|
||||
var (
|
||||
x *configContext
|
||||
vx interface{}
|
||||
ix interface{}
|
||||
sc map[string]*atomic.Value
|
||||
sx map[string]*atomic.Value
|
||||
ok bool
|
||||
)
|
||||
|
||||
@@ -108,68 +100,32 @@ func (c *configContext) Merge(cfg Config) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
sc = make(map[string]*atomic.Value, 0)
|
||||
s := c.getMap()
|
||||
|
||||
if vx = x.cfg.Load(); vx == nil {
|
||||
sx = make(map[string]*atomic.Value, 0)
|
||||
} else if sx, ok = vx.(map[string]*atomic.Value); !ok {
|
||||
sx = make(map[string]*atomic.Value, 0)
|
||||
}
|
||||
|
||||
for k, v := range sx {
|
||||
for k, v := range x.getMap() {
|
||||
if k == "" || v == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ix = v.Load()
|
||||
if ix == nil {
|
||||
if i := v.Load(); i == nil {
|
||||
continue
|
||||
} else {
|
||||
s[k] = &atomic.Value{}
|
||||
s[k].Store(i)
|
||||
}
|
||||
|
||||
sc[k] = &atomic.Value{}
|
||||
sc[k].Store(ix)
|
||||
}
|
||||
|
||||
c.cfg.Store(sc)
|
||||
c.cfg.Store(s)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//Deprecated: use Store.
|
||||
func (c *configContext) ObjectStore(key string, obj interface{}) {
|
||||
var (
|
||||
v interface{}
|
||||
s map[string]*atomic.Value
|
||||
ok bool
|
||||
)
|
||||
|
||||
if v = c.obj.Load(); v == nil {
|
||||
s = make(map[string]*atomic.Value, 0)
|
||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
||||
s = make(map[string]*atomic.Value, 0)
|
||||
}
|
||||
|
||||
if _, ok = s[key]; !ok {
|
||||
s[key] = &atomic.Value{}
|
||||
}
|
||||
|
||||
s[key].Store(obj)
|
||||
c.obj.Store(s)
|
||||
c.Store(key, obj)
|
||||
}
|
||||
|
||||
//Deprecated: use Load.
|
||||
func (c *configContext) ObjectLoad(key string) interface{} {
|
||||
var (
|
||||
v interface{}
|
||||
s map[string]*atomic.Value
|
||||
ok bool
|
||||
)
|
||||
|
||||
if v = c.obj.Load(); v == nil {
|
||||
return nil
|
||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
||||
return nil
|
||||
} else if _, ok = s[key]; !ok {
|
||||
return nil
|
||||
} else {
|
||||
return s[key].Load()
|
||||
}
|
||||
return c.Load(key)
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ package context
|
||||
import "context"
|
||||
|
||||
func IsolateParent(parent context.Context) context.Context {
|
||||
//nolint #govet
|
||||
x, _ := context.WithCancel(parent)
|
||||
return x
|
||||
}
|
||||
|
@@ -30,9 +30,8 @@ import (
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/nabbar/golib/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
)
|
||||
|
||||
type GinTonic interface {
|
||||
@@ -102,11 +101,11 @@ func (c *ctxGinTonic) CancelOnSignal(s ...os.Signal) {
|
||||
|
||||
select {
|
||||
case <-sc:
|
||||
logger.InfoLevel.Logf("Os Signal recieved, calling context cancel !")
|
||||
liblog.InfoLevel.Logf("Os Signal received, calling context cancel !")
|
||||
c.c()
|
||||
return
|
||||
case <-c.Done():
|
||||
logger.InfoLevel.Logf("Context has been closed...")
|
||||
liblog.InfoLevel.Logf("Context has been closed...")
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
@@ -91,7 +91,7 @@ type Error interface {
|
||||
IsCodeError(code CodeError) bool
|
||||
//HasCodeError check if current error or parent has the given error code
|
||||
HasCodeError(code CodeError) bool
|
||||
//GetCodeError return the CodeError value of the curent error
|
||||
//GetCodeError return the CodeError value of the current error
|
||||
GetCodeError() CodeError
|
||||
//GetCodeErrorParent return a slice of CodeError value of all parent Error and the code of the current Error
|
||||
GetCodeErrorParent() []CodeError
|
||||
|
@@ -60,7 +60,7 @@ func (r *DefaultReturn) SetError(code int, msg string, file string, line int) {
|
||||
}
|
||||
|
||||
func (r *DefaultReturn) AddParent(code int, msg string, file string, line int) {
|
||||
return
|
||||
// nothing
|
||||
}
|
||||
|
||||
func (r DefaultReturn) JSON() []byte {
|
||||
@@ -89,6 +89,7 @@ func (r DefaultReturn) GinTonicErrorAbort(ctx *gin.Context, httpCode int) {
|
||||
}
|
||||
|
||||
ctx.Errors = append(ctx.Errors, &gin.Error{
|
||||
//nolint #goerr113
|
||||
Err: goErr.New(r.Message),
|
||||
Type: gin.ErrorTypeAny,
|
||||
})
|
||||
|
58
go.mod
58
go.mod
@@ -3,37 +3,93 @@ module github.com/nabbar/golib
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/DataDog/zstd v1.4.8 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/PuerkitoBio/goquery v1.6.1 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||
github.com/VictoriaMetrics/metrics v1.17.2 // indirect
|
||||
github.com/andybalholm/cascadia v1.2.0 // indirect
|
||||
github.com/aokoli/goutils v1.1.1 // indirect
|
||||
github.com/armon/go-metrics v0.3.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.3.2
|
||||
github.com/aws/aws-sdk-go-v2/config v1.1.5
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.1.5
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.3.1
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.5.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.1.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.2.2 // indirect
|
||||
github.com/cockroachdb/errors v1.8.3 // indirect
|
||||
github.com/cockroachdb/pebble v0.0.0-20210406003833-3d4c32f510a8 // indirect
|
||||
github.com/cockroachdb/redact v1.0.9 // indirect
|
||||
github.com/fatih/color v1.10.0
|
||||
github.com/fxamacker/cbor/v2 v2.2.0
|
||||
github.com/gin-gonic/gin v1.7.1
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.3.0
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-playground/validator/v10 v10.5.0
|
||||
github.com/gobuffalo/envy v1.9.0 // indirect
|
||||
github.com/gobuffalo/packd v1.0.0 // indirect
|
||||
github.com/gobuffalo/packr v1.30.1
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-github/v33 v33.0.0
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
|
||||
github.com/hashicorp/go-msgpack v1.1.5 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.6.8
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/memberlist v0.2.3 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 // indirect
|
||||
github.com/json-iterator/go v1.1.10 // indirect
|
||||
github.com/klauspost/compress v1.11.13 // indirect
|
||||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lni/dragonboat/v3 v3.3.2
|
||||
github.com/matcornic/hermes/v2 v2.1.0
|
||||
github.com/mattn/go-runewidth v0.0.12 // indirect
|
||||
github.com/miekg/dns v1.1.41 // indirect
|
||||
github.com/mitchellh/copystructure v1.1.2 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/onsi/ginkgo v1.16.1
|
||||
github.com/onsi/gomega v1.11.0
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.3+incompatible
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/ugorji/go v1.2.5 // indirect
|
||||
github.com/vanng822/go-premailer v1.20.1 // indirect
|
||||
github.com/vbauerster/mpb/v5 v5.4.0
|
||||
github.com/xanzy/go-gitlab v0.48.0
|
||||
github.com/xhit/go-simple-mail v2.2.2+incompatible
|
||||
github.com/xujiajun/nutsdb v0.6.0
|
||||
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
|
||||
golang.org/x/exp v0.0.0-20210405174845-4513512abef3 // indirect
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 // indirect
|
||||
golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
)
|
||||
|
@@ -64,7 +64,8 @@ func GetClientTimeout(serverName string, http2Tr bool, GlobalTimeout time.Durati
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: dl.DialContext,
|
||||
DisableCompression: true,
|
||||
TLSClientConfig: certificates.GetTLSConfig(serverName),
|
||||
//nolint #staticcheck
|
||||
TLSClientConfig: certificates.GetTLSConfig(serverName),
|
||||
}
|
||||
|
||||
return getclient(tr, http2Tr, GlobalTimeout)
|
||||
|
@@ -35,7 +35,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
)
|
||||
@@ -129,10 +128,37 @@ func (p PoolServerConfig) MapRun(f MapRunPoolServerConfig) PoolServerConfig {
|
||||
return r
|
||||
}
|
||||
|
||||
//nolint #maligned
|
||||
type ServerConfig struct {
|
||||
getTLSDefault func() libtls.TLSConfig
|
||||
|
||||
// Name is the name of the current server
|
||||
// the configuration allow multipke server, which each one must be identify by a name
|
||||
// If not defined, will use the listen address
|
||||
Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name" validate:"required"`
|
||||
|
||||
// Listen is the local address (ip, hostname, unix socket, ...) with a port
|
||||
// The server will bind with this address only and listen for the port defined
|
||||
Listen string `mapstructure:"listen" json:"listen" yaml:"listen" toml:"listen" validate:"required,hostname_port"`
|
||||
|
||||
// Expose is the address use to call this server. This can be allow to use a single fqdn to multiple server"
|
||||
Expose string `mapstructure:"expose" json:"expose" yaml:"expose" toml:"expose" validate:"required,url"`
|
||||
|
||||
// HandlerKeys is an options to associate current server with a specifc handler defined by the key
|
||||
// This allow to defined multiple server in only one config for different handler to start multiple api
|
||||
HandlerKeys string `mapstructure:"handler_keys" json:"handler_keys" yaml:"handler_keys" toml:"handler_keys"`
|
||||
|
||||
//private
|
||||
getTLSDefault func() libtls.TLSConfig
|
||||
|
||||
//private
|
||||
getParentContext func() context.Context
|
||||
|
||||
// TimeoutCacheInfo defined the validity time of cache for info (name, version, hash)
|
||||
TimeoutCacheInfo time.Duration `mapstructure:"timeout_cache_info" json:"timeout_cache_info" yaml:"timeout_cache_info" toml:"timeout_cache_info"`
|
||||
|
||||
// TimeoutCacheHealth defined the validity time of cache for healthcheck of this server
|
||||
TimeoutCacheHealth time.Duration `mapstructure:"timeout_cache_health" json:"timeout_cache_health" yaml:"timeout_cache_health" toml:"timeout_cache_health"`
|
||||
|
||||
// Enabled allow to disable a server without clean his configuration
|
||||
Disabled bool `mapstructure:"disabled" json:"disabled" yaml:"disabled" toml:"disabled"`
|
||||
|
||||
@@ -140,11 +166,13 @@ type ServerConfig struct {
|
||||
// y defined if the component for status is mandatory or not
|
||||
Mandatory bool `mapstructure:"mandatory" json:"mandatory" yaml:"mandatory" toml:"mandatory"`
|
||||
|
||||
// TimeoutCacheInfo defined the validity time of cache for info (name, version, hash)
|
||||
TimeoutCacheInfo time.Duration `mapstructure:"timeout_cache_info" json:"timeout_cache_info" yaml:"timeout_cache_info" toml:"timeout_cache_info"`
|
||||
// TLSMandatory is a flag to defined that TLS must be valid to start current server.
|
||||
TLSMandatory bool `mapstructure:"tls_mandatory" json:"tls_mandatory" yaml:"tls_mandatory" toml:"tls_mandatory"`
|
||||
|
||||
// TimeoutCacheHealth defined the validity time of cache for healthcheck of this server
|
||||
TimeoutCacheHealth time.Duration `mapstructure:"timeout_cache_health" json:"timeout_cache_health" yaml:"timeout_cache_health" toml:"timeout_cache_health"`
|
||||
// TLS is the tls configuration for this server.
|
||||
// To allow tls on this server, at least the TLS Config option InheritDefault must be at true and the default TLS config must be set.
|
||||
// If you don't want any tls config, just omit or set an empty struct.
|
||||
TLS libtls.Config `mapstructure:"tls" json:"tls" yaml:"tls" toml:"tls"`
|
||||
|
||||
/*** http options ***/
|
||||
|
||||
@@ -220,30 +248,6 @@ type ServerConfig struct {
|
||||
// be larger than 2^32-1. If the value is zero or larger than the
|
||||
// maximum, a default value will be used instead.
|
||||
MaxUploadBufferPerStream int32 `json:"max_upload_buffer_per_stream" json:"max_upload_buffer_per_stream" yaml:"max_upload_buffer_per_stream" toml:"max_upload_buffer_per_stream"`
|
||||
|
||||
// Name is the name of the current server
|
||||
// the configuration allow multipke server, which each one must be identify by a name
|
||||
// If not defined, will use the listen address
|
||||
Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name" validate:"required"`
|
||||
|
||||
// Listen is the local address (ip, hostname, unix socket, ...) with a port
|
||||
// The server will bind with this address only and listen for the port defined
|
||||
Listen string `mapstructure:"listen" json:"listen" yaml:"listen" toml:"listen" validate:"required,hostname_port"`
|
||||
|
||||
// Expose is the address use to call this server. This can be allow to use a single fqdn to multiple server"
|
||||
Expose string `mapstructure:"expose" json:"expose" yaml:"expose" toml:"expose" validate:"required,url"`
|
||||
|
||||
// HandlerKeys is an options to associate current server with a specifc handler defined by the key
|
||||
// This allow to defined multiple server in only one config for different handler to start multiple api
|
||||
HandlerKeys string `mapstructure:"handler_keys" json:"handler_keys" yaml:"handler_keys" toml:"handler_keys"`
|
||||
|
||||
// TLSMandatory is a flag to defined that TLS must be valid to start current server.
|
||||
TLSMandatory bool `mapstructure:"tls_mandatory" json:"tls_mandatory" yaml:"tls_mandatory" toml:"tls_mandatory"`
|
||||
|
||||
// TLS is the tls configuration for this server.
|
||||
// To allow tls on this server, at least the TLS Config option InheritDefault must be at true and the default TLS config must be set.
|
||||
// If you don't want any tls config, just omit or set an empty struct.
|
||||
TLS libtls.Config `mapstructure:"tls" json:"tls" yaml:"tls" toml:"tls"`
|
||||
}
|
||||
|
||||
func (c *ServerConfig) Clone() ServerConfig {
|
||||
@@ -319,7 +323,7 @@ func (c ServerConfig) GetListen() *url.URL {
|
||||
|
||||
if c.Listen != "" {
|
||||
if add, err = url.Parse(c.Listen); err != nil {
|
||||
if host, prt, err := net.SplitHostPort(c.Listen); err == nil {
|
||||
if host, prt, e := net.SplitHostPort(c.Listen); e == nil {
|
||||
add = &url.URL{
|
||||
Host: fmt.Sprintf("%s:%s", host, prt),
|
||||
}
|
||||
|
@@ -36,13 +36,10 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/nabbar/golib/status"
|
||||
|
||||
"github.com/nabbar/golib/logger"
|
||||
|
||||
"github.com/nabbar/golib/semaphore"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
libsem "github.com/nabbar/golib/semaphore"
|
||||
libsts "github.com/nabbar/golib/status"
|
||||
)
|
||||
|
||||
type FieldType uint8
|
||||
@@ -82,7 +79,7 @@ type PoolServer interface {
|
||||
|
||||
StatusInfo(bindAddress string) (name string, release string, hash string)
|
||||
StatusHealth(bindAddress string) error
|
||||
StatusRoute(prefix string, fctMessage status.FctMessage, sts status.RouteStatus)
|
||||
StatusRoute(prefix string, fctMessage libsts.FctMessage, sts libsts.RouteStatus)
|
||||
}
|
||||
|
||||
func NewPool(srv ...Server) PoolServer {
|
||||
@@ -353,7 +350,7 @@ func (p pool) ListenMultiHandler(handler map[string]http.Handler) liberr.Error {
|
||||
var e liberr.Error
|
||||
|
||||
e = ErrorPoolListen.Error(nil)
|
||||
logger.InfoLevel.Log("Calling listen for All Servers")
|
||||
liblog.InfoLevel.Log("Calling listen for All Servers")
|
||||
|
||||
p.MapRun(func(srv Server) {
|
||||
if len(handler) < 1 {
|
||||
@@ -371,7 +368,7 @@ func (p pool) ListenMultiHandler(handler map[string]http.Handler) liberr.Error {
|
||||
}
|
||||
})
|
||||
|
||||
logger.InfoLevel.Log("End of Calling listen for All Servers")
|
||||
liblog.InfoLevel.Log("End of Calling listen for All Servers")
|
||||
|
||||
if !e.HasParent() {
|
||||
e = nil
|
||||
@@ -380,64 +377,66 @@ func (p pool) ListenMultiHandler(handler map[string]http.Handler) liberr.Error {
|
||||
return e
|
||||
}
|
||||
|
||||
func (p pool) Restart() {
|
||||
func (p pool) runMapCommand(f func(sem libsem.Sem, srv Server)) {
|
||||
if p.Len() < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
s semaphore.Sem
|
||||
s libsem.Sem
|
||||
x context.Context
|
||||
c context.CancelFunc
|
||||
)
|
||||
|
||||
x, c = context.WithTimeout(context.Background(), timeoutShutdown)
|
||||
|
||||
defer func() {
|
||||
c()
|
||||
s.DeferMain()
|
||||
}()
|
||||
|
||||
x, c = context.WithTimeout(context.Background(), timeoutRestart)
|
||||
s = semaphore.NewSemaphoreWithContext(x, 0)
|
||||
s = libsem.NewSemaphoreWithContext(x, 0)
|
||||
|
||||
p.MapRun(func(srv Server) {
|
||||
_ = s.NewWorker()
|
||||
go func() {
|
||||
defer s.DeferWorker()
|
||||
srv.Restart()
|
||||
}()
|
||||
go func(sem libsem.Sem, srv Server) {
|
||||
f(sem, srv)
|
||||
}(s, srv)
|
||||
})
|
||||
|
||||
_ = s.WaitAll()
|
||||
}
|
||||
|
||||
func (p pool) Shutdown() {
|
||||
if p.Len() < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
s semaphore.Sem
|
||||
x context.Context
|
||||
c context.CancelFunc
|
||||
)
|
||||
|
||||
func (p pool) runMapRestart(sem libsem.Sem, srv Server) {
|
||||
defer func() {
|
||||
c()
|
||||
s.DeferMain()
|
||||
if sem != nil {
|
||||
sem.DeferWorker()
|
||||
}
|
||||
}()
|
||||
|
||||
x, c = context.WithTimeout(context.Background(), timeoutShutdown)
|
||||
s = semaphore.NewSemaphoreWithContext(x, 0)
|
||||
if srv != nil {
|
||||
srv.Restart()
|
||||
}
|
||||
}
|
||||
|
||||
p.MapRun(func(srv Server) {
|
||||
_ = s.NewWorker()
|
||||
go func() {
|
||||
defer s.DeferWorker()
|
||||
srv.Shutdown()
|
||||
}()
|
||||
})
|
||||
func (p pool) runMapShutdown(sem libsem.Sem, srv Server) {
|
||||
defer func() {
|
||||
if sem != nil {
|
||||
sem.DeferWorker()
|
||||
}
|
||||
}()
|
||||
|
||||
_ = s.WaitAll()
|
||||
if srv != nil {
|
||||
srv.Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
func (p pool) Restart() {
|
||||
p.runMapCommand(p.runMapRestart)
|
||||
}
|
||||
|
||||
func (p pool) Shutdown() {
|
||||
p.runMapCommand(p.runMapShutdown)
|
||||
}
|
||||
|
||||
func (p pool) StatusInfo(bindAddress string) (name string, release string, hash string) {
|
||||
@@ -453,10 +452,11 @@ func (p pool) StatusHealth(bindAddress string) error {
|
||||
return s.StatusHealth()
|
||||
}
|
||||
|
||||
//nolint #goerr113
|
||||
return fmt.Errorf("missing server '%s'", bindAddress)
|
||||
}
|
||||
|
||||
func (p pool) StatusRoute(keyPrefix string, fctMessage status.FctMessage, sts status.RouteStatus) {
|
||||
func (p pool) StatusRoute(keyPrefix string, fctMessage libsts.FctMessage, sts libsts.RouteStatus) {
|
||||
p.MapRun(func(srv Server) {
|
||||
bind := srv.GetBindable()
|
||||
sts.ComponentNew(fmt.Sprintf("%s-%s", keyPrefix, bind), srv.StatusComponent(fctMessage))
|
||||
|
@@ -45,6 +45,8 @@ import (
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
const _TimeoutWaitingPortFreeing = 500 * time.Microsecond
|
||||
|
||||
type srvRun struct {
|
||||
err *atomic.Value
|
||||
run *atomic.Value
|
||||
@@ -109,6 +111,7 @@ func (s *srvRun) setErr(e error) {
|
||||
if e != nil {
|
||||
s.err.Store(e)
|
||||
} else {
|
||||
//nolint #goerr113
|
||||
s.err.Store(errors.New(""))
|
||||
}
|
||||
}
|
||||
@@ -141,6 +144,7 @@ func (s *srvRun) Merge(srv Server) bool {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
//nolint #gocognit
|
||||
func (s *srvRun) Listen(cfg *ServerConfig, handler http.Handler) liberr.Error {
|
||||
ssl, err := cfg.GetTLS()
|
||||
if err != nil {
|
||||
@@ -263,6 +267,7 @@ func (s *srvRun) Listen(cfg *ServerConfig, handler http.Handler) liberr.Error {
|
||||
s.setRunning(true)
|
||||
err = s.srv.ListenAndServeTLS("", "")
|
||||
} else if tlsMandatory {
|
||||
//nolint #goerr113
|
||||
err = fmt.Errorf("missing valid server certificates")
|
||||
} else {
|
||||
liblog.InfoLevel.Logf("Server '%s' is starting with bindable: %s", name, host)
|
||||
@@ -333,7 +338,7 @@ func (s *srvRun) PortInUse(listen string) liberr.Error {
|
||||
}
|
||||
}()
|
||||
|
||||
ctx, cnl = context.WithTimeout(context.TODO(), 2*time.Second)
|
||||
ctx, cnl = context.WithTimeout(context.TODO(), _TimeoutWaitingPortFreeing)
|
||||
con, err = dia.DialContext(ctx, "tcp", listen)
|
||||
|
||||
if con != nil {
|
||||
|
@@ -34,24 +34,22 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/nabbar/golib/status"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
libsts "github.com/nabbar/golib/status"
|
||||
)
|
||||
|
||||
const (
|
||||
timeoutShutdown = 10 * time.Second
|
||||
timeoutRestart = 30 * time.Second
|
||||
)
|
||||
|
||||
type server struct {
|
||||
run *atomic.Value
|
||||
cfg ServerConfig
|
||||
cfg *atomic.Value
|
||||
}
|
||||
|
||||
type Server interface {
|
||||
GetConfig() *ServerConfig
|
||||
SetConfig(cfg *ServerConfig)
|
||||
SetConfig(cfg *ServerConfig) bool
|
||||
|
||||
GetName() string
|
||||
GetBindable() string
|
||||
@@ -69,16 +67,50 @@ type Server interface {
|
||||
|
||||
StatusInfo() (name string, release string, hash string)
|
||||
StatusHealth() error
|
||||
StatusComponent(message status.FctMessage) status.Component
|
||||
StatusComponent(message libsts.FctMessage) libsts.Component
|
||||
}
|
||||
|
||||
func NewServer(cfg *ServerConfig) Server {
|
||||
c := new(atomic.Value)
|
||||
c.Store(cfg.Clone())
|
||||
|
||||
return &server{
|
||||
cfg: cfg.Clone(),
|
||||
cfg: c,
|
||||
run: new(atomic.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) GetConfig() *ServerConfig {
|
||||
if s.cfg == nil {
|
||||
return nil
|
||||
} else if i := s.cfg.Load(); i == nil {
|
||||
return nil
|
||||
} else if c, ok := i.(ServerConfig); !ok {
|
||||
return nil
|
||||
} else {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) SetConfig(cfg *ServerConfig) bool {
|
||||
if cfg == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if s.cfg == nil {
|
||||
s.cfg = new(atomic.Value)
|
||||
}
|
||||
|
||||
c := cfg.Clone()
|
||||
|
||||
if c.Name == "" {
|
||||
c.Name = c.GetListen().Host
|
||||
}
|
||||
|
||||
s.cfg.Store(cfg.Clone())
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *server) getRun() run {
|
||||
if s.run == nil {
|
||||
return newRun()
|
||||
@@ -103,32 +135,20 @@ func (s *server) getErr() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) GetConfig() *ServerConfig {
|
||||
return &s.cfg
|
||||
}
|
||||
|
||||
func (s *server) SetConfig(cfg *ServerConfig) {
|
||||
s.cfg = cfg.Clone()
|
||||
}
|
||||
|
||||
func (s server) GetName() string {
|
||||
if s.cfg.Name == "" {
|
||||
s.cfg.Name = s.GetBindable()
|
||||
}
|
||||
|
||||
return s.cfg.Name
|
||||
return s.GetConfig().Name
|
||||
}
|
||||
|
||||
func (s *server) GetBindable() string {
|
||||
return s.cfg.GetListen().Host
|
||||
return s.GetConfig().GetListen().Host
|
||||
}
|
||||
|
||||
func (s *server) GetExpose() string {
|
||||
return s.cfg.GetExpose().String()
|
||||
return s.GetConfig().GetExpose().String()
|
||||
}
|
||||
|
||||
func (s *server) GetHandlerKey() string {
|
||||
return s.cfg.GetHandlerKey()
|
||||
return s.GetConfig().GetHandlerKey()
|
||||
}
|
||||
|
||||
func (s *server) IsRunning() bool {
|
||||
@@ -136,12 +156,12 @@ func (s *server) IsRunning() bool {
|
||||
}
|
||||
|
||||
func (s *server) IsTLS() bool {
|
||||
return s.cfg.IsTLS()
|
||||
return s.GetConfig().IsTLS()
|
||||
}
|
||||
|
||||
func (s *server) Listen(handler http.Handler) liberr.Error {
|
||||
r := s.getRun()
|
||||
e := r.Listen(&s.cfg, handler)
|
||||
e := r.Listen(s.GetConfig(), handler)
|
||||
s.setRun(r)
|
||||
|
||||
return e
|
||||
@@ -163,12 +183,11 @@ func (s *server) Shutdown() {
|
||||
}
|
||||
|
||||
func (s *server) Merge(srv Server) bool {
|
||||
if x, ok := srv.(*server); ok {
|
||||
s.cfg = x.cfg
|
||||
return true
|
||||
if x, ok := srv.(*server); !ok {
|
||||
return false
|
||||
} else {
|
||||
return s.SetConfig(x.GetConfig())
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *server) StatusInfo() (name string, release string, hash string) {
|
||||
@@ -180,17 +199,20 @@ func (s *server) StatusInfo() (name string, release string, hash string) {
|
||||
}
|
||||
|
||||
func (s *server) StatusHealth() error {
|
||||
if !s.cfg.Disabled && s.IsRunning() {
|
||||
c := s.GetConfig()
|
||||
if !c.Disabled && s.IsRunning() {
|
||||
return nil
|
||||
} else if s.cfg.Disabled {
|
||||
} else if c.Disabled {
|
||||
//nolint #goerr113
|
||||
return fmt.Errorf("server disabled")
|
||||
} else if e := s.getErr(); e != nil {
|
||||
return e
|
||||
} else {
|
||||
//nolint #goerr113
|
||||
return fmt.Errorf("server is offline -- missing error")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) StatusComponent(message status.FctMessage) status.Component {
|
||||
return status.NewComponent(s.cfg.Mandatory, s.StatusInfo, s.StatusHealth, message, s.cfg.TimeoutCacheInfo, s.cfg.TimeoutCacheHealth)
|
||||
func (s *server) StatusComponent(message libsts.FctMessage) libsts.Component {
|
||||
return libsts.NewComponent(s.GetConfig().Mandatory, s.StatusInfo, s.StatusHealth, message, s.GetConfig().TimeoutCacheInfo, s.GetConfig().TimeoutCacheHealth)
|
||||
}
|
||||
|
132
ldap/ldap.go
132
ldap/ldap.go
@@ -59,10 +59,11 @@ func NewLDAP(ctx context.Context, cnf *Config, attributes []string) (*HelperLDAP
|
||||
|
||||
return &HelperLDAP{
|
||||
Attributes: attributes,
|
||||
tlsConfig: libcrt.GetTLSConfig(cnf.Uri),
|
||||
tlsMode: tlsmode_init,
|
||||
config: cnf.Clone(),
|
||||
ctx: libctx.IsolateParent(ctx),
|
||||
//nolint #staticcheck
|
||||
tlsConfig: libcrt.GetTLSConfig(cnf.Uri),
|
||||
tlsMode: _TLSModeInit,
|
||||
config: cnf.Clone(),
|
||||
ctx: libctx.IsolateParent(ctx),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -83,15 +84,15 @@ func (lc *HelperLDAP) ForceTLSMode(tlsMode TLSMode, tlsConfig *tls.Config) {
|
||||
}
|
||||
|
||||
switch tlsMode {
|
||||
case TLSMODE_TLS:
|
||||
lc.tlsMode = TLSMODE_TLS
|
||||
case TLSMODE_STARTTLS:
|
||||
lc.tlsMode = TLSMODE_STARTTLS
|
||||
case TLSMODE_NONE:
|
||||
case TLSModeTLS:
|
||||
lc.tlsMode = TLSModeTLS
|
||||
case TLSModeStarttls:
|
||||
lc.tlsMode = TLSModeStarttls
|
||||
case TLSModeNone:
|
||||
lc.tlsConfig = nil
|
||||
lc.tlsMode = TLSMODE_NONE
|
||||
case tlsmode_init:
|
||||
lc.tlsMode = tlsmode_init
|
||||
lc.tlsMode = TLSModeNone
|
||||
case _TLSModeInit:
|
||||
lc.tlsMode = _TLSModeInit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +176,7 @@ func (lc *HelperLDAP) starttls(l *ldap.Conn) liberr.Error {
|
||||
|
||||
func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) {
|
||||
if lc == nil {
|
||||
return TLSMODE_NONE, ErrorEmptyParams.Error(nil)
|
||||
return TLSModeNone, ErrorEmptyParams.Error(nil)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -192,32 +193,32 @@ func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) {
|
||||
if lc.config.Portldaps != 0 {
|
||||
l, err = lc.dialTLS()
|
||||
|
||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSMODE_TLS.String())
|
||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSModeTLS.String())
|
||||
|
||||
if err == nil {
|
||||
return TLSMODE_TLS, nil
|
||||
return TLSModeTLS, nil
|
||||
}
|
||||
}
|
||||
|
||||
if lc.config.PortLdap == 0 {
|
||||
return tlsmode_init, ErrorLDAPServerConfig.Error(nil)
|
||||
return _TLSModeInit, ErrorLDAPServerConfig.Error(nil)
|
||||
}
|
||||
|
||||
l, err = lc.dial()
|
||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSMODE_NONE.String())
|
||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSModeNone.String())
|
||||
|
||||
if err != nil {
|
||||
return tlsmode_init, err
|
||||
return _TLSModeInit, err
|
||||
}
|
||||
|
||||
err = lc.starttls(l)
|
||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSMODE_STARTTLS.String())
|
||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSModeStarttls.String())
|
||||
|
||||
if err == nil {
|
||||
return TLSMODE_STARTTLS, nil
|
||||
return TLSModeStarttls, nil
|
||||
}
|
||||
|
||||
return TLSMODE_NONE, nil
|
||||
return TLSModeNone, nil
|
||||
}
|
||||
|
||||
func (lc *HelperLDAP) connect() liberr.Error {
|
||||
@@ -235,7 +236,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
||||
err liberr.Error
|
||||
)
|
||||
|
||||
if lc.tlsMode == tlsmode_init {
|
||||
if lc.tlsMode == _TLSModeInit {
|
||||
m, e := lc.tryConnect()
|
||||
|
||||
if e != nil {
|
||||
@@ -245,7 +246,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
||||
lc.tlsMode = m
|
||||
}
|
||||
|
||||
if lc.tlsMode == TLSMODE_TLS {
|
||||
if lc.tlsMode == TLSModeTLS {
|
||||
l, err = lc.dialTLS()
|
||||
if err != nil {
|
||||
if l != nil {
|
||||
@@ -255,7 +256,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
||||
}
|
||||
}
|
||||
|
||||
if lc.tlsMode == TLSMODE_NONE || lc.tlsMode == TLSMODE_STARTTLS {
|
||||
if lc.tlsMode == TLSModeNone || lc.tlsMode == TLSModeStarttls {
|
||||
l, err = lc.dial()
|
||||
if err != nil {
|
||||
if l != nil {
|
||||
@@ -265,7 +266,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
||||
}
|
||||
}
|
||||
|
||||
if lc.tlsMode == TLSMODE_STARTTLS {
|
||||
if lc.tlsMode == TLSModeStarttls {
|
||||
err = lc.starttls(l)
|
||||
if err != nil {
|
||||
if l != nil {
|
||||
@@ -346,7 +347,7 @@ func (lc *HelperLDAP) Connect() liberr.Error {
|
||||
return err
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Bind success on LDAP server %s with tls mode '%s'", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String())
|
||||
liblog.DebugLevel.Logf("Bind success on LDAP server %s with tls mode '%s'", lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -376,7 +377,7 @@ func (lc *HelperLDAP) runSearch(filter string, attributes []string) (*ldap.Searc
|
||||
return nil, ErrorLDAPSearch.ErrorParent(err)
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Search success on server '%s' with tls mode '%s', with filter [%s] and attribute %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), filter, attributes)
|
||||
liblog.DebugLevel.Logf("Search success on server '%s' with tls mode '%s', with filter [%s] and attribute %v", lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), filter, attributes)
|
||||
return src, nil
|
||||
}
|
||||
|
||||
@@ -405,46 +406,10 @@ func (lc *HelperLDAP) getUserName(username string) (string, liberr.Error) {
|
||||
|
||||
//UserInfo used to retrieve the information of a given username.
|
||||
func (lc *HelperLDAP) UserInfo(username string) (map[string]string, liberr.Error) {
|
||||
var (
|
||||
err liberr.Error
|
||||
src *ldap.SearchResult
|
||||
userRes map[string]string
|
||||
)
|
||||
|
||||
if username, err = lc.getUserName(username); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userRes = make(map[string]string)
|
||||
attributes := append(lc.Attributes, "cn")
|
||||
|
||||
src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterUser, userFieldUid, username), attributes)
|
||||
|
||||
if err != nil {
|
||||
return userRes, err
|
||||
}
|
||||
|
||||
if len(src.Entries) != 1 {
|
||||
if len(src.Entries) > 1 {
|
||||
return userRes, ErrorLDAPUserNotUniq.Error(nil)
|
||||
} else {
|
||||
return userRes, ErrorLDAPUserNotFound.Error(nil)
|
||||
}
|
||||
}
|
||||
|
||||
for _, attr := range attributes {
|
||||
userRes[attr] = src.Entries[0].GetAttributeValue(attr)
|
||||
}
|
||||
|
||||
if _, ok := userRes["DN"]; !ok {
|
||||
userRes["DN"] = src.Entries[0].DN
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Map info retrieve in ldap server '%s' with tls mode '%s' about user [%s] : %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), username, userRes)
|
||||
return userRes, nil
|
||||
return lc.UserInfoByField(username, userFieldUid)
|
||||
}
|
||||
|
||||
//UserInfo used to retrieve the information of a given username.
|
||||
//UserInfoByField used to retrieve the information of a given username but use a given field to make the search.
|
||||
func (lc *HelperLDAP) UserInfoByField(username string, fieldOfUnicValue string) (map[string]string, liberr.Error) {
|
||||
var (
|
||||
err liberr.Error
|
||||
@@ -481,39 +446,16 @@ func (lc *HelperLDAP) UserInfoByField(username string, fieldOfUnicValue string)
|
||||
userRes["DN"] = src.Entries[0].DN
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Map info retrieve in ldap server '%s' with tls mode '%s' about user [%s] : %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), username, userRes)
|
||||
liblog.DebugLevel.Logf("Map info retrieve in ldap server '%s' with tls mode '%s' about user [%s] : %v", lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), username, userRes)
|
||||
return userRes, nil
|
||||
}
|
||||
|
||||
//GroupInfo used to retrieve the information of a given group cn.
|
||||
func (lc *HelperLDAP) GroupInfo(groupname string) (map[string]interface{}, liberr.Error) {
|
||||
var (
|
||||
err liberr.Error
|
||||
src *ldap.SearchResult
|
||||
grpInfo map[string]interface{}
|
||||
)
|
||||
|
||||
src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterGroup, groupFieldCN, groupname), []string{})
|
||||
if err != nil {
|
||||
return grpInfo, err
|
||||
}
|
||||
|
||||
if len(src.Entries) == 0 {
|
||||
return nil, ErrorLDAPGroupNotFound.Error(nil)
|
||||
}
|
||||
|
||||
grpInfo = make(map[string]interface{}, len(src.Entries[0].Attributes))
|
||||
for _, entry := range src.Entries {
|
||||
for _, entryAttribute := range entry.Attributes {
|
||||
grpInfo[entryAttribute.Name] = entryAttribute.Values
|
||||
}
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Info for group [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grpInfo)
|
||||
return grpInfo, nil
|
||||
return lc.GroupInfoByField(groupname, groupFieldCN)
|
||||
}
|
||||
|
||||
//GroupInfo used to retrieve the information of a given group cn.
|
||||
//GroupInfoByField used to retrieve the information of a given group cn, but use a given field to make the search.
|
||||
func (lc *HelperLDAP) GroupInfoByField(groupname string, fieldForUnicValue string) (map[string]interface{}, liberr.Error) {
|
||||
var (
|
||||
err liberr.Error
|
||||
@@ -537,7 +479,7 @@ func (lc *HelperLDAP) GroupInfoByField(groupname string, fieldForUnicValue strin
|
||||
}
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Info for group [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grpInfo)
|
||||
liblog.DebugLevel.Logf("Info for group [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), grpInfo)
|
||||
return grpInfo, nil
|
||||
}
|
||||
|
||||
@@ -562,13 +504,13 @@ func (lc *HelperLDAP) UserMemberOf(username string) ([]string, liberr.Error) {
|
||||
|
||||
for _, entry := range src.Entries {
|
||||
for _, mmb := range entry.GetAttributeValues("memberOf") {
|
||||
liblog.DebugLevel.Logf("Group find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), mmb)
|
||||
liblog.DebugLevel.Logf("Group find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), mmb)
|
||||
mmo := lc.ParseEntries(mmb)
|
||||
grp = append(grp, mmo["cn"]...)
|
||||
}
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Groups find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grp)
|
||||
liblog.DebugLevel.Logf("Groups find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), grp)
|
||||
return grp, nil
|
||||
}
|
||||
|
||||
@@ -618,7 +560,7 @@ func (lc *HelperLDAP) UsersOfGroup(groupname string) ([]string, liberr.Error) {
|
||||
}
|
||||
}
|
||||
|
||||
liblog.DebugLevel.Logf("Member of groups [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grp)
|
||||
liblog.DebugLevel.Logf("Member of groups [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), grp)
|
||||
return grp, nil
|
||||
}
|
||||
|
||||
|
@@ -35,13 +35,13 @@ import (
|
||||
type TLSMode uint8
|
||||
|
||||
const (
|
||||
tlsmode_init TLSMode = iota
|
||||
_TLSModeInit TLSMode = iota
|
||||
//TLSModeNone no tls connection.
|
||||
TLSMODE_NONE TLSMode = iota + 1
|
||||
TLSModeNone TLSMode = iota + 1
|
||||
//TLSModeTLS strict tls connection.
|
||||
TLSMODE_TLS
|
||||
//TLSModeStartTLS starttls connection (tls into a no tls connection).
|
||||
TLSMODE_STARTTLS
|
||||
TLSModeTLS
|
||||
//TLSModeStarttls starttls connection (tls into a no tls connection).
|
||||
TLSModeStarttls
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,17 +51,17 @@ const (
|
||||
|
||||
func (m TLSMode) String() string {
|
||||
switch m {
|
||||
case TLSMODE_STARTTLS:
|
||||
case TLSModeStarttls:
|
||||
return "starttls"
|
||||
case TLSMODE_TLS:
|
||||
case TLSModeTLS:
|
||||
return "tls"
|
||||
case TLSMODE_NONE:
|
||||
case TLSModeNone:
|
||||
return "none"
|
||||
case tlsmode_init:
|
||||
case _TLSModeInit:
|
||||
return "not defined"
|
||||
}
|
||||
|
||||
return tlsmode_init.String()
|
||||
return _TLSModeInit.String()
|
||||
}
|
||||
|
||||
func GetDefaultAttributes() []string {
|
||||
@@ -123,6 +123,7 @@ func (cnf Config) Validate() errors.Error {
|
||||
}
|
||||
|
||||
for _, err := range err.(validator.ValidationErrors) {
|
||||
//nolint #goerr113
|
||||
e.AddParent(fmt.Errorf("config field '%s' is not validated by constraint '%s'", err.StructNamespace(), err.ActualTag()))
|
||||
}
|
||||
}
|
||||
|
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package mail
|
||||
|
||||
import "io"
|
||||
|
||||
const maxLineChars = 76
|
||||
|
||||
type base64LineWrap struct {
|
||||
writer io.Writer
|
||||
numLineChars int
|
||||
}
|
||||
|
||||
func (e *base64LineWrap) Write(p []byte) (n int, err error) {
|
||||
n = 0
|
||||
// while we have more chars than are allowed
|
||||
for len(p)+e.numLineChars > maxLineChars {
|
||||
numCharsToWrite := maxLineChars - e.numLineChars
|
||||
// write the chars we can
|
||||
/* #nosec */
|
||||
//nolint #nosec
|
||||
_, _ = e.writer.Write(p[:numCharsToWrite])
|
||||
// write a line break
|
||||
/* #nosec */
|
||||
//nolint #nosec
|
||||
_, _ = e.writer.Write([]byte("\r\n"))
|
||||
// reset the line count
|
||||
e.numLineChars = 0
|
||||
// remove the chars that have been written
|
||||
p = p[numCharsToWrite:]
|
||||
// set the num of chars written
|
||||
n += numCharsToWrite
|
||||
}
|
||||
|
||||
// write what is left
|
||||
/* #nosec */
|
||||
//nolint #nosec
|
||||
_, _ = e.writer.Write(p)
|
||||
e.numLineChars += len(p)
|
||||
n += len(p)
|
||||
|
||||
return
|
||||
}
|
@@ -28,9 +28,9 @@ package mail
|
||||
type ContentType uint8
|
||||
|
||||
const (
|
||||
// TextPlain sets body type to text/plain in message body
|
||||
// ContentPlainText sets body type to text/plain in message body.
|
||||
ContentPlainText ContentType = iota
|
||||
// TextHTML sets body type to text/html in message body
|
||||
// ContentHTML sets body type to text/html in message body.
|
||||
ContentHTML
|
||||
)
|
||||
|
||||
@@ -44,14 +44,3 @@ func (c ContentType) String() string {
|
||||
|
||||
return ContentPlainText.String()
|
||||
}
|
||||
|
||||
func (c ContentType) getContentType() string {
|
||||
switch c {
|
||||
case ContentPlainText:
|
||||
return "text/plain"
|
||||
case ContentHTML:
|
||||
return "text/html"
|
||||
}
|
||||
|
||||
return ContentPlainText.getContentType()
|
||||
}
|
||||
|
200
mail/encoder.go
200
mail/encoder.go
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package mail
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
w *bufio.Writer
|
||||
charset string
|
||||
usedChars int
|
||||
}
|
||||
|
||||
// newEncoder returns a new mime header encoder that writes to w. The c
|
||||
// parameter specifies the name of the character set of the text that will be
|
||||
// encoded. The u parameter indicates how many characters have been used
|
||||
// already.
|
||||
func newEncoder(w io.Writer, c string, u int) *encoder {
|
||||
return &encoder{bufio.NewWriter(w), strings.ToUpper(c), u}
|
||||
}
|
||||
|
||||
// encode encodes p using the "Q" encoding and writes it to the underlying
|
||||
// io.Writer. It limits line length to 75 characters.
|
||||
func (e *encoder) encode(p []byte) (n int, err error) {
|
||||
var output bytes.Buffer
|
||||
allPrintable := true
|
||||
|
||||
// some lines we encode end in "
|
||||
//maxLineLength := 75 - 1
|
||||
maxLineLength := 76
|
||||
|
||||
// prevent header injection
|
||||
p = e.secureHeader(p)
|
||||
|
||||
// check to see if we have all printable characters
|
||||
for _, c := range p {
|
||||
if !e.isVchar(c) && !e.isWSP(c) {
|
||||
allPrintable = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// all characters are printable. just do line folding
|
||||
if allPrintable {
|
||||
text := string(p)
|
||||
words := strings.Split(text, " ")
|
||||
|
||||
lineBuffer := ""
|
||||
firstWord := true
|
||||
|
||||
// split the line where necessary
|
||||
for _, word := range words {
|
||||
|
||||
newWord := ""
|
||||
if !firstWord {
|
||||
newWord += " "
|
||||
}
|
||||
newWord += word
|
||||
|
||||
// check line length
|
||||
if (e.usedChars+len(lineBuffer)+len(newWord) /*+len(" ")+len(word)*/) > maxLineLength && (lineBuffer != "" || e.usedChars != 0) {
|
||||
output.WriteString(lineBuffer + "\r\n")
|
||||
|
||||
// first word on newline needs a space in front
|
||||
if !firstWord {
|
||||
lineBuffer = ""
|
||||
} else {
|
||||
lineBuffer = " "
|
||||
}
|
||||
|
||||
// reset since not on the first line anymore
|
||||
e.usedChars = 0
|
||||
}
|
||||
lineBuffer += newWord /*word*/
|
||||
|
||||
firstWord = false
|
||||
}
|
||||
|
||||
output.WriteString(lineBuffer)
|
||||
|
||||
} else {
|
||||
firstLine := true
|
||||
|
||||
// A single encoded word can not be longer than 75 characters
|
||||
if e.usedChars == 0 {
|
||||
maxLineLength = 75
|
||||
}
|
||||
|
||||
wordBegin := "=?" + e.charset + "?Q?"
|
||||
wordEnd := "?="
|
||||
|
||||
lineBuffer := wordBegin
|
||||
|
||||
for i := 0; i < len(p); {
|
||||
// encode the character
|
||||
encodedChar, runeLength := e.encodeChar(p, i)
|
||||
|
||||
// Check line length
|
||||
if len(lineBuffer)+e.usedChars+len(encodedChar) > (maxLineLength - len(wordEnd)) {
|
||||
output.WriteString(lineBuffer + wordEnd + "\r\n")
|
||||
lineBuffer = " " + wordBegin
|
||||
firstLine = false
|
||||
}
|
||||
|
||||
lineBuffer += encodedChar
|
||||
|
||||
i = i + runeLength
|
||||
|
||||
// reset since not on the first line anymore
|
||||
if !firstLine {
|
||||
e.usedChars = 0
|
||||
maxLineLength = 76
|
||||
}
|
||||
}
|
||||
|
||||
output.WriteString(lineBuffer + wordEnd)
|
||||
}
|
||||
|
||||
_, _ = e.w.Write(output.Bytes())
|
||||
_ = e.w.Flush()
|
||||
n = output.Len()
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// encode takes a string and position in that string and encodes one utf-8
|
||||
// character. It then returns the encoded string and number of runes in the
|
||||
// character.
|
||||
func (e *encoder) encodeChar(text []byte, i int) (encodedString string, runeLength int) {
|
||||
started := false
|
||||
|
||||
for ; i < len(text) && (!utf8.RuneStart(text[i]) || !started); i++ {
|
||||
switch c := text[i]; {
|
||||
case c == ' ':
|
||||
encodedString += "_"
|
||||
case e.isVchar(c) && c != '=' && c != '?' && c != '_':
|
||||
encodedString += string(c)
|
||||
default:
|
||||
encodedString += fmt.Sprintf("=%02X", c)
|
||||
}
|
||||
|
||||
runeLength++
|
||||
|
||||
started = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// secureHeader removes all unnecessary values to prevent
|
||||
// header injection
|
||||
func (e *encoder) secureHeader(text []byte) []byte {
|
||||
secureValue := strings.TrimSpace(string(text))
|
||||
secureValue = strings.Replace(secureValue, "\r", "", -1)
|
||||
secureValue = strings.Replace(secureValue, "\n", "", -1)
|
||||
secureValue = strings.Replace(secureValue, "\t", "", -1)
|
||||
|
||||
return []byte(secureValue)
|
||||
}
|
||||
|
||||
// isVchar returns true if c is an RFC 5322 VCHAR character.
|
||||
func (e *encoder) isVchar(c byte) bool {
|
||||
// Visible (printing) characters.
|
||||
return '!' <= c && c <= '~'
|
||||
}
|
||||
|
||||
// isWSP returns true if c is a WSP (white space).
|
||||
// WSP is a space or horizontal tab (RFC5234 Appendix B).
|
||||
func (e *encoder) isWSP(c byte) bool {
|
||||
return c == ' ' || c == '\t'
|
||||
}
|
@@ -28,16 +28,16 @@ package mail
|
||||
type Encoding uint8
|
||||
|
||||
const (
|
||||
// EncodingNone turns off encoding on the message body
|
||||
// EncodingNone turns off encoding on the message body.
|
||||
EncodingNone Encoding = iota
|
||||
|
||||
// EncodingBinary is equal to EncodingNone, but string is set to binrary instead of none
|
||||
// EncodingBinary is equal to EncodingNone, but string is set to binary instead of none.
|
||||
EncodingBinary
|
||||
|
||||
// EncodingBase64 sets the message body encoding to base64
|
||||
// EncodingBase64 sets the message body encoding to base64.
|
||||
EncodingBase64
|
||||
|
||||
// EncodingQuotedPrintable sets the message body encoding to quoted-printable
|
||||
// EncodingQuotedPrintable sets the message body encoding to quoted-printable.
|
||||
EncodingQuotedPrintable
|
||||
)
|
||||
|
||||
@@ -54,16 +54,3 @@ func (e Encoding) String() string {
|
||||
}
|
||||
return EncodingNone.String()
|
||||
}
|
||||
|
||||
func (e Encoding) getEncoding() string {
|
||||
switch e {
|
||||
case EncodingNone, EncodingBinary:
|
||||
return "binary"
|
||||
case EncodingBase64:
|
||||
return "base64"
|
||||
case EncodingQuotedPrintable:
|
||||
return "quoted-printable"
|
||||
}
|
||||
|
||||
return EncodingNone.getEncoding()
|
||||
}
|
||||
|
21
mail/mail.go
21
mail/mail.go
@@ -36,7 +36,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
MailDateTimeLayout = time.RFC1123Z
|
||||
DateTimeLayout = time.RFC1123Z
|
||||
|
||||
headerMimeVersion = "MIME-Version"
|
||||
headerDate = "Date"
|
||||
@@ -44,17 +44,16 @@ const (
|
||||
)
|
||||
|
||||
type mail struct {
|
||||
headers textproto.MIMEHeader
|
||||
charset string
|
||||
encoding Encoding
|
||||
date time.Time
|
||||
attach []File
|
||||
inline []File
|
||||
body []Body
|
||||
charset string
|
||||
subject string
|
||||
headers textproto.MIMEHeader
|
||||
address *email
|
||||
encoding Encoding
|
||||
priority Priority
|
||||
|
||||
address *email
|
||||
attach []File
|
||||
inline []File
|
||||
body []Body
|
||||
}
|
||||
|
||||
func (m *mail) Email() Email {
|
||||
@@ -112,7 +111,7 @@ func (m *mail) SetDateString(layout, datetime string) liberr.Error {
|
||||
}
|
||||
|
||||
func (m *mail) GetDateString() string {
|
||||
return m.date.Format(MailDateTimeLayout)
|
||||
return m.date.Format(DateTimeLayout)
|
||||
}
|
||||
|
||||
func (m *mail) AddHeader(key string, values ...string) {
|
||||
@@ -182,7 +181,7 @@ func (m *mail) GetHeaders() textproto.MIMEHeader {
|
||||
h = m.addHeader(h, key, values...)
|
||||
})
|
||||
|
||||
for k, _ := range m.headers {
|
||||
for k := range m.headers {
|
||||
h = m.addHeader(h, k, m.headers.Values(k)...)
|
||||
}
|
||||
|
||||
|
@@ -34,11 +34,11 @@ const (
|
||||
type Priority uint8
|
||||
|
||||
const (
|
||||
// PriorityNormal sets the email priority to normal
|
||||
// PriorityNormal sets the email priority to normal.
|
||||
PriorityNormal Priority = iota
|
||||
// PriorityLow sets the email priority to Low
|
||||
// PriorityLow sets the email priority to Low.
|
||||
PriorityLow
|
||||
// PriorityHigh sets the email priority to High
|
||||
// PriorityHigh sets the email priority to High.
|
||||
PriorityHigh
|
||||
)
|
||||
|
||||
@@ -71,9 +71,9 @@ func (p Priority) headerPriority() string {
|
||||
func (p Priority) headerImportance() string {
|
||||
switch p {
|
||||
case PriorityLow:
|
||||
return "Low"
|
||||
return PriorityLow.String()
|
||||
case PriorityHigh:
|
||||
return "High"
|
||||
return PriorityHigh.String()
|
||||
case PriorityNormal:
|
||||
return ""
|
||||
}
|
||||
@@ -84,9 +84,9 @@ func (p Priority) headerImportance() string {
|
||||
func (p Priority) headerMSMailPriority() string {
|
||||
switch p {
|
||||
case PriorityLow:
|
||||
return "Low"
|
||||
return PriorityLow.String()
|
||||
case PriorityHigh:
|
||||
return "High"
|
||||
return PriorityHigh.String()
|
||||
case PriorityNormal:
|
||||
return ""
|
||||
}
|
||||
|
@@ -31,29 +31,32 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/nabbar/golib/smtp"
|
||||
|
||||
"github.com/nabbar/golib/ioutils"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
libiot "github.com/nabbar/golib/ioutils"
|
||||
libsmtp "github.com/nabbar/golib/smtp"
|
||||
simple "github.com/xhit/go-simple-mail"
|
||||
)
|
||||
|
||||
const (
|
||||
_MinSizeAddr = 4
|
||||
)
|
||||
|
||||
type Sender interface {
|
||||
Close() error
|
||||
Send(ctx context.Context, cli smtp.SMTP) liberr.Error
|
||||
SendClose(ctx context.Context, cli smtp.SMTP) liberr.Error
|
||||
Send(ctx context.Context, cli libsmtp.SMTP) liberr.Error
|
||||
SendClose(ctx context.Context, cli libsmtp.SMTP) liberr.Error
|
||||
}
|
||||
|
||||
type sender struct {
|
||||
data ioutils.FileProgress
|
||||
data libiot.FileProgress
|
||||
from string
|
||||
rcpt []string
|
||||
}
|
||||
|
||||
//nolint #gocognit
|
||||
func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
||||
e := simple.NewMSG()
|
||||
f := make([]ioutils.FileProgress, 0)
|
||||
f := make([]libiot.FileProgress, 0)
|
||||
|
||||
switch m.GetPriority() {
|
||||
case PriorityHigh:
|
||||
@@ -142,7 +145,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
||||
|
||||
if len(m.attach) > 0 {
|
||||
for _, i := range m.attach {
|
||||
if t, er := ioutils.NewFileProgressTemp(); er != nil {
|
||||
if t, er := libiot.NewFileProgressTemp(); er != nil {
|
||||
return nil, er
|
||||
} else if _, er := t.ReadFrom(i.data); er != nil {
|
||||
return nil, ErrorIORead.ErrorParent(er)
|
||||
@@ -156,7 +159,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
||||
|
||||
if len(m.inline) > 0 {
|
||||
for _, i := range m.inline {
|
||||
if t, er := ioutils.NewFileProgressTemp(); er != nil {
|
||||
if t, er := libiot.NewFileProgressTemp(); er != nil {
|
||||
return nil, er
|
||||
} else if _, er := t.ReadFrom(i.data); er != nil {
|
||||
return nil, ErrorIORead.ErrorParent(er)
|
||||
@@ -206,7 +209,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
||||
s.rcpt = append(s.rcpt, m.Email().GetRecipients(RecipientCC)...)
|
||||
s.rcpt = append(s.rcpt, m.Email().GetRecipients(RecipientBCC)...)
|
||||
|
||||
if tmp, err := ioutils.NewFileProgressTemp(); err != nil {
|
||||
if tmp, err := libiot.NewFileProgressTemp(); err != nil {
|
||||
return nil, err
|
||||
} else if _, er := tmp.WriteString(e.GetMessage()); er != nil {
|
||||
return nil, ErrorIOWrite.ErrorParent(er)
|
||||
@@ -222,7 +225,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sender) SendClose(ctx context.Context, cli smtp.SMTP) liberr.Error {
|
||||
func (s *sender) SendClose(ctx context.Context, cli libsmtp.SMTP) liberr.Error {
|
||||
defer func() {
|
||||
_ = s.Close()
|
||||
}()
|
||||
@@ -234,14 +237,16 @@ func (s *sender) SendClose(ctx context.Context, cli smtp.SMTP) liberr.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sender) Send(ctx context.Context, cli smtp.SMTP) liberr.Error {
|
||||
func (s *sender) Send(ctx context.Context, cli libsmtp.SMTP) liberr.Error {
|
||||
if e := cli.Check(ctx); e != nil {
|
||||
return ErrorSmtpClient.ErrorParent(e)
|
||||
}
|
||||
|
||||
if len(s.from) < 4 {
|
||||
if len(s.from) < _MinSizeAddr {
|
||||
//nolint #goerr113
|
||||
return ErrorParamsEmpty.ErrorParent(fmt.Errorf("parameters 'from' is not valid"))
|
||||
} else if len(s.rcpt) < 1 || len(s.rcpt[0]) < 4 {
|
||||
} else if len(s.rcpt) < 1 || len(s.rcpt[0]) < _MinSizeAddr {
|
||||
//nolint #goerr113
|
||||
return ErrorParamsEmpty.ErrorParent(fmt.Errorf("parameters 'receipient' is not valid"))
|
||||
}
|
||||
|
||||
|
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package mail
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"mime/quotedprintable"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// base64Encode base64 encodes the provided text with line wrapping
|
||||
func base64Encode(text []byte) []byte {
|
||||
// create buffer
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// create base64 encoder that linewraps
|
||||
encoder := base64.NewEncoder(base64.StdEncoding, &base64LineWrap{writer: buf})
|
||||
|
||||
// write the encoded text to buf
|
||||
/* #nosec */
|
||||
//nolint #nosec
|
||||
_, _ = encoder.Write(text)
|
||||
_ = encoder.Close()
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// qpEncode uses the quoted-printable encoding to encode the provided text
|
||||
func qpEncode(text []byte) []byte {
|
||||
// create buffer
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
encoder := quotedprintable.NewWriter(buf)
|
||||
|
||||
/* #nosec */
|
||||
//nolint #nosec
|
||||
_, _ = encoder.Write(text)
|
||||
_ = encoder.Close()
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func encodeHeader(text string, charset string, usedChars int) string {
|
||||
// create buffer
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// encode
|
||||
encoder := newEncoder(buf, charset, usedChars)
|
||||
/* #nosec */
|
||||
//nolint #nosec
|
||||
_, _ = encoder.encode([]byte(text))
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func escapeQuotes(s string) string {
|
||||
quoteEscaper := strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
|
||||
return quoteEscaper.Replace(s)
|
||||
}
|
@@ -28,10 +28,10 @@ package mailer
|
||||
import "github.com/matcornic/hermes/v2"
|
||||
|
||||
type email struct {
|
||||
t Themes
|
||||
d TextDirection
|
||||
p hermes.Product
|
||||
b *hermes.Body
|
||||
t Themes
|
||||
d TextDirection
|
||||
c bool
|
||||
}
|
||||
|
||||
|
@@ -33,27 +33,14 @@ import (
|
||||
)
|
||||
|
||||
func (e *email) GenerateHTML() (*bytes.Buffer, liberr.Error) {
|
||||
var buf = bytes.NewBuffer(make([]byte, 0))
|
||||
|
||||
h := hermes.Hermes{
|
||||
Theme: e.t.getHermes(),
|
||||
TextDirection: e.d.getDirection(),
|
||||
Product: e.p,
|
||||
DisableCSSInlining: e.c,
|
||||
}
|
||||
|
||||
if p, e := h.GenerateHTML(hermes.Email{
|
||||
Body: *e.b,
|
||||
}); e != nil {
|
||||
return nil, ErrorMailerHtml.ErrorParent(e)
|
||||
} else {
|
||||
buf.WriteString(p)
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
return e.generated(e.genHtml)
|
||||
}
|
||||
|
||||
func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
||||
return e.generated(e.genText)
|
||||
}
|
||||
|
||||
func (e email) generated(f func(h hermes.Hermes, m hermes.Email) (string, error)) (*bytes.Buffer, liberr.Error) {
|
||||
var buf = bytes.NewBuffer(make([]byte, 0))
|
||||
|
||||
h := hermes.Hermes{
|
||||
@@ -63,7 +50,7 @@ func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
||||
DisableCSSInlining: e.c,
|
||||
}
|
||||
|
||||
if p, e := h.GeneratePlainText(hermes.Email{
|
||||
if p, e := f(h, hermes.Email{
|
||||
Body: *e.b,
|
||||
}); e != nil {
|
||||
return nil, ErrorMailerText.ErrorParent(e)
|
||||
@@ -73,3 +60,11 @@ func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (e *email) genText(h hermes.Hermes, m hermes.Email) (string, error) {
|
||||
return h.GeneratePlainText(m)
|
||||
}
|
||||
|
||||
func (e *email) genHtml(h hermes.Hermes, m hermes.Email) (string, error) {
|
||||
return h.GenerateHTML(m)
|
||||
}
|
||||
|
@@ -66,6 +66,7 @@ func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options {
|
||||
} else {
|
||||
d.Dir = dataDir
|
||||
|
||||
//nolint #exhaustive
|
||||
switch o.RWMode {
|
||||
case nutsdb.MMap:
|
||||
d.RWMode = nutsdb.MMap
|
||||
@@ -73,6 +74,7 @@ func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options {
|
||||
d.RWMode = nutsdb.FileIO
|
||||
}
|
||||
|
||||
//nolint #exhaustive
|
||||
switch o.StartFileLoadingMode {
|
||||
case nutsdb.MMap:
|
||||
d.StartFileLoadingMode = nutsdb.MMap
|
||||
@@ -81,6 +83,7 @@ func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options {
|
||||
}
|
||||
}
|
||||
|
||||
//nolint #exhaustive
|
||||
switch o.EntryIdxMode {
|
||||
case nutsdb.HintKeyAndRAMIdxMode:
|
||||
d.EntryIdxMode = nutsdb.HintKeyAndRAMIdxMode
|
||||
|
@@ -104,7 +104,7 @@ func (s *snap) Save(opt Options, writer io.Writer) liberr.Error {
|
||||
_ = t.Close()
|
||||
}()
|
||||
|
||||
if _, e = archive.CreateArchive(archive.ArchiveTypeTarGzip, t, s.path); e != nil {
|
||||
if _, e = archive.CreateArchive(archive.TypeTarGzip, t, s.path); e != nil {
|
||||
return ErrorFolderArchive.Error(e)
|
||||
}
|
||||
|
||||
|
@@ -29,12 +29,30 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const EMPTY_GROUP = "<nil>"
|
||||
const EmptyHandlerGroup = "<nil>"
|
||||
|
||||
var (
|
||||
defaultRouters = NewRouterList()
|
||||
defaultRouters = NewRouterList(DefaultGinInit)
|
||||
)
|
||||
|
||||
func DefaultGinInit() *gin.Engine {
|
||||
engine := gin.New()
|
||||
engine.Use(gin.Logger(), gin.Recovery())
|
||||
|
||||
return engine
|
||||
}
|
||||
|
||||
func DefaultGinWithTrustyProxy(trustyProxy []string) *gin.Engine {
|
||||
engine := gin.New()
|
||||
engine.Use(gin.Logger(), gin.Recovery())
|
||||
|
||||
if len(trustyProxy) > 0 {
|
||||
engine.TrustedProxies = trustyProxy
|
||||
}
|
||||
|
||||
return engine
|
||||
}
|
||||
|
||||
type routerItem struct {
|
||||
method string
|
||||
relative string
|
||||
@@ -42,6 +60,7 @@ type routerItem struct {
|
||||
}
|
||||
|
||||
type routerList struct {
|
||||
init func() *gin.Engine
|
||||
list map[string][]routerItem
|
||||
}
|
||||
|
||||
@@ -52,6 +71,7 @@ type RouterList interface {
|
||||
Register(method string, relativePath string, router ...gin.HandlerFunc)
|
||||
RegisterInGroup(group, method string, relativePath string, router ...gin.HandlerFunc)
|
||||
Handler(engine *gin.Engine)
|
||||
Engine() *gin.Engine
|
||||
}
|
||||
|
||||
func RoutersRegister(method string, relativePath string, router ...gin.HandlerFunc) {
|
||||
@@ -66,15 +86,16 @@ func RoutersHandler(engine *gin.Engine) {
|
||||
defaultRouters.Handler(engine)
|
||||
}
|
||||
|
||||
func NewRouterList() RouterList {
|
||||
func NewRouterList(initGin func() *gin.Engine) RouterList {
|
||||
return &routerList{
|
||||
init: initGin,
|
||||
list: make(map[string][]routerItem),
|
||||
}
|
||||
}
|
||||
|
||||
func (l routerList) Handler(engine *gin.Engine) {
|
||||
for grpRoute, grpList := range l.list {
|
||||
if grpRoute == EMPTY_GROUP {
|
||||
if grpRoute == EmptyHandlerGroup {
|
||||
for _, r := range grpList {
|
||||
engine.Handle(r.method, r.relative, r.router...)
|
||||
}
|
||||
@@ -89,7 +110,7 @@ func (l routerList) Handler(engine *gin.Engine) {
|
||||
|
||||
func (l *routerList) RegisterInGroup(group, method string, relativePath string, router ...gin.HandlerFunc) {
|
||||
if group == "" {
|
||||
group = EMPTY_GROUP
|
||||
group = EmptyHandlerGroup
|
||||
}
|
||||
|
||||
if _, ok := l.list[group]; !ok {
|
||||
@@ -106,3 +127,11 @@ func (l *routerList) RegisterInGroup(group, method string, relativePath string,
|
||||
func (l *routerList) Register(method string, relativePath string, router ...gin.HandlerFunc) {
|
||||
l.RegisterInGroup("", method, relativePath, router...)
|
||||
}
|
||||
|
||||
func (l routerList) Engine() *gin.Engine {
|
||||
if l.init != nil {
|
||||
return l.init()
|
||||
} else {
|
||||
return DefaultGinInit()
|
||||
}
|
||||
}
|
||||
|
@@ -44,14 +44,13 @@ func SetGinHandler(fct func(c *gin.Context)) gin.HandlerFunc {
|
||||
}
|
||||
|
||||
func Handler(routerList RouterList) http.Handler {
|
||||
engine := gin.New()
|
||||
engine.Use(gin.Logger(), gin.Recovery())
|
||||
e := routerList.Engine()
|
||||
|
||||
if routerList == nil {
|
||||
RoutersHandler(engine)
|
||||
RoutersHandler(e)
|
||||
} else {
|
||||
routerList.Handler(engine)
|
||||
routerList.Handler(e)
|
||||
}
|
||||
|
||||
return engine
|
||||
return e
|
||||
}
|
||||
|
11
smtp/dial.go
11
smtp/dial.go
@@ -70,17 +70,6 @@ func (s *smtpClient) dial(ctx context.Context, addr string) (con net.Conn, err l
|
||||
return
|
||||
}
|
||||
|
||||
func (s *smtpClient) dialStarttls(ctx context.Context, addr string, tlsConfig *tls.Config) (con net.Conn, err liberr.Error) {
|
||||
defer func() {
|
||||
if err != nil && con != nil {
|
||||
_ = con.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
con, err = s.dial(ctx, addr)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *smtpClient) client(ctx context.Context, addr string, tlsConfig *tls.Config) (cli *smtp.Client, con net.Conn, err liberr.Error) {
|
||||
var e error
|
||||
|
||||
|
@@ -120,7 +120,7 @@ func (s *smtpClient) Client(ctx context.Context) (*smtp.Client, errors.Error) {
|
||||
return s.cli, nil
|
||||
}
|
||||
|
||||
// validateLine checks to see if a line has CR or LF as per RFC 5321
|
||||
// validateLine checks to see if a line has CR or LF as per RFC 5321.
|
||||
func (s smtpClient) validateLine(line string) errors.Error {
|
||||
if strings.ContainsAny(line, "\n\r") {
|
||||
return ErrorSMTPLineCRLF.Error(nil)
|
||||
|
@@ -29,10 +29,9 @@ import (
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/nabbar/golib/version"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nabbar/golib/router"
|
||||
librtr "github.com/nabbar/golib/router"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
)
|
||||
|
||||
const statusOK = "OK"
|
||||
@@ -82,8 +81,8 @@ type RouteStatus interface {
|
||||
HttpStatusCode(codeOk, codeKO, codeWarning int)
|
||||
|
||||
Get(c *gin.Context)
|
||||
Register(prefix string, register router.RegisterRouter)
|
||||
RegisterGroup(group, prefix string, register router.RegisterRouterInGroup)
|
||||
Register(prefix string, register librtr.RegisterRouter)
|
||||
RegisterGroup(group, prefix string, register librtr.RegisterRouterInGroup)
|
||||
|
||||
ComponentNew(key string, cpt Component)
|
||||
ComponentDel(key string)
|
||||
@@ -102,10 +101,10 @@ func New(Name string, Release string, Hash string, msgOk string, msgKo string, m
|
||||
cKO: http.StatusServiceUnavailable,
|
||||
mWM: msgWarm,
|
||||
cWM: http.StatusOK,
|
||||
c: make(map[string]*atomic.Value, 0),
|
||||
c: make(map[string]*atomic.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func NewVersion(version version.Version, msgOk string, msgKO string, msgWarm string) RouteStatus {
|
||||
func NewVersion(version libver.Version, msgOk string, msgKO string, msgWarm string) RouteStatus {
|
||||
return New(version.GetPackage(), version.GetRelease(), version.GetBuild(), msgOk, msgKO, msgWarm)
|
||||
}
|
||||
|
@@ -31,12 +31,11 @@ import (
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nabbar/golib/router"
|
||||
"github.com/nabbar/golib/semaphore"
|
||||
librtr "github.com/nabbar/golib/router"
|
||||
libsem "github.com/nabbar/golib/semaphore"
|
||||
)
|
||||
|
||||
type rtrStatus struct {
|
||||
@@ -74,7 +73,7 @@ func (r *rtrStatus) cleanPrefix(prefix string) string {
|
||||
return path.Clean(strings.TrimRight(path.Join("/", prefix), "/"))
|
||||
}
|
||||
|
||||
func (r *rtrStatus) Register(prefix string, register router.RegisterRouter) {
|
||||
func (r *rtrStatus) Register(prefix string, register librtr.RegisterRouter) {
|
||||
prefix = r.cleanPrefix(prefix)
|
||||
|
||||
var m = r.m
|
||||
@@ -86,7 +85,7 @@ func (r *rtrStatus) Register(prefix string, register router.RegisterRouter) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rtrStatus) RegisterGroup(group, prefix string, register router.RegisterRouterInGroup) {
|
||||
func (r *rtrStatus) RegisterGroup(group, prefix string, register librtr.RegisterRouterInGroup) {
|
||||
prefix = r.cleanPrefix(prefix)
|
||||
|
||||
var m = r.m
|
||||
@@ -107,7 +106,7 @@ func (r *rtrStatus) Get(x *gin.Context) {
|
||||
key string
|
||||
err liberr.Error
|
||||
rsp *Response
|
||||
sem semaphore.Sem
|
||||
sem libsem.Sem
|
||||
)
|
||||
|
||||
defer func() {
|
||||
@@ -130,7 +129,7 @@ func (r *rtrStatus) Get(x *gin.Context) {
|
||||
Components: make([]CptResponse, 0),
|
||||
}
|
||||
|
||||
sem = semaphore.NewSemaphoreWithContext(x, 0)
|
||||
sem = libsem.NewSemaphoreWithContext(x, 0)
|
||||
|
||||
for key, atm = range r.c {
|
||||
if atm == nil {
|
||||
@@ -182,7 +181,7 @@ func (r *rtrStatus) Get(x *gin.Context) {
|
||||
|
||||
func (r *rtrStatus) ComponentNew(key string, cpt Component) {
|
||||
if len(r.c) < 1 {
|
||||
r.c = make(map[string]*atomic.Value, 0)
|
||||
r.c = make(map[string]*atomic.Value)
|
||||
}
|
||||
|
||||
if _, ok := r.c[key]; !ok {
|
||||
|
@@ -75,6 +75,8 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
//nolint #gosec
|
||||
/* #nosec */
|
||||
if file, err := os.OpenFile(LoggerFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user