diff --git a/backend/go.mod b/backend/go.mod index 50675e1b..d3eb7127 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -17,6 +17,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/qri-io/jsonschema v0.2.1 + github.com/rotisserie/eris v0.5.4 github.com/stretchr/testify v1.7.0 github.com/vrischmann/envconfig v1.3.0 golang.org/x/crypto v0.5.0 diff --git a/backend/go.sum b/backend/go.sum index 4564dcc8..10f07f78 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -76,6 +76,8 @@ github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0= github.com/qri-io/jsonschema v0.2.1/go.mod h1:g7DPkiOsK1xv6T/Ao5scXRkd+yTFygcANPBaaqW+VrI= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk= +github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/backend/internal/acme/acmesh.go b/backend/internal/acme/acmesh.go index 397e72e9..6a9d313b 100644 --- a/backend/internal/acme/acmesh.go +++ b/backend/internal/acme/acmesh.go @@ -13,12 +13,14 @@ import ( "npm/internal/entity/certificateauthority" "npm/internal/entity/dnsprovider" "npm/internal/logger" + + "github.com/rotisserie/eris" ) func getAcmeShFilePath() (string, error) { path, err := exec.LookPath("acme.sh") if err != nil { - return path, fmt.Errorf("Cannot find acme.sh execuatable script in PATH") + return path, eris.Wrapf(err, "Cannot find acme.sh execuatable script in PATH") } return path, nil } @@ -107,7 +109,7 @@ func shExec(args []string, envs []string) (string, error) { b, e := c.CombinedOutput() if e != nil { - // logger.Error("AcmeShError", fmt.Errorf("Command error: %s -- %v\n%+v", acmeSh, args, e)) + // logger.Error("AcmeShError", eris.Wrapf(e, "Command error: %s -- %v\n%+v", acmeSh, args, e)) logger.Warn(string(b)) } diff --git a/backend/internal/acme/errors.go b/backend/internal/acme/errors.go index b929ce66..d68850ff 100644 --- a/backend/internal/acme/errors.go +++ b/backend/internal/acme/errors.go @@ -1,10 +1,12 @@ package acme -import "errors" +import ( + "github.com/rotisserie/eris" +) // All errors relating to Acme.sh use var ( - ErrDNSNeedsDNSProvider = errors.New("RequestCert dns method requires a dns provider") - ErrHTTPHasDNSProvider = errors.New("RequestCert http method does not need a dns provider") - ErrMethodNotSupported = errors.New("RequestCert method not supported") + ErrDNSNeedsDNSProvider = eris.New("RequestCert dns method requires a dns provider") + ErrHTTPHasDNSProvider = eris.New("RequestCert http method does not need a dns provider") + ErrMethodNotSupported = eris.New("RequestCert method not supported") ) diff --git a/backend/internal/api/handler/helpers.go b/backend/internal/api/handler/helpers.go index f0a4278c..ae47ebda 100644 --- a/backend/internal/api/handler/helpers.go +++ b/backend/internal/api/handler/helpers.go @@ -1,7 +1,6 @@ package handler import ( - "fmt" "net/http" "strconv" "strings" @@ -11,6 +10,7 @@ import ( "npm/internal/model" "github.com/go-chi/chi" + "github.com/rotisserie/eris" ) const defaultLimit = 10 @@ -45,7 +45,7 @@ func getDateRanges(r *http.Request) (time.Time, time.Time, error) { var fromErr error fromDate, fromErr = time.Parse(time.RFC3339, from) if fromErr != nil { - return fromDate, toDate, fmt.Errorf("From date is not in correct format: %v", strings.ReplaceAll(time.RFC3339, "Z", "+")) + return fromDate, toDate, eris.Errorf("From date is not in correct format: %v", strings.ReplaceAll(time.RFC3339, "Z", "+")) } } @@ -53,7 +53,7 @@ func getDateRanges(r *http.Request) (time.Time, time.Time, error) { var toErr error toDate, toErr = time.Parse(time.RFC3339, to) if toErr != nil { - return fromDate, toDate, fmt.Errorf("To date is not in correct format: %v", strings.ReplaceAll(time.RFC3339, "Z", "+")) + return fromDate, toDate, eris.Errorf("To date is not in correct format: %v", strings.ReplaceAll(time.RFC3339, "Z", "+")) } } @@ -104,14 +104,14 @@ func getQueryVarInt(r *http.Request, varName string, required bool, defaultValue varValue := queryValues.Get(varName) if varValue == "" && required { - return 0, fmt.Errorf("%v was not supplied in the request", varName) + return 0, eris.Errorf("%v was not supplied in the request", varName) } else if varValue == "" { return defaultValue, nil } varInt, intErr := strconv.Atoi(varValue) if intErr != nil { - return 0, fmt.Errorf("%v is not a valid number", varName) + return 0, eris.Wrapf(intErr, "%v is not a valid number", varName) } return varInt, nil @@ -123,7 +123,7 @@ func getQueryVarBool(r *http.Request, varName string, required bool, defaultValu varValue := queryValues.Get(varName) if varValue == "" && required { - return false, fmt.Errorf("%v was not supplied in the request", varName) + return false, eris.Errorf("%v was not supplied in the request", varName) } else if varValue == "" { return defaultValue, nil } @@ -140,13 +140,13 @@ func getURLParamInt(r *http.Request, varName string) (int, error) { var paramInt int if paramStr == "" && required { - return 0, fmt.Errorf("%v was not supplied in the request", varName) + return 0, eris.Errorf("%v was not supplied in the request", varName) } else if paramStr == "" { return defaultValue, nil } if paramInt, err = strconv.Atoi(paramStr); err != nil { - return 0, fmt.Errorf("%v is not a valid number", varName) + return 0, eris.Wrapf(err, "%v is not a valid number", varName) } return paramInt, nil @@ -158,7 +158,7 @@ func getURLParamString(r *http.Request, varName string) (string, error) { paramStr := chi.URLParam(r, varName) if paramStr == "" && required { - return "", fmt.Errorf("%v was not supplied in the request", varName) + return "", eris.Errorf("%v was not supplied in the request", varName) } else if paramStr == "" { return defaultValue, nil } diff --git a/backend/internal/api/handler/not_found.go b/backend/internal/api/handler/not_found.go index 07f40c71..341be08b 100644 --- a/backend/internal/api/handler/not_found.go +++ b/backend/internal/api/handler/not_found.go @@ -1,7 +1,6 @@ package handler import ( - "errors" "io" "io/fs" "mime" @@ -11,11 +10,13 @@ import ( "npm/embed" h "npm/internal/api/http" + + "github.com/rotisserie/eris" ) var ( assetsSub fs.FS - errIsDir = errors.New("path is dir") + errIsDir = eris.New("path is dir") ) // NotFound is a json error handler for 404's and method not allowed. diff --git a/backend/internal/api/http/requests.go b/backend/internal/api/http/requests.go index 3e7103c0..a5b35833 100644 --- a/backend/internal/api/http/requests.go +++ b/backend/internal/api/http/requests.go @@ -3,16 +3,16 @@ package http import ( "context" "encoding/json" - "errors" "github.com/qri-io/jsonschema" + "github.com/rotisserie/eris" ) var ( // ErrInvalidJSON is an error for invalid json - ErrInvalidJSON = errors.New("JSON is invalid") + ErrInvalidJSON = eris.New("JSON is invalid") // ErrInvalidPayload is an error for invalid incoming data - ErrInvalidPayload = errors.New("Payload is invalid") + ErrInvalidPayload = eris.New("Payload is invalid") ) // ValidateRequestSchema takes a Schema and the Content to validate against it diff --git a/backend/internal/api/middleware/schema.go b/backend/internal/api/middleware/schema.go index 3254e042..a0352dc7 100644 --- a/backend/internal/api/middleware/schema.go +++ b/backend/internal/api/middleware/schema.go @@ -3,13 +3,13 @@ package middleware import ( "context" "encoding/json" - "fmt" "net/http" c "npm/internal/api/context" h "npm/internal/api/http" "github.com/qri-io/jsonschema" + "github.com/rotisserie/eris" ) // CheckRequestSchema checks the payload against schema @@ -17,7 +17,7 @@ func CheckRequestSchema(ctx context.Context, schemaData string, payload []byte) // Create root schema rs := &jsonschema.Schema{} if err := json.Unmarshal([]byte(schemaData), rs); err != nil { - return nil, fmt.Errorf("Schema Fatal: %v", err) + return nil, eris.Wrapf(err, "Schema Fatal: %v", err) } // Validate it diff --git a/backend/internal/api/schema/create_dns_provider.go b/backend/internal/api/schema/create_dns_provider.go index 90dcef93..fea8f80d 100644 --- a/backend/internal/api/schema/create_dns_provider.go +++ b/backend/internal/api/schema/create_dns_provider.go @@ -7,6 +7,8 @@ import ( "npm/internal/dnsproviders" "npm/internal/logger" "npm/internal/util" + + "github.com/rotisserie/eris" ) // CreateDNSProvider is the schema for incoming data validation @@ -18,7 +20,7 @@ func CreateDNSProvider() string { for providerName, provider := range allProviders { schema, err := provider.GetJsonSchema() if err != nil { - logger.Error("ProviderSchemaError", fmt.Errorf("Invalid Provider Schema for %s: %v", provider.Title, err)) + logger.Error("ProviderSchemaError", eris.Wrapf(err, "Invalid Provider Schema for %s: %v", provider.Title, err)) } else { allSchemasWrapped = append(allSchemasWrapped, createDNSProviderType(providerName, schema)) } diff --git a/backend/internal/database/migrator.go b/backend/internal/database/migrator.go index 8b81c408..f90d927f 100644 --- a/backend/internal/database/migrator.go +++ b/backend/internal/database/migrator.go @@ -15,6 +15,7 @@ import ( "npm/internal/util" "github.com/jmoiron/sqlx" + "github.com/rotisserie/eris" ) // MigrationConfiguration options for the migrator. @@ -34,7 +35,7 @@ func ConfigureMigrator(c *MigrationConfiguration) error { mConfiguration.mux.Lock() defer mConfiguration.mux.Unlock() if c == nil { - return fmt.Errorf("a non nil Configuration is mandatory") + return eris.Errorf("a non nil Configuration is mandatory") } if strings.TrimSpace(c.Table) != "" { mConfiguration.Table = c.Table @@ -101,7 +102,7 @@ func tableExists(db *sqlx.DB, tableName string) bool { row := db.QueryRowx(query, tableName) if row == nil { - logger.Error("MigratorError", fmt.Errorf("Cannot check if table exists, no row returned: %v", tableName)) + logger.Error("MigratorError", eris.Errorf("Cannot check if table exists, no row returned: %v", tableName)) return false } diff --git a/backend/internal/dnsproviders/common.go b/backend/internal/dnsproviders/common.go index 4986bcb5..0e8bb4b6 100644 --- a/backend/internal/dnsproviders/common.go +++ b/backend/internal/dnsproviders/common.go @@ -2,7 +2,8 @@ package dnsproviders import ( "encoding/json" - "errors" + + "github.com/rotisserie/eris" ) // providerField should mimick jsonschema, so that @@ -111,5 +112,5 @@ func Get(provider string) (Provider, error) { if item, found := all[provider]; found { return item, nil } - return Provider{}, errors.New("provider_not_found") + return Provider{}, eris.New("provider_not_found") } diff --git a/backend/internal/entity/accesslist/methods.go b/backend/internal/entity/accesslist/methods.go index c399cf49..bce8bf31 100644 --- a/backend/internal/entity/accesslist/methods.go +++ b/backend/internal/entity/accesslist/methods.go @@ -2,7 +2,6 @@ package accesslist import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a row by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // Create will create a row from this model func Create(m *Model) (int, error) { if m.ID != 0 { - return 0, goerrors.New("Cannot create access list when model already has an ID") + return 0, eris.New("Cannot create access list when model already has an ID") } m.Touch(true) @@ -60,7 +61,7 @@ func Create(m *Model) (int, error) { // Update will Update a row from this model func Update(m *Model) error { if m.ID == 0 { - return goerrors.New("Cannot update access list when model doesn't have an ID") + return eris.New("Cannot update access list when model doesn't have an ID") } m.Touch(false) diff --git a/backend/internal/entity/accesslist/model.go b/backend/internal/entity/accesslist/model.go index 7dc175ea..55ed0ca1 100644 --- a/backend/internal/entity/accesslist/model.go +++ b/backend/internal/entity/accesslist/model.go @@ -7,6 +7,8 @@ import ( "npm/internal/database" "npm/internal/entity/user" "npm/internal/types" + + "github.com/rotisserie/eris" ) const ( @@ -52,7 +54,7 @@ func (m *Model) Save() error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } if m.ID == 0 { diff --git a/backend/internal/entity/auth/methods.go b/backend/internal/entity/auth/methods.go index 9cfb7faa..a2497fca 100644 --- a/backend/internal/entity/auth/methods.go +++ b/backend/internal/entity/auth/methods.go @@ -1,10 +1,11 @@ package auth import ( - goerrors "errors" "fmt" "npm/internal/database" + + "github.com/rotisserie/eris" ) // GetByID finds a auth by ID @@ -24,7 +25,7 @@ func GetByUserIDType(userID int, authType string) (Model, error) { // Create will create a Auth from this model func Create(auth *Model) (int, error) { if auth.ID != 0 { - return 0, goerrors.New("Cannot create auth when model already has an ID") + return 0, eris.New("Cannot create auth when model already has an ID") } auth.Touch(true) @@ -62,7 +63,7 @@ func Create(auth *Model) (int, error) { // Update will Update a Auth from this model func Update(auth *Model) error { if auth.ID == 0 { - return goerrors.New("Cannot update auth when model doesn't have an ID") + return eris.New("Cannot update auth when model doesn't have an ID") } auth.Touch(false) diff --git a/backend/internal/entity/auth/model.go b/backend/internal/entity/auth/model.go index b5640bbf..d92cfa79 100644 --- a/backend/internal/entity/auth/model.go +++ b/backend/internal/entity/auth/model.go @@ -1,13 +1,13 @@ package auth import ( - goerrors "errors" "fmt" "time" "npm/internal/database" "npm/internal/types" + "github.com/rotisserie/eris" "golang.org/x/crypto/bcrypt" ) @@ -86,12 +86,12 @@ func (m *Model) SetPassword(password string) error { // ValidateSecret will check if a given secret matches the encrypted secret func (m *Model) ValidateSecret(secret string) error { if m.Type != TypePassword { - return goerrors.New("Could not validate Secret, auth type is not a Password") + return eris.New("Could not validate Secret, auth type is not a Password") } err := bcrypt.CompareHashAndPassword([]byte(m.Secret), []byte(secret)) if err != nil { - return goerrors.New("Invalid Password") + return eris.New("Invalid Password") } return nil diff --git a/backend/internal/entity/certificate/methods.go b/backend/internal/entity/certificate/methods.go index d1832164..70a2810e 100644 --- a/backend/internal/entity/certificate/methods.go +++ b/backend/internal/entity/certificate/methods.go @@ -2,7 +2,6 @@ package certificate import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -11,6 +10,8 @@ import ( "npm/internal/jobqueue" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a row by ID @@ -23,7 +24,7 @@ func GetByID(id int) (Model, error) { // Create will create a row from this model func Create(certificate *Model) (int, error) { if certificate.ID != 0 { - return 0, goerrors.New("Cannot create certificate when model already has an ID") + return 0, eris.New("Cannot create certificate when model already has an ID") } certificate.Touch(true) @@ -77,7 +78,7 @@ func Create(certificate *Model) (int, error) { // Update will Update a Auth from this model func Update(certificate *Model) error { if certificate.ID == 0 { - return goerrors.New("Cannot update certificate when model doesn't have an ID") + return eris.New("Cannot update certificate when model doesn't have an ID") } certificate.Touch(false) diff --git a/backend/internal/entity/certificate/model.go b/backend/internal/entity/certificate/model.go index 0e39191d..d5ce2b55 100644 --- a/backend/internal/entity/certificate/model.go +++ b/backend/internal/entity/certificate/model.go @@ -1,7 +1,6 @@ package certificate import ( - "errors" "fmt" "os" "regexp" @@ -17,6 +16,8 @@ import ( "npm/internal/logger" "npm/internal/types" "npm/internal/util" + + "github.com/rotisserie/eris" ) const ( @@ -90,15 +91,15 @@ func (m *Model) Save() error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } if !m.Validate() { - return fmt.Errorf("Certificate data is incorrect or incomplete for this type") + return eris.Errorf("Certificate data is incorrect or incomplete for this type") } if !m.ValidateWildcardSupport() { - return fmt.Errorf("Cannot use Wildcard domains with this CA") + return eris.Errorf("Cannot use Wildcard domains with this CA") } m.setDefaultStatus() @@ -215,7 +216,7 @@ func (m *Model) Expand(items []string) error { // Returns: (key, fullchain, certFolder) func (m *Model) GetCertificateLocations() (string, string, string) { if m.ID == 0 { - logger.Error("GetCertificateLocationsError", errors.New("GetCertificateLocations called before certificate was saved")) + logger.Error("GetCertificateLocationsError", eris.New("GetCertificateLocations called before certificate was saved")) return "", "", "" } diff --git a/backend/internal/entity/certificateauthority/methods.go b/backend/internal/entity/certificateauthority/methods.go index 9d0a14ee..1631a6cf 100644 --- a/backend/internal/entity/certificateauthority/methods.go +++ b/backend/internal/entity/certificateauthority/methods.go @@ -2,7 +2,6 @@ package certificateauthority import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a row by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // Create will create a row from this model func Create(ca *Model) (int, error) { if ca.ID != 0 { - return 0, goerrors.New("Cannot create certificate authority when model already has an ID") + return 0, eris.New("Cannot create certificate authority when model already has an ID") } ca.Touch(true) @@ -64,7 +65,7 @@ func Create(ca *Model) (int, error) { // Update will Update a row from this model func Update(ca *Model) error { if ca.ID == 0 { - return goerrors.New("Cannot update certificate authority when model doesn't have an ID") + return eris.New("Cannot update certificate authority when model doesn't have an ID") } ca.Touch(false) diff --git a/backend/internal/entity/certificateauthority/model.go b/backend/internal/entity/certificateauthority/model.go index e5817d0a..ddb49ad3 100644 --- a/backend/internal/entity/certificateauthority/model.go +++ b/backend/internal/entity/certificateauthority/model.go @@ -1,7 +1,6 @@ package certificateauthority import ( - goerrors "errors" "fmt" "os" "path/filepath" @@ -10,6 +9,8 @@ import ( "npm/internal/database" "npm/internal/errors" "npm/internal/types" + + "github.com/rotisserie/eris" ) const ( @@ -79,7 +80,7 @@ func (m *Model) Check() error { var err error if m.CABundle != "" { - if _, fileerr := os.Stat(filepath.Clean(m.CABundle)); goerrors.Is(fileerr, os.ErrNotExist) { + if _, fileerr := os.Stat(filepath.Clean(m.CABundle)); eris.Is(fileerr, os.ErrNotExist) { err = errors.ErrCABundleDoesNotExist } } diff --git a/backend/internal/entity/dnsprovider/methods.go b/backend/internal/entity/dnsprovider/methods.go index c31c742e..9549eccf 100644 --- a/backend/internal/entity/dnsprovider/methods.go +++ b/backend/internal/entity/dnsprovider/methods.go @@ -2,7 +2,6 @@ package dnsprovider import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a row by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // Create will create a row from this model func Create(provider *Model) (int, error) { if provider.ID != 0 { - return 0, goerrors.New("Cannot create dns provider when model already has an ID") + return 0, eris.New("Cannot create dns provider when model already has an ID") } provider.Touch(true) @@ -64,7 +65,7 @@ func Create(provider *Model) (int, error) { // Update will Update a row from this model func Update(provider *Model) error { if provider.ID == 0 { - return goerrors.New("Cannot update dns provider when model doesn't have an ID") + return eris.New("Cannot update dns provider when model doesn't have an ID") } provider.Touch(false) diff --git a/backend/internal/entity/dnsprovider/model.go b/backend/internal/entity/dnsprovider/model.go index 0514c260..7a4f5311 100644 --- a/backend/internal/entity/dnsprovider/model.go +++ b/backend/internal/entity/dnsprovider/model.go @@ -8,6 +8,8 @@ import ( "npm/internal/dnsproviders" "npm/internal/logger" "npm/internal/types" + + "github.com/rotisserie/eris" ) const ( @@ -54,7 +56,7 @@ func (m *Model) Save() error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } if m.ID == 0 { diff --git a/backend/internal/entity/host/methods.go b/backend/internal/entity/host/methods.go index ddb1ebd4..5e6ed141 100644 --- a/backend/internal/entity/host/methods.go +++ b/backend/internal/entity/host/methods.go @@ -2,7 +2,6 @@ package host import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a Host by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // create will create a Host from this model func create(host *Model) (int, error) { if host.ID != 0 { - return 0, goerrors.New("Cannot create host when model already has an ID") + return 0, eris.New("Cannot create host when model already has an ID") } host.Touch(true) @@ -102,7 +103,7 @@ func create(host *Model) (int, error) { // update will Update a Host from this model func update(host *Model) error { if host.ID == 0 { - return goerrors.New("Cannot update host when model doesn't have an ID") + return eris.New("Cannot update host when model doesn't have an ID") } host.Touch(false) diff --git a/backend/internal/entity/host/model.go b/backend/internal/entity/host/model.go index 5502e0d9..12b68da2 100644 --- a/backend/internal/entity/host/model.go +++ b/backend/internal/entity/host/model.go @@ -12,6 +12,8 @@ import ( "npm/internal/status" "npm/internal/types" "npm/internal/util" + + "github.com/rotisserie/eris" ) const ( @@ -87,7 +89,7 @@ func (m *Model) Save(skipConfiguration bool) error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } if !skipConfiguration { diff --git a/backend/internal/entity/nginxtemplate/methods.go b/backend/internal/entity/nginxtemplate/methods.go index 70faef79..3852a039 100644 --- a/backend/internal/entity/nginxtemplate/methods.go +++ b/backend/internal/entity/nginxtemplate/methods.go @@ -2,7 +2,6 @@ package nginxtemplate import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a Host by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // Create will create a Host from this model func Create(host *Model) (int, error) { if host.ID != 0 { - return 0, goerrors.New("Cannot create host template when model already has an ID") + return 0, eris.New("Cannot create host template when model already has an ID") } host.Touch(true) @@ -62,7 +63,7 @@ func Create(host *Model) (int, error) { // Update will Update a Host from this model func Update(host *Model) error { if host.ID == 0 { - return goerrors.New("Cannot update host template when model doesn't have an ID") + return eris.New("Cannot update host template when model doesn't have an ID") } host.Touch(false) diff --git a/backend/internal/entity/nginxtemplate/model.go b/backend/internal/entity/nginxtemplate/model.go index ecaac006..af3a4d27 100644 --- a/backend/internal/entity/nginxtemplate/model.go +++ b/backend/internal/entity/nginxtemplate/model.go @@ -6,6 +6,8 @@ import ( "npm/internal/database" "npm/internal/types" + + "github.com/rotisserie/eris" ) const ( @@ -50,7 +52,7 @@ func (m *Model) Save() error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } if m.ID == 0 { diff --git a/backend/internal/entity/setting/methods.go b/backend/internal/entity/setting/methods.go index 1d9eef96..f6ac0f4d 100644 --- a/backend/internal/entity/setting/methods.go +++ b/backend/internal/entity/setting/methods.go @@ -2,7 +2,6 @@ package setting import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a setting by ID @@ -29,7 +30,7 @@ func GetByName(name string) (Model, error) { // Create will Create a Setting from this model func Create(setting *Model) (int, error) { if setting.ID != 0 { - return 0, goerrors.New("Cannot create setting when model already has an ID") + return 0, eris.New("Cannot create setting when model already has an ID") } setting.Touch(true) @@ -63,7 +64,7 @@ func Create(setting *Model) (int, error) { // Update will Update a Setting from this model func Update(setting *Model) error { if setting.ID == 0 { - return goerrors.New("Cannot update setting when model doesn't have an ID") + return eris.New("Cannot update setting when model doesn't have an ID") } setting.Touch(false) diff --git a/backend/internal/entity/stream/methods.go b/backend/internal/entity/stream/methods.go index 0accd501..446bf15b 100644 --- a/backend/internal/entity/stream/methods.go +++ b/backend/internal/entity/stream/methods.go @@ -2,7 +2,6 @@ package stream import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a auth by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // Create will create a Auth from this model func Create(host *Model) (int, error) { if host.ID != 0 { - return 0, goerrors.New("Cannot create stream when model already has an ID") + return 0, eris.New("Cannot create stream when model already has an ID") } host.Touch(true) @@ -66,7 +67,7 @@ func Create(host *Model) (int, error) { // Update will Update a Host from this model func Update(host *Model) error { if host.ID == 0 { - return goerrors.New("Cannot update stream when model doesn't have an ID") + return eris.New("Cannot update stream when model doesn't have an ID") } host.Touch(false) diff --git a/backend/internal/entity/stream/model.go b/backend/internal/entity/stream/model.go index 60f47f75..ad158d75 100644 --- a/backend/internal/entity/stream/model.go +++ b/backend/internal/entity/stream/model.go @@ -6,6 +6,8 @@ import ( "npm/internal/database" "npm/internal/types" + + "github.com/rotisserie/eris" ) const ( @@ -52,7 +54,7 @@ func (m *Model) Save() error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } if m.ID == 0 { diff --git a/backend/internal/entity/upstream/methods.go b/backend/internal/entity/upstream/methods.go index 4418db72..547fb77a 100644 --- a/backend/internal/entity/upstream/methods.go +++ b/backend/internal/entity/upstream/methods.go @@ -2,7 +2,6 @@ package upstream import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a Upstream by ID @@ -22,7 +23,7 @@ func GetByID(id int) (Model, error) { // create will create a Upstream from this model func create(u *Model) (int, error) { if u.ID != 0 { - return 0, goerrors.New("Cannot create upstream when model already has an ID") + return 0, eris.New("Cannot create upstream when model already has an ID") } u.Touch(true) @@ -80,7 +81,7 @@ func create(u *Model) (int, error) { // update will Update a Upstream from this model func update(u *Model) error { if u.ID == 0 { - return goerrors.New("Cannot update upstream when model doesn't have an ID") + return eris.New("Cannot update upstream when model doesn't have an ID") } u.Touch(false) diff --git a/backend/internal/entity/upstream/model.go b/backend/internal/entity/upstream/model.go index 588e23c3..e42aebd8 100644 --- a/backend/internal/entity/upstream/model.go +++ b/backend/internal/entity/upstream/model.go @@ -12,6 +12,8 @@ import ( "npm/internal/status" "npm/internal/types" "npm/internal/util" + + "github.com/rotisserie/eris" ) const ( @@ -73,7 +75,7 @@ func (m *Model) Save(skipConfiguration bool) error { var err error if m.UserID == 0 { - return fmt.Errorf("User ID must be specified") + return eris.Errorf("User ID must be specified") } // ensure name is trimmed of whitespace diff --git a/backend/internal/entity/upstreamserver/methods.go b/backend/internal/entity/upstreamserver/methods.go index 69a12c57..63586856 100644 --- a/backend/internal/entity/upstreamserver/methods.go +++ b/backend/internal/entity/upstreamserver/methods.go @@ -2,7 +2,6 @@ package upstreamserver import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a Upstream Server by ID @@ -34,7 +35,7 @@ func GetByUpstreamID(upstreamID int) ([]Model, error) { // create will create a Upstream Server from this model func create(u *Model) (int, error) { if u.ID != 0 { - return 0, goerrors.New("Cannot create upstream server when model already has an ID") + return 0, eris.New("Cannot create upstream server when model already has an ID") } u.Touch(true) @@ -82,7 +83,7 @@ func create(u *Model) (int, error) { // update will Update a Upstream from this model func update(u *Model) error { if u.ID == 0 { - return goerrors.New("Cannot update upstream server when model doesn't have an ID") + return eris.New("Cannot update upstream server when model doesn't have an ID") } u.Touch(false) diff --git a/backend/internal/entity/upstreamserver/model.go b/backend/internal/entity/upstreamserver/model.go index 50f7f23b..82eaef5a 100644 --- a/backend/internal/entity/upstreamserver/model.go +++ b/backend/internal/entity/upstreamserver/model.go @@ -6,6 +6,8 @@ import ( "npm/internal/database" "npm/internal/types" + + "github.com/rotisserie/eris" ) const ( @@ -53,7 +55,7 @@ func (m *Model) Save() error { var err error if m.UpstreamID == 0 { - return fmt.Errorf("Upstream ID must be specified") + return eris.Errorf("Upstream ID must be specified") } if m.ID == 0 { diff --git a/backend/internal/entity/user/methods.go b/backend/internal/entity/user/methods.go index c80890ed..5d6f3294 100644 --- a/backend/internal/entity/user/methods.go +++ b/backend/internal/entity/user/methods.go @@ -2,7 +2,6 @@ package user import ( "database/sql" - goerrors "errors" "fmt" "npm/internal/database" @@ -10,6 +9,8 @@ import ( "npm/internal/errors" "npm/internal/logger" "npm/internal/model" + + "github.com/rotisserie/eris" ) // GetByID finds a user by ID @@ -33,7 +34,7 @@ func Create(user *Model) (int, error) { // database schema, but it's a bit more complex because of the is_deleted field. if user.ID != 0 { - return 0, goerrors.New("Cannot create user when model already has an ID") + return 0, eris.New("Cannot create user when model already has an ID") } // Check if an existing user with this email exists @@ -77,7 +78,7 @@ func Create(user *Model) (int, error) { // Update will Update a User from this model func Update(user *Model) error { if user.ID == 0 { - return goerrors.New("Cannot update user when model doesn't have an ID") + return eris.New("Cannot update user when model doesn't have an ID") } // Check that the email address isn't associated with another user diff --git a/backend/internal/entity/user/model.go b/backend/internal/entity/user/model.go index bf2f4c84..e7598547 100644 --- a/backend/internal/entity/user/model.go +++ b/backend/internal/entity/user/model.go @@ -1,7 +1,6 @@ package user import ( - goerrors "errors" "fmt" "strings" "time" @@ -14,6 +13,7 @@ import ( "npm/internal/util" "github.com/drexedam/gravatar" + "github.com/rotisserie/eris" ) const ( @@ -100,7 +100,7 @@ func (m *Model) Delete() bool { // SetPermissions will wipe out any existing permissions and add new ones for this user func (m *Model) SetPermissions(permissions []string) error { if m.ID == 0 { - return fmt.Errorf("Cannot set permissions without first saving the User") + return eris.Errorf("Cannot set permissions without first saving the User") } db := database.GetInstance() @@ -156,12 +156,12 @@ func (m *Model) generateGravatar() { func (m *Model) SaveCapabilities() error { // m.Capabilities if m.ID == 0 { - return fmt.Errorf("Cannot save capabilities on unsaved user") + return eris.Errorf("Cannot save capabilities on unsaved user") } // there must be at least 1 capability if len(m.Capabilities) == 0 { - return goerrors.New("At least 1 capability required for a user") + return eris.New("At least 1 capability required for a user") } db := database.GetInstance() @@ -183,7 +183,7 @@ func (m *Model) SaveCapabilities() error { } } if !found { - return fmt.Errorf("Capability `%s` is not valid", cap) + return eris.Errorf("Capability `%s` is not valid", cap) } } diff --git a/backend/internal/errors/errors.go b/backend/internal/errors/errors.go index 39735a1d..314c59e1 100644 --- a/backend/internal/errors/errors.go +++ b/backend/internal/errors/errors.go @@ -1,16 +1,18 @@ package errors -import "errors" +import ( + "github.com/rotisserie/eris" +) // All error messages used by the service package to report // problems back to calling clients var ( - ErrDatabaseUnavailable = errors.New("database-unavailable") - ErrDuplicateEmailUser = errors.New("email-already-exists") - ErrInvalidLogin = errors.New("invalid-login-credentials") - ErrUserDisabled = errors.New("user-disabled") - ErrSystemUserReadonly = errors.New("cannot-save-system-users") - ErrValidationFailed = errors.New("request-failed-validation") - ErrCurrentPasswordInvalid = errors.New("current-password-invalid") - ErrCABundleDoesNotExist = errors.New("ca-bundle-does-not-exist") + ErrDatabaseUnavailable = eris.New("database-unavailable") + ErrDuplicateEmailUser = eris.New("email-already-exists") + ErrInvalidLogin = eris.New("invalid-login-credentials") + ErrUserDisabled = eris.New("user-disabled") + ErrSystemUserReadonly = eris.New("cannot-save-system-users") + ErrValidationFailed = eris.New("request-failed-validation") + ErrCurrentPasswordInvalid = eris.New("current-password-invalid") + ErrCABundleDoesNotExist = eris.New("ca-bundle-does-not-exist") ) diff --git a/backend/internal/jobqueue/main.go b/backend/internal/jobqueue/main.go index 69af04a0..bed99953 100644 --- a/backend/internal/jobqueue/main.go +++ b/backend/internal/jobqueue/main.go @@ -2,7 +2,8 @@ package jobqueue import ( "context" - "errors" + + "github.com/rotisserie/eris" ) var ( @@ -30,7 +31,7 @@ func Start() { // Shutdown will gracefully stop the queue func Shutdown() error { if cancel == nil { - return errors.New("Unable to shutdown, jobqueue has not been started") + return eris.New("Unable to shutdown, jobqueue has not been started") } cancel() return nil @@ -39,7 +40,7 @@ func Shutdown() error { // AddJob adds a job to the queue for processing func AddJob(j Job) error { if worker == nil { - return errors.New("Unable to add job, jobqueue has not been started") + return eris.New("Unable to add job, jobqueue has not been started") } worker.Queue.AddJob(j) return nil diff --git a/backend/internal/jwt/jwt.go b/backend/internal/jwt/jwt.go index 9dcb6c7b..95b1101d 100644 --- a/backend/internal/jwt/jwt.go +++ b/backend/internal/jwt/jwt.go @@ -1,13 +1,13 @@ package jwt import ( - "fmt" "time" "npm/internal/entity/user" "npm/internal/logger" "github.com/dgrijalva/jwt-go" + "github.com/rotisserie/eris" ) // UserJWTClaims is the structure of a JWT for a User @@ -47,7 +47,7 @@ func Generate(userObj *user.Model) (GeneratedResponse, error) { var err error token.Signature, err = token.SignedString(key) if err != nil { - logger.Error("JWTError", fmt.Errorf("Error signing token: %v", err)) + logger.Error("JWTError", eris.Wrapf(err, "Error signing token: %v", err)) return response, err } diff --git a/backend/internal/jwt/keys.go b/backend/internal/jwt/keys.go index e48c334d..39ec7c4e 100644 --- a/backend/internal/jwt/keys.go +++ b/backend/internal/jwt/keys.go @@ -4,9 +4,10 @@ import ( "crypto/rsa" "crypto/x509" "encoding/pem" - "errors" "npm/internal/config" + + "github.com/rotisserie/eris" ) var ( @@ -21,7 +22,7 @@ func GetPrivateKey() (*rsa.PrivateKey, error) { var blankKey *rsa.PrivateKey if config.PrivateKey == "" { - return blankKey, errors.New("Could not get Private Key from configuration") + return blankKey, eris.New("Could not get Private Key from configuration") } var err error @@ -48,7 +49,7 @@ func GetPublicKey() (*rsa.PublicKey, error) { var blankKey *rsa.PublicKey if config.PublicKey == "" { - return blankKey, errors.New("Could not get Public Key filename, check environment variables") + return blankKey, eris.New("Could not get Public Key filename, check environment variables") } var err error diff --git a/backend/internal/logger/logger.go b/backend/internal/logger/logger.go index f82145ee..2cbadc4b 100644 --- a/backend/internal/logger/logger.go +++ b/backend/internal/logger/logger.go @@ -11,6 +11,7 @@ import ( "github.com/fatih/color" "github.com/getsentry/sentry-go" + "github.com/rotisserie/eris" ) var colorReset, colorGray, colorYellow, colorBlue, colorRed, colorMagenta, colorBlack, colorWhite *color.Color @@ -98,7 +99,7 @@ func (l *Logger) Configure(c *Config) error { defer l.mux.Unlock() if c == nil { - return fmt.Errorf("a non nil Config is mandatory") + return eris.Errorf("a non nil Config is mandatory") } if err := c.LogThreshold.validate(); err != nil { @@ -125,7 +126,7 @@ func (l Level) validate() error { case DebugLevel, InfoLevel, WarnLevel, ErrorLevel: return nil default: - return fmt.Errorf("invalid \"Level\" %d", l) + return eris.Errorf("invalid \"Level\" %d", l) } } diff --git a/backend/internal/logger/logger_test.go b/backend/internal/logger/logger_test.go index 4851f580..6ddad72e 100644 --- a/backend/internal/logger/logger_test.go +++ b/backend/internal/logger/logger_test.go @@ -2,14 +2,13 @@ package logger import ( "bytes" - "errors" - "fmt" "io" "log" "os" "testing" "github.com/getsentry/sentry-go" + "github.com/rotisserie/eris" "github.com/stretchr/testify/assert" ) @@ -34,7 +33,7 @@ func TestThreshold(t *testing.T) { Info("this should display") assert.NotEmpty(t, buf.String()) - Error("ErrorClass", errors.New("this should display")) + Error("ErrorClass", eris.New("this should display")) assert.NotEmpty(t, buf.String()) } @@ -97,7 +96,7 @@ func TestError(t *testing.T) { LogThreshold: ErrorLevel, })) - Error("TestErrorClass", fmt.Errorf("this is a %s error", "test")) + Error("TestErrorClass", eris.Errorf("this is a %s error", "test")) assert.Contains(t, buf.String(), "ERROR") assert.Contains(t, buf.String(), "this is a test error") } diff --git a/backend/internal/nginx/exec.go b/backend/internal/nginx/exec.go index 727aad36..fa939498 100644 --- a/backend/internal/nginx/exec.go +++ b/backend/internal/nginx/exec.go @@ -1,10 +1,11 @@ package nginx import ( - "fmt" "os/exec" "npm/internal/logger" + + "github.com/rotisserie/eris" ) func reloadNginx() (string, error) { @@ -14,7 +15,7 @@ func reloadNginx() (string, error) { func getNginxFilePath() (string, error) { path, err := exec.LookPath("nginx") if err != nil { - return path, fmt.Errorf("Cannot find nginx execuatable script in PATH") + return path, eris.Wrapf(err, "Cannot find nginx execuatable script in PATH") } return path, nil } @@ -34,7 +35,7 @@ func shExec(args []string) (string, error) { b, e := c.CombinedOutput() if e != nil { - logger.Error("NginxError", fmt.Errorf("Command error: %s -- %v\n%+v", ng, args, e)) + logger.Error("NginxError", eris.Wrapf(err, "Command error: %s -- %v\n%+v", ng, args, e)) logger.Warn(string(b)) } diff --git a/backend/internal/types/jsonb.go b/backend/internal/types/jsonb.go index ff3f7930..b3755222 100644 --- a/backend/internal/types/jsonb.go +++ b/backend/internal/types/jsonb.go @@ -3,7 +3,8 @@ package types import ( "database/sql/driver" "encoding/json" - "fmt" + + "github.com/rotisserie/eris" ) // JSONB can be anything @@ -28,7 +29,7 @@ func (j *JSONB) Scan(src interface{}) error { case []uint8: srcString = string(src.([]uint8)) default: - return fmt.Errorf("Incompatible type for JSONB: %v", v) + return eris.Errorf("Incompatible type for JSONB: %v", v) } jsonb.Encoded = srcString diff --git a/backend/internal/validator/hosts.go b/backend/internal/validator/hosts.go index 3bdf69a2..f92b6a80 100644 --- a/backend/internal/validator/hosts.go +++ b/backend/internal/validator/hosts.go @@ -1,12 +1,12 @@ package validator import ( - "fmt" - "npm/internal/entity/certificate" "npm/internal/entity/host" "npm/internal/entity/nginxtemplate" "npm/internal/entity/upstream" + + "github.com/rotisserie/eris" ) // ValidateHost will check if associated objects exist and other checks @@ -17,32 +17,32 @@ func ValidateHost(h host.Model) error { // This will not determine if the certificate is Ready to use, // as this validation only cares that the row exists. if _, cErr := certificate.GetByID(h.CertificateID); cErr != nil { - return fmt.Errorf("Certificate #%d does not exist", h.CertificateID) + return eris.Wrapf(cErr, "Certificate #%d does not exist", h.CertificateID) } } if h.UpstreamID > 0 { // Check upstream exists if _, uErr := upstream.GetByID(h.UpstreamID); uErr != nil { - return fmt.Errorf("Upstream #%d does not exist", h.UpstreamID) + return eris.Wrapf(uErr, "Upstream #%d does not exist", h.UpstreamID) } } // Ensure either UpstreamID is set or appropriate proxy host params are set if h.UpstreamID > 0 && (h.ProxyHost != "" || h.ProxyPort > 0) { - return fmt.Errorf("Proxy Host or Port cannot be set when using an Upstream") + return eris.Errorf("Proxy Host or Port cannot be set when using an Upstream") } if h.UpstreamID == 0 && (h.ProxyHost == "" || h.ProxyPort < 1) { - return fmt.Errorf("Proxy Host and Port must be specified, unless using an Upstream") + return eris.Errorf("Proxy Host and Port must be specified, unless using an Upstream") } // Check the nginx template exists and has the same type. nginxTemplate, tErr := nginxtemplate.GetByID(h.NginxTemplateID) if tErr != nil { - return fmt.Errorf("Host Template #%d does not exist", h.NginxTemplateID) + return eris.Wrapf(tErr, "Host Template #%d does not exist", h.NginxTemplateID) } if nginxTemplate.Type != h.Type { - return fmt.Errorf("Host Template #%d is not valid for this host type", h.NginxTemplateID) + return eris.Errorf("Host Template #%d is not valid for this host type", h.NginxTemplateID) } return nil diff --git a/backend/internal/validator/upstreams.go b/backend/internal/validator/upstreams.go index c8c96481..6697555f 100644 --- a/backend/internal/validator/upstreams.go +++ b/backend/internal/validator/upstreams.go @@ -1,11 +1,10 @@ package validator import ( - "errors" - "fmt" - "npm/internal/entity/nginxtemplate" "npm/internal/entity/upstream" + + "github.com/rotisserie/eris" ) // ValidateUpstream will check if associated objects exist and other checks @@ -13,7 +12,7 @@ import ( func ValidateUpstream(u upstream.Model) error { // Needs to have more than 1 server if len(u.Servers) < 2 { - return errors.New("Upstreams require at least 2 servers") + return eris.New("Upstreams require at least 2 servers") } // Backup servers aren't permitted with hash balancing @@ -21,7 +20,7 @@ func ValidateUpstream(u upstream.Model) error { // check all servers for a backup param for _, server := range u.Servers { if server.Backup { - return errors.New("Backup servers cannot be used with hash balancing") + return eris.New("Backup servers cannot be used with hash balancing") } } } @@ -29,10 +28,10 @@ func ValidateUpstream(u upstream.Model) error { // Check the nginx template exists and has the same type. nginxTemplate, err := nginxtemplate.GetByID(u.NginxTemplateID) if err != nil { - return fmt.Errorf("Nginx Template #%d does not exist", u.NginxTemplateID) + return eris.Errorf("Nginx Template #%d does not exist", u.NginxTemplateID) } if nginxTemplate.Type != "upstream" { - return fmt.Errorf("Host Template #%d is not valid for this upstream", u.NginxTemplateID) + return eris.Errorf("Host Template #%d is not valid for this upstream", u.NginxTemplateID) } return nil