MM-45991 Wrap errors (#20785)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8e0d46e0c6
Коммит
a28a967eba
778
model/client4.go
778
model/client4.go
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@@ -122,7 +122,7 @@ func (o *Command) IsValid() *AppError {
|
||||
|
||||
if o.AutocompleteData != nil {
|
||||
if err := o.AutocompleteData.IsValid(); err != nil {
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.autocomplete_data.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("Command.IsValid", "model.command.is_valid.autocomplete_data.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3078,19 +3078,20 @@ const ConfigAccessTagAnySysConsoleRead = "*_read"
|
||||
// environment with ExperimentalSettings.RestrictedSystemAdmin set to true.
|
||||
//
|
||||
// Example:
|
||||
// type HairSettings struct {
|
||||
// // Colour is writeable with either PermissionSysconsoleWriteReporting or PermissionSysconsoleWriteUserManagementGroups.
|
||||
// // It is readable by PermissionSysconsoleReadReporting and PermissionSysconsoleReadUserManagementGroups permissions.
|
||||
// // PermissionManageSystem grants read and write access.
|
||||
// Colour string `access:"reporting,user_management_groups"`
|
||||
//
|
||||
// // Length is only readable and writable via PermissionManageSystem.
|
||||
// Length string
|
||||
// type HairSettings struct {
|
||||
// // Colour is writeable with either PermissionSysconsoleWriteReporting or PermissionSysconsoleWriteUserManagementGroups.
|
||||
// // It is readable by PermissionSysconsoleReadReporting and PermissionSysconsoleReadUserManagementGroups permissions.
|
||||
// // PermissionManageSystem grants read and write access.
|
||||
// Colour string `access:"reporting,user_management_groups"`
|
||||
//
|
||||
// // Product is only writeable by PermissionManageSystem if ExperimentalSettings.RestrictSystemAdmin is false.
|
||||
// // PermissionManageSystem can always read the value.
|
||||
// Product bool `access:write_restrictable`
|
||||
// }
|
||||
// // Length is only readable and writable via PermissionManageSystem.
|
||||
// Length string
|
||||
//
|
||||
// // Product is only writeable by PermissionManageSystem if ExperimentalSettings.RestrictSystemAdmin is false.
|
||||
// // PermissionManageSystem can always read the value.
|
||||
// Product bool `access:write_restrictable`
|
||||
// }
|
||||
type Config struct {
|
||||
ServiceSettings ServiceSettings
|
||||
TeamSettings TeamSettings
|
||||
@@ -3500,19 +3501,19 @@ func (s *LdapSettings) isValid() *AppError {
|
||||
|
||||
if *s.UserFilter != "" {
|
||||
if _, err := ldap.CompileFilter(*s.UserFilter); err != nil {
|
||||
return NewAppError("ValidateFilter", "ent.ldap.validate_filter.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("ValidateFilter", "ent.ldap.validate_filter.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
if *s.GuestFilter != "" {
|
||||
if _, err := ldap.CompileFilter(*s.GuestFilter); err != nil {
|
||||
return NewAppError("LdapSettings.isValid", "ent.ldap.validate_guest_filter.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("LdapSettings.isValid", "ent.ldap.validate_guest_filter.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
if *s.AdminFilter != "" {
|
||||
if _, err := ldap.CompileFilter(*s.AdminFilter); err != nil {
|
||||
return NewAppError("LdapSettings.isValid", "ent.ldap.validate_admin_filter.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("LdapSettings.isValid", "ent.ldap.validate_admin_filter.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3644,13 +3645,13 @@ func (s *ServiceSettings) isValid() *AppError {
|
||||
|
||||
if *s.SiteURL != "" {
|
||||
if _, err := url.ParseRequestURI(*s.SiteURL); err != nil {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
if *s.WebsocketURL != "" {
|
||||
if _, err := url.ParseRequestURI(*s.WebsocketURL); err != nil {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.websocket_url.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.websocket_url.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3706,7 +3707,7 @@ func (s *ElasticsearchSettings) isValid() *AppError {
|
||||
}
|
||||
|
||||
if _, err := time.Parse("15:04", *s.PostsAggregatorJobStartTime); err != nil {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.posts_aggregator_job_start_time.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.posts_aggregator_job_start_time.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
if *s.LiveIndexingBatchSize < 1 {
|
||||
@@ -3756,7 +3757,7 @@ func (s *DataRetentionSettings) isValid() *AppError {
|
||||
}
|
||||
|
||||
if _, err := time.Parse("15:04", *s.DeletionJobStartTime); err != nil {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.data_retention.deletion_job_start_time.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.data_retention.deletion_job_start_time.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -3782,7 +3783,7 @@ func (s *MessageExportSettings) isValid() *AppError {
|
||||
} else if s.DailyRunTime == nil {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.daily_runtime.app_error", nil, "", http.StatusBadRequest)
|
||||
} else if _, err := time.Parse("15:04", *s.DailyRunTime); err != nil {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.daily_runtime.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.daily_runtime.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
} else if s.BatchSize == nil || *s.BatchSize < 0 {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.batch_size.app_error", nil, "", http.StatusBadRequest)
|
||||
} else if s.ExportFormat == nil || (*s.ExportFormat != ComplianceExportTypeActiance && *s.ExportFormat != ComplianceExportTypeGlobalrelay && *s.ExportFormat != ComplianceExportTypeCsv) {
|
||||
|
||||
@@ -161,7 +161,7 @@ func GetInfoForBytes(name string, data io.ReadSeeker, size int) (*FileInfo, *App
|
||||
if err != nil {
|
||||
// Still return the rest of the info even though it doesn't appear to be an actual gif
|
||||
info.HasPreviewImage = true
|
||||
return info, NewAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return info, NewAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
info.HasPreviewImage = frameCount == 1
|
||||
} else {
|
||||
|
||||
@@ -123,22 +123,24 @@ func (o *IncomingWebhook) PreUpdate() {
|
||||
// try to handle that. An example invalid JSON string from an incoming webhook
|
||||
// might look like this (strings for both "text" and "fallback" attributes are
|
||||
// invalid JSON strings because they contain unescaped newlines and tabs):
|
||||
// `{
|
||||
// "text": "this is a test
|
||||
// that contains a newline and tabs",
|
||||
// "attachments": [
|
||||
// {
|
||||
// "fallback": "Required plain-text summary of the attachment
|
||||
// that contains a newline and tabs",
|
||||
// "color": "#36a64f",
|
||||
// ...
|
||||
// "text": "Optional text that appears within the attachment
|
||||
// that contains a newline and tabs",
|
||||
// ...
|
||||
// "thumb_url": "http://example.com/path/to/thumb.png"
|
||||
// }
|
||||
// ]
|
||||
// }`
|
||||
//
|
||||
// `{
|
||||
// "text": "this is a test
|
||||
// that contains a newline and tabs",
|
||||
// "attachments": [
|
||||
// {
|
||||
// "fallback": "Required plain-text summary of the attachment
|
||||
// that contains a newline and tabs",
|
||||
// "color": "#36a64f",
|
||||
// ...
|
||||
// "text": "Optional text that appears within the attachment
|
||||
// that contains a newline and tabs",
|
||||
// ...
|
||||
// "thumb_url": "http://example.com/path/to/thumb.png"
|
||||
// }
|
||||
// ]
|
||||
// }`
|
||||
//
|
||||
// This function will search for `"key": "value"` pairs, and escape \n, \t
|
||||
// from the value.
|
||||
func escapeControlCharsFromPayload(by []byte) []byte {
|
||||
@@ -191,7 +193,7 @@ func IncomingWebhookRequestFromJSON(data io.Reader) (*IncomingWebhookRequest, *A
|
||||
if err != nil {
|
||||
o, err = decodeIncomingWebhookRequest(escapeControlCharsFromPayload(by))
|
||||
if err != nil {
|
||||
return nil, NewAppError("IncomingWebhookRequestFromJSON", "model.incoming_hook.parse_data.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return nil, NewAppError("IncomingWebhookRequestFromJSON", "model.incoming_hook.parse_data.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ func GenerateTriggerId(userId string, s crypto.Signer) (string, string, *AppErro
|
||||
sum.Write([]byte(triggerData))
|
||||
signature, err := s.Sign(rand.Reader, sum.Sum(nil), h)
|
||||
if err != nil {
|
||||
return "", "", NewAppError("GenerateTriggerId", "interactive_message.generate_trigger_id.signing_failed", nil, err.Error(), http.StatusInternalServerError)
|
||||
return "", "", NewAppError("GenerateTriggerId", "interactive_message.generate_trigger_id.signing_failed", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
base64Sig := base64.StdEncoding.EncodeToString(signature)
|
||||
@@ -283,7 +283,7 @@ func (r *PostActionIntegrationRequest) GenerateTriggerId(s crypto.Signer) (strin
|
||||
func DecodeAndVerifyTriggerId(triggerId string, s *ecdsa.PrivateKey) (string, string, *AppError) {
|
||||
triggerIdBytes, err := base64.StdEncoding.DecodeString(triggerId)
|
||||
if err != nil {
|
||||
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed", nil, err.Error(), http.StatusBadRequest)
|
||||
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
split := strings.Split(string(triggerIdBytes), ":")
|
||||
@@ -303,7 +303,7 @@ func DecodeAndVerifyTriggerId(triggerId string, s *ecdsa.PrivateKey) (string, st
|
||||
|
||||
signature, err := base64.StdEncoding.DecodeString(split[3])
|
||||
if err != nil {
|
||||
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed_signature", nil, err.Error(), http.StatusBadRequest)
|
||||
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed_signature", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
var esig struct {
|
||||
@@ -311,7 +311,7 @@ func DecodeAndVerifyTriggerId(triggerId string, s *ecdsa.PrivateKey) (string, st
|
||||
}
|
||||
|
||||
if _, err := asn1.Unmarshal(signature, &esig); err != nil {
|
||||
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.signature_decode_failed", nil, err.Error(), http.StatusBadRequest)
|
||||
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.signature_decode_failed", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
triggerData := strings.Join([]string{clientTriggerId, userId, timestampStr}, ":") + ":"
|
||||
|
||||
@@ -79,7 +79,7 @@ func (us *UploadSession) IsValid() *AppError {
|
||||
}
|
||||
|
||||
if err := us.Type.IsValid(); err != nil {
|
||||
return NewAppError("UploadSession.IsValid", "model.upload_session.is_valid.type.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
return NewAppError("UploadSession.IsValid", "model.upload_session.is_valid.type.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
if !IsValidId(us.UserId) && us.UserId != UploadNoUserID {
|
||||
|
||||
@@ -381,7 +381,7 @@ func (u *User) IsValid() *AppError {
|
||||
|
||||
if len(u.Timezone) > 0 {
|
||||
if tzJSON, err := json.Marshal(u.Timezone); err != nil {
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.marshal.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return NewAppError("User.IsValid", "model.user.is_valid.marshal.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
} else if utf8.RuneCount(tzJSON) > UserTimezoneMaxRunes {
|
||||
return InvalidUserError("timezone_limit", u.Id)
|
||||
}
|
||||
|
||||
@@ -234,12 +234,11 @@ func (er *AppError) Error() string {
|
||||
sb.WriteString(er.DetailedError)
|
||||
}
|
||||
|
||||
// render all wrapped errors
|
||||
// render the wrapped error
|
||||
err := er.wrapped
|
||||
for err != nil {
|
||||
if err != nil {
|
||||
sb.WriteString(", ")
|
||||
sb.WriteString(err.Error())
|
||||
err = errors.Unwrap(err)
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
|
||||
@@ -103,12 +103,12 @@ func TestAppErrorRender(t *testing.T) {
|
||||
|
||||
t.Run("WrappedMultiple", func(t *testing.T) {
|
||||
aerr := NewAppError("here", "message", nil, "", http.StatusTeapot).Wrap(fmt.Errorf("my error (%w)", fmt.Errorf("inner error")))
|
||||
assert.EqualError(t, aerr, "here: message, my error (inner error), inner error")
|
||||
assert.EqualError(t, aerr, "here: message, my error (inner error)")
|
||||
})
|
||||
|
||||
t.Run("DetailedWrappedMultiple", func(t *testing.T) {
|
||||
aerr := NewAppError("here", "message", nil, "details", http.StatusTeapot).Wrap(fmt.Errorf("my error (%w)", fmt.Errorf("inner error")))
|
||||
assert.EqualError(t, aerr, "here: message, details, my error (inner error), inner error")
|
||||
assert.EqualError(t, aerr, "here: message, details, my error (inner error)")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func NewWebSocketClientWithDialer(dialer *websocket.Dialer, url, authToken strin
|
||||
func makeClient(dialer *websocket.Dialer, url, connectURL, authToken string, header http.Header) (*WebSocketClient, error) {
|
||||
conn, _, err := dialer.Dial(connectURL, header)
|
||||
if err != nil {
|
||||
return nil, NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return nil, NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
client := &WebSocketClient{
|
||||
@@ -140,7 +140,7 @@ func (wsc *WebSocketClient) ConnectWithDialer(dialer *websocket.Dialer) *AppErro
|
||||
var err error
|
||||
wsc.Conn, _, err = dialer.Dial(wsc.ConnectURL, nil)
|
||||
if err != nil {
|
||||
return NewAppError("Connect", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return NewAppError("Connect", "model.websocket_client.connect_fail.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
// Super racy and should not be done anyways.
|
||||
// All of this needs to be redesigned for v6.
|
||||
@@ -235,7 +235,7 @@ func (wsc *WebSocketClient) Listen() {
|
||||
_, r, err := wsc.Conn.NextReader()
|
||||
if err != nil {
|
||||
if !websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseNoStatusReceived) {
|
||||
wsc.ListenError = NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
wsc.ListenError = NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -245,7 +245,7 @@ func (wsc *WebSocketClient) Listen() {
|
||||
// This should use a different error ID, but en.json is not imported anyways.
|
||||
// It's a different bug altogether but we let it be for now.
|
||||
// See MM-24520.
|
||||
wsc.ListenError = NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
wsc.ListenError = NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user