...
1 package bsl
2
3 import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "regexp"
8 )
9
10 const (
11
12 constraintViolationErr = "com.ncr.nep.common.exception.PayloadConstraintViolationException"
13
14 tenantAccessDeniedErr = "com.ncr.nep.common.exception.TenantAccessDeniedException"
15
16 accessDeniedErr = "com.ncr.nep.common.exception.AccessDeniedException"
17
18 invalidCredentialsErr = "com.ncr.nep.common.exception.InvalidCredentialsException"
19
20 resourceNotExistsErr = "com.ncr.nep.common.exception.ResourceDoesNotExistException"
21
22 resourceAlreadyExistsErr = "com.ncr.nep.common.exception.ResourceAlreadyExistsException"
23
24 inactiveAccountErr = "com.ncr.nep.security.authn.AccountInactiveException"
25
26 lockedAccountErr = "com.ncr.nep.security.authn.AccountLockedException"
27
28 businessConstraintViolationErr = "com.ncr.nep.common.exception.BusinessConstraintViolationException"
29
30 genericErr = "javax.ws.rs.ClientErrorException"
31 )
32
33 var (
34
35 wellKnownErrorTypes = map[string]string{
36 tenantAccessDeniedErr: "Access Denied, Tenant cannot access resource",
37 accessDeniedErr: "Access Denied, Authorization Required",
38 invalidCredentialsErr: "Incorrect username, password, or organization.",
39 resourceNotExistsErr: "Resource does not exist",
40 resourceAlreadyExistsErr: "the resources already exists",
41 constraintViolationErr: "Constraint violation",
42 inactiveAccountErr: "Your account is inactive. Contact your organization admin to activate your account.",
43 lockedAccountErr: "Your account has been locked. Contact your organization admin to unlock your account.",
44 businessConstraintViolationErr: "Invalid Value supplied",
45 genericErr: "Client Error Exception",
46 }
47 )
48
49
50 type Error struct {
51 Err error
52 Message string
53 StatusCode int
54 Verbose string
55 ErrorType string
56 URL string
57 Path string
58 Method string
59 }
60
61
62 type ErrorResponse struct {
63 StatusCode int `json:"statusCode"`
64 Message string `json:"message"`
65 ErrorType string `json:"errorType"`
66 Details []string `json:"details"`
67 ConstraintViolations []ConstraintViolation `json:"constraintViolations"`
68 }
69
70
71 type ConstraintViolation struct {
72 InvalidValue string `json:"invalidValue"`
73 Message string `json:"message"`
74 PropertyPath string `json:"propertyPath"`
75 }
76
77
78 func New(msg string) *Error {
79 return Wrap(errors.New(msg))
80 }
81
82
83 func Wrap(err error) *Error {
84 if err == nil {
85 return &Error{}
86 }
87 msg := err.Error()
88 if msg == "" {
89 msg = "Internal Server Error"
90 }
91 return &Error{
92 Err: err,
93 Message: msg,
94 }
95 }
96
97
98 func (b *Error) SetMessage(msg string) *Error {
99 b.Message = msg
100 return b
101 }
102
103
104 func (b *Error) SetStatusCode(code int) *Error {
105 b.StatusCode = code
106 return b
107 }
108
109
110 func (b *Error) SetURL(url string) *Error {
111 b.URL = url
112 return b
113 }
114
115
116 func (b *Error) SetPath(path string) *Error {
117 b.Path = path
118 return b
119 }
120
121
122 func (b *Error) SetMethod(method string) *Error {
123 b.Method = method
124 return b
125 }
126
127
128 func (b *Error) SetErrorType(errorType string) *Error {
129 b.ErrorType = errorType
130 return b
131 }
132
133
134 func (b *Error) SetVerbose(verbose string) *Error {
135 b.Verbose = verbose
136 return b
137 }
138
139
140 func (b *Error) Error() string {
141 return b.Message
142 }
143
144
145 func (b *Error) Unwrap() error {
146 if b != nil {
147 return b.Err
148 }
149 return nil
150 }
151
152
153
154 func (b *Error) UnmarshalErrorResponse(body []byte) *Error {
155 if len(body) > 0 {
156 bslErrResponse := &ErrorResponse{}
157 err := json.Unmarshal(body, &bslErrResponse)
158 if err != nil {
159 b.Message = fmt.Sprintf("an error occurred unmarshaling json response. %s", err.Error())
160 return b
161 }
162 if val, exists := wellKnownErrorTypes[bslErrResponse.ErrorType]; exists {
163 switch val {
164 case wellKnownErrorTypes[constraintViolationErr], wellKnownErrorTypes[businessConstraintViolationErr], wellKnownErrorTypes[resourceNotExistsErr]:
165 msg := stripSymbols(bslErrResponse.Message)
166 if msg == "" {
167 b.Message = val
168 break
169 }
170 b.Message = msg
171 default:
172 b.Message = val
173 }
174 }
175 return b.SetStatusCode(bslErrResponse.StatusCode).SetErrorType(bslErrResponse.ErrorType).SetVerbose(string(body))
176 }
177 return b
178 }
179
180
181 func (b *Error) Extensions() map[string]interface{} {
182 return map[string]interface{}{
183 "statusCode": b.StatusCode,
184
185 "method": b.Method,
186 "path": b.Path,
187 "url": b.URL,
188 "errorType": b.ErrorType,
189 }
190 }
191
192
193 func (b *Error) Is(target error) bool {
194 if target == nil {
195 return false
196 }
197
198 return b.Message == target.Error()
199 }
200
201
202 func (b *Error) IsError(target *Error) bool {
203 return b.Message == target.Message && b.Method == target.Method && b.ErrorType == target.ErrorType && b.StatusCode == target.StatusCode && b.URL == target.URL && b.Path == target.Path
204 }
205
206
207 func stripSymbols(message string) string {
208 reg, err := regexp.Compile(`[\[/]|[\]/]`)
209 if err != nil {
210 return "Internal Server Error"
211 }
212 return string(reg.ReplaceAll([]byte(message), []byte("")))
213 }
214
View as plain text