Refactor package errors + packages names :

- Refactor ErrorType, list errors managment, codeError
- Add interface Error with error interface implement
- Add type CodeError assign typiclly to const that represent code of error
- Add func to registry func to retrieve message from an uint16 codeError (typicaly a switch of each codeError const)
- Add default errorCode with default errorMessage if no one code or message is found
- Add modeError to manage how to manage compatibility between Error interface and error interface
- Add Error interface that allow parent link (parent as error or Error interface), code and trace management
- Add trace finder to allow find func/file/line caller when Error is call
- Add http 2 transport in httpcli
- Add http 2 transport in httpserver
- Add function to get client http with timeout management in httpcli
- Add function to get Error if occurs of http client in httpcli
- Add test for smtp package
- Chg return error by returning Error in all packages
- Chg package njs-archive by archive
- Chg package njs-certif by certificates
- Chg package njs-console by console
- Chg package njs-crypt by crypt
- Chg package njs-errors by errors
- Chg package njs-httpcli by httpcli
- Chg package njs-httpserver by httpserver
- Chg package njs-ioutils by ioutils
- Chg package njs-ldap by ldap
- Chg package njs-logger by logger
- Chg package njs-password by password
- Chg package njs-progress by progress
- Chg package njs-router by router
- Chg package njs-semaphore by semaphore
- Chg package njs-smtp by smtp
- Chg package njs-static by static
- Chg package njs-status by status
- Chg package njs-version by version
- Fix dependancies gopkg by github/go-ldap for go module compatibility
- Fix gin Abort call by gin Abort with Error in static package
- Fix issue #18 in status package : replace partner by component
- Fix go vet error
- Del deprecated function
- Del useless function & files
- Bump dependancies
- Apply CHG in README.md
This commit is contained in:
Nicolas JUHEL
2020-07-14 11:00:57 +02:00
parent 9570840431
commit ca39d7ad26
103 changed files with 2647 additions and 885 deletions

View File

@@ -11,7 +11,7 @@ go get -u github.com/nabbar/golib/...
second, import the needed lib in your code
```go
import "github.com/nabbar/golib/njs-version"
import "github.com/nabbar/golib/version"
```
more information in each lib

View File

@@ -23,31 +23,30 @@
*
*/
package njs_archive
package archive
import (
"os"
"github.com/nabbar/golib/njs-archive/bz2"
"github.com/nabbar/golib/njs-archive/gzip"
"github.com/nabbar/golib/njs-archive/tar"
"github.com/nabbar/golib/njs-archive/zip"
"github.com/nabbar/golib/archive/bz2"
"github.com/nabbar/golib/archive/gzip"
"github.com/nabbar/golib/archive/tar"
"github.com/nabbar/golib/archive/zip"
//. "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
//. "github.com/nabbar/golib/logger"
iou "github.com/nabbar/golib/njs-ioutils"
iou "github.com/nabbar/golib/ioutils"
)
type ArchiveType uint8
func ExtractFile(src *os.File, fileNameContain, fileNameRegex string) (*os.File, error) {
var err error
func ExtractFile(src *os.File, fileNameContain, fileNameRegex string) (*os.File, Error) {
loc := src.Name()
if dst, err := bz2.GetFile(src, fileNameContain, fileNameRegex); err == nil {
//DebugLevel.Log("try deleting source archive...")
if err = iou.DelTempFile(src, true); err != nil {
if err = iou.DelTempFile(src); err != nil {
return nil, err
}
//DebugLevel.Log("try another archive...")
@@ -56,7 +55,7 @@ func ExtractFile(src *os.File, fileNameContain, fileNameRegex string) (*os.File,
if dst, err := gzip.GetFile(src, fileNameContain, fileNameRegex); err == nil {
//DebugLevel.Log("try deleting source archive...")
if err = iou.DelTempFile(src, true); err != nil {
if err = iou.DelTempFile(src); err != nil {
return nil, err
}
//DebugLevel.Log("try another archive...")
@@ -65,7 +64,7 @@ func ExtractFile(src *os.File, fileNameContain, fileNameRegex string) (*os.File,
if dst, err := tar.GetFile(src, fileNameContain, fileNameRegex); err == nil {
//DebugLevel.Log("try deleting source archive...")
if err = iou.DelTempFile(src, true); err != nil {
if err = iou.DelTempFile(src); err != nil {
return nil, err
}
//DebugLevel.Log("try another archive...")
@@ -74,17 +73,24 @@ func ExtractFile(src *os.File, fileNameContain, fileNameRegex string) (*os.File,
if dst, err := zip.GetFile(src, fileNameContain, fileNameRegex); err == nil {
//DebugLevel.Log("try deleting source archive...")
if err = iou.DelTempFile(src, true); err != nil {
if err = iou.DelTempFile(src); err != nil {
return nil, err
}
//DebugLevel.Log("try another archive...")
return ExtractFile(dst, fileNameContain, fileNameRegex)
}
var (
err error
)
if _, err = src.Seek(0, 0); err != nil {
e1 := FILE_SEEK.ErrorParent(err)
if src, err = os.Open(loc); err != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "reopening file", err)
return nil, err
e2 := FILE_OPEN.ErrorParent(err)
e2.AddParentError(e1)
return nil, e2
}
}

52
archive/bz2/error.go Normal file
View File

@@ -0,0 +1,52 @@
/*
* 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 bz2
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Archive + 10
FILE_SEEK
IO_COPY
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case FILE_SEEK:
return "cannot seek into file"
case IO_COPY:
return "io copy occurs error"
}
return ""
}

View File

@@ -30,15 +30,16 @@ import (
"io"
"os"
//. "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
//. "github.com/nabbar/golib/logger"
iou "github.com/nabbar/golib/njs-ioutils"
iou "github.com/nabbar/golib/ioutils"
)
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err error) {
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err Error) {
if _, e := src.Seek(0, 0); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking buffer", e)
return nil, e
return nil, FILE_SEEK.ErrorParent(e)
}
r := bzip2.NewReader(src)
@@ -46,12 +47,12 @@ func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File,
if t, e := iou.NewTempFile(); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "init new temporary buffer", e)
return nil, e
} else if _, e = io.Copy(t, r); e != nil {
} else if _, e := io.Copy(t, r); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "copy buffer from archive reader", e)
return nil, e
return nil, IO_COPY.ErrorParent(e)
} else if _, e = t.Seek(0, 0); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking temp file", e)
return nil, e
return nil, FILE_SEEK.ErrorParent(e)
} else {
return t, nil
}

52
archive/error.go Normal file
View File

@@ -0,0 +1,52 @@
/*
* 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 archive
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Archive
FILE_SEEK
FILE_OPEN
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case FILE_SEEK:
return "cannot seek into file"
case FILE_OPEN:
return "cannot open file"
}
return ""
}

55
archive/gzip/error.go Normal file
View File

@@ -0,0 +1,55 @@
/*
* 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 gzip
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Archive + 20
GZ_READER
FILE_SEEK
IO_COPY
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case GZ_READER:
return "cannot create new reader GZip"
case FILE_SEEK:
return "cannot seek into file"
case IO_COPY:
return "io copy occurs error"
}
return ""
}

View File

@@ -30,21 +30,22 @@ import (
"io"
"os"
//. "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
//. "github.com/nabbar/golib/logger"
iou "github.com/nabbar/golib/njs-ioutils"
iou "github.com/nabbar/golib/ioutils"
)
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err error) {
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err Error) {
if _, e := src.Seek(0, 0); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking buffer", e)
return nil, e
return nil, FILE_SEEK.ErrorParent(e)
}
r, e := gz.NewReader(src)
if e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "init gzip reader", e)
return nil, e
return nil, GZ_READER.ErrorParent(e)
}
defer r.Close()
@@ -52,12 +53,12 @@ func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File,
if t, e := iou.NewTempFile(); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "init new temporary buffer", e)
return nil, e
} else if _, e = io.Copy(t, r); e != nil {
} else if _, e := io.Copy(t, r); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "copy buffer from archive reader", e)
return nil, e
} else if _, e = t.Seek(0, 0); e != nil {
return nil, IO_COPY.ErrorParent(e)
} else if _, e := t.Seek(0, 0); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking temp file", e)
return nil, e
return nil, FILE_SEEK.ErrorParent(e)
} else {
return t, nil
}

55
archive/tar/error.go Normal file
View File

@@ -0,0 +1,55 @@
/*
* 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 tar
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Archive + 30
TAR_NEXT
FILE_SEEK
IO_COPY
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case TAR_NEXT:
return "cannot get next tar file"
case FILE_SEEK:
return "cannot seek into file"
case IO_COPY:
return "io copy occurs error"
}
return ""
}

View File

@@ -30,17 +30,18 @@ import (
"io"
"os"
"github.com/nabbar/golib/njs-archive/archive"
"github.com/nabbar/golib/archive/archive"
//. "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
//. "github.com/nabbar/golib/logger"
iou "github.com/nabbar/golib/njs-ioutils"
iou "github.com/nabbar/golib/ioutils"
)
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err error) {
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err Error) {
if _, e := src.Seek(0, 0); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking buffer", e)
return nil, e
return nil, FILE_SEEK.ErrorParent(e)
}
r := tar.NewReader(src)
@@ -52,7 +53,7 @@ func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File,
return nil, nil
} else if e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "trying to read next file", e)
return nil, e
return nil, TAR_NEXT.ErrorParent(e)
}
if h.FileInfo().Mode()&os.ModeType == os.ModeType {
@@ -64,12 +65,12 @@ func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File,
if t, e := iou.NewTempFile(); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "init new temporary buffer", e)
return nil, e
} else if _, e = io.Copy(t, r); e != nil {
} else if _, e := io.Copy(t, r); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "copy buffer from archive reader", e)
return nil, e
} else if _, e = t.Seek(0, 0); e != nil {
return nil, IO_COPY.ErrorParent(e)
} else if _, e := t.Seek(0, 0); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking temp file", e)
return nil, e
return nil, FILE_SEEK.ErrorParent(e)
} else {
return t, nil
}

61
archive/zip/error.go Normal file
View File

@@ -0,0 +1,61 @@
/*
* 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 zip
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Archive + 40
FILE_OPEN
FILE_CLOSE
FILE_SEEK
IO_COPY
ZIP_OPEN
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case FILE_OPEN:
return "cannot open zipped file"
case FILE_CLOSE:
return "closing file occurs error"
case FILE_SEEK:
return "cannot seek into file"
case IO_COPY:
return "io copy occurs error"
case ZIP_OPEN:
return "cannot open zip file"
}
return ""
}

View File

@@ -30,25 +30,26 @@ import (
"io"
"os"
//. "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
//. "github.com/nabbar/golib/logger"
iou "github.com/nabbar/golib/njs-ioutils"
iou "github.com/nabbar/golib/ioutils"
"github.com/nabbar/golib/njs-archive/archive"
"github.com/nabbar/golib/archive/archive"
)
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err error) {
func GetFile(src *os.File, filenameContain, filenameRegex string) (dst *os.File, err Error) {
location := iou.GetTempFilePath(src)
if err = src.Close(); err != nil {
if e := src.Close(); err != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "trying to close temp file", err)
return
return dst, FILE_CLOSE.ErrorParent(e)
}
return getFile(location, filenameContain, filenameRegex)
}
func getFile(src string, filenameContain, filenameRegex string) (dst *os.File, err error) {
func getFile(src string, filenameContain, filenameRegex string) (dst *os.File, err Error) {
var (
r *zip.ReadCloser
e error
@@ -56,10 +57,12 @@ func getFile(src string, filenameContain, filenameRegex string) (dst *os.File, e
if r, e = zip.OpenReader(src); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "trying to open zip file", e)
return nil, e
return nil, ZIP_OPEN.ErrorParent(e)
}
defer r.Close()
defer func() {
_ = r.Close()
}()
for _, f := range r.File {
if f.Mode()&os.ModeType == os.ModeType {
@@ -75,25 +78,30 @@ func getFile(src string, filenameContain, filenameRegex string) (dst *os.File, e
return nil, nil
}
func extratFile(f *zip.File) (dst *os.File, err error) {
var r io.ReadCloser
func extratFile(f *zip.File) (dst *os.File, err Error) {
var (
r io.ReadCloser
e error
)
if r, err = f.Open(); err != nil {
if r, e = f.Open(); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "open zipped file reader", err)
return
return dst, FILE_OPEN.ErrorParent(e)
}
defer r.Close()
defer func() {
_ = r.Close()
}()
if dst, err = iou.NewTempFile(); err != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "init new temporary buffer", err)
return
} else if _, err = io.Copy(dst, r); err != nil {
} else if _, e = io.Copy(dst, r); e != nil {
//ErrorLevel.LogErrorCtx(DebugLevel, "copy buffer from archive reader", err)
return
return dst, IO_COPY.ErrorParent(e)
}
_, err = dst.Seek(0, 0)
_, e = dst.Seek(0, 0)
//ErrorLevel.LogErrorCtx(DebugLevel, "seeking temp file", err)
return
return dst, FILE_SEEK.ErrorParent(e)
}

61
certificates/error.go Normal file
View File

@@ -0,0 +1,61 @@
/*
* 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 certificates
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Certif
FILE_STAT_ERROR
FILE_READ_ERROR
CERT_APPEND_KO
CERT_LOAD_KEYPAIR
CERT_PARSE_KEYPAIR
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case FILE_STAT_ERROR:
return "cannot get file stat"
case FILE_READ_ERROR:
return "cannot read file"
case CERT_APPEND_KO:
return "cannot append PEM file"
case CERT_LOAD_KEYPAIR:
return "cannot X509 parsing certificate string"
case CERT_PARSE_KEYPAIR:
return "cannot x509 loading certificate file"
}
return ""
}

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_certif
package certificates
import (
"crypto/tls"
@@ -32,7 +32,7 @@ import (
"runtime"
"strings"
logger "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
)
var (
@@ -40,6 +40,7 @@ var (
certificates = make([]tls.Certificate, 0)
caCertificates = x509.NewCertPool()
tlsMinVersion uint16 = tls.VersionTLS12
tlsMaxVersion uint16 = tls.VersionTLS12
cipherList = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
@@ -76,21 +77,26 @@ func AddRootCAContents(rootContent string) bool {
return false
}
func AddRootCAFile(rootFile string) bool {
func AddRootCAFile(rootFile string) Error {
if rootFile == "" {
return false
return EMPTY_PARAMS.Error(nil)
}
if _, e := os.Stat(rootFile); logger.ErrorLevel.LogErrorCtxf(logger.InfoLevel, "checking certificates file '%s'", e, rootFile) {
return false
if _, e := os.Stat(rootFile); e != nil {
return FILE_STAT_ERROR.ErrorParent(e)
}
c, e := ioutil.ReadFile(rootFile) // #nosec
if !logger.ErrorLevel.LogErrorCtxf(logger.InfoLevel, "loading certificates file '%s'", e, rootFile) {
return rootCA.AppendCertsFromPEM(c)
if e == nil {
if rootCA.AppendCertsFromPEM(c) {
return nil
}
return CERT_APPEND_KO.Error(nil)
}
return false
return FILE_READ_ERROR.ErrorParent(e)
}
func AddCACertificateContents(caContent string) bool {
@@ -101,61 +107,68 @@ func AddCACertificateContents(caContent string) bool {
return false
}
func AddCACertificateFile(caFile string) bool {
func AddCACertificateFile(caFile string) Error {
if caFile == "" {
return false
return EMPTY_PARAMS.Error(nil)
}
if _, e := os.Stat(caFile); logger.ErrorLevel.LogErrorCtxf(logger.InfoLevel, "checking certificates file '%s'", e, caFile) {
return false
if _, e := os.Stat(caFile); e != nil {
return FILE_STAT_ERROR.ErrorParent(e)
}
c, e := ioutil.ReadFile(caFile) // #nosec
if !logger.ErrorLevel.LogErrorCtxf(logger.InfoLevel, "loading certificates file '%s'", e, caFile) {
return caCertificates.AppendCertsFromPEM(c)
if e == nil {
if caCertificates.AppendCertsFromPEM(c) {
return nil
}
return CERT_APPEND_KO.Error(nil)
}
return false
return FILE_READ_ERROR.ErrorParent(e)
}
func CheckCertificates() bool {
return len(certificates) > 0
}
func AddCertificateContents(keyContents, certContents string) bool {
func AddCertificateContents(keyContents, certContents string) Error {
keyContents = strings.TrimSpace(keyContents)
certContents = strings.TrimSpace(certContents)
if keyContents != "" && keyContents != "\n" && certContents != "" && certContents != "\n" {
c, err := tls.X509KeyPair([]byte(certContents), []byte(keyContents))
if !logger.ErrorLevel.LogErrorCtx(logger.InfoLevel, "loading certificates contents", err) {
if err == nil {
certificates = append(certificates, c)
return true
return nil
}
return CERT_PARSE_KEYPAIR.ErrorParent(err)
}
return false
return EMPTY_PARAMS.Error(nil)
}
func AddCertificateFile(keyFile, certFile string) bool {
func AddCertificateFile(keyFile, certFile string) Error {
if keyFile == "" || certFile == "" {
return false
return EMPTY_PARAMS.Error(nil)
}
if _, e := os.Stat(keyFile); logger.ErrorLevel.LogErrorCtxf(logger.InfoLevel, "loading certificates file '%s'", e, keyFile) {
return false
if _, e := os.Stat(keyFile); e != nil {
return FILE_STAT_ERROR.ErrorParent(e)
}
if _, e := os.Stat(certFile); logger.ErrorLevel.LogErrorCtxf(logger.InfoLevel, "loading certificates file '%s'", e, certFile) {
return false
if _, e := os.Stat(certFile); e != nil {
return FILE_STAT_ERROR.ErrorParent(e)
}
if c, e := tls.LoadX509KeyPair(certFile, keyFile); !logger.ErrorLevel.LogErrorCtx(logger.InfoLevel, "loading X509 Pair file", e) {
if c, e := tls.LoadX509KeyPair(certFile, keyFile); e == nil {
certificates = append(certificates, c)
return true
return nil
} else {
return CERT_LOAD_KEYPAIR.ErrorParent(e)
}
return false
}
func GetCertificates() []tls.Certificate {
@@ -178,29 +191,30 @@ func GetClientCA() *x509.CertPool {
return caCertificates
}
func SetStringTlsVersion(tlsVersStr string) {
func SetVersionMin(vers uint16) {
tlsMinVersion = vers
}
func SetVersionMax(vers uint16) {
tlsMaxVersion = vers
}
func SetStringTlsVersion(tlsVersStr string) uint16 {
tlsVersStr = strings.ToLower(tlsVersStr)
tlsVersStr = strings.Replace(tlsVersStr, "TLS", "", -1)
tlsVersStr = strings.TrimSpace(tlsVersStr)
switch tlsVersStr {
case "1", "1.0":
tlsMinVersion = tls.VersionTLS10
return tls.VersionTLS10
case "1.1":
tlsMinVersion = tls.VersionTLS11
return tls.VersionTLS11
case "1.2":
return tls.VersionTLS12
case "1.3":
return tls.VersionTLS13
default:
tlsMinVersion = tls.VersionTLS12
}
}
func SetTlsVersion(tlsVers uint16) {
switch tlsVers {
case tls.VersionTLS10:
tlsMinVersion = tls.VersionTLS10
case tls.VersionTLS11:
tlsMinVersion = tls.VersionTLS11
default:
tlsMinVersion = tls.VersionTLS12
return tls.VersionTLS12
}
}
@@ -287,10 +301,17 @@ func GetTLSConfig(serverName string) *tls.Config {
cnf := &tls.Config{
RootCAs: rootCA,
ClientCAs: caCertificates,
MinVersion: tlsMinVersion,
InsecureSkipVerify: false,
}
if tlsMinVersion > 0 {
cnf.MinVersion = tlsMinVersion
}
if tlsMaxVersion > 0 {
cnf.MaxVersion = tlsMaxVersion
}
if serverName != "" {
cnf.ServerName = serverName
}
@@ -326,8 +347,9 @@ func GetTlsConfigCertificates() *tls.Config {
cnf.ClientAuth = clientAuth
}
cnf.Certificates = certificates
cnf.BuildNameToCertificate()
if len(cnf.Certificates) > 0 {
cnf.Certificates = certificates
}
return cnf
}

View File

@@ -23,13 +23,15 @@
*
*/
package njs_console
package console
import (
"bufio"
"fmt"
"github.com/fatih/color"
. "github.com/nabbar/golib/errors"
)
type colorType uint8
@@ -84,13 +86,28 @@ func (c colorType) Print(text string) {
}
}
func (c colorType) BuffPrintf(buff *bufio.ReadWriter, format string, args ...interface{}) (n int, err error) {
func (c colorType) BuffPrintf(buff *bufio.ReadWriter, format string, args ...interface{}) (n int, err Error) {
if colorList[c] != nil && buff != nil {
return colorList[c].Fprintf(buff, format, args...) // #nosec
i, e := colorList[c].Fprintf(buff, format, args...) // #nosec
if e != nil {
return i, COLOR_IO_FRINTF.ErrorParent(e)
}
return i, nil
} else if buff != nil {
return buff.Write([]byte(fmt.Sprintf(format, args...)))
i, e := buff.Write([]byte(fmt.Sprintf(format, args...)))
if e != nil {
return i, COLOR_BUFF_WRITE.ErrorParent(e)
}
return i, nil
} else {
return 0, fmt.Errorf("buffer is not defined")
return 0, COLOR_BUFF_UNDEFINED.Error(nil)
}
}

55
console/error.go Normal file
View File

@@ -0,0 +1,55 @@
/*
* 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 console
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Console
COLOR_IO_FRINTF
COLOR_BUFF_WRITE
COLOR_BUFF_UNDEFINED
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case COLOR_IO_FRINTF:
return "cannot write on IO"
case COLOR_BUFF_WRITE:
return "cannot write on buffer"
case COLOR_BUFF_UNDEFINED:
return "buffer is not defined"
}
return ""
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_console
package console
import (
"strings"

View File

@@ -23,7 +23,7 @@
*
*/
package njs_console
package console
import (
"bufio"

View File

@@ -23,15 +23,17 @@
*
*/
package njs_crypt
package crypt
import (
"io"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/hex"
"fmt"
"io"
. "github.com/nabbar/golib/errors"
)
var (
@@ -39,20 +41,22 @@ var (
cryptNonce = make([]byte, 12)
)
func SetKeyHex(key, nonce string) error {
func SetKeyHex(key, nonce string) Error {
var err error
// Load your secret key from a safe place and reuse it across multiple
// Seal/Open calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
cryptKey, err = hex.DecodeString(key)
if err != nil {
return fmt.Errorf("converting hexa key error : %v", err)
return HEXA_KEY.ErrorParent(err)
}
cryptNonce, err = hex.DecodeString(nonce)
if err != nil {
return fmt.Errorf("converting hexa nonce error : %v", err)
return HEXA_NONCE.ErrorParent(err)
}
return nil
@@ -63,51 +67,55 @@ func SetKeyByte(key [32]byte, nonce [12]byte) {
cryptNonce = nonce[:]
}
func GenKeyByte() ([]byte, []byte, error) {
func GenKeyByte() ([]byte, []byte, Error) {
// Never use more than 2^32 random key with a given key because of the risk of a repeat.
if _, err := io.ReadFull(rand.Reader, cryptKey); err != nil {
return make([]byte, 32), make([]byte, 12), fmt.Errorf("key generate error : %v", err)
return make([]byte, 32), make([]byte, 12), BYTE_KEYGEN.ErrorParent(err)
}
// Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
if _, err := io.ReadFull(rand.Reader, cryptNonce); err != nil {
return make([]byte, 32), make([]byte, 12), fmt.Errorf("nonce generate error : %v", err)
return make([]byte, 32), make([]byte, 12), BYTE_NONCEGEN.ErrorParent(err)
}
return cryptKey, cryptNonce, nil
}
func Encrypt(clearValue []byte) (string, error) {
func Encrypt(clearValue []byte) (string, Error) {
// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
block, err := aes.NewCipher(cryptKey)
if err != nil {
return "", fmt.Errorf("init AES block error : %v", err)
return "", AES_BLOCK.ErrorParent(err)
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("AES GSM cipher init : %v", err)
return "", AES_GCM.ErrorParent(err)
}
return hex.EncodeToString(aesgcm.Seal(nil, cryptNonce, clearValue, nil)), nil
}
func Decrypt(hexaVal string) ([]byte, error) {
func Decrypt(hexaVal string) ([]byte, Error) {
// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
ciphertext, err := hex.DecodeString(hexaVal)
if err != nil {
return nil, fmt.Errorf("hexa decode crypted value error : %v", err)
return nil, HEXA_DECODE.ErrorParent(err)
}
block, err := aes.NewCipher(cryptKey)
if err != nil {
return nil, fmt.Errorf("AES block init error : %v", err)
return nil, AES_BLOCK.ErrorParent(err)
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("AES GSM cipher init error : %v", err)
return nil, AES_GCM.ErrorParent(err)
}
return aesgcm.Open(nil, cryptNonce, ciphertext, nil)
if res, err := aesgcm.Open(nil, cryptNonce, ciphertext, nil); err != nil {
return res, AES_DECRYPT.ErrorParent(err)
} else {
return res, nil
}
}

70
crypt/error.go Normal file
View File

@@ -0,0 +1,70 @@
/*
* 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 crypt
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Crypt
HEXA_DECODE
HEXA_KEY
HEXA_NONCE
BYTE_KEYGEN
BYTE_NONCEGEN
AES_BLOCK
AES_GCM
AES_DECRYPT
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case HEXA_DECODE:
return "hexa decode error"
case HEXA_KEY:
return "converting hexa key error"
case HEXA_NONCE:
return "converting hexa nonce error"
case BYTE_KEYGEN:
return "key generate error"
case BYTE_NONCEGEN:
return "nonce generate error"
case AES_BLOCK:
return "init AES block error"
case AES_GCM:
return "init AES GCM error"
case AES_DECRYPT:
return "decrypt AES GCM error"
}
return ""
}

88
errors/code.go Normal file
View File

@@ -0,0 +1,88 @@
/*
* 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 errors
import (
"strconv"
)
var msgfct = make([]Message, 0)
type Message func(code CodeError) (message string)
type CodeError uint16
const UNK_ERROR CodeError = 0
const UNK_MESSAGE = "unknown error"
func (c CodeError) GetUint16() uint16 {
return uint16(c)
}
func (c CodeError) GetInt() int {
return int(c)
}
func (c CodeError) GetString() string {
return strconv.Itoa(c.GetInt())
}
func (c CodeError) GetMessage() string {
if c == UNK_ERROR {
return UNK_MESSAGE
}
for _, f := range msgfct {
m := f(c)
if m != "" {
return m
}
}
return UNK_MESSAGE
}
func (c CodeError) Error(p Error) Error {
return NewError(c.GetUint16(), c.GetMessage(), p)
}
func (c CodeError) ErrorParent(p ...error) Error {
e := c.Error(nil)
e.AddParent(p...)
return e
}
func (c CodeError) IfError(e Error) Error {
return NewErrorIfError(c.GetUint16(), c.GetMessage(), e)
}
func (c CodeError) Iferror(e error) Error {
return NewErrorIferror(c.GetUint16(), c.GetMessage(), e)
}
func RegisterFctMessage(fct Message) {
msgfct = append(msgfct, fct)
}

397
errors/errors.go Normal file
View File

@@ -0,0 +1,397 @@
/*
* 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 errors
import (
errs "errors"
"fmt"
"runtime"
"strconv"
"strings"
)
var (
defaultGlue = ", "
defaultPattern = "[Error #%s] %s"
defaultPatternTrace = "[Error #%s] %s (%s)"
)
func SetDefaultGlue(glue string) {
defaultGlue = glue
}
func GetDefaultGlue() string {
return defaultGlue
}
func SetDefaultPattern(pattern string) {
defaultPattern = pattern
}
func GetDefaultPattern() string {
return defaultPattern
}
func SetDefaultPatternTrace(patternTrace string) {
defaultPatternTrace = patternTrace
}
func GetDefaultPatternTrace() string {
return defaultPatternTrace
}
type errors struct {
c uint16
e string
p []Error
t runtime.Frame
}
type Error interface {
IsCodeError(code CodeError) bool
HasCodeError(code CodeError) bool
IsError(e error) bool
HasError(err error) bool
AddParent(parent ...error)
SetParent(parent ...error)
AddParentError(parent ...Error)
SetParentError(parent ...Error)
Code() string
CodeFull(glue string) string
CodeSlice() []string
CodeError(pattern string) string
CodeErrorFull(pattern, glue string) string
CodeErrorSlice(pattern string) []string
CodeErrorTrace(pattern string) string
CodeErrorTraceFull(pattern, glue string) string
CodeErrorTraceSlice(pattern string) []string
Error() string
StringError() string
StringErrorFull(glue string) string
StringErrorSlice() []string
GetError() error
GetErrorFull(glue string) error
GetErrorSlice() []error
GetIError() Error
GetIErrorSlice() []Error
GetTrace() string
GetTraceSlice() []string
}
func MakeErrorIfError(err ...Error) Error {
var e Error = nil
for _, p := range err {
if p == nil {
continue
}
if e == nil {
e = p
} else {
e.AddParentError(p)
}
}
return e
}
func NewError(code uint16, message string, parent Error) Error {
if parent == nil {
parent = &errors{
c: 0,
e: "",
p: make([]Error, 0),
}
}
return &errors{
c: code,
e: message,
p: parent.GetIErrorSlice(),
t: getFrame(),
}
}
func NewErrorIferror(code uint16, message string, parent error) Error {
if parent == nil {
return nil
}
p := make([]Error, 0)
p = append(p, &errors{
c: 0,
e: parent.Error(),
p: nil,
})
return &errors{
c: code,
e: message,
p: p,
t: getFrame(),
}
}
func NewErrorIfError(code uint16, message string, parent Error) Error {
if parent == nil {
return nil
}
return &errors{
c: code,
e: message,
p: parent.GetIErrorSlice(),
t: getFrame(),
}
}
func (e *errors) AddParent(parent ...error) {
for _, v := range parent {
if v == nil {
continue
}
e.p = append(e.p, &errors{
c: 0,
e: v.Error(),
p: nil,
})
}
}
func (e *errors) IsCodeError(code CodeError) bool {
return e.c == code.GetUint16()
}
func (e *errors) IsError(err error) bool {
return e.e == err.Error()
}
func (e *errors) HasCodeError(code CodeError) bool {
if e.IsCodeError(code) {
return true
}
for _, p := range e.p {
if p.IsCodeError(code) {
return true
}
}
return false
}
func (e *errors) HasError(err error) bool {
if e.IsError(err) {
return true
}
for _, p := range e.p {
if p.IsError(err) {
return true
}
}
return false
}
func (e *errors) SetParent(parent ...error) {
e.p = make([]Error, 0)
e.AddParent(parent...)
}
func (e *errors) AddParentError(parent ...Error) {
e.p = append(e.p, parent...)
}
func (e *errors) SetParentError(parent ...Error) {
e.p = parent
}
func (e *errors) Code() string {
return strconv.Itoa(int(e.c))
}
func (e *errors) CodeFull(glue string) string {
if glue == "" {
glue = defaultGlue
}
return strings.Join(e.CodeSlice(), glue)
}
func (e *errors) CodeSlice() []string {
var r = []string{e.Code()}
for _, v := range e.p {
r = append(r, v.Code())
}
return r
}
func (e *errors) Error() string {
return modeError.error(e)
}
func (e *errors) StringError() string {
return e.e
}
func (e *errors) StringErrorFull(glue string) string {
if glue == "" {
glue = defaultGlue
}
return strings.Join(e.StringErrorSlice(), glue)
}
func (e *errors) StringErrorSlice() []string {
var r = []string{e.Error()}
for _, v := range e.p {
r = append(r, v.Error())
}
return r
}
func (e *errors) GetError() error {
return errs.New(e.e)
}
func (e *errors) GetErrorFull(glue string) error {
return errs.New(e.StringErrorFull(glue))
}
func (e *errors) GetErrorSlice() []error {
var r = []error{e.GetError()}
for _, v := range e.p {
r = append(r, v.GetError())
}
return r
}
func (e *errors) GetIError() Error {
return e
}
func (e *errors) GetIErrorSlice() []Error {
var r = []Error{e}
for _, v := range e.p {
r = append(r, v.GetIError())
}
return r
}
func (e *errors) GetTrace() string {
if e.t.File != "" {
return fmt.Sprintf("%s#%d", e.t.File, e.t.Line)
} else if e.t.Function != "" {
return fmt.Sprintf("%s#%d", e.t.Function, e.t.Line)
}
return ""
}
func (e *errors) GetTraceSlice() []string {
var r = []string{e.GetTrace()}
for _, v := range e.p {
if t := v.GetTrace(); t != "" {
r = append(r, v.GetTrace())
}
}
return r
}
func (e *errors) CodeError(pattern string) string {
if pattern == "" {
pattern = defaultPattern
}
return fmt.Sprintf(pattern, e.Code(), e.Error())
}
func (e *errors) CodeErrorFull(pattern, glue string) string {
if glue == "" {
glue = defaultGlue
}
return strings.Join(e.CodeErrorSlice(pattern), glue)
}
func (e *errors) CodeErrorSlice(pattern string) []string {
var r = []string{e.CodeError(pattern)}
for _, v := range e.p {
r = append(r, v.CodeError(pattern))
}
return r
}
func (e *errors) CodeErrorTrace(pattern string) string {
if pattern == "" {
pattern = defaultPatternTrace
}
return fmt.Sprintf(pattern, e.Code(), e.GetTrace(), e.Error())
}
func (e *errors) CodeErrorTraceFull(pattern, glue string) string {
if glue == "" {
glue = defaultGlue
}
return strings.Join(e.CodeErrorTraceSlice(pattern), glue)
}
func (e *errors) CodeErrorTraceSlice(pattern string) []string {
var r = []string{e.CodeErrorTrace(pattern)}
for _, v := range e.p {
r = append(r, v.CodeErrorTrace(pattern))
}
return r
}

99
errors/mode.go Normal file
View File

@@ -0,0 +1,99 @@
/*
* 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 errors
var modeError = ERROR_RETURN_Default
func SetModeReturnError(mode ErrorMode) {
modeError = mode
}
func GetModeReturnError() ErrorMode {
return modeError
}
type ErrorMode uint8
const (
ERROR_RETURN_Default ErrorMode = iota
ERROR_RETURN_Code
ERROR_RETURN_CodeFull
ERROR_RETURN_CodeError
ERROR_RETURN_CodeErrorFull
ERROR_RETURN_CodeErrorTrace
ERROR_RETURN_CodeErrorTraceFull
ERROR_RETURN_StringError
ERROR_RETURN_StringErrorFull
)
func (m ErrorMode) String() string {
switch m {
case ERROR_RETURN_Code:
return "Code"
case ERROR_RETURN_CodeFull:
return "CodeFull"
case ERROR_RETURN_CodeError:
return "CodeError"
case ERROR_RETURN_CodeErrorFull:
return "CodeErrorFull"
case ERROR_RETURN_CodeErrorTrace:
return "CodeErrorTrace"
case ERROR_RETURN_CodeErrorTraceFull:
return "CodeErrorTraceFull"
case ERROR_RETURN_StringError:
return "StringError"
case ERROR_RETURN_StringErrorFull:
return "StringErrorFull"
default:
return "default"
}
}
func (m ErrorMode) error(e *errors) string {
switch m {
case ERROR_RETURN_Code:
return e.Code()
case ERROR_RETURN_CodeFull:
return e.CodeFull("")
case ERROR_RETURN_CodeError:
return e.CodeError("")
case ERROR_RETURN_CodeErrorFull:
return e.CodeErrorFull("", "")
case ERROR_RETURN_CodeErrorTrace:
return e.CodeErrorTrace("")
case ERROR_RETURN_CodeErrorTraceFull:
return e.CodeErrorTraceFull("", "")
case ERROR_RETURN_StringError:
return e.StringError()
case ERROR_RETURN_StringErrorFull:
return e.StringErrorFull("")
default:
return e.StringError()
}
}

51
errors/modules.go Normal file
View File

@@ -0,0 +1,51 @@
/*
* 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 errors
const (
MIN_PKG_Archive = 100
// MIN_PKG_Artifact = 200 // unused
MIN_PKG_Certif = 300
MIN_PKG_Console = 400
MIN_PKG_Crypt = 500
MIN_PKG_Httpcli = 600
MIN_PKG_Httpserver = 700
MIN_PKG_IOUtils = 800
MIN_PKG_LDAP = 900
// MIN_PKG_Logger = 1000 // unused
// MIN_PKG_Password = 1100 // unused
// MIN_PKG_Progress = 1200 // unused
MIN_PKG_Router = 1300
MIN_PKG_Semaphore = 1400
MIN_PKG_SMTP = 1500
MIN_PKG_Static = 1600
// MIN_PKG_Status = 1700 // unused
// MIN_PKG_Update = 1800 // unused
MIN_PKG_Version = 1900
MIN_AVAILABLE = 2000
)

67
errors/trace.go Normal file
View File

@@ -0,0 +1,67 @@
/*
* 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 errors
import (
"path"
"reflect"
"runtime"
"strings"
)
var currPkgs = path.Base(reflect.TypeOf(UNK_ERROR).PkgPath())
func getFrame() runtime.Frame {
// Set size to targetFrameIndex+2 to ensure we have room for one more caller than we need
programCounters := make([]uintptr, 0)
n := runtime.Callers(0, programCounters)
if n > 0 {
frames := runtime.CallersFrames(programCounters[:n])
more := true
for more {
var (
frame runtime.Frame
)
frame, more = frames.Next()
if strings.Contains(frame.Function, currPkgs) {
continue
}
return frame
}
}
return getNilFrame()
}
func getNilFrame() runtime.Frame {
return runtime.Frame{Function: "", File: "", Line: 0}
}

8
go.mod
View File

@@ -6,6 +6,7 @@ require (
github.com/VividCortex/ewma v1.1.1 // indirect
github.com/fatih/color v1.9.0
github.com/gin-gonic/gin v1.6.3
github.com/go-ldap/ldap/v3 v3.2.2
github.com/go-playground/validator/v10 v10.3.0 // indirect
github.com/gobuffalo/envy v1.9.0 // indirect
github.com/gobuffalo/packd v1.0.0 // indirect
@@ -27,12 +28,13 @@ require (
github.com/spf13/jwalterweatherman v1.1.0
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/vbauerster/mpb v3.4.0+incompatible // indirect
github.com/vbauerster/mpb/v5 v5.2.2
github.com/vbauerster/mpb/v5 v5.2.3
github.com/vjeantet/ldapserver v0.0.0-20170919170217-479fece7c5f1 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
golang.org/x/text v0.3.3 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect

16
go.sum
View File

@@ -1,4 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
@@ -26,6 +28,11 @@ github.com/gin-gonic/gin v1.6.2 h1:88crIK23zO6TqlQBt+f9FrPJNKm9ZEr7qjp9vl/d5TM=
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk=
github.com/go-ldap/ldap/v3 v3.2.2 h1:XIXsu/Z2SbIMrh51WMAf0t7zWftlCKoZiLU6MS8KWm8=
github.com/go-ldap/ldap/v3 v3.2.2/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -176,6 +183,8 @@ github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tL
github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU=
github.com/vbauerster/mpb/v5 v5.2.2 h1:zIICVOm+XD+uV6crpSORaL6I0Q1WqOdvxZTp+r3L9cw=
github.com/vbauerster/mpb/v5 v5.2.2/go.mod h1:W5Fvgw4dm3/0NhqzV8j6EacfuTe5SvnzBRwiXxDR9ww=
github.com/vbauerster/mpb/v5 v5.2.3 h1:OfqncMAhUojApki4/AxW4Z14cpiYBw7+MVLOyGklBmM=
github.com/vbauerster/mpb/v5 v5.2.3/go.mod h1:K4iCHQp5sWnmAgEn+uW1sAxSilctb4JPAGXx49jV+Aw=
github.com/vjeantet/ldapserver v0.0.0-20170919170217-479fece7c5f1/go.mod h1:+KHPMCVmFBVXK3UAUom0AgP/IeOXH5C3ieEwA+JU3WE=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -191,6 +200,8 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -215,6 +226,8 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYc
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -255,7 +268,10 @@ golang.org/x/sys v0.0.0-20200620081246-981b61492c35/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=

92
httpcli/cli.go Normal file
View File

@@ -0,0 +1,92 @@
/*
* 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 httpcli
import (
"crypto/tls"
"net"
"net/http"
"time"
"golang.org/x/net/http2"
. "github.com/nabbar/golib/errors"
njs_certif "github.com/nabbar/golib/certificates"
)
const (
TIMEOUT_30_SEC = 30 * time.Second
TIMEOUT_10_SEC = 10 * time.Second
TIMEOUT_5_SEC = 5 * time.Second
TIMEOUT_1_SEC = 1 * time.Second
)
func GetClient(serverName string) *http.Client {
c, e := getClient(true, TIMEOUT_30_SEC, TIMEOUT_10_SEC, TIMEOUT_30_SEC, TIMEOUT_30_SEC, TIMEOUT_5_SEC, TIMEOUT_1_SEC, njs_certif.GetTLSConfig(serverName))
if e != nil {
c, _ = getClient(false, TIMEOUT_30_SEC, TIMEOUT_10_SEC, TIMEOUT_30_SEC, TIMEOUT_30_SEC, TIMEOUT_5_SEC, TIMEOUT_1_SEC, njs_certif.GetTLSConfig(serverName))
}
return c
}
func GetClientError(serverName string) (*http.Client, Error) {
return getClient(true, TIMEOUT_30_SEC, TIMEOUT_10_SEC, TIMEOUT_30_SEC, TIMEOUT_30_SEC, TIMEOUT_5_SEC, TIMEOUT_1_SEC, njs_certif.GetTLSConfig(serverName))
}
func GetClientTimeout(serverName string, GlobalTimeout, DialTimeOut, DialKeepAlive, IdleConnTimeout, TLSHandshakeTimeout, ExpectContinueTimeout time.Duration) (*http.Client, Error) {
return getClient(true, GlobalTimeout, DialTimeOut, DialKeepAlive, IdleConnTimeout, TLSHandshakeTimeout, ExpectContinueTimeout, njs_certif.GetTLSConfig(serverName))
}
func getClient(http2Transport bool, GlobalTimeout, DialTimeOut, DialKeepAlive, IdleConnTimeout, TLSHandshakeTimeout, ExpectContinueTimeout time.Duration, tlsConfig *tls.Config) (*http.Client, Error) {
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: DialTimeOut,
KeepAlive: DialKeepAlive,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: IdleConnTimeout,
TLSHandshakeTimeout: TLSHandshakeTimeout,
ExpectContinueTimeout: ExpectContinueTimeout,
DisableCompression: true,
TLSClientConfig: tlsConfig,
}
if http2Transport {
if e := http2.ConfigureTransport(tr); e != nil {
return nil, HTTP2_CONFIGURE.ErrorParent(e)
}
}
return &http.Client{
Transport: tr,
Timeout: GlobalTimeout,
}, nil
}

67
httpcli/error.go Normal file
View File

@@ -0,0 +1,67 @@
/*
* 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 httpcli
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Httpcli
URL_PARSE
HTTP_CLIENT
HTTP_REQUEST
HTTP_DO
IO_READ
BUFFER_WRITE
HTTP2_CONFIGURE
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case URL_PARSE:
return "uri/url parse error"
case HTTP_CLIENT:
return "error on creating a new http/http2 client"
case HTTP_REQUEST:
return "error on creating a new http/http2 request"
case HTTP_DO:
return "error on sending a http/http2 request"
case IO_READ:
return "error on reading i/o stream"
case BUFFER_WRITE:
return "error on writing bytes on buffer"
case HTTP2_CONFIGURE:
return "error while configure http2 transport for client"
}
return ""
}

View File

@@ -23,21 +23,17 @@
*
*/
package njs_httpcli
package httpcli
import (
"bytes"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"strings"
"time"
njs_certif "github.com/nabbar/golib/njs-certif"
njs_logger "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
. "github.com/nabbar/golib/logger"
)
type httpClient struct {
@@ -46,11 +42,11 @@ type httpClient struct {
}
type HTTP interface {
Check() bool
Call(file *bytes.Buffer) (bool, *bytes.Buffer)
Check() Error
Call(file *bytes.Buffer) (bool, *bytes.Buffer, Error)
}
func NewClient(uri string) HTTP {
func NewClient(uri string) (HTTP, Error) {
var (
pUri *url.URL
err error
@@ -59,85 +55,100 @@ func NewClient(uri string) HTTP {
if uri != "" {
pUri, err = url.Parse(uri)
njs_logger.PanicLevel.LogErrorCtx(njs_logger.NilLevel, fmt.Sprintf("parsing url '%s'", uri), err)
if err != nil {
return nil, URL_PARSE.ErrorParent(err)
}
host = pUri.Host
} else {
pUri = nil
host = ""
}
c, e := GetClientError(host)
if e != nil {
return nil, HTTP_CLIENT.Error(e)
}
return &httpClient{
url: pUri,
cli: GetClient(host),
cli: c,
}, nil
}
func (obj *httpClient) Check() Error {
req, e := obj.newRequest(http.MethodHead, nil)
if e != nil {
return e
}
_, e = obj.doRequest(req)
return e
}
func GetClient(serverName string) *http.Client {
return &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 10 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 30 * time.Second,
TLSHandshakeTimeout: 5 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
DisableCompression: true,
TLSClientConfig: njs_certif.GetTLSConfig(serverName),
},
func (obj *httpClient) Call(body *bytes.Buffer) (bool, *bytes.Buffer, Error) {
req, e := obj.newRequest(http.MethodPost, body)
if e != nil {
return false, nil, e
}
res, e := obj.doRequest(req)
if e != nil {
return false, nil, e
}
return obj.checkResponse(res)
}
func (obj *httpClient) Check() bool {
obj.doRequest(obj.newRequest(http.MethodHead, nil))
return true
}
func (obj *httpClient) Call(body *bytes.Buffer) (bool, *bytes.Buffer) {
return obj.checkResponse(
obj.doRequest(
obj.newRequest(http.MethodPost, body),
),
)
}
func (obj *httpClient) newRequest(method string, body *bytes.Buffer) *http.Request {
func (obj *httpClient) newRequest(method string, body *bytes.Buffer) (*http.Request, Error) {
var reader *bytes.Reader
if body != nil && body.Len() > 0 {
reader = bytes.NewReader(body.Bytes())
}
req, err := http.NewRequest(method, obj.url.String(), reader)
njs_logger.PanicLevel.LogErrorCtx(njs_logger.NilLevel, fmt.Sprintf("creating '%s' request to '%s'", method, obj.url.Host), err)
req, e := http.NewRequest(method, obj.url.String(), reader)
if e != nil {
return req, HTTP_REQUEST.ErrorParent(e)
}
return req
return req, nil
}
func (obj *httpClient) doRequest(req *http.Request) *http.Response {
res, err := obj.cli.Do(req)
njs_logger.PanicLevel.LogErrorCtx(njs_logger.NilLevel, fmt.Sprintf("running request '%s:%s'", req.Method, req.URL.Host), err)
func (obj *httpClient) doRequest(req *http.Request) (*http.Response, Error) {
res, e := obj.cli.Do(req)
return res
if e != nil {
return res, HTTP_DO.ErrorParent(e)
}
return res, nil
}
func (obj *httpClient) checkResponse(res *http.Response) (bool, *bytes.Buffer) {
func (obj *httpClient) checkResponse(res *http.Response) (bool, *bytes.Buffer, Error) {
var buf *bytes.Buffer
if res.Body != nil {
bdy, err := ioutil.ReadAll(res.Body)
if err == nil {
_, err = buf.Write(bdy)
if err != nil {
return false, nil, IO_READ.ErrorParent(err)
}
njs_logger.DebugLevel.LogError(err)
_, err = buf.Write(bdy)
if err != nil {
return false, nil, BUFFER_WRITE.ErrorParent(err)
}
DebugLevel.LogError(err)
}
njs_logger.InfoLevel.Logf("Calling '%s:%s' result %s (Body : %d bytes)", res.Request.Method, res.Request.URL.Host, res.Status, buf.Len())
return strings.HasPrefix(res.Status, "2"), buf
return strings.HasPrefix(res.Status, "2"), buf, nil
}

46
httpserver/error.go Normal file
View File

@@ -0,0 +1,46 @@
/*
* 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 httpserver
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Httpserver
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
}
return ""
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_httpserver
package httpserver
import (
"context"
@@ -40,8 +40,18 @@ import (
"syscall"
"time"
njs_certif "github.com/nabbar/golib/njs-certif"
njs_logger "github.com/nabbar/golib/njs-logger"
"golang.org/x/net/http2"
njs_certif "github.com/nabbar/golib/certificates"
. "github.com/nabbar/golib/logger"
)
const (
TIMEOUT_30_SEC = 30 * time.Second
TIMEOUT_10_SEC = 10 * time.Second
TIMEOUT_5_SEC = 5 * time.Second
TIMEOUT_1_SEC = 1 * time.Second
)
type modelServer struct {
@@ -169,22 +179,36 @@ func (srv *modelServer) Listen() {
srv.srv = &http.Server{
Addr: srv.GetBindable(),
ErrorLog: njs_logger.GetLogger(njs_logger.ErrorLevel, log.LstdFlags | log.LstdFlags | log.Lmicroseconds, "server '%s'", srv.GetBindable()),
ErrorLog: GetLogger(ErrorLevel, log.LstdFlags|log.Lmicroseconds, "[http/http2 server '%s']", srv.GetBindable()),
Handler: srv.hdl,
TLSConfig: srv.ssl,
}
njs_logger.InfoLevel.Logf("Server starting with bindable: %s", srv.GetBindable())
cnf := &http2.Server{
//MaxHandlers: 0,
//MaxConcurrentStreams: 0,
//MaxReadFrameSize: 0,
//PermitProhibitedCipherSuites: false,
IdleTimeout: TIMEOUT_30_SEC,
//MaxUploadBufferPerConnection: 0,
//MaxUploadBufferPerStream: 0,
//NewWriteScheduler: nil,
}
err := http2.ConfigureServer(srv.srv, cnf)
FatalLevel.Logf("Configuring Server '%s' Error: %v", srv.host, err)
go func() {
if srv.ssl == nil || !njs_certif.CheckCertificates() {
InfoLevel.Logf("Server '%s' is starting with bindable: %s", srv.host, srv.GetBindable())
if err := srv.srv.ListenAndServe(); err != nil {
njs_logger.FatalLevel.Logf("Listen Error: %v", err)
FatalLevel.Logf("Listen Server '%s' Error: %v", srv.host, err)
return
}
} else {
InfoLevel.Logf("TLS Server '%s' is starting with bindable: %s", srv.host, srv.GetBindable())
if err := srv.srv.ListenAndServeTLS("", ""); err != nil {
njs_logger.FatalLevel.Logf("Listen config Error: %v", err)
FatalLevel.Logf("Listen TLS Server '%s' Error: %v", srv.host, err)
return
}
}
@@ -213,7 +237,7 @@ func (srv *modelServer) Restart() {
}
func (srv *modelServer) Shutdown() {
njs_logger.InfoLevel.Logf("Shutdown Server ...")
InfoLevel.Logf("Shutdown Server '%s'...", srv.addr.Host)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
@@ -223,7 +247,7 @@ func (srv *modelServer) Shutdown() {
}
if err := srv.srv.Shutdown(ctx); err != nil {
njs_logger.FatalLevel.Logf("Server Shutdown Error: %v", err)
FatalLevel.Logf("Shutdown Server '%s' Error: %v", srv.host, err)
}
srv.srv = nil

61
ioutils/error.go Normal file
View File

@@ -0,0 +1,61 @@
/*
* 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 ioutils
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_IOUtils
SYSCALL_RLIMIT_GET
SYSCALL_RLIMIT_SET
IO_TEMP_FILE_NEW
IO_TEMP_FILE_CLOSE
IO_TEMP_FILE_REMOVE
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case SYSCALL_RLIMIT_GET:
return "error on retrieve value in syscall rlimit"
case SYSCALL_RLIMIT_SET:
return "error on changing value in syscall rlimit"
case IO_TEMP_FILE_NEW:
return "error occur while trying to create new temporary file"
case IO_TEMP_FILE_CLOSE:
return "closing temporary file occurs error"
case IO_TEMP_FILE_REMOVE:
return "error occurs on removing temporary file"
}
return ""
}

View File

@@ -23,7 +23,9 @@
*
*/
package njs_ioutils
package ioutils
import . "github.com/nabbar/golib/errors"
/**
* SystemFileDescriptor is returning current Limit & max system limit for file descriptor (open file or I/O resource) currently set in the system
@@ -49,6 +51,6 @@ package njs_ioutils
* Normally no problem will be result in the build
*
*/
func SystemFileDescriptor(newValue int) (current int, max int, err error) {
func SystemFileDescriptor(newValue int) (current int, max int, err Error) {
return systemFileDescriptor(newValue)
}

View File

@@ -25,13 +25,14 @@
*
*/
package njs_ioutils
package ioutils
import (
"github.com/nabbar/golib/njs-ioutils/maxstdio"
. "github.com/nabbar/golib/errors"
"github.com/nabbar/golib/ioutils/maxstdio"
)
func systemFileDescriptor(newValue int) (current int, max int, err error) {
func systemFileDescriptor(newValue int) (current int, max int, err Error) {
rLimit := maxstdio.GetMaxStdio()
if rLimit < 0 {

View File

@@ -25,14 +25,22 @@
*
*/
package njs_ioutils
package ioutils
import "syscall"
import (
"syscall"
func systemFileDescriptor(newValue int) (current int, max int, err error) {
var rLimit syscall.Rlimit
. "github.com/nabbar/golib/errors"
)
if err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil {
func systemFileDescriptor(newValue int) (current int, max int, err Error) {
var (
rLimit syscall.Rlimit
e error
)
if e = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); e != nil {
err = SYSCALL_RLIMIT_GET.ErrorParent(e)
return
}
@@ -56,7 +64,8 @@ func systemFileDescriptor(newValue int) (current int, max int, err error) {
}
if chg {
if err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil {
if e = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); e != nil {
err = SYSCALL_RLIMIT_SET.ErrorParent(e)
return
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_ioutils
package ioutils
import "io"

View File

@@ -23,21 +23,19 @@
*
*/
package njs_ioutils
package ioutils
import (
"fmt"
"io/ioutil"
"os"
"path"
. "github.com/nabbar/golib/errors"
)
func NewTempFile() (*os.File, error) {
if f, e := ioutil.TempFile(os.TempDir(), ""); e != nil {
return nil, e
} else {
return f, nil
}
func NewTempFile() (*os.File, Error) {
f, e := ioutil.TempFile(os.TempDir(), "")
return f, IO_TEMP_FILE_NEW.Iferror(e)
}
func GetTempFilePath(f *os.File) string {
@@ -48,24 +46,18 @@ func GetTempFilePath(f *os.File) string {
return path.Join(os.TempDir(), path.Base(f.Name()))
}
func DelTempFile(f *os.File, ignoreErrClose bool) error {
func DelTempFile(f *os.File) Error {
if f == nil {
return nil
}
n := GetTempFilePath(f)
a := f.Close()
e1 := IO_TEMP_FILE_CLOSE.Iferror(a)
b := os.Remove(n)
e2 := IO_TEMP_FILE_REMOVE.Iferror(b)
if ignoreErrClose {
return b
}
if a != nil && b != nil {
return fmt.Errorf("%v, %v", a, b)
} else if a != nil {
return a
}
return b
return MakeErrorIfError(e2, e1)
}

70
ldap/error.go Normal file
View File

@@ -0,0 +1,70 @@
/*
* 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 ldap
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_LDAP
LDAP_SERVER_CONFIG
LDAP_SERVER_DIAL
LDAP_SERVER_TLS
LDAP_SERVER_STARTTLS
LDAP_BIND
LDAP_SEARCH
LDAP_USER_NOT_UNIQ
LDAP_USER_NOT_FOUND
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case LDAP_SERVER_CONFIG:
return "LDAP server config is not well defined"
case LDAP_SERVER_DIAL:
return "dialing server occurs error "
case LDAP_SERVER_TLS:
return "cannot start dial to server with TLS Mode"
case LDAP_SERVER_STARTTLS:
return "cannot init starttls mode on opening server connection"
case LDAP_BIND:
return "error on binding user/pass"
case LDAP_SEARCH:
return "error on calling search on connected server"
case LDAP_USER_NOT_UNIQ:
return "user uid is not uniq"
case LDAP_USER_NOT_FOUND:
return "user uid is not found"
}
return ""
}

View File

@@ -23,17 +23,18 @@
*
*/
package njs_ldap
package ldap
import (
"crypto/tls"
"fmt"
"strings"
"github.com/pkg/errors"
"github.com/nabbar/golib/njs-certif"
"github.com/nabbar/golib/njs-logger"
"gopkg.in/ldap.v3"
"github.com/go-ldap/ldap/v3"
njs_certif "github.com/nabbar/golib/certificates"
. "github.com/nabbar/golib/errors"
. "github.com/nabbar/golib/logger"
)
//HelperLDAP struct use to manage connection to server and request it
@@ -48,9 +49,9 @@ type HelperLDAP struct {
}
//NewLDAP build a new LDAP helper based on config struct given
func NewLDAP(cnf *Config, attributes []string) *HelperLDAP {
func NewLDAP(cnf *Config, attributes []string) (*HelperLDAP, Error) {
if cnf == nil {
panic("given config is a nil struct")
return nil, EMPTY_PARAMS.Error(nil)
}
return &HelperLDAP{
@@ -58,7 +59,7 @@ func NewLDAP(cnf *Config, attributes []string) *HelperLDAP {
tlsConfig: njs_certif.GetTLSConfig(cnf.Uri),
tlsMode: tlsmode_init,
config: cnf.Clone(),
}
}, nil
}
//SetCredentials used to defined the BindDN and password for connection
@@ -79,45 +80,45 @@ func (lc *HelperLDAP) ForceTLSMode(tlsMode TLSMode, tlsConfig *tls.Config) {
}
}
func (lc *HelperLDAP) tryConnect() (TLSMode, error) {
func (lc *HelperLDAP) tryConnect() (TLSMode, Error) {
var (
l *ldap.Conn
err error
)
defer func(l *ldap.Conn) {
defer func() {
if l != nil {
l.Close()
}
}(l)
}()
if lc.config.Portldaps != 0 {
l, err = ldap.DialTLS("tcp", lc.config.ServerAddr(true), lc.tlsConfig)
if err == nil {
njs_logger.DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
return TLSMODE_TLS, nil
}
}
if lc.config.PortLdap == 0 {
return 0, fmt.Errorf("ldap server not well defined")
return tlsmode_init, LDAP_SERVER_CONFIG.Error(nil)
}
l, err = ldap.Dial("tcp", lc.config.ServerAddr(false))
if err != nil {
return 0, err
return 0, LDAP_SERVER_DIAL.ErrorParent(err)
}
if e := l.StartTLS(lc.tlsConfig); e == nil {
njs_logger.DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
if err = l.StartTLS(lc.tlsConfig); err == nil {
DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
return TLSMODE_STARTTLS, nil
}
njs_logger.DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
return TLSMODE_NONE, nil
}
func (lc *HelperLDAP) connect() error {
func (lc *HelperLDAP) connect() Error {
if lc.conn == nil {
var (
l *ldap.Conn
@@ -137,25 +138,25 @@ func (lc *HelperLDAP) connect() error {
if lc.tlsMode == TLSMODE_TLS {
l, err = ldap.DialTLS("tcp", lc.config.ServerAddr(true), lc.tlsConfig)
if err != nil {
return fmt.Errorf("ldap connection error with tls mode '%s': %v", lc.tlsMode.String(), err)
return LDAP_SERVER_TLS.ErrorParent(err)
}
}
if lc.tlsMode == TLSMODE_NONE || lc.tlsMode == TLSMODE_STARTTLS {
l, err = ldap.Dial("tcp", lc.config.ServerAddr(false))
if err != nil {
return fmt.Errorf("ldap connection error with tls mode '%s': %v", lc.tlsMode.String(), err)
return LDAP_SERVER_DIAL.ErrorParent(err)
}
}
if lc.tlsMode == TLSMODE_STARTTLS {
err = l.StartTLS(lc.tlsConfig)
if err != nil {
return fmt.Errorf("ldap connection error with tls mode '%s': %v", lc.tlsMode.String(), err)
return LDAP_SERVER_STARTTLS.ErrorParent(err)
}
}
njs_logger.DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
DebugLevel.Logf("ldap connected with tls mode '%s'", lc.tlsMode.String())
lc.conn = l
}
@@ -163,7 +164,7 @@ func (lc *HelperLDAP) connect() error {
}
//Check used to check if connection success (without any bind)
func (lc *HelperLDAP) Check() error {
func (lc *HelperLDAP) Check() Error {
if err := lc.connect(); err != nil {
return err
}
@@ -181,37 +182,39 @@ func (lc *HelperLDAP) Close() {
}
//AuthUser used to test bind given user uid and password
func (lc *HelperLDAP) AuthUser(username, password string) error {
func (lc *HelperLDAP) AuthUser(username, password string) Error {
if err := lc.connect(); err != nil {
return err
}
if username == "" || password == "" {
return errors.New("Cannot bind with partial credentials, bindDN or bind password is empty string")
return EMPTY_PARAMS.Error(nil)
}
return lc.conn.Bind(username, password)
err := lc.conn.Bind(username, password)
return LDAP_BIND.Iferror(err)
}
//Connect used to connect and bind to server
func (lc *HelperLDAP) Connect() error {
func (lc *HelperLDAP) Connect() Error {
if err := lc.AuthUser(lc.bindDN, lc.bindPass); err != nil {
return fmt.Errorf("error while trying to bind on LDAP server %s with tls mode '%s': %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), err)
return err
}
njs_logger.DebugLevel.Logf("Bind success on LDAP server %s with tls mode '%s'", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String())
DebugLevel.Logf("Bind success on LDAP server %s with tls mode '%s'", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String())
return nil
}
func (lc *HelperLDAP) runSearch(filter string, attributes []string) (*ldap.SearchResult, error) {
func (lc *HelperLDAP) runSearch(filter string, attributes []string) (*ldap.SearchResult, Error) {
var (
err error
src *ldap.SearchResult
)
if err = lc.Connect(); err != nil {
return nil, err
if e := lc.Connect(); e != nil {
return nil, e
}
defer lc.Close()
@@ -227,17 +230,17 @@ func (lc *HelperLDAP) runSearch(filter string, attributes []string) (*ldap.Searc
)
if src, err = lc.conn.Search(searchRequest); err != nil {
return nil, fmt.Errorf("error while looking for '%s' on ldap server %s with tls mode '%s': %v", filter, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), err)
return nil, LDAP_SEARCH.ErrorParent(err)
}
njs_logger.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)
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)
return src, nil
}
//UserInfo used to retrieve the information of a given username
func (lc *HelperLDAP) UserInfo(username string) (map[string]string, error) {
func (lc *HelperLDAP) UserInfo(username string) (map[string]string, Error) {
var (
err error
e Error
src *ldap.SearchResult
userRes map[string]string
)
@@ -250,18 +253,18 @@ func (lc *HelperLDAP) UserInfo(username string) (map[string]string, error) {
userRes = make(map[string]string)
attributes := append(lc.Attributes, "cn")
if src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterUser, username), attributes); err != nil {
return userRes, err
src, e = lc.runSearch(fmt.Sprintf(lc.config.FilterUser, username), attributes)
if e != nil {
return userRes, e
}
if len(src.Entries) != 1 {
if len(src.Entries) > 1 {
err = errors.New("Username not unique")
return userRes, LDAP_USER_NOT_UNIQ.Error(nil)
} else {
err = errors.New("Username not found")
return userRes, LDAP_USER_NOT_FOUND.Error(nil)
}
return userRes, fmt.Errorf("error while looking for username '%s' on ldap server '%s' with tls mode '%s': %v", username, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), err)
}
for _, attr := range attributes {
@@ -272,14 +275,14 @@ func (lc *HelperLDAP) UserInfo(username string) (map[string]string, error) {
userRes["DN"] = src.Entries[0].DN
}
njs_logger.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)
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
}
//UserMemberOf returns the group list of a given user.
func (lc *HelperLDAP) UserMemberOf(username string) ([]string, error) {
func (lc *HelperLDAP) UserMemberOf(username string) ([]string, Error) {
var (
err error
err Error
src *ldap.SearchResult
grp []string
)
@@ -291,26 +294,27 @@ func (lc *HelperLDAP) UserMemberOf(username string) ([]string, error) {
grp = make([]string, 0)
if src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterUser, username), []string{"memberOf"}); err != nil {
src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterUser, username), []string{"memberOf"})
if err != nil {
return grp, err
}
for _, entry := range src.Entries {
for _, mmb := range entry.GetAttributeValues("memberOf") {
njs_logger.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)
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)
mmo := lc.ParseEntries(mmb)
grp = append(grp, mmo["cn"]...)
}
}
njs_logger.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)
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)
return grp, nil
}
//UserIsInGroup used to check if a given username is a group member of a list of reference group name
func (lc *HelperLDAP) UserIsInGroup(username string, groupname []string) (bool, error) {
func (lc *HelperLDAP) UserIsInGroup(username string, groupname []string) (bool, Error) {
var (
err error
err Error
grpMmbr []string
)
@@ -319,13 +323,14 @@ func (lc *HelperLDAP) UserIsInGroup(username string, groupname []string) (bool,
username = usr["uid"][0]
}
if grpMmbr, err = lc.UserMemberOf(username); err != nil {
grpMmbr, err = lc.UserMemberOf(username)
if err != nil {
return false, err
}
for _, grpSrch := range groupname {
for _, grpItem := range grpMmbr {
if strings.ToUpper(grpSrch) == strings.ToUpper(grpItem) {
if strings.EqualFold(grpSrch, grpItem) {
return true, nil
}
}
@@ -335,16 +340,17 @@ func (lc *HelperLDAP) UserIsInGroup(username string, groupname []string) (bool,
}
//UsersOfGroup used to retrieve the member list of a given group name
func (lc *HelperLDAP) UsersOfGroup(groupname string) ([]string, error) {
func (lc *HelperLDAP) UsersOfGroup(groupname string) ([]string, Error) {
var (
err error
err Error
src *ldap.SearchResult
grp []string
)
grp = make([]string, 0)
if src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterGroup, groupname), []string{"member"}); err != nil {
src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterGroup, groupname), []string{"member"})
if err != nil {
return grp, err
}
@@ -355,7 +361,7 @@ func (lc *HelperLDAP) UsersOfGroup(groupname string) ([]string, error) {
}
}
njs_logger.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)
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)
return grp, nil
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_ldap
package ldap
import (
"fmt"

View File

@@ -22,12 +22,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_logger
package logger
import (
"github.com/sirupsen/logrus"
"io"
"strings"
"github.com/sirupsen/logrus"
)
// Format a uint8 type customized with function to manage the result logger format

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_logger
package logger
import (
"fmt"

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_logger
package logger
import (
"encoding/json"
@@ -341,7 +341,7 @@ func (level Level) logDetails(message string, data interface{}, err error, field
return
}
var tags = make(map[string]interface{}, 0)
var tags = make(map[string]interface{})
if enableGID {
tags[tagStack] = getGID()

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_logger
package logger
import (
"log"
@@ -38,9 +38,9 @@ import (
)
const (
tagStack = "stack"
tagTime = "time"
tagLevel = "level"
tagStack = "stack"
tagTime = "time"
//tagLevel = "level" //unused
tagCaller = "func"
tagFile = "file"
tagLine = "line"

View File

@@ -1,102 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2019 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 njs_errors
import (
"fmt"
"path"
"runtime"
"strings"
)
type ErrorCode interface {
Error() error
ErrorFull() error
String() string
StringFull() string
Code() string
Trace() runtime.Frame
}
type errorCode struct {
code string
err ErrorType
ori error
trace runtime.Frame
}
// Error return an error type of the current error code, with no code in reference
func (e errorCode) Error() error {
return e.err.Error(e.ori)
}
// String return a string of the current error code, with no code in reference
func (e errorCode) String() string {
return e.err.String()
}
// Code return a string of the current code, with no error in reference
func (e errorCode) Code() string {
return e.code
}
// Trace return a runtime frame of the current error
func (e errorCode) Trace() runtime.Frame {
return e.trace
}
// StringFull return a error type of the current code, with error and origin in reference
func (e errorCode) StringFull() string {
return e.ErrorFull().Error()
}
// ErrorFull return a error type of the current code, with error and origin in reference
func (e errorCode) ErrorFull() error {
if e.trace != getNilFrame() {
var t = make([]string, 0)
if e.trace.File != "" {
t = append(t, path.Base(e.trace.File))
}
if e.trace.Function != "" {
t = append(t, e.trace.Function)
}
if e.trace.Line > 0 {
t = append(t, fmt.Sprintf("%v", e.trace.Line))
}
if len(t) > 0 {
return fmt.Errorf("(%s) [%s] %v", e.code, strings.Join(t, "|"), e.Error())
}
}
return fmt.Errorf("(%s) %v", e.code, e.Error())
}

View File

@@ -1,134 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2019 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 njs_errors
import (
"path"
"reflect"
"runtime"
"strings"
)
var (
currPkgs = path.Base(reflect.TypeOf(ERR_UNKNOWN).PkgPath())
_listCodeErrors = make(map[string]ErrorType, 0)
)
// SetErrorCode Register a new error with code and an error string as ErrorType
func SetErrorCode(code string, err ErrorType) {
if _listCodeErrors == nil || len(_listCodeErrors) < 1 {
_listCodeErrors = make(map[string]ErrorType, 0)
}
_listCodeErrors[code] = err
}
// SetErrorCodeString Register a new error with code and an error string as string
func SetErrorCodeString(code, err string) {
SetErrorCode(code, ErrorType(err))
}
// DelErrorCode Remove an error with code from the register list
func DelErrorCode(code string) {
var _lst = _listCodeErrors
DelAllErrorCode()
for k, v := range _lst {
if k != code {
_listCodeErrors[k] = v
}
}
}
// DelAllErrorCode Clean the complete list of couple code - error
func DelAllErrorCode() {
_listCodeErrors = make(map[string]ErrorType, 0)
}
// GetErrorCode return an ErrorCode interface mapped to code given in parameters.
// If the code is not found an 'ERR_UNKNOWN' will be used instead of the awaiting error
// If an origin error is given in params, this origin error will be used in the reference of generated error or string
func GetErrorCode(code string, origin error) ErrorCode {
return getErrorCode(code, origin, getNilFrame())
}
// GetTraceErrorCode return an ErrorCode interface mapped to given params code.
// If the code is not found an 'ERR_UNKNOWN' will be used instead of the awaiting error
// If an origin error is given in params, this origin error will be used in the reference of generated error or string
// This function add a trace of error generated
func GetTraceErrorCode(code string, origin error) ErrorCode {
return getErrorCode(code, origin, getFrame())
}
func getErrorCode(code string, origin error, trace runtime.Frame) ErrorCode {
var (
e ErrorType
ok bool
)
if e, ok = _listCodeErrors[code]; !ok {
e = ERR_UNKNOWN
}
return &errorCode{
code: code,
err: e,
ori: origin,
trace: trace,
}
}
func getFrame() runtime.Frame {
// Set size to targetFrameIndex+2 to ensure we have room for one more caller than we need
programCounters := make([]uintptr, 0)
n := runtime.Callers(0, programCounters)
if n > 0 {
frames := runtime.CallersFrames(programCounters[:n])
more := true
for more {
var (
frame runtime.Frame
)
frame, more = frames.Next()
if strings.Contains(frame.Function, currPkgs) {
continue
}
return frame
}
}
return getNilFrame()
}
func getNilFrame() runtime.Frame {
return runtime.Frame{Function: "", File: "", Line: 0}
}

View File

@@ -1,71 +0,0 @@
/*
MIT License
Copyright (c) 2019 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 njs_smtp
import "strings"
func cleanMergeSlice(str []string, args ...string) []string {
for _, s := range args {
if s != "" {
str = append(str, s)
}
}
return str
}
func unicSliceString(str []string) []string {
var new = make([]string, 0)
for _, s := range str {
if !existSliceString(new, s) {
new = append(new, s)
}
}
return new
}
func existSliceString(slc []string, str string) bool {
for _, s := range slc {
if s == str {
return true
}
}
return false
}
func cleanJoin(str []string, glue string) string {
var new = make([]string, 0)
for _, s := range str {
if s != "" {
new = append(new, s)
}
}
return strings.Join(new, glue)
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_password
package password
import (
"math/rand"

View File

@@ -23,20 +23,23 @@
*
*/
package njs_progress
package progress
import (
"context"
njs_semaphore "github.com/nabbar/golib/njs-semaphore"
"github.com/vbauerster/mpb/v5"
. "github.com/nabbar/golib/errors"
sem "github.com/nabbar/golib/semaphore"
)
type bar struct {
u bool
t int64
b *mpb.Bar
s njs_semaphore.Sem
s sem.Sem
}
type Bar interface {
@@ -45,19 +48,19 @@ type Bar interface {
Increment(n int)
Refill(amount int64)
NewWorker() error
NewWorker() Error
NewWorkerTry() bool
DeferWorker()
DeferMain(dropBar bool)
WaitAll() error
WaitAll() Error
Context() context.Context
Cancel()
GetBarMPB() *mpb.Bar
}
func newBar(b *mpb.Bar, s njs_semaphore.Sem, total int64) Bar {
func newBar(b *mpb.Bar, s sem.Sem, total int64) Bar {
return &bar{
u: total > 0,
t: total,
@@ -89,7 +92,7 @@ func (b *bar) Refill(amount int64) {
b.b.SetRefill(amount)
}
func (b *bar) NewWorker() error {
func (b *bar) NewWorker() Error {
if !b.u {
b.t++
b.b.SetTotal(b.t, false)
@@ -112,7 +115,7 @@ func (b *bar) DeferMain(dropBar bool) {
b.s.DeferMain()
}
func (b *bar) WaitAll() error {
func (b *bar) WaitAll() Error {
return b.s.WaitAll()
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_progress
package progress
import (
"context"
@@ -31,7 +31,7 @@ import (
"github.com/vbauerster/mpb/v5/decor"
njs_semaphore "github.com/nabbar/golib/njs-semaphore"
njs_semaphore "github.com/nabbar/golib/semaphore"
"github.com/vbauerster/mpb/v5"
)

View File

@@ -23,15 +23,16 @@
*
*/
package njs_router
package router
import (
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
njs_logger "github.com/nabbar/golib/njs-logger"
. "github.com/nabbar/golib/errors"
. "github.com/nabbar/golib/logger"
)
type AuthCode uint8
@@ -71,7 +72,7 @@ func AuthForbidden(c *gin.Context, err error) {
}
type authorization struct {
check func(AuthHeader string) (AuthCode, error)
check func(AuthHeader string) (AuthCode, Error)
router []gin.HandlerFunc
authType string
}
@@ -82,7 +83,7 @@ type Authorization interface {
Append(router ...gin.HandlerFunc)
}
func NewAuthorization(HeadAuthType string, authCheckFunc func(AuthHeader string) (AuthCode, error)) Authorization {
func NewAuthorization(HeadAuthType string, authCheckFunc func(AuthHeader string) (AuthCode, Error)) Authorization {
return &authorization{
check: authCheckFunc,
authType: HeadAuthType,
@@ -104,7 +105,7 @@ func (a authorization) Handler(c *gin.Context) {
auth := c.Request.Header.Get(HEAD_AUTH_SEND)
if auth == "" {
AuthRequire(c, fmt.Errorf("header '%s' is missing", HEAD_AUTH_SEND))
AuthRequire(c, HEADER_AUTH_MISSING.Error(nil).GetErrorFull(""))
return
}
@@ -118,7 +119,7 @@ func (a authorization) Handler(c *gin.Context) {
}
if authValue == "" {
AuthRequire(c, fmt.Errorf("reading authorization error : auth string is empty"))
AuthRequire(c, HEADER_AUTH_EMPTY.Error(nil).GetErrorFull(""))
return
} else {
code, err := a.check(authValue)
@@ -126,17 +127,16 @@ func (a authorization) Handler(c *gin.Context) {
switch code {
case AUTH_CODE_SUCCESS:
for _, r := range a.router {
njs_logger.DebugLevel.Logf("Calling router '%s=%s'", c.Request.Method, c.Request.URL.RawPath)
DebugLevel.Logf("Calling router '%s=%s'", c.Request.Method, c.Request.URL.RawPath)
r(c)
}
case AUTH_CODE_REQUIRE:
AuthRequire(c, fmt.Errorf("authorization error : %v", err))
AuthRequire(c, HEADER_AUTH_REQUIRE.Error(err).GetErrorFull(""))
case AUTH_CODE_FORBIDDEN:
AuthForbidden(c, fmt.Errorf("authorization error : %v", err))
AuthForbidden(c, HEADER_AUTH_FORBIDDEN.Error(err).GetErrorFull(""))
default:
err := fmt.Errorf("auth response code is not valid")
c.Errors = append(c.Errors, &gin.Error{
Err: err,
Err: HEADER_AUTH_ERROR.Error(err).GetErrorFull(""),
Type: gin.ErrorTypePrivate,
})
c.AbortWithStatus(http.StatusInternalServerError)

61
router/error.go Normal file
View File

@@ -0,0 +1,61 @@
/*
* 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 router
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Router
HEADER_AUTH_MISSING
HEADER_AUTH_EMPTY
HEADER_AUTH_REQUIRE
HEADER_AUTH_FORBIDDEN
HEADER_AUTH_ERROR
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case HEADER_AUTH_MISSING:
return "missing authorization header"
case HEADER_AUTH_EMPTY:
return "authorization header is empty"
case HEADER_AUTH_REQUIRE:
return "authorization check failed, authorization still require"
case HEADER_AUTH_FORBIDDEN:
return "authorization check success but unauthorized client"
case HEADER_AUTH_ERROR:
return "authorization check return an invalid response code"
}
return ""
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_router
package router
import (
"net/http"
@@ -50,7 +50,7 @@ type Headers interface {
func NewHeaders() Headers {
return &headers{
head: make(http.Header, 0),
head: make(http.Header),
}
}
@@ -96,7 +96,7 @@ func (h headers) Handler(c *gin.Context) {
// It appends to any existing values associated with key.
func (h *headers) Add(key, value string) {
if h.head == nil {
h.head = make(http.Header, 0)
h.head = make(http.Header)
}
h.head.Add(key, value)
@@ -107,7 +107,7 @@ func (h *headers) Add(key, value string) {
// values associated with key.
func (h *headers) Set(key, value string) {
if h.head == nil {
h.head = make(http.Header, 0)
h.head = make(http.Header)
}
h.head.Set(key, value)
@@ -121,7 +121,7 @@ func (h *headers) Set(key, value string) {
// access the map directly.
func (h headers) Get(key string) string {
if h.head == nil {
h.head = make(http.Header, 0)
h.head = make(http.Header)
}
return h.head.Get(key)
@@ -130,7 +130,7 @@ func (h headers) Get(key string) string {
// Del deletes the values associated with key.
func (h *headers) Del(key string) {
if h.head == nil {
h.head = make(http.Header, 0)
h.head = make(http.Header)
}
h.head.Del(key)

View File

@@ -23,7 +23,7 @@
*
*/
package njs_router
package router
import (
"github.com/gin-gonic/gin"
@@ -68,7 +68,7 @@ func RoutersHandler(engine *gin.Engine) {
func NewRouterList() RouterList {
return &routerList{
list: make(map[string][]routerItem, 0),
list: make(map[string][]routerItem),
}
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_router
package router
import (
"net/http"
@@ -38,16 +38,6 @@ func init() {
}
}
//Compatibility
// @TODO: clean this func
// deprecated
// SetGinHnadler func that return given func as ginTonic HandlerFunc interface type
// use SetGinHandler instead of SetGinHnadler
func SetGinHnadler(fct func(c *gin.Context)) gin.HandlerFunc {
return SetGinHandler(fct)
}
// SetGinHandler func that return given func as ginTonic HandlerFunc interface type
func SetGinHandler(fct func(c *gin.Context)) gin.HandlerFunc {
return fct

View File

@@ -23,7 +23,7 @@
*
*/
package njs_semaphore
package semaphore
import (
"context"

View File

@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2019 Nicolas JUHEL
* 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
@@ -21,27 +21,32 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package njs_errors
package semaphore
import "fmt"
import errors "github.com/nabbar/golib/errors"
type ErrorType string
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Semaphore
NEW_WORKER
WAITALL
)
const ERR_UNKNOWN ErrorType = "unknown error"
// String return the string form of the current ErrorType
func (e ErrorType) String() string {
return string(e)
func init() {
errors.RegisterFctMessage(getMessage)
}
// Error return an error type of the current ErrorType
// If an origin error is given (and not nil), this origin error will be append of the string (comma separated)
func (e ErrorType) Error(origin error) error {
if origin != nil {
return fmt.Errorf("%s, %v", e.String(), origin)
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case NEW_WORKER:
return "error on acquire one new semaphore worker"
case WAITALL:
return "error on acquire to wait all pending thread"
}
return fmt.Errorf("%s", e.String())
return ""
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_semaphore
package semaphore
import (
"context"
@@ -31,6 +31,8 @@ import (
"time"
"golang.org/x/sync/semaphore"
. "github.com/nabbar/golib/errors"
)
type sem struct {
@@ -41,12 +43,12 @@ type sem struct {
}
type Sem interface {
NewWorker() error
NewWorker() Error
NewWorkerTry() bool
DeferWorker()
DeferMain()
WaitAll() error
WaitAll() Error
Context() context.Context
Cancel()
}
@@ -70,20 +72,18 @@ func NewSemaphore(maxSimultaneous int, timeout time.Duration, deadline time.Time
}
}
func (s *sem) NewWorker() error {
if e := s.s.Acquire(s.x, 1); e != nil {
return e
}
return nil
func (s *sem) NewWorker() Error {
e := s.s.Acquire(s.x, 1)
return NEW_WORKER.Iferror(e)
}
func (s *sem) NewWorkerTry() bool {
return s.s.TryAcquire(1)
}
func (s *sem) WaitAll() error {
return s.s.Acquire(s.Context(), s.m)
func (s *sem) WaitAll() Error {
e := s.s.Acquire(s.Context(), s.m)
return WAITALL.Iferror(e)
}
func (s *sem) DeferWorker() {
@@ -102,6 +102,7 @@ func (s *sem) Cancel() {
func (s *sem) Context() context.Context {
if s.x == nil {
s.x, s.c = GetContext(0, GetEmptyTime(), nil)
}
return s.x

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_smtp
package smtp
import (
"net/mail"

View File

@@ -22,13 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_smtp
package smtp
import (
"bytes"
"io/ioutil"
"net/http"
"os"
. "github.com/nabbar/golib/errors"
)
type attachment struct {
@@ -86,15 +88,15 @@ func NewAttachment(name string) Attachment {
}
}
func NewAttachmentFile(name string, filepath string) (Attachment, error) {
func NewAttachmentFile(name string, filepath string) (Attachment, Error) {
var b = bytes.NewBuffer([]byte{})
if _, e := os.Stat(filepath); e != nil {
return nil, e
return nil, FILE_STAT.ErrorParent(e)
}
if bb, e := ioutil.ReadFile(filepath); e != nil {
return nil, e
return nil, FILE_READ.ErrorParent(e)
} else {
b.Write(bb)
}

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_smtp
package smtp
import (
"bytes"
@@ -34,8 +34,9 @@ import (
"strconv"
"strings"
njs_certif "github.com/nabbar/golib/njs-certif"
. "github.com/nabbar/golib/njs-logger"
njs_certif "github.com/nabbar/golib/certificates"
. "github.com/nabbar/golib/errors"
)
type smtpConfig struct {
@@ -58,9 +59,9 @@ type smtpClient struct {
}
type SMTP interface {
Client() (*smtp.Client, error)
Client() (*smtp.Client, Error)
Close()
Check() error
Check() Error
Clone() SMTP
ForceHost(host string)
@@ -141,7 +142,7 @@ func (n NETMode) string() string {
}
// ParseDSN parses the DSN string to a Config
func newSMTPConfig(dsn string) (*smtpConfig, error) {
func newSMTPConfig(dsn string) (*smtpConfig, Error) {
var (
smtpcnf = &smtpConfig{
DSN: dsn,
@@ -191,9 +192,9 @@ func newSMTPConfig(dsn string) (*smtpConfig, error) {
// dsn[i-1] must be == ')' if an address is specified
if dsn[i-1] != ')' {
if strings.ContainsRune(dsn[k+1:i], ')') {
return nil, fmt.Errorf("invalid DSN: did you forget to escape a param value")
return nil, CONFIG_INVALID_DSN.Error(nil)
}
return nil, fmt.Errorf("invalid DSN: network address not terminated (missing closing brace)")
return nil, CONFIG_INVALID_NETWORK.Error(nil)
}
if strings.ContainsRune(dsn[k+1:i-1], ':') {
@@ -225,7 +226,7 @@ func newSMTPConfig(dsn string) (*smtpConfig, error) {
if dsn[j] == '?' {
if val, err := url.ParseQuery(dsn[j+1:]); err != nil {
return nil, err
return nil, CONFIG_INVALID_PARAMS.ErrorParent(err)
} else {
if val.Get("ServerName") != "" {
@@ -250,7 +251,7 @@ func newSMTPConfig(dsn string) (*smtpConfig, error) {
}
if !foundSlash && len(dsn) > 0 {
return nil, fmt.Errorf("invalid DSN: missing the slash ending the host")
return nil, CONFIG_INVALID_HOST.Error(nil)
}
return smtpcnf, nil
@@ -261,7 +262,7 @@ func newSMTPConfig(dsn string) (*smtpConfig, error) {
// - params available are : ServerName (string), SkipVerify (boolean)
// - tls mode acceptable are : starttls, tls, <any other value to no tls/startls>
// - net aceeptable are : tcp4, tcp6, unix
func NewSMTP(dsn string, tlsConfig *tls.Config) (SMTP, error) {
func NewSMTP(dsn string, tlsConfig *tls.Config) (SMTP, Error) {
if tlsConfig == nil {
tlsConfig = njs_certif.GetTLSConfig("")
}
@@ -277,7 +278,7 @@ func NewSMTP(dsn string, tlsConfig *tls.Config) (SMTP, error) {
}
// Client Get SMTP Client interface
func (s *smtpClient) Client() (*smtp.Client, error) {
func (s *smtpClient) Client() (*smtp.Client, Error) {
if s.cli == nil {
var (
err error
@@ -299,35 +300,34 @@ func (s *smtpClient) Client() (*smtp.Client, error) {
if s.cfg.TLS == TLS_TLS {
s.con, err = tls.Dial(s.cfg.Net.string(), addr, tlsc)
if ErrorLevel.LogErrorCtxf(DebugLevel, "trying to intialize SMTP '%s' over tls connection to '%s'", err, s.cfg.Net.string(), addr) {
if err != nil {
s.cfg.TLS = TLS_STARTTLS
err = nil
}
}
if s.cfg.TLS != TLS_TLS {
s.con, err = net.Dial(s.cfg.Net.string(), addr)
if ErrorLevel.LogErrorCtxf(DebugLevel, "Dial initiated to server '%s' over '%s'", err, addr, s.cfg.Net.string()) {
return nil, err
if err != nil {
return nil, SMTP_DIAL.ErrorParent(err)
}
}
s.cli, err = smtp.NewClient(s.con, addr)
if ErrorLevel.LogErrorCtxf(DebugLevel, "SMTP Client initiated to server '%s' over '%s'", err, addr, s.cfg.Net.string()) {
return nil, err
if err != nil {
return nil, SMTP_CLIENT_INIT.ErrorParent(err)
}
if s.cfg.TLS == TLS_STARTTLS {
err = s.cli.StartTLS(tlsc)
if ErrorLevel.LogErrorCtxf(DebugLevel, "SMTP Client STARTTLS initiated to server '%s' over '%s'", err, addr, s.cfg.Net.string()) {
return nil, err
if err != nil {
return nil, SMTP_CLIENT_STARTTLS.ErrorParent(err)
}
}
if s.cfg.User != "" || s.cfg.Pass != "" {
err = s.cli.Auth(smtp.PlainAuth("", s.cfg.User, s.cfg.Pass, addr))
if ErrorLevel.LogErrorCtxf(DebugLevel, "SMTP Client authentificate user '%s' with server '%s' over '%s'", err, s.cfg.User, addr, s.cfg.Net.string()) {
return nil, err
if err != nil {
return nil, SMTP_CLIENT_AUTH.ErrorParent(err)
}
}
@@ -341,25 +341,25 @@ func (s *smtpClient) Client() (*smtp.Client, error) {
func (s *smtpClient) Close() {
if s.cli != nil {
if e := s.cli.Quit(); e != nil {
s.cli.Close()
_ = s.cli.Close()
}
s.cli = nil
}
if s.con != nil {
s.con.Close()
_ = s.con.Close()
s.con = nil
}
}
// Check Try to initiate SMTP dial and negotiation and try to close connection
func (s *smtpClient) Check() error {
func (s *smtpClient) Check() Error {
defer s.Close()
if c, e := s.Client(); e != nil {
return e
} else if e = c.Noop(); e != nil {
return e
} else if e := c.Noop(); e != nil {
return SMTP_CLIENT_NOOP.ErrorParent(e)
}
return nil

145
smtp/error.go Normal file
View File

@@ -0,0 +1,145 @@
/*
* 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 smtp
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_SMTP
FILE_STAT
FILE_READ
CONFIG_INVALID_DSN
CONFIG_INVALID_NETWORK
CONFIG_INVALID_PARAMS
CONFIG_INVALID_HOST
SMTP_DIAL
SMTP_SEND
SMTP_CLIENT_INIT
SMTP_CLIENT_STARTTLS
SMTP_CLIENT_AUTH
SMTP_CLIENT_NOOP
SMTP_CLIENT_MAIL
SMTP_CLIENT_RCPT
SMTP_CLIENT_DATA
SMTP_CLIENT_EMPTY
SMTP_CLIENT_SEND_RECOVERED
SMTP_CLIENT_FROM_EMPTY
SMTP_CLIENT_TO_EMPTY
SMTP_CLIENT_SUBJECT_EMPTY
SMTP_CLIENT_MAILER_EMPTY
RAND_READER
BUFFER_EMPTY
BUFFER_WRITE_STRING
BUFFER_WRITE_BYTES
IO_WRITER_MISSING
IO_WRITER_ERROR
EMPTY_HTML
EMPTY_CONTENTS
TEMPLATE_PARSING
TEMPLATE_EXECUTE
TEMPLATE_CLONE
TEMPLATE_HTML2TEXT
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case FILE_STAT:
return "error occurs on getting stat of file"
case FILE_READ:
return "error occurs on reading file"
case CONFIG_INVALID_DSN:
return "invalid DSN: did you forget to escape a param value"
case CONFIG_INVALID_NETWORK:
return "invalid DSN: network address not terminated (missing closing brace)"
case CONFIG_INVALID_PARAMS:
return "invalid DSN: parsing uri parameters occurs an error"
case CONFIG_INVALID_HOST:
return "invalid DSN: missing the slash ending the host"
case SMTP_DIAL:
return "error while trying to dial with SMTP server"
case SMTP_SEND:
return "error while sending mail to SMTP server"
case SMTP_CLIENT_INIT:
return "error while trying to initialize new client for dial connection to SMTP Server"
case SMTP_CLIENT_STARTTLS:
return "error while trying to starttls on SMTP server"
case SMTP_CLIENT_AUTH:
return "error while trying to authenticate to SMTP server"
case SMTP_CLIENT_NOOP:
return "error on sending noop command to check connection with SMTP server"
case SMTP_CLIENT_MAIL:
return "error on sending mail command to initialize new mail transaction with SMTP server"
case SMTP_CLIENT_RCPT:
return "error on sending rcpt command to specify add recipient email for the new mail"
case SMTP_CLIENT_DATA:
return "error on opening io writer to send data on client"
case SMTP_CLIENT_EMPTY:
return "cannot send email without any attachment and contents"
case SMTP_CLIENT_SEND_RECOVERED:
return "recovered error while client sending mail"
case SMTP_CLIENT_FROM_EMPTY:
return "sender From address cannot be empty"
case SMTP_CLIENT_TO_EMPTY:
return "list of recipient To address cannot be empty"
case SMTP_CLIENT_SUBJECT_EMPTY:
return "subject of the new mail cannot be empty"
case SMTP_CLIENT_MAILER_EMPTY:
return "mailer of the new mail cannot be empty"
case RAND_READER:
return "error on reading on random reader io"
case BUFFER_EMPTY:
return "buffer is empty"
case BUFFER_WRITE_STRING:
return "error on write string into buffer"
case BUFFER_WRITE_BYTES:
return "error on write bytes into buffer"
case IO_WRITER_MISSING:
return "io writer is not defined"
case IO_WRITER_ERROR:
return "error occur on write on io writer"
case EMPTY_HTML:
return "text/html content is empty"
case EMPTY_CONTENTS:
return "mail content is empty"
case TEMPLATE_PARSING:
return "error occur on parsing template"
case TEMPLATE_EXECUTE:
return "error occur on execute template"
case TEMPLATE_CLONE:
return "error occur while cloning template"
case TEMPLATE_HTML2TEXT:
return "error occur on reading io reader html and convert it to text"
}
return ""
}

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_smtp
package smtp
import (
"bytes"
@@ -31,6 +31,8 @@ import (
"fmt"
"io"
"net/smtp"
. "github.com/nabbar/golib/errors"
)
type ContentType uint8
@@ -63,14 +65,14 @@ type ioData struct {
b string
}
func (i *ioData) getBoundary() (string, error) {
func (i *ioData) getBoundary() (string, Error) {
if i.b == "" {
var buf [30]byte
_, err := io.ReadFull(rand.Reader, buf[:])
if err != nil {
return "", err
return "", RAND_READER.ErrorParent(err)
}
bnd := fmt.Sprintf("%x", buf[:])
@@ -85,11 +87,11 @@ func (i ioData) GetBuffer() *bytes.Buffer {
return i.p
}
func (i *ioData) CRLF() error {
func (i *ioData) CRLF() Error {
return i.String("\r\n")
}
func (i *ioData) ContentType(ct ContentType, charset string) error {
func (i *ioData) ContentType(ct ContentType, charset string) Error {
if charset != "" {
return i.Header("Content-Type", fmt.Sprintf("\"%s\"; charset=%s", ct.String(), charset))
} else {
@@ -97,7 +99,7 @@ func (i *ioData) ContentType(ct ContentType, charset string) error {
}
}
func (i *ioData) BoundaryStart(ct ContentType) error {
func (i *ioData) BoundaryStart(ct ContentType) Error {
if b, err := i.getBoundary(); err != nil {
return err
} else if err = i.Header("Content-Type", fmt.Sprintf("%s; boundary=\"%s\"", ct.String(), b)); err != nil {
@@ -107,7 +109,7 @@ func (i *ioData) BoundaryStart(ct ContentType) error {
}
}
func (i *ioData) BoundaryPart() error {
func (i *ioData) BoundaryPart() Error {
if i.b == "" {
return nil
}
@@ -121,7 +123,7 @@ func (i *ioData) BoundaryPart() error {
}
}
func (i *ioData) BoundaryEnd() error {
func (i *ioData) BoundaryEnd() Error {
if b, err := i.getBoundary(); err != nil {
return err
} else if err = i.CRLF(); err != nil {
@@ -133,23 +135,23 @@ func (i *ioData) BoundaryEnd() error {
}
}
func (i *ioData) Header(key, value string) error {
func (i *ioData) Header(key, value string) Error {
return i.String(fmt.Sprintf("%s: %s\r\n", key, value))
}
func (i *ioData) String(value string) error {
func (i *ioData) String(value string) Error {
if i.p == nil {
i.p = bytes.NewBuffer(make([]byte, 0))
}
if _, e := i.p.WriteString(value); e != nil {
return e
return BUFFER_WRITE_STRING.ErrorParent(e)
}
return nil
}
func (i *ioData) Bytes(value []byte) error {
func (i *ioData) Bytes(value []byte) Error {
if i.p == nil {
i.p = bytes.NewBuffer(make([]byte, 0))
}
@@ -161,7 +163,7 @@ func (i *ioData) Bytes(value []byte) error {
if (n+1)%76 == 0 {
if _, e := i.p.Write(tmp); e != nil {
return e
return BUFFER_WRITE_BYTES.ErrorParent(e)
} else if e := i.CRLF(); e != nil {
return e
}
@@ -172,7 +174,7 @@ func (i *ioData) Bytes(value []byte) error {
if len(tmp) != 0 {
if _, e := i.p.Write(tmp); e != nil {
return e
return BUFFER_WRITE_BYTES.ErrorParent(e)
} else if e := i.CRLF(); e != nil {
return e
}
@@ -181,28 +183,27 @@ func (i *ioData) Bytes(value []byte) error {
return nil
}
func (i *ioData) Send() error {
func (i *ioData) Send() Error {
if i.w == nil {
return fmt.Errorf("empty writer")
return IO_WRITER_MISSING.Error(nil)
}
if i.p == nil || i.p.Len() < 1 {
return fmt.Errorf("empty buffer")
return BUFFER_EMPTY.Error(nil)
}
if _, e := i.w.Write(i.p.Bytes()); e != nil {
return e
return IO_WRITER_ERROR.ErrorParent(e)
}
return nil
}
func (i *ioData) AttachmentStart(c ContentType) error {
func (i *ioData) AttachmentStart(c ContentType) Error {
return i.BoundaryStart(c)
}
func (i *ioData) AttachmentAddFile(contentType, attachmentName string, attachment *bytes.Buffer) error {
func (i *ioData) AttachmentAddFile(contentType, attachmentName string, attachment *bytes.Buffer) Error {
var (
e error
c = make([]byte, base64.StdEncoding.EncodedLen(attachment.Len()))
)
@@ -210,10 +211,10 @@ func (i *ioData) AttachmentAddFile(contentType, attachmentName string, attachmen
base64.StdEncoding.Encode(c, attachment.Bytes())
if len(c) < 1 {
return fmt.Errorf("encoded buffer is empty")
return BUFFER_EMPTY.Error(nil)
}
if e = i.BoundaryPart(); e != nil {
if e := i.BoundaryPart(); e != nil {
return e
} else if e = i.Header("Content-Type", contentType); e != nil {
return e
@@ -234,14 +235,14 @@ func (i *ioData) AttachmentAddFile(contentType, attachmentName string, attachmen
return nil
}
func (i *ioData) AttachmentAddBody(m MailTemplate, ct ContentType) error {
func (i *ioData) AttachmentAddBody(m MailTemplate, ct ContentType) Error {
var (
e error
e Error
p *bytes.Buffer
)
if m.IsEmpty() {
return fmt.Errorf("text/html content is empty")
return EMPTY_HTML.Error(nil)
}
switch ct {
@@ -280,7 +281,7 @@ func (i *ioData) AttachmentAddBody(m MailTemplate, ct ContentType) error {
return nil
}
func (i *ioData) AttachmentEnd() error {
func (i *ioData) AttachmentEnd() Error {
if e := i.BoundaryEnd(); e != nil {
return e
} else if e = i.BoundaryEnd(); e != nil {
@@ -291,24 +292,24 @@ func (i *ioData) AttachmentEnd() error {
}
type IOData interface {
ContentType(ct ContentType, charset string) error
Header(key, value string) error
String(value string) error
Bytes(value []byte) error
CRLF() error
ContentType(ct ContentType, charset string) Error
Header(key, value string) Error
String(value string) Error
Bytes(value []byte) Error
CRLF() Error
Send() error
Send() Error
GetBuffer() *bytes.Buffer
AttachmentStart(c ContentType) error
AttachmentAddFile(contentType, attachmentName string, attachment *bytes.Buffer) error
AttachmentAddBody(m MailTemplate, ct ContentType) error
AttachmentEnd() error
AttachmentStart(c ContentType) Error
AttachmentAddFile(contentType, attachmentName string, attachment *bytes.Buffer) Error
AttachmentAddBody(m MailTemplate, ct ContentType) Error
AttachmentEnd() Error
}
func NewIOData(cli *smtp.Client) (IOData, error) {
func NewIOData(cli *smtp.Client) (IOData, Error) {
if w, e := cli.Data(); e != nil {
return nil, e
return nil, SMTP_CLIENT_DATA.ErrorParent(e)
} else {
return &ioData{
w: w,

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_smtp
package smtp
import "strings"
@@ -99,7 +99,7 @@ func (lst listMailAddress) String() string {
}
func (lst listMailAddress) Clone() ListMailAddress {
var l = make(listMailAddress, 0)
var l = make(listMailAddress)
for _, a := range lst {
l.Add(a.Clone())
@@ -125,5 +125,5 @@ type ListMailAddress interface {
}
func NewListMailAddress() ListMailAddress {
return make(listMailAddress, 0)
return make(listMailAddress)
}

View File

@@ -1,4 +1,4 @@
package njs_smtp
package smtp
import (
"bytes"
@@ -6,9 +6,10 @@ import (
"io/ioutil"
"os"
"github.com/jaytaylor/html2text"
"github.com/olekukonko/tablewriter"
"github.com/jaytaylor/html2text"
. "github.com/nabbar/golib/errors"
)
type mailTemplate struct {
@@ -34,7 +35,7 @@ func (m mailTemplate) GetTextOption() html2text.Options {
return m.opt
}
func (m mailTemplate) GetBufferHtml(data interface{}) (*bytes.Buffer, error) {
func (m mailTemplate) GetBufferHtml(data interface{}) (*bytes.Buffer, Error) {
var res = bytes.NewBuffer(make([]byte, 0))
if data == nil {
@@ -42,30 +43,31 @@ func (m mailTemplate) GetBufferHtml(data interface{}) (*bytes.Buffer, error) {
}
if err := m.tpl.Execute(res, data); err != nil {
return nil, err
return nil, TEMPLATE_EXECUTE.ErrorParent(err)
}
return res, nil
}
func (m mailTemplate) GetBufferText(data interface{}) (*bytes.Buffer, error) {
func (m mailTemplate) GetBufferText(data interface{}) (*bytes.Buffer, Error) {
var (
res = bytes.NewBuffer(make([]byte, 0))
str string
e error
)
if buf, err := m.GetBufferHtml(data); err != nil {
return nil, err
} else if str, err = html2text.FromReader(buf, m.opt); err != nil {
return nil, err
} else if _, err = res.WriteString(str); err != nil {
return nil, err
} else if str, e = html2text.FromReader(buf, m.opt); e != nil {
return nil, TEMPLATE_HTML2TEXT.ErrorParent(e)
} else if _, e = res.WriteString(str); e != nil {
return nil, BUFFER_WRITE_STRING.ErrorParent(e)
}
return res, nil
}
func (m mailTemplate) GetBufferRich(data interface{}) (*bytes.Buffer, error) {
func (m mailTemplate) GetBufferRich(data interface{}) (*bytes.Buffer, Error) {
panic("implement me")
}
@@ -85,7 +87,7 @@ func (m mailTemplate) IsEmpty() bool {
return false
}
func (m mailTemplate) Clone() (MailTemplate, error) {
func (m mailTemplate) Clone() (MailTemplate, Error) {
res := &mailTemplate{
data: nil,
char: m.char,
@@ -94,7 +96,7 @@ func (m mailTemplate) Clone() (MailTemplate, error) {
}
if tpl, err := m.tpl.Clone(); err != nil {
return nil, err
return nil, TEMPLATE_CLONE.ErrorParent(err)
} else {
res.tpl = tpl
}
@@ -103,7 +105,7 @@ func (m mailTemplate) Clone() (MailTemplate, error) {
}
type MailTemplate interface {
Clone() (MailTemplate, error)
Clone() (MailTemplate, Error)
IsEmpty() bool
@@ -113,14 +115,14 @@ type MailTemplate interface {
SetTextOption(opt html2text.Options)
GetTextOption() html2text.Options
GetBufferHtml(data interface{}) (*bytes.Buffer, error)
GetBufferText(data interface{}) (*bytes.Buffer, error)
GetBufferRich(data interface{}) (*bytes.Buffer, error)
GetBufferHtml(data interface{}) (*bytes.Buffer, Error)
GetBufferText(data interface{}) (*bytes.Buffer, Error)
GetBufferRich(data interface{}) (*bytes.Buffer, Error)
RegisterData(data interface{})
}
func NewMailTemplate(name, tpl string, isFile bool) (MailTemplate, error) {
func NewMailTemplate(name, tpl string, isFile bool) (MailTemplate, Error) {
var (
err error
res = &mailTemplate{
@@ -154,17 +156,17 @@ func NewMailTemplate(name, tpl string, isFile bool) (MailTemplate, error) {
if isFile {
var fs []byte
if _, err = os.Stat(tpl); err != nil {
return nil, err
return nil, FILE_STAT.ErrorParent(err)
} else if fs, err = ioutil.ReadFile(tpl); err != nil {
return nil, err
return nil, FILE_READ.ErrorParent(err)
}
tpl = string(fs)
}
if res.tpl, err = res.tpl.Parse(tpl); err != nil {
return nil, err
return nil, TEMPLATE_PARSING.ErrorParent(err)
}
return res, err
return res, nil
}

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_smtp
package smtp
import (
"bytes"
@@ -31,7 +31,9 @@ import (
"net/smtp"
"time"
njs_version "github.com/nabbar/golib/njs-version"
vers "github.com/nabbar/golib/version"
. "github.com/nabbar/golib/errors"
)
type sendmail struct {
@@ -136,7 +138,7 @@ func (s *sendmail) SetMailer(mailer string) {
s.mailer = mailer
}
func (s *sendmail) NJSMailer(version njs_version.Version) {
func (s *sendmail) NJSMailer(version vers.Version) {
s.mailer = version.GetHeader()
}
@@ -144,7 +146,7 @@ func (s *sendmail) SetTestMode(enable bool) {
s.testMode = enable
}
func (s sendmail) Clone() (SendMail, error) {
func (s sendmail) Clone() (SendMail, Error) {
var (
la = make([]Attachment, 0)
)
@@ -208,42 +210,43 @@ func (s sendmail) Clone() (SendMail, error) {
return res, nil
}
func (s sendmail) SendSMTP(cli SMTP) (err error, buff *bytes.Buffer) {
var c *smtp.Client
func (s sendmail) SendSMTP(cli SMTP) (err Error, buff *bytes.Buffer) {
var (
e error
c *smtp.Client
)
defer func(cli *smtp.Client) {
if cli != nil {
cli.Quit()
cli.Close()
_ = cli.Quit()
_ = cli.Close()
}
}(c)
if c, err = cli.Client(); err != nil {
return
} else if err, buff = s.Send(c); err != nil {
c.Reset()
return err, buff
} else if e, buff = s.Send(c); e != nil {
_ = c.Reset()
return SMTP_SEND.ErrorParent(e), buff
} else {
return
}
}
func (s sendmail) Send(cli *smtp.Client) (err error, buff *bytes.Buffer) {
func (s sendmail) Send(cli *smtp.Client) (err Error, buff *bytes.Buffer) {
var (
iod IOData
)
defer func() {
if r := recover(); r != nil && err != nil {
err = fmt.Errorf("%v, %v", err, r)
} else if r != nil {
err = fmt.Errorf("%v", r)
if r := recover(); r != nil {
err = SMTP_CLIENT_SEND_RECOVERED.ErrorParent(err, fmt.Errorf("%v", r))
}
if cli != nil {
cli.Reset()
cli.Quit()
cli.Close()
_ = cli.Reset()
_ = cli.Quit()
_ = cli.Close()
}
}()
@@ -260,38 +263,44 @@ func (s sendmail) Send(cli *smtp.Client) (err error, buff *bytes.Buffer) {
} else if s.msgText.Len() > 0 {
ctBody = CONTENTTYPE_TEXT
} else {
return fmt.Errorf("no attachment & no contents"), nil
return SMTP_CLIENT_EMPTY.Error(nil), nil
}
if len(s.from.AddressOnly()) < 7 {
return fmt.Errorf("from address is empty"), nil
return SMTP_CLIENT_FROM_EMPTY.Error(nil), nil
}
if err = cli.Noop(); err != nil {
if e := cli.Noop(); e != nil {
err = SMTP_CLIENT_NOOP.ErrorParent(e)
return
}
if err = cli.Mail(s.from.String()); err != nil {
if e := cli.Mail(s.from.String()); e != nil {
err = SMTP_CLIENT_MAIL.ErrorParent(e)
return
}
if s.testMode {
if err = cli.Rcpt(s.from.String()); err != nil {
if e := cli.Rcpt(s.from.String()); e != nil {
err = SMTP_CLIENT_RCPT.ErrorParent(e)
return
}
} else {
for _, a := range s.to.Slice() {
if err = cli.Rcpt(a.String()); err != nil {
if e := cli.Rcpt(a.String()); e != nil {
err = SMTP_CLIENT_RCPT.ErrorParent(e)
return
}
}
for _, a := range s.cc.Slice() {
if err = cli.Rcpt(a.String()); err != nil {
if e := cli.Rcpt(a.String()); e != nil {
err = SMTP_CLIENT_RCPT.ErrorParent(e)
return
}
}
for _, a := range s.bcc.Slice() {
if err = cli.Rcpt(a.String()); err != nil {
if e := cli.Rcpt(a.String()); e != nil {
err = SMTP_CLIENT_RCPT.ErrorParent(e)
return
}
}
@@ -306,7 +315,7 @@ func (s sendmail) Send(cli *smtp.Client) (err error, buff *bytes.Buffer) {
}
if s.to.IsEmpty() {
return fmt.Errorf("to address is empty"), nil
return SMTP_CLIENT_TO_EMPTY.Error(nil), nil
} else if err = iod.Header("To", s.to.String()); err != nil {
return
}
@@ -334,7 +343,7 @@ func (s sendmail) Send(cli *smtp.Client) (err error, buff *bytes.Buffer) {
}
if len(s.subject) < 1 {
return fmt.Errorf("subjetc is empty"), nil
return SMTP_CLIENT_SUBJECT_EMPTY.Error(nil), nil
} else {
var (
b = []byte(s.subject)
@@ -349,7 +358,7 @@ func (s sendmail) Send(cli *smtp.Client) (err error, buff *bytes.Buffer) {
}
if len(s.mailer) < 1 {
return fmt.Errorf("mailer is empty"), nil
return SMTP_CLIENT_MAILER_EMPTY.Error(nil), nil
} else {
if err = iod.Header("X-Mailer", s.mailer); err != nil {
return
@@ -376,13 +385,13 @@ func (s sendmail) Send(cli *smtp.Client) (err error, buff *bytes.Buffer) {
return
}
} else if s.msgHtml.IsEmpty() {
return fmt.Errorf("empty content mail"), nil
return EMPTY_CONTENTS.Error(nil), nil
} else if err = iod.AttachmentAddBody(s.msgHtml, CONTENTTYPE_TEXT); err != nil {
return
}
} else if ctBody == CONTENTTYPE_HTML {
if s.msgHtml.IsEmpty() {
return fmt.Errorf("empty content mail"), nil
return EMPTY_CONTENTS.Error(nil), nil
} else if err = iod.AttachmentAddBody(s.msgHtml, CONTENTTYPE_HTML); err != nil {
return
}
@@ -442,13 +451,13 @@ type SendMail interface {
SetMessageId(id string)
SetMailer(mailer string)
NJSMailer(version njs_version.Version)
NJSMailer(version vers.Version)
SetTestMode(enable bool)
Clone() (SendMail, error)
Send(cli *smtp.Client) (err error, buff *bytes.Buffer)
SendSMTP(cli SMTP) (err error, buff *bytes.Buffer)
Clone() (SendMail, Error)
Send(cli *smtp.Client) (err Error, buff *bytes.Buffer)
SendSMTP(cli SMTP) (err Error, buff *bytes.Buffer)
}
func NewSendMail() SendMail {

58
static/error.go Normal file
View File

@@ -0,0 +1,58 @@
/*
* 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 static
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Static
EMPTY_PACKED
INDEX_NOT_FOUND
INDEX_REQUESTED_NOT_SET
FILE_NOT_FOUND
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case EMPTY_PACKED:
return "packed file is empty"
case INDEX_NOT_FOUND:
return "mode index is defined but index.(html|htm) is not found"
case INDEX_REQUESTED_NOT_SET:
return "request call index but mode index is false"
case FILE_NOT_FOUND:
return "requested packed file is not found"
}
return ""
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_static
package static
import (
"bytes"
@@ -33,14 +33,14 @@ import (
"path/filepath"
"strings"
njs_router "github.com/nabbar/golib/njs-router"
"github.com/gin-gonic/gin/render"
njs_logger "github.com/nabbar/golib/njs-logger"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/render"
"github.com/gobuffalo/packr"
. "github.com/nabbar/golib/errors"
. "github.com/nabbar/golib/logger"
njs_router "github.com/nabbar/golib/router"
)
const (
@@ -64,11 +64,11 @@ type Static interface {
SetDownloadAll()
SetDownload(file string)
IsDownload(file string) bool
Has(file string) bool
Find(file string) ([]byte, error)
Health() error
Health() Error
Get(c *gin.Context)
}
@@ -119,21 +119,21 @@ func (s staticHandler) print() {
}
for _, f := range s.box.List() {
njs_logger.DebugLevel.Logf("Embedded file : %s", f)
DebugLevel.Logf("Embedded file : %s", f)
}
s.debug = true
}
func (s staticHandler) Health() error {
func (s staticHandler) Health() Error {
s.print()
if len(s.box.List()) < 1 {
return fmt.Errorf("empty packed file stored")
return EMPTY_PACKED.Error(nil)
}
if s.index && !s.box.Has("index.html") && !s.box.Has("index.htm") {
return fmt.Errorf("cannot find 'index.html' file")
return INDEX_NOT_FOUND.Error(nil)
}
return nil
@@ -160,12 +160,12 @@ func (s staticHandler) Get(c *gin.Context) {
calledFile = FileIndex
requestPath = FileIndex
} else {
c.Abort()
_ = c.AbortWithError(http.StatusNotFound, INDEX_REQUESTED_NOT_SET.Error(nil))
return
}
}
if obj, err := s.box.Find(requestPath); !njs_logger.ErrorLevel.LogErrorCtxf(njs_logger.NilLevel, "find file '%s' error for request '%s%s' :", err, calledFile, s.prefix, requestPath) {
if obj, err := s.box.Find(requestPath); !ErrorLevel.LogErrorCtxf(DebugLevel, "find file '%s' error for request '%s%s' :", err, calledFile, s.prefix, requestPath) {
head := s.head()
if s.allDwnld || s.IsDownload(requestPath) {
@@ -179,7 +179,7 @@ func (s staticHandler) Get(c *gin.Context) {
Reader: bytes.NewReader(obj),
})
} else {
c.Abort()
_ = c.AbortWithError(http.StatusNotFound, FILE_NOT_FOUND.Error(nil))
}
}

View File

@@ -23,7 +23,7 @@
*
*/
package njs_status
package status
import (
"fmt"
@@ -31,13 +31,15 @@ import (
"path"
"strings"
njs_router "github.com/nabbar/golib/njs-router"
njs_router "github.com/nabbar/golib/router"
njs_version "github.com/nabbar/golib/njs-version"
njs_version "github.com/nabbar/golib/version"
"github.com/gin-gonic/gin"
)
// @TODO : see compliant with https://tools.ietf.org/html/draft-inadarei-api-health-check-02
type StatusItemResponse struct {
Name string
Status string
@@ -48,7 +50,7 @@ type StatusItemResponse struct {
type StatusResponse struct {
StatusItemResponse
Partner []StatusItemResponse
Component []StatusItemResponse
}
const statusOK = "OK"
@@ -63,7 +65,7 @@ type statusItem struct {
release string
}
type statusPartner struct {
type statusComponent struct {
statusItem
WarnIfErr bool
later *initLater
@@ -71,8 +73,8 @@ type statusPartner struct {
type mainPackage struct {
statusItem
ptn []statusPartner
header func(c *gin.Context)
cpt []statusComponent
header gin.HandlerFunc
later *initLater
init bool
}
@@ -87,18 +89,18 @@ type initLater struct {
type Status interface {
Register(prefix string, register njs_router.RegisterRouter)
AddPartner(name, msgOK, msgKO, release, build string, WarnIfError bool, health func() error)
AddVersionPartner(vers njs_version.Version, msgOK, msgKO string, WarnIfError bool, health func() error)
AddComponent(name, msgOK, msgKO, release, build string, WarnIfError bool, health func() error)
AddVersionComponent(vers njs_version.Version, msgOK, msgKO string, WarnIfError bool, health func() error)
LaterAddPartner(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, WarnIfError bool)
LaterAddVersionPartner(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, WarnIfError bool)
LaterAddComponent(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, WarnIfError bool)
LaterAddVersionComponent(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, WarnIfError bool)
Get(c *gin.Context)
}
func NewStatusLater(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, Header func(c *gin.Context)) Status {
func NewStatusLater(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, Header gin.HandlerFunc) Status {
return &mainPackage{
ptn: make([]statusPartner, 0),
cpt: make([]statusComponent, 0),
header: Header,
later: &initLater{
version: nil,
@@ -110,19 +112,19 @@ func NewStatusLater(info func() (name, release, build string), msg func() (ok st
}
}
func NewStatus(name, msgOK, msgKO, release, build string, health func() error, Header func(c *gin.Context)) Status {
func NewStatus(name, msgOK, msgKO, release, build string, health func() error, Header gin.HandlerFunc) Status {
return &mainPackage{
statusItem: newItem(name, msgOK, msgKO, release, build, health),
ptn: make([]statusPartner, 0),
cpt: make([]statusComponent, 0),
header: Header,
later: nil,
init: false,
}
}
func NewVersionStatusLater(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, Header func(c *gin.Context)) Status {
func NewVersionStatusLater(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, Header gin.HandlerFunc) Status {
return &mainPackage{
ptn: make([]statusPartner, 0),
cpt: make([]statusComponent, 0),
header: Header,
later: &initLater{
version: vers,
@@ -134,7 +136,7 @@ func NewVersionStatusLater(vers func() njs_version.Version, msg func() (ok strin
}
}
func NewVersionStatus(vers njs_version.Version, msgOK, msgKO string, health func() error, Header func(c *gin.Context)) Status {
func NewVersionStatus(vers njs_version.Version, msgOK, msgKO string, health func() error, Header gin.HandlerFunc) Status {
return NewStatus(vers.GetPackage(), msgOK, msgKO, vers.GetRelease(), vers.GetBuild(), health, Header)
}
@@ -149,16 +151,16 @@ func newItem(name, msgOK, msgKO, release, build string, health func() error) sta
}
}
func (p *mainPackage) AddPartner(name, msgOK, msgKO, release, build string, WarnIfError bool, health func() error) {
p.ptn = append(p.ptn, statusPartner{
func (p *mainPackage) AddComponent(name, msgOK, msgKO, release, build string, WarnIfError bool, health func() error) {
p.cpt = append(p.cpt, statusComponent{
statusItem: newItem(name, msgOK, msgKO, release, build, health),
WarnIfErr: WarnIfError,
later: nil,
})
}
func (p *mainPackage) LaterAddPartner(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, WarnIfError bool) {
p.ptn = append(p.ptn, statusPartner{
func (p *mainPackage) LaterAddComponent(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, WarnIfError bool) {
p.cpt = append(p.cpt, statusComponent{
WarnIfErr: WarnIfError,
later: &initLater{
version: nil,
@@ -169,12 +171,12 @@ func (p *mainPackage) LaterAddPartner(info func() (name, release, build string),
})
}
func (p *mainPackage) AddVersionPartner(vers njs_version.Version, msgOK, msgKO string, WarnIfError bool, health func() error) {
p.AddPartner(vers.GetPackage(), msgOK, msgKO, vers.GetRelease(), vers.GetBuild(), WarnIfError, health)
func (p *mainPackage) AddVersionComponent(vers njs_version.Version, msgOK, msgKO string, WarnIfError bool, health func() error) {
p.AddComponent(vers.GetPackage(), msgOK, msgKO, vers.GetRelease(), vers.GetBuild(), WarnIfError, health)
}
func (p *mainPackage) LaterAddVersionPartner(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, WarnIfError bool) {
p.ptn = append(p.ptn, statusPartner{
func (p *mainPackage) LaterAddVersionComponent(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, WarnIfError bool) {
p.cpt = append(p.cpt, statusComponent{
WarnIfErr: WarnIfError,
later: &initLater{
version: vers,
@@ -204,14 +206,14 @@ func (p *mainPackage) initStatus() {
p.later = nil
}
var ptn = make([]statusPartner, 0)
var cpt = make([]statusComponent, 0)
for _, part := range p.ptn {
for _, part := range p.cpt {
if part.later != nil {
if part.later.info != nil {
name, release, build := part.later.info()
ok, ko := part.later.msg()
part = statusPartner{
part = statusComponent{
statusItem: newItem(name, ok, ko, release, build, part.health),
WarnIfErr: part.WarnIfErr,
later: nil,
@@ -219,7 +221,7 @@ func (p *mainPackage) initStatus() {
} else if p.later.version != nil {
v := p.later.version()
ok, ko := p.later.msg()
part = statusPartner{
part = statusComponent{
statusItem: newItem(v.GetPackage(), ok, ko, v.GetRelease(), v.GetBuild(), part.health),
WarnIfErr: part.WarnIfErr,
later: nil,
@@ -231,11 +233,11 @@ func (p *mainPackage) initStatus() {
}
}
ptn = append(ptn, part)
cpt = append(cpt, part)
}
p.init = true
p.ptn = ptn
p.cpt = cpt
}
func (p *mainPackage) cleanPrefix(prefix string) string {
@@ -302,20 +304,20 @@ func (p *mainPackage) Get(c *gin.Context) {
make([]StatusItemResponse, 0),
}
for _, pkg := range p.ptn {
for _, pkg := range p.cpt {
pres := pkg.GetStatusResponse(c)
if res.Status == statusOK && pres.Status == statusKO && !pkg.WarnIfErr {
res.Status = statusKO
} else if pres.Status == statusKO {
hasError = true
}
res.Partner = append(res.Partner, pres)
res.Component = append(res.Component, pres)
}
if res.Status != statusOK {
c.AbortWithStatusJSON(http.StatusInternalServerError, &res)
} else if hasError {
c.JSON(http.StatusMultiStatus, &res)
c.JSON(http.StatusAccepted, &res)
} else {
c.JSON(http.StatusOK, &res)
}

View File

@@ -30,16 +30,16 @@ import (
"io/ioutil"
"os"
njs_archive "github.com/nabbar/golib/njs-archive"
njs_archive "github.com/nabbar/golib/archive"
iou "github.com/nabbar/golib/njs-ioutils"
iou "github.com/nabbar/golib/ioutils"
)
// git archive --format=tar --output=git.tar HEAD
//const fileName = "./git.tar"
const fileName = "./vendor.zip"
//const contain = "njs-version/license_mit.go"
//const contain = "version/license_mit.go"
const contain = "vendor/github.com/gin-gonic/gin/internal/json/json.go"
//const regex = ""
@@ -57,13 +57,17 @@ func main() {
panic(err)
}
defer src.Close()
defer func() {
_ = src.Close()
}()
if tmp, err = iou.NewTempFile(); err != nil {
panic(err)
}
defer iou.DelTempFile(tmp, true)
defer func() {
_ = iou.DelTempFile(tmp)
}()
if _, err = io.Copy(tmp, src); err != nil {
panic(err)
@@ -73,7 +77,9 @@ func main() {
panic(err)
}
defer rio.Close()
defer func() {
_ = rio.Close()
}()
if _, err = rio.Seek(0, 0); err != nil {
panic(err)

View File

@@ -29,21 +29,21 @@ import (
"math/rand"
"time"
njs_progress "github.com/nabbar/golib/njs-progress"
npb "github.com/nabbar/golib/progress"
"github.com/vbauerster/mpb/v5"
)
var (
pb njs_progress.ProgressBar
br njs_progress.Bar
pb npb.ProgressBar
br npb.Bar
)
func main() {
println("Starting...")
pb = njs_progress.NewProgressBar(0, time.Time{}, nil, mpb.WithWidth(64))
pb = npb.NewProgressBar(0, time.Time{}, nil, mpb.WithWidth(64))
pb.SetSemaphoreOption(0, 0)
br = pb.NewBarSimple("test bar")
br = pb.NewBarSimpleETA("test bar")
defer br.DeferMain(false)

101
test/test-smtp/main.go Normal file
View File

@@ -0,0 +1,101 @@
package main
import (
"bytes"
"crypto/tls"
"fmt"
"github.com/jaytaylor/html2text"
"github.com/olekukonko/tablewriter"
"github.com/nabbar/golib/logger"
"github.com/nabbar/golib/smtp"
)
const (
CONFIG_SMTP_DSN = "user@example.com:test_password@tcp4(mail.example.com:25)/starttls?ServerName=mail.example.com"
CONFIG_EMAIL_FROM = "sender@example.com"
CONFIG_EMAIL_TO = "recipient@example.com"
CONFIG_MAILER = "Nabbar SMTP Tester"
CONFIG_SUBJECT = "Testing Send Mail"
CONFIG_TESTMODE = false
CONFIG_TEMPLATE_TEST = `<html><head></head><body><b>Hello {{.Name}}</b>, this is a test e-mail sent by <i>Go</i> with package nabbar/golib/smtp.</body></html>`
)
func main() {
var (
cfg smtp.SMTP
tpl smtp.MailTemplate
snd smtp.SendMail
err error
buff = bytes.NewBuffer(make([]byte, 0))
)
logger.EnableColor()
logger.AddGID(true)
logger.FileTrace(true)
logger.SetFormat(logger.TextFormat)
logger.SetLevel(logger.DebugLevel)
tpl, err = smtp.NewMailTemplate("mail", CONFIG_TEMPLATE_TEST, false)
logger.FatalLevel.LogErrorCtxf(logger.InfoLevel, "mail template parsing", err)
tpl.SetCharset("utf-8")
tpl.RegisterData(struct {
Name string
}{Name: "éloïse"})
tpl.SetTextOption(html2text.Options{
PrettyTables: true,
PrettyTablesOptions: &html2text.PrettyTablesOptions{
AutoFormatHeader: true,
AutoWrapText: true,
ReflowDuringAutoWrap: true,
ColWidth: tablewriter.MAX_ROW_WIDTH,
ColumnSeparator: tablewriter.COLUMN,
RowSeparator: tablewriter.ROW,
CenterSeparator: tablewriter.CENTER,
HeaderAlignment: tablewriter.ALIGN_DEFAULT,
FooterAlignment: tablewriter.ALIGN_DEFAULT,
Alignment: tablewriter.ALIGN_DEFAULT,
ColumnAlignment: []int{},
NewLine: tablewriter.NEWLINE,
HeaderLine: true,
RowLine: false,
AutoMergeCells: false,
Borders: tablewriter.Border{Left: true, Right: true, Bottom: true, Top: true},
},
OmitLinks: true,
})
if p, e := tpl.GetBufferHtml(nil); e == nil {
fmt.Printf("\n\n\n\t >> HTML Mail : \n")
print(p.String())
fmt.Printf("\n\n")
}
if p, e := tpl.GetBufferText(nil); e == nil {
fmt.Printf("\n\n\n\t >> Text Mail : \n")
print(p.String())
fmt.Printf("\n\n")
}
snd = smtp.NewSendMail()
snd.SetTo(smtp.MailAddressParser(CONFIG_EMAIL_TO))
snd.SetFrom(smtp.MailAddressParser(CONFIG_EMAIL_FROM))
snd.SetMailer(CONFIG_MAILER)
snd.SetSubject(CONFIG_SUBJECT)
snd.SetTestMode(CONFIG_TESTMODE)
snd.SetForceOnly(smtp.CONTENTTYPE_HTML)
snd.SetHtml(tpl)
cfg, err = smtp.NewSMTP(CONFIG_SMTP_DSN, &tls.Config{})
logger.FatalLevel.LogErrorCtxf(logger.InfoLevel, "smtp config parsing", err)
logger.FatalLevel.LogErrorCtxf(logger.InfoLevel, "smtp checking working", cfg.Check())
err, buff = snd.SendSMTP(cfg)
logger.FatalLevel.LogErrorCtxf(logger.InfoLevel, "Sending Mail", err)
fmt.Printf("\n\n\n\t >> Buff Mail : \n")
print(buff.String())
fmt.Printf("\n\n")
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"os"
njs_ioutils "github.com/nabbar/golib/njs-ioutils"
njs_ioutils "github.com/nabbar/golib/ioutils"
)
func main() {

55
version/error.go Normal file
View File

@@ -0,0 +1,55 @@
/*
* 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 version
import errors "github.com/nabbar/golib/errors"
const (
EMPTY_PARAMS errors.CodeError = iota + errors.MIN_PKG_Version
GOVERSION_INIT
GOVERSION_RUNTIME
GOVERSION_CONTRAINT
)
func init() {
errors.RegisterFctMessage(getMessage)
}
func getMessage(code errors.CodeError) (message string) {
switch code {
case EMPTY_PARAMS:
return "given parameters is empty"
case GOVERSION_INIT:
return "init GoVersion contraint error"
case GOVERSION_RUNTIME:
return "extract GoVersion runtime error"
case GOVERSION_CONTRAINT:
return "current binary is build with a non-compatible version of Go"
}
return ""
}

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
import "fmt"

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func licence_agpl_v3() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func licence_apache2() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func license_cc_by_4() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func license_cc_sa_4() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func licence_cc0_v1() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func licence_gpl_v3() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func licence_lgpl_v3() string {
return `

View File

@@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package njs_version
package version
func license_mit() string {
return `

Some files were not shown because too many files have changed in this diff Show More