From 92837fa1ee69c4420ea0033a35b5058ca8afc76f Mon Sep 17 00:00:00 2001 From: Claudio Costa Date: Wed, 1 Sep 2021 14:43:12 +0200 Subject: [PATCH] [MM-22051] Remove To/From JSON (#18070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Posts * Add missing translation * Fix internal store marshaling * [MM-22051] Remove To/From JSON (Channels) (#18116) * Channels * Channel members * ChannelSearch * Channel categories, list, sidebar, stats, view * Fix conversions * [MM-22051] Remove To/From JSON (Users) (#18121) * User related structs * Fix return * Team related structures (#18127) * [MM-22051] Remove To/From JSON (Status, Bot, Reaction, Thread, FileInfo) (#18130) * Status * Bot * Reaction * Thread * FileInfo * Some fixes * Translations update from Weblate (#18143) * Translated using Weblate (German) Currently translated at 100.0% (2309 of 2309 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ * Translated using Weblate (Turkish) Currently translated at 100.0% (2309 of 2309 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2309 of 2309 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/hu/ * Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ * Translated using Weblate (German) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ * Translated using Weblate (Turkish) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/hu/ * Translated using Weblate (English (Australia)) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/en_AU/ * Translated using Weblate (Bulgarian) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/bg/ * Translated using Weblate (Japanese) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ja/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/zh_Hans/ Co-authored-by: JtheBAB Co-authored-by: Kaya Zeren Co-authored-by: Tóth Csaba // Online ERP Hungary Kft Co-authored-by: Matthew Williams Co-authored-by: Nikolai Zahariev Co-authored-by: kaakaa Co-authored-by: aeomin Co-authored-by: Weblate (bot) Co-authored-by: JtheBAB Co-authored-by: Kaya Zeren Co-authored-by: Tóth Csaba // Online ERP Hungary Kft Co-authored-by: Matthew Williams Co-authored-by: Nikolai Zahariev Co-authored-by: kaakaa Co-authored-by: aeomin * [MM-22051] Remove To/From JSON methods from model (#18138) * Scheme * Role * Session * Config * Status * Fix logic * Emoji * GuestsInvite * Group * Command * ClusterInfo * License * Job * System * Plugin * Command2 * IncomingWebhook * OutgoingWebhook * Fix tests * Update traslation * Some fixes * Add missing return * Simplify * Make Config.ToJSONFiltered() return []byte * Make Busy.ToJSON() return []byte * Include error in log * Split logic * [MM-22051] Remove To/From JSON (final) (#18150) * SwitchRequest * PluginEventData * Permalink * PushNotification * SuggestCommand * PluginsResponse * WebSocketMessage * RemoteCluster * SharedChannel * PluginStatuses * InitialLoad * ClusterDiscovery * ClusterStats * MfaSecret * GroupSyncable * SAML * WebSocketRequest * TypingRequest * SecurityBulletin * OAuthApp * IntegrationAction * DataRetention * Preference * FileInfoList * Compliance * Preferences * FileInfoSearchResults * TermsOfService * InstallMarketplacePluginRequest * GitLabUser * UploadSessions * Remove unused helpers * Fix tests * [MM-23280] Fix linting for ToJSON/FromJSON (#18153) * SwitchRequest * PluginEventData * Permalink * PushNotification * SuggestCommand * PluginsResponse * WebSocketMessage * RemoteCluster * SharedChannel * PluginStatuses * InitialLoad * ClusterDiscovery * ClusterStats * MfaSecret * GroupSyncable * SAML * WebSocketRequest * TypingRequest * SecurityBulletin * OAuthApp * IntegrationAction * DataRetention * Preference * FileInfoList * Compliance * Preferences * FileInfoSearchResults * TermsOfService * InstallMarketplacePluginRequest * GitLabUser * UploadSessions * Remove unused helpers * Fix tests * Fix linting for ToJSON/FromJSON * Fix conversions Co-authored-by: Weblate (bot) Co-authored-by: JtheBAB Co-authored-by: Kaya Zeren Co-authored-by: Tóth Csaba // Online ERP Hungary Kft Co-authored-by: Matthew Williams Co-authored-by: Nikolai Zahariev Co-authored-by: kaakaa Co-authored-by: aeomin Co-authored-by: Mattermod --- api4/apitestlib.go | 2 +- api4/bot.go | 7 +- api4/channel.go | 37 +- api4/channel_category.go | 47 +- api4/channel_local.go | 6 +- api4/channel_test.go | 4 +- api4/cluster.go | 8 +- api4/command.go | 31 +- api4/command_local.go | 6 +- api4/compliance.go | 6 +- api4/config.go | 35 +- api4/config_local.go | 4 +- api4/data_retention.go | 87 +- api4/elasticsearch.go | 2 +- api4/emoji.go | 11 +- api4/file.go | 5 +- api4/file_test.go | 9 +- api4/group.go | 6 +- api4/integration_action.go | 6 +- api4/integration_action_test.go | 5 +- api4/job.go | 26 +- api4/ldap.go | 2 +- api4/license.go | 4 +- api4/license_test.go | 7 +- api4/oauth.go | 27 +- api4/openGraph.go | 2 +- api4/plugin.go | 7 +- api4/post.go | 35 +- api4/post_test.go | 20 +- api4/preference.go | 8 +- api4/preference_test.go | 12 +- api4/reaction.go | 24 +- api4/remote_cluster.go | 36 +- api4/role.go | 17 +- api4/saml.go | 2 +- api4/scheme.go | 30 +- api4/status.go | 29 +- api4/system.go | 56 +- api4/team.go | 184 +- api4/team_local.go | 16 +- api4/team_test.go | 11 +- api4/terms_of_service.go | 2 +- api4/upload.go | 8 +- api4/upload_test.go | 9 +- api4/user.go | 199 ++- api4/user_local.go | 26 +- api4/user_test.go | 20 +- api4/webhook.go | 38 +- api4/webhook_local.go | 12 +- app/busy.go | 10 +- app/busy_test.go | 15 +- app/channel.go | 54 +- app/cluster_handlers.go | 29 +- app/command_autocomplete.go | 6 +- app/email/email.go | 8 +- app/emoji.go | 7 +- app/group.go | 14 +- app/import_validators.go | 2 +- app/integration_action.go | 10 +- app/integration_action_test.go | 30 +- app/license.go | 31 +- app/notification.go | 18 +- app/notification_push.go | 21 +- app/notification_push_test.go | 27 +- app/oauth.go | 8 +- app/oauth_test.go | 8 +- .../main.go | 14 +- app/plugin_install_test.go | 5 +- app/plugin_requests.go | 4 +- app/post.go | 32 +- app/preference.go | 14 +- app/reaction.go | 8 +- app/role.go | 8 +- app/security_update_check.go | 7 +- app/slashcommands/command_expand_collapse.go | 9 +- app/slashcommands/command_loadtest.go | 7 +- app/slashcommands/command_share_test.go | 8 +- app/status.go | 38 +- app/team.go | 23 +- app/team_test.go | 28 +- app/user.go | 18 +- app/user_test.go | 23 +- app/web_conn_test.go | 11 +- app/web_hub.go | 6 +- app/webhook.go | 22 +- app/webhook_test.go | 10 +- einterfaces/mocks/OAuthProvider.go | 4 +- einterfaces/oauthproviders.go | 2 +- i18n/en.json | 10 +- migrations/advanced_permissions_phase_2.go | 18 +- model/bot.go | 23 - model/channel.go | 6 - model/channel_list.go | 20 - model/channel_member.go | 6 - model/channel_search.go | 10 - model/channel_sidebar.go | 22 - model/channel_stats.go | 11 - model/channel_view.go | 17 - model/client4.go | 1580 +++++++++++++---- model/client4_test.go | 12 +- model/cluster_discovery.go | 13 - model/cluster_discovery_test.go | 24 +- model/cluster_info.go | 26 - model/cluster_info_test.go | 21 - model/cluster_stats.go | 11 - model/command.go | 15 - model/command_args.go | 9 - model/command_autocomplete.go | 45 - model/command_autocomplete_test.go | 9 - model/command_request.go | 15 - model/command_response.go | 4 +- model/command_response_test.go | 4 +- model/compliance.go | 15 - model/config.go | 7 +- model/config_test.go | 5 +- model/custom_status.go | 74 +- model/data_retention_policy.go | 62 - model/emoji.go | 19 - model/emoji_search.go | 16 - model/emoji_search_test.go | 19 - model/file.go | 16 - model/file_info.go | 31 - model/file_info_list.go | 17 - model/file_info_search_results.go | 19 - model/gitlab/gitlab.go | 14 +- model/group.go | 31 - model/group_syncable.go | 16 - model/guest_invite.go | 14 - model/incoming_webhook.go | 35 +- model/incoming_webhook_test.go | 14 +- model/initial_load.go | 16 - model/initial_load_test.go | 20 - model/integration_action.go | 62 - model/integration_action_test.go | 81 - model/job.go | 33 - model/license.go | 17 - model/license_test.go | 64 - model/link_metadata_test.go | 6 +- model/manifest.go | 23 - model/manifest_test.go | 51 - model/marketplace_plugin.go | 9 - model/mfa_secret.go | 16 - model/mfa_secret_test.go | 19 - model/modeltestlib_test.go | 8 - model/oauth.go | 24 - model/oauth_test.go | 16 - model/outgoing_webhook.go | 43 - model/outgoing_webhook_test.go | 18 - model/permalink.go | 7 - model/plugin_event_data.go | 16 - model/plugin_status.go | 16 - model/plugins_response.go | 16 - model/plugins_response_test.go | 34 - model/post.go | 68 +- model/post_list.go | 14 +- model/post_list_test.go | 11 +- model/post_metadata.go | 9 - model/post_search_results.go | 14 +- model/post_test.go | 45 +- model/preference.go | 12 +- model/preferences.go | 26 - model/push_notification.go | 36 - model/push_notification_test.go | 47 - model/push_response.go | 20 - model/push_response_test.go | 10 - model/reaction.go | 45 - model/remote_cluster.go | 53 - model/remote_cluster_test.go | 29 - model/role.go | 35 - model/saml.go | 24 - model/saml_test.go | 22 - model/scheme.go | 59 - model/security_bulletin.go | 30 - model/security_bulletin_test.go | 53 - model/session.go | 27 - model/session_test.go | 20 - model/shared_channel.go | 24 - model/shared_channel_test.go | 20 - model/status.go | 41 +- model/status_test.go | 36 +- model/suggest_command.go | 16 - model/suggest_command_test.go | 19 - model/switch_request.go | 16 - model/switch_request_test.go | 19 - model/system.go | 53 - model/system_test.go | 30 - model/team.go | 78 - model/team_member.go | 80 - model/team_member_test.go | 23 - model/team_search.go | 27 - model/team_search_test.go | 21 - model/team_stats.go | 16 - model/team_test.go | 8 - model/terms_of_service.go | 13 - model/terms_of_service_test.go | 14 - model/thread.go | 36 - model/typing_request.go | 16 - model/typing_request_test.go | 20 - model/upload_session.go | 35 - model/user.go | 75 +- model/user_access_token.go | 24 - model/user_access_token_search.go | 27 - model/user_access_token_search_test.go | 18 - model/user_access_token_test.go | 18 - model/user_autocomplete.go | 42 - model/user_search.go | 23 - model/user_search_test.go | 19 - model/user_terms_of_service.go | 13 - ..._test.go => user_terms_of_service_test.go} | 15 - model/user_test.go | 8 - model/users_stats.go | 16 - model/utils.go | 36 +- model/utils_test.go | 12 +- model/websocket_client.go | 7 +- model/websocket_message.go | 37 +- model/websocket_message_test.go | 43 +- model/websocket_request.go | 12 - model/websocket_request_test.go | 23 - plugin/environment_test.go | 5 +- services/remotecluster/ping_test.go | 13 +- services/remotecluster/send_test.go | 7 +- .../remotecluster/sendprofileImage_test.go | 4 +- store/sqlstore/adapters.go | 16 +- store/sqlstore/channel_store.go | 4 +- store/sqlstore/job_store.go | 7 +- store/sqlstore/post_store.go | 6 +- store/sqlstore/session_store.go | 2 +- store/sqlstore/thread_store.go | 2 +- store/sqlstore/user_store.go | 2 +- store/storetest/channel_store.go | 39 +- store/storetest/link_metadata_store.go | 1 - store/storetest/mocks/JSONSerializable.go | 4 +- store/storetest/preference_store.go | 6 +- store/storetest/team_store.go | 2 +- utils/license.go | 19 +- web/handlers.go | 2 +- web/oauth.go | 4 +- web/oauth_test.go | 26 +- web/saml.go | 4 +- web/web.go | 4 +- web/webhook.go | 6 +- wsapi/status.go | 2 +- 242 files changed, 2812 insertions(+), 3975 deletions(-) delete mode 100644 model/cluster_info_test.go delete mode 100644 model/emoji_search_test.go delete mode 100644 model/initial_load_test.go delete mode 100644 model/mfa_secret_test.go delete mode 100644 model/plugins_response_test.go delete mode 100644 model/preferences.go delete mode 100644 model/saml_test.go delete mode 100644 model/security_bulletin_test.go delete mode 100644 model/suggest_command_test.go delete mode 100644 model/switch_request_test.go delete mode 100644 model/system_test.go delete mode 100644 model/team_search_test.go delete mode 100644 model/typing_request_test.go delete mode 100644 model/user_access_token_search_test.go delete mode 100644 model/user_search_test.go rename model/{user_terms_of_Service_test.go => user_terms_of_service_test.go} (62%) delete mode 100644 model/websocket_request_test.go diff --git a/api4/apitestlib.go b/api4/apitestlib.go index ce765a4ed3..25fa24f5e7 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -911,7 +911,7 @@ func CheckEtag(t *testing.T, data interface{}, resp *model.Response) { t.Helper() require.Empty(t, data) - require.Equal(t, resp.StatusCode, http.StatusNotModified, "wrong status code for etag") + require.Equal(t, http.StatusNotModified, resp.StatusCode, "wrong status code for etag") } func checkHTTPStatus(t *testing.T, resp *model.Response, expectedStatus int) { diff --git a/api4/bot.go b/api4/bot.go index 98f410e0e4..fc948af374 100644 --- a/api4/bot.go +++ b/api4/bot.go @@ -279,8 +279,9 @@ func convertBotToUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - userPatch := model.UserPatchFromJson(r.Body) - if userPatch == nil || userPatch.Password == nil || *userPatch.Password == "" { + var userPatch model.UserPatch + jsonErr := json.NewDecoder(r.Body).Decode(&userPatch) + if jsonErr != nil || userPatch.Password == nil || *userPatch.Password == "" { c.SetInvalidParam("userPatch") return } @@ -298,7 +299,7 @@ func convertBotToUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - user, err := c.App.ConvertBotToUser(bot, userPatch, systemAdmin) + user, err := c.App.ConvertBotToUser(bot, &userPatch, systemAdmin) if err != nil { c.Err = err return diff --git a/api4/channel.go b/api4/channel.go index deeee292dd..db80ad8ab0 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -233,7 +233,7 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) privacy, ok := props["privacy"].(string) if !ok || (model.ChannelType(privacy) != model.ChannelTypeOpen && model.ChannelType(privacy) != model.ChannelTypePrivate) { c.SetInvalidParam("privacy") @@ -395,7 +395,7 @@ func restoreChannel(c *Context, w http.ResponseWriter, r *http.Request) { } func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) { - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) allowed := false if len(userIds) != 2 { @@ -479,7 +479,7 @@ func searchGroupChannels(c *Context, w http.ResponseWriter, r *http.Request) { } func createGroupChannel(c *Context, w http.ResponseWriter, r *http.Request) { - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) if len(userIds) == 0 { c.SetInvalidParam("user_ids") @@ -816,7 +816,7 @@ func getPublicChannelsByIdsForTeam(c *Context, w http.ResponseWriter, r *http.Re return } - channelIds := model.ArrayFromJson(r.Body) + channelIds := model.ArrayFromJSON(r.Body) if len(channelIds) == 0 { c.SetInvalidParam("channel_ids") return @@ -1244,7 +1244,7 @@ func getChannelMembersTimezones(c *Context, w http.ResponseWriter, r *http.Reque return } - w.Write([]byte(model.ArrayToJson(membersTimezones))) + w.Write([]byte(model.ArrayToJSON(membersTimezones))) } func getChannelMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1253,7 +1253,7 @@ func getChannelMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) return } - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) if len(userIds) == 0 { c.SetInvalidParam("user_ids") return @@ -1335,8 +1335,8 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) { return } - view := model.ChannelViewFromJson(r.Body) - if view == nil { + var view model.ChannelView + if jsonErr := json.NewDecoder(r.Body).Decode(&view); jsonErr != nil { c.SetInvalidParam("channel_view") return } @@ -1352,7 +1352,7 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) { return } - times, err := c.App.ViewChannel(view, c.Params.UserId, c.AppContext.Session().Id, view.CollapsedThreadsSupported) + times, err := c.App.ViewChannel(&view, c.Params.UserId, c.AppContext.Session().Id, view.CollapsedThreadsSupported) if err != nil { c.Err = err return @@ -1378,7 +1378,7 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) newRoles := props["roles"] if !(model.IsValidUserRoles(newRoles)) { @@ -1412,8 +1412,8 @@ func updateChannelMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.R return } - schemeRoles := model.SchemeRolesFromJson(r.Body) - if schemeRoles == nil { + var schemeRoles model.SchemeRoles + if jsonErr := json.NewDecoder(r.Body).Decode(&schemeRoles); jsonErr != nil { c.SetInvalidParam("scheme_roles") return } @@ -1444,7 +1444,7 @@ func updateChannelMemberNotifyProps(c *Context, w http.ResponseWriter, r *http.R return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) if props == nil { c.SetInvalidParam("notify_props") return @@ -1477,7 +1477,7 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) userId, ok := props["user_id"].(string) if !ok || !model.IsValidId(userId) { c.SetInvalidParam("user_id") @@ -1663,15 +1663,16 @@ func updateChannelScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - schemeID := model.SchemeIDFromJson(r.Body) - if schemeID == nil || !model.IsValidId(*schemeID) { + var p model.SchemeIDPatch + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil || p.SchemeID == nil || !model.IsValidId(*p.SchemeID) { c.SetInvalidParam("scheme_id") return } + schemeID := p.SchemeID auditRec := c.MakeAuditRecord("updateChannelScheme", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddMeta("new_scheme_id", schemeID) + auditRec.AddMeta("new_scheme_id", *schemeID) if c.App.Srv().License() == nil { c.Err = model.NewAppError("Api4.UpdateChannelScheme", "api.channel.update_channel_scheme.license.error", nil, "", http.StatusNotImplemented) @@ -1898,7 +1899,7 @@ func moveChannel(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) teamId, ok := props["team_id"].(string) if !ok { c.SetInvalidParam("team_id") diff --git a/api4/channel_category.go b/api4/channel_category.go index c61f64006c..0e7c7f3165 100644 --- a/api4/channel_category.go +++ b/api4/channel_category.go @@ -29,7 +29,13 @@ func getCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.Requ return } - w.Write(categories.ToJson()) + categoriesJSON, jsonErr := json.Marshal(categories) + if jsonErr != nil { + c.Err = model.NewAppError("getCategoriesForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(categoriesJSON) } func createCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -64,8 +70,15 @@ func createCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Req return } + categoryJSON, jsonErr := json.Marshal(category) + if jsonErr != nil { + c.Err = model.NewAppError("createCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + auditRec.Success() - w.Write(category.ToJson()) + + w.Write(categoryJSON) } func getCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -85,7 +98,7 @@ func getCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *http.R return } - w.Write([]byte(model.ArrayToJson(order))) + w.Write([]byte(model.ArrayToJSON(order))) } func updateCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -102,7 +115,7 @@ func updateCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *htt auditRec := c.MakeAuditRecord("updateCategoryOrderForTeamForUser", audit.Fail) defer c.LogAuditRec(auditRec) - categoryOrder := model.ArrayFromJson(r.Body) + categoryOrder := model.ArrayFromJSON(r.Body) for _, categoryId := range categoryOrder { if !c.App.SessionHasPermissionToCategory(*c.AppContext.Session(), c.Params.UserId, c.Params.TeamId, categoryId) { @@ -118,7 +131,7 @@ func updateCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *htt } auditRec.Success() - w.Write([]byte(model.ArrayToJson(categoryOrder))) + w.Write([]byte(model.ArrayToJSON(categoryOrder))) } func getCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -138,7 +151,13 @@ func getCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Reques return } - w.Write(categories.ToJson()) + categoriesJSON, jsonErr := json.Marshal(categories) + if jsonErr != nil { + c.Err = model.NewAppError("getCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(categoriesJSON) } func updateCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -180,8 +199,14 @@ func updateCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.R return } + categoriesJSON, jsonErr := json.Marshal(categories) + if jsonErr != nil { + c.Err = model.NewAppError("updateCategoriesForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + auditRec.Success() - w.Write(model.SidebarCategoriesWithChannelsToJson(categories)) + w.Write(categoriesJSON) } func validateSidebarCategory(c *Context, teamId, userId string, category *model.SidebarCategoryWithChannels) *model.AppError { @@ -264,8 +289,14 @@ func updateCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Req return } + categoryJSON, jsonErr := json.Marshal(categories[0]) + if jsonErr != nil { + c.Err = model.NewAppError("updateCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + auditRec.Success() - w.Write(categories[0].ToJson()) + w.Write(categoryJSON) } func deleteCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api4/channel_local.go b/api4/channel_local.go index 82b98bb9fa..8fe5f2e9b1 100644 --- a/api4/channel_local.go +++ b/api4/channel_local.go @@ -71,7 +71,7 @@ func localUpdateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Reques return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) privacy, ok := props["privacy"].(string) if !ok || (model.ChannelType(privacy) != model.ChannelTypeOpen && model.ChannelType(privacy) != model.ChannelTypePrivate) { c.SetInvalidParam("privacy") @@ -145,7 +145,7 @@ func localAddChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) userId, ok := props["user_id"].(string) if !ok || !model.IsValidId(userId) { c.SetInvalidParam("user_id") @@ -326,7 +326,7 @@ func localMoveChannel(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) teamId, ok := props["team_id"].(string) if !ok { c.SetInvalidParam("team_id") diff --git a/api4/channel_test.go b/api4/channel_test.go index fa82aa5aa8..8146892b15 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -5,6 +5,7 @@ package api4 import ( "context" + "encoding/json" "fmt" "net/http" "os" @@ -3071,7 +3072,8 @@ func TestRemoveChannelMember(t *testing.T) { continue } - post := model.PostFromJson(strings.NewReader(postData.(string))) + var post model.Post + json.Unmarshal([]byte(postData.(string)), &post) if post.ChannelId == expectedPost.ChannelId && post.Message == expectedPost.Message { return } diff --git a/api4/cluster.go b/api4/cluster.go index 1ee33a46f0..a51c7fbb06 100644 --- a/api4/cluster.go +++ b/api4/cluster.go @@ -4,6 +4,7 @@ package api4 import ( + "encoding/json" "net/http" "github.com/mattermost/mattermost-server/v6/model" @@ -25,5 +26,10 @@ func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) { } infos := c.App.GetClusterStatus() - w.Write([]byte(model.ClusterInfosToJson(infos))) + js, jsonErr := json.Marshal(infos) + if jsonErr != nil { + c.Err = model.NewAppError("getClusterStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } diff --git a/api4/command.go b/api4/command.go index 7a62028aaf..4db1ee886c 100644 --- a/api4/command.go +++ b/api4/command.go @@ -30,8 +30,8 @@ func (api *API) InitCommand() { } func createCommand(c *Context, w http.ResponseWriter, r *http.Request) { - cmd := model.CommandFromJson(r.Body) - if cmd == nil { + var cmd model.Command + if jsonErr := json.NewDecoder(r.Body).Decode(&cmd); jsonErr != nil { c.SetInvalidParam("command") return } @@ -47,7 +47,7 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) { cmd.CreatorId = c.AppContext.Session().UserId - rcmd, err := c.App.CreateCommand(cmd) + rcmd, err := c.App.CreateCommand(&cmd) if err != nil { c.Err = err return @@ -69,8 +69,8 @@ func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) { return } - cmd := model.CommandFromJson(r.Body) - if cmd == nil || cmd.Id != c.Params.CommandId { + var cmd model.Command + if jsonErr := json.NewDecoder(r.Body).Decode(&cmd); jsonErr != nil || cmd.Id != c.Params.CommandId { c.SetInvalidParam("command") return } @@ -106,7 +106,7 @@ func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) { return } - rcmd, err := c.App.UpdateCommand(oldCmd, cmd) + rcmd, err := c.App.UpdateCommand(oldCmd, &cmd) if err != nil { c.Err = err return @@ -126,8 +126,8 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) { return } - cmr, err := model.CommandMoveRequestFromJson(r.Body) - if err != nil { + var cmr model.CommandMoveRequest + if jsonErr := json.NewDecoder(r.Body).Decode(&cmr); jsonErr != nil { c.SetInvalidParam("team_id") return } @@ -298,8 +298,8 @@ func getCommand(c *Context, w http.ResponseWriter, r *http.Request) { } func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) { - commandArgs := model.CommandArgsFromJson(r.Body) - if commandArgs == nil { + var commandArgs model.CommandArgs + if jsonErr := json.NewDecoder(r.Body).Decode(&commandArgs); jsonErr != nil { c.SetInvalidParam("command_args") return } @@ -347,7 +347,7 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("commandargs", commandArgs) // overwrite in case teamid changed - response, err := c.App.ExecuteCommand(c.AppContext, commandArgs) + response, err := c.App.ExecuteCommand(c.AppContext, &commandArgs) if err != nil { c.Err = err return @@ -423,7 +423,12 @@ func listCommandAutocompleteSuggestions(c *Context, w http.ResponseWriter, r *ht suggestions := c.App.GetSuggestions(c.AppContext, commandArgs, commands, roleId) - w.Write(model.AutocompleteSuggestionsToJSON(suggestions)) + js, jsonErr := json.Marshal(suggestions) + if jsonErr != nil { + c.Err = model.NewAppError("listCommandAutocompleteSuggestions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) { @@ -470,5 +475,5 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) { resp := make(map[string]string) resp["token"] = rcmd.Token - w.Write([]byte(model.MapToJson(resp))) + w.Write([]byte(model.MapToJSON(resp))) } diff --git a/api4/command_local.go b/api4/command_local.go index fa59673aa2..d14d6a10eb 100644 --- a/api4/command_local.go +++ b/api4/command_local.go @@ -23,8 +23,8 @@ func (api *API) InitCommandLocal() { } func localCreateCommand(c *Context, w http.ResponseWriter, r *http.Request) { - cmd := model.CommandFromJson(r.Body) - if cmd == nil { + var cmd model.Command + if jsonErr := json.NewDecoder(r.Body).Decode(&cmd); jsonErr != nil { c.SetInvalidParam("command") return } @@ -33,7 +33,7 @@ func localCreateCommand(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) c.LogAudit("attempt") - rcmd, err := c.App.CreateCommand(cmd) + rcmd, err := c.App.CreateCommand(&cmd) if err != nil { c.Err = err return diff --git a/api4/compliance.go b/api4/compliance.go index f45b3de7b5..32d1380eea 100644 --- a/api4/compliance.go +++ b/api4/compliance.go @@ -23,8 +23,8 @@ func (api *API) InitCompliance() { } func createComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) { - job := model.ComplianceFromJson(r.Body) - if job == nil { + var job model.Compliance + if jsonErr := json.NewDecoder(r.Body).Decode(&job); jsonErr != nil { c.SetInvalidParam("compliance") return } @@ -39,7 +39,7 @@ func createComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) job.UserId = c.AppContext.Session().UserId - rjob, err := c.App.SaveComplianceReport(job) + rjob, err := c.App.SaveComplianceReport(&job) if err != nil { c.Err = err return diff --git a/api4/config.go b/api4/config.go index bfaa13865b..1168c3fc90 100644 --- a/api4/config.go +++ b/api4/config.go @@ -69,7 +69,12 @@ func getConfig(c *Context, w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud { - w.Write([]byte(cfg.ToJsonFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable))) + js, jsonErr := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) + if jsonErr != nil { + c.Err = model.NewAppError("getConfig", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) return } if err := json.NewEncoder(w).Encode(cfg); err != nil { @@ -103,7 +108,7 @@ func configReload(c *Context, w http.ResponseWriter, r *http.Request) { } func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { c.SetInvalidParam("config") return @@ -170,7 +175,7 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { }, }) if mergeErr != nil { - c.Err = model.NewAppError("getConfig", "api.config.update_config.restricted_merge.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("updateConfig", "api.config.update_config.restricted_merge.app_error", nil, err.Error(), http.StatusInternalServerError) } auditRec.Success() @@ -178,7 +183,12 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud { - w.Write([]byte(cfg.ToJsonFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable))) + js, jsonErr := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) + if jsonErr != nil { + c.Err = model.NewAppError("updateConfig", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) return } @@ -207,7 +217,7 @@ func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) { config = c.App.ClientConfigWithComputed() } - w.Write([]byte(model.MapToJson(config))) + w.Write([]byte(model.MapToJSON(config))) } func getEnvironmentConfig(c *Context, w http.ResponseWriter, r *http.Request) { @@ -218,11 +228,11 @@ func getEnvironmentConfig(c *Context, w http.ResponseWriter, r *http.Request) { }) w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") - w.Write([]byte(model.StringInterfaceToJson(envConfig))) + w.Write([]byte(model.StringInterfaceToJSON(envConfig))) } func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { c.SetInvalidParam("config") return @@ -294,12 +304,17 @@ func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) { }, }) if mergeErr != nil { - c.Err = model.NewAppError("getConfig", "api.config.patch_config.restricted_merge.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("patchConfig", "api.config.patch_config.restricted_merge.app_error", nil, err.Error(), http.StatusInternalServerError) } w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud { - w.Write([]byte(cfg.ToJsonFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable))) + js, jsonErr := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) + if jsonErr != nil { + c.Err = model.NewAppError("patchConfig", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) return } @@ -372,7 +387,7 @@ func makeFilterConfigByPermission(accessType filterType) func(c *Context, struct } func migrateConfig(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) from, ok := props["from"].(string) if !ok { c.SetInvalidParam("from") diff --git a/api4/config_local.go b/api4/config_local.go index 6c82b78340..91ef138e43 100644 --- a/api4/config_local.go +++ b/api4/config_local.go @@ -35,7 +35,7 @@ func localGetConfig(c *Context, w http.ResponseWriter, r *http.Request) { } func localUpdateConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { c.SetInvalidParam("config") return @@ -87,7 +87,7 @@ func localUpdateConfig(c *Context, w http.ResponseWriter, r *http.Request) { } func localPatchConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { c.SetInvalidParam("config") return diff --git a/api4/data_retention.go b/api4/data_retention.go index b11f89f3fe..824f8b8f7b 100644 --- a/api4/data_retention.go +++ b/api4/data_retention.go @@ -40,7 +40,12 @@ func getGlobalPolicy(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write(policy.ToJson()) + js, jsonErr := json.Marshal(policy) + if jsonErr != nil { + c.Err = model.NewAppError("getGlobalPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getPolicies(c *Context, w http.ResponseWriter, r *http.Request) { @@ -58,7 +63,12 @@ func getPolicies(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write(policies.ToJson()) + js, jsonErr := json.Marshal(policies) + if jsonErr != nil { + c.Err = model.NewAppError("getPolicies", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getPoliciesCount(c *Context, w http.ResponseWriter, r *http.Request) { @@ -89,12 +99,18 @@ func getPolicy(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - w.Write(policy.ToJson()) + + js, jsonErr := json.Marshal(policy) + if jsonErr != nil { + c.Err = model.NewAppError("getPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func createPolicy(c *Context, w http.ResponseWriter, r *http.Request) { - policy, jsonErr := model.RetentionPolicyWithTeamAndChannelIdsFromJson(r.Body) - if jsonErr != nil { + var policy model.RetentionPolicyWithTeamAndChannelIDs + if jsonErr := json.NewDecoder(r.Body).Decode(&policy); jsonErr != nil { c.SetInvalidParam("policy") return } @@ -107,22 +123,28 @@ func createPolicy(c *Context, w http.ResponseWriter, r *http.Request) { return } - newPolicy, err := c.App.CreateRetentionPolicy(policy) + newPolicy, err := c.App.CreateRetentionPolicy(&policy) if err != nil { c.Err = err return } auditRec.AddMeta("policy", newPolicy) // overwrite meta + js, jsonErr := json.Marshal(newPolicy) + if jsonErr != nil { + c.Err = model.NewAppError("createPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } auditRec.Success() w.WriteHeader(http.StatusCreated) - w.Write(newPolicy.ToJson()) + w.Write(js) } func patchPolicy(c *Context, w http.ResponseWriter, r *http.Request) { - patch, jsonErr := model.RetentionPolicyWithTeamAndChannelIdsFromJson(r.Body) - if jsonErr != nil { + var patch model.RetentionPolicyWithTeamAndChannelIDs + if jsonErr := json.NewDecoder(r.Body).Decode(&patch); jsonErr != nil { c.SetInvalidParam("policy") + return } c.RequirePolicyId() patch.ID = c.Params.PolicyId @@ -136,13 +158,18 @@ func patchPolicy(c *Context, w http.ResponseWriter, r *http.Request) { return } - policy, err := c.App.PatchRetentionPolicy(patch) + policy, err := c.App.PatchRetentionPolicy(&patch) if err != nil { c.Err = err return } + js, jsonErr := json.Marshal(policy) + if jsonErr != nil { + c.Err = model.NewAppError("patchPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } auditRec.Success() - w.Write(policy.ToJson()) + w.Write(js) } func deletePolicy(c *Context, w http.ResponseWriter, r *http.Request) { @@ -199,23 +226,28 @@ func searchTeamsInPolicy(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.TeamSearchFromJson(r.Body) - if props == nil { + var props model.TeamSearch + if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { c.SetInvalidParam("team_search") return } + props.PolicyID = model.NewString(c.Params.PolicyId) props.IncludePolicyID = model.NewBool(true) - teams, _, err := c.App.SearchAllTeams(props) + teams, _, err := c.App.SearchAllTeams(&props) if err != nil { c.Err = err return } c.App.SanitizeTeams(*c.AppContext.Session(), teams) - payload := []byte(model.TeamListToJson(teams)) - w.Write(payload) + js, jsonErr := json.Marshal(teams) + if jsonErr != nil { + c.Err = model.NewAppError("searchTeamsInPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func addTeamsToPolicy(c *Context, w http.ResponseWriter, r *http.Request) { @@ -330,8 +362,13 @@ func searchChannelsInPolicy(c *Context, w http.ResponseWriter, r *http.Request) return } - payload := []byte(channels.ToJson()) - w.Write(payload) + channelsJSON, jsonErr := json.Marshal(channels) + if jsonErr != nil { + c.Err = model.NewAppError("searchChannelsInPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(channelsJSON) } func addChannelsToPolicy(c *Context, w http.ResponseWriter, r *http.Request) { @@ -412,7 +449,12 @@ func getTeamPoliciesForUser(c *Context, w http.ResponseWriter, r *http.Request) return } - w.Write(policies.ToJson()) + js, jsonErr := json.Marshal(policies) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamPoliciesForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getChannelPoliciesForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -435,5 +477,10 @@ func getChannelPoliciesForUser(c *Context, w http.ResponseWriter, r *http.Reques return } - w.Write(policies.ToJson()) + js, jsonErr := json.Marshal(policies) + if jsonErr != nil { + c.Err = model.NewAppError("getChannelPoliciesForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } diff --git a/api4/elasticsearch.go b/api4/elasticsearch.go index 9e940cdf80..045b2034f7 100644 --- a/api4/elasticsearch.go +++ b/api4/elasticsearch.go @@ -16,7 +16,7 @@ func (api *API) InitElasticsearch() { } func testElasticsearch(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { cfg = c.App.Config() } diff --git a/api4/emoji.go b/api4/emoji.go index fba90b3c0d..23bc5a98a7 100644 --- a/api4/emoji.go +++ b/api4/emoji.go @@ -8,7 +8,6 @@ import ( "io" "io/ioutil" "net/http" - "strings" "github.com/mattermost/mattermost-server/v6/app" "github.com/mattermost/mattermost-server/v6/audit" @@ -83,15 +82,15 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) { return } - emoji := model.EmojiFromJson(strings.NewReader(props["emoji"][0])) - if emoji == nil { + var emoji model.Emoji + if jsonErr := json.Unmarshal([]byte(props["emoji"][0]), &emoji); jsonErr != nil { c.SetInvalidParam("emoji") return } auditRec.AddMeta("emoji", emoji) - newEmoji, err := c.App.CreateEmoji(c.AppContext.Session().UserId, emoji, m) + newEmoji, err := c.App.CreateEmoji(c.AppContext.Session().UserId, &emoji, m) if err != nil { c.Err = err return @@ -255,8 +254,8 @@ func getEmojiImage(c *Context, w http.ResponseWriter, r *http.Request) { } func searchEmojis(c *Context, w http.ResponseWriter, r *http.Request) { - emojiSearch := model.EmojiSearchFromJson(r.Body) - if emojiSearch == nil { + var emojiSearch model.EmojiSearch + if jsonErr := json.NewDecoder(r.Body).Decode(&emojiSearch); jsonErr != nil { c.SetInvalidParam("term") return } diff --git a/api4/file.go b/api4/file.go index dcbd71e2ca..72e50a0d6f 100644 --- a/api4/file.go +++ b/api4/file.go @@ -575,7 +575,7 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() auditRec.AddMeta("link", link) - w.Write([]byte(model.MapToJson(resp))) + w.Write([]byte(model.MapToJSON(resp))) } func getFilePreview(c *Context, w http.ResponseWriter, r *http.Request) { @@ -745,7 +745,8 @@ func searchFiles(c *Context, w http.ResponseWriter, r *http.Request) { return } - params, jsonErr := model.SearchParameterFromJson(r.Body) + var params model.SearchParameter + jsonErr := json.NewDecoder(r.Body).Decode(¶ms) if jsonErr != nil { c.Err = model.NewAppError("searchFiles", "api.post.search_files.invalid_body.app_error", nil, jsonErr.Error(), http.StatusBadRequest) return diff --git a/api4/file_test.go b/api4/file_test.go index 19dc24faab..1eb0e8ab58 100644 --- a/api4/file_test.go +++ b/api4/file_test.go @@ -6,6 +6,7 @@ package api4 import ( "bytes" "crypto/rand" + "encoding/json" "fmt" "io" "io/ioutil" @@ -77,10 +78,14 @@ func testDoUploadFileRequest(t testing.TB, c *model.Client4, url string, blob [] defer closeBody(resp) if resp.StatusCode >= 300 { - return nil, model.BuildResponse(resp), model.AppErrorFromJson(resp.Body) + return nil, model.BuildResponse(resp), model.AppErrorFromJSON(resp.Body) } - return model.FileUploadResponseFromJson(resp.Body), model.BuildResponse(resp), nil + var res model.FileUploadResponse + if jsonErr := json.NewDecoder(resp.Body).Decode(&res); jsonErr != nil { + return nil, nil, model.NewAppError("doUploadFile", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &res, model.BuildResponse(resp), nil } func testUploadFilesPost( diff --git a/api4/group.go b/api4/group.go index 6dd83ebe33..d017036895 100644 --- a/api4/group.go +++ b/api4/group.go @@ -114,8 +114,8 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } - groupPatch := model.GroupPatchFromJson(r.Body) - if groupPatch == nil { + var groupPatch model.GroupPatch + if jsonErr := json.NewDecoder(r.Body).Decode(&groupPatch); jsonErr != nil { c.SetInvalidParam("group") return } @@ -167,7 +167,7 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { } } - group.Patch(groupPatch) + group.Patch(&groupPatch) group, err = c.App.UpdateGroup(group) if err != nil { diff --git a/api4/integration_action.go b/api4/integration_action.go index 680e1239dd..be19c4928b 100644 --- a/api4/integration_action.go +++ b/api4/integration_action.go @@ -23,10 +23,8 @@ func doPostAction(c *Context, w http.ResponseWriter, r *http.Request) { return } - actionRequest := model.DoPostActionRequestFromJson(r.Body) - if actionRequest == nil { - actionRequest = &model.DoPostActionRequest{} - } + var actionRequest model.DoPostActionRequest + json.NewDecoder(r.Body).Decode(&actionRequest) var cookie *model.PostActionCookie if actionRequest.Cookie != "" { diff --git a/api4/integration_action_test.go b/api4/integration_action_test.go index 8b62200b2c..8f8b3446dc 100644 --- a/api4/integration_action_test.go +++ b/api4/integration_action_test.go @@ -4,7 +4,6 @@ package api4 import ( - "bytes" "encoding/json" "io/ioutil" "net/http" @@ -25,7 +24,9 @@ func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { bb, err := ioutil.ReadAll(r.Body) assert.NoError(th.t, err) assert.NotEmpty(th.t, string(bb)) - poir := model.PostActionIntegrationRequestFromJson(bytes.NewReader(bb)) + var poir model.PostActionIntegrationRequest + jsonErr := json.Unmarshal(bb, &poir) + assert.NoError(th.t, jsonErr) assert.NotEmpty(th.t, poir.UserId) assert.NotEmpty(th.t, poir.UserName) assert.NotEmpty(th.t, poir.ChannelId) diff --git a/api4/job.go b/api4/job.go index 27af0e0c59..5cac87a950 100644 --- a/api4/job.go +++ b/api4/job.go @@ -104,8 +104,8 @@ func downloadJob(c *Context, w http.ResponseWriter, r *http.Request) { } func createJob(c *Context, w http.ResponseWriter, r *http.Request) { - job := model.JobFromJson(r.Body) - if job == nil { + var job model.Job + if jsonErr := json.NewDecoder(r.Body).Decode(&job); jsonErr != nil { c.SetInvalidParam("job") return } @@ -114,7 +114,7 @@ func createJob(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) auditRec.AddMeta("job", job) - hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.AppContext.Session(), job) + hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.AppContext.Session(), &job) if permissionRequired == nil { c.Err = model.NewAppError("unableToCreateJob", "api.job.unable_to_create_job.incorrect_job_type", nil, "", http.StatusBadRequest) return @@ -125,17 +125,17 @@ func createJob(c *Context, w http.ResponseWriter, r *http.Request) { return } - job, err := c.App.CreateJob(job) + rjob, err := c.App.CreateJob(&job) if err != nil { c.Err = err return } auditRec.Success() - auditRec.AddMeta("job", job) // overwrite meta + auditRec.AddMeta("job", rjob) // overwrite meta w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(job); err != nil { + if err := json.NewEncoder(w).Encode(rjob); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } @@ -167,7 +167,12 @@ func getJobs(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.JobsToJson(jobs))) + js, jsonErr := json.Marshal(jobs) + if jsonErr != nil { + c.Err = model.NewAppError("getJobs", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getJobsByType(c *Context, w http.ResponseWriter, r *http.Request) { @@ -192,7 +197,12 @@ func getJobsByType(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.JobsToJson(jobs))) + js, jsonErr := json.Marshal(jobs) + if jsonErr != nil { + c.Err = model.NewAppError("getJobsByType", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func cancelJob(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api4/ldap.go b/api4/ldap.go index 7f89b803a9..d5af45e8ae 100644 --- a/api4/ldap.go +++ b/api4/ldap.go @@ -275,7 +275,7 @@ func unlinkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { } func migrateIdLdap(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) toAttribute, ok := props["toAttribute"].(string) if !ok || toAttribute == "" { c.SetInvalidParam("toAttribute") diff --git a/api4/license.go b/api4/license.go index e51e5124e8..22a7653c91 100644 --- a/api4/license.go +++ b/api4/license.go @@ -48,7 +48,7 @@ func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) { clientLicense = c.App.Srv().GetSanitizedClientLicense() } - w.Write([]byte(model.MapToJson(clientLicense))) + w.Write([]byte(model.MapToJSON(clientLicense))) } func addLicense(c *Context, w http.ResponseWriter, r *http.Request) { @@ -302,5 +302,5 @@ func getPrevTrialLicense(c *Context, w http.ResponseWriter, r *http.Request) { clientLicense = utils.GetSanitizedClientLicense(utils.GetClientLicense(license)) } - w.Write([]byte(model.MapToJson(clientLicense))) + w.Write([]byte(model.MapToJSON(clientLicense))) } diff --git a/api4/license_test.go b/api4/license_test.go index 46d710c872..ed1b78589f 100644 --- a/api4/license_test.go +++ b/api4/license_test.go @@ -224,11 +224,12 @@ func TestRequestTrialLicense(t *testing.T) { nUsers := 1 license := model.NewTestLicense() license.Features.Users = model.NewInt(nUsers) - licenseStr := license.ToJson() + licenseJSON, jsonErr := json.Marshal(license) + require.NoError(t, jsonErr) testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { res.WriteHeader(http.StatusOK) response := map[string]string{ - "license": licenseStr, + "license": string(licenseJSON), } err := json.NewEncoder(res).Encode(response) require.NoError(t, err) @@ -238,7 +239,7 @@ func TestRequestTrialLicense(t *testing.T) { mockLicenseValidator := mocks2.LicenseValidatorIface{} defer testutils.ResetLicenseValidator() - mockLicenseValidator.On("ValidateLicense", mock.Anything).Return(true, licenseStr) + mockLicenseValidator.On("ValidateLicense", mock.Anything).Return(true, string(licenseJSON)) utils.LicenseValidator = &mockLicenseValidator licenseManagerMock := &mocks.LicenseInterface{} licenseManagerMock.On("CanStartTrial").Return(true, nil).Once() diff --git a/api4/oauth.go b/api4/oauth.go index caec4423cc..78194a3256 100644 --- a/api4/oauth.go +++ b/api4/oauth.go @@ -25,9 +25,8 @@ func (api *API) InitOAuth() { } func createOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { - oauthApp := model.OAuthAppFromJson(r.Body) - - if oauthApp == nil { + var oauthApp model.OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oauthApp); jsonErr != nil { c.SetInvalidParam("oauth_app") return } @@ -46,7 +45,7 @@ func createOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { oauthApp.CreatorId = c.AppContext.Session().UserId - rapp, err := c.App.CreateOAuthApp(oauthApp) + rapp, err := c.App.CreateOAuthApp(&oauthApp) if err != nil { c.Err = err return @@ -78,8 +77,8 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { return } - oauthApp := model.OAuthAppFromJson(r.Body) - if oauthApp == nil { + var oauthApp model.OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oauthApp); jsonErr != nil { c.SetInvalidParam("oauth_app") return } @@ -106,7 +105,7 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { oauthApp.IsTrusted = oldOAuthApp.IsTrusted } - updatedOAuthApp, err := c.App.UpdateOAuthApp(oldOAuthApp, oauthApp) + updatedOAuthApp, err := c.App.UpdateOAuthApp(oldOAuthApp, &oauthApp) if err != nil { c.Err = err return @@ -143,7 +142,12 @@ func getOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.OAuthAppListToJson(apps))) + js, jsonErr := json.Marshal(apps) + if jsonErr != nil { + c.Err = model.NewAppError("getOAuthApps", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { @@ -289,5 +293,10 @@ func getAuthorizedOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) return } - w.Write([]byte(model.OAuthAppListToJson(apps))) + js, jsonErr := json.Marshal(apps) + if jsonErr != nil { + c.Err = model.NewAppError("getAuthorizedOAuthApps", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } diff --git a/api4/openGraph.go b/api4/openGraph.go index f851908267..8dc201cf4b 100644 --- a/api4/openGraph.go +++ b/api4/openGraph.go @@ -37,7 +37,7 @@ func getOpenGraphMetadata(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) url := "" ok := false diff --git a/api4/plugin.go b/api4/plugin.go index 84046cff36..5163c9df07 100644 --- a/api4/plugin.go +++ b/api4/plugin.go @@ -264,7 +264,12 @@ func getWebappPlugins(c *Context, w http.ResponseWriter, r *http.Request) { } } - w.Write([]byte(model.ManifestListToJson(clientManifests))) + js, jsonErr := json.Marshal(clientManifests) + if jsonErr != nil { + c.Err = model.NewAppError("getWebappPlugins", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getMarketplacePlugins(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api4/post.go b/api4/post.go index 60aa404156..15ba956c0c 100644 --- a/api4/post.go +++ b/api4/post.go @@ -36,8 +36,8 @@ func (api *API) InitPost() { } func createPost(c *Context, w http.ResponseWriter, r *http.Request) { - post := model.PostFromJson(r.Body) - if post == nil { + var post model.Post + if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { c.SetInvalidParam("post") return } @@ -46,7 +46,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createPost", audit.Fail) defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) - auditRec.AddMeta("post", post) + auditRec.AddMeta("post", &post) hasPermission := false if c.App.SessionHasPermissionToChannel(*c.AppContext.Session(), post.ChannelId, model.PermissionCreatePost) { @@ -78,7 +78,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) { } } - rp, err := c.App.CreatePostAsUser(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(post), c.AppContext.Session().Id, setOnlineBool) + rp, err := c.App.CreatePostAsUser(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(&post), c.AppContext.Session().Id, setOnlineBool) if err != nil { c.Err = err return @@ -484,8 +484,8 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) { return } - params, jsonErr := model.SearchParameterFromJson(r.Body) - if jsonErr != nil { + var params model.SearchParameter + if jsonErr := json.NewDecoder(r.Body).Decode(¶ms); jsonErr != nil { c.Err = model.NewAppError("searchPosts", "api.post.search_posts.invalid_body.app_error", nil, jsonErr.Error(), http.StatusBadRequest) return } @@ -558,9 +558,8 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) { return } - post := model.PostFromJson(r.Body) - - if post == nil { + var post model.Post + if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { c.SetInvalidParam("post") return } @@ -598,7 +597,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) { post.Id = c.Params.PostId - rpost, err := c.App.UpdatePost(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(post), false) + rpost, err := c.App.UpdatePost(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(&post), false) if err != nil { c.Err = err return @@ -618,9 +617,8 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) { return } - post := model.PostPatchFromJson(r.Body) - - if post == nil { + var post model.PostPatch + if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { c.SetInvalidParam("post") return } @@ -650,7 +648,7 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) { return } - patchedPost, err := c.App.PatchPost(c.AppContext, c.Params.PostId, c.App.PostPatchWithProxyRemovedFromImageURLs(post)) + patchedPost, err := c.App.PatchPost(c.AppContext, c.Params.PostId, c.App.PostPatchWithProxyRemovedFromImageURLs(&post)) if err != nil { c.Err = err return @@ -670,7 +668,7 @@ func setPostUnread(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapBoolFromJson(r.Body) + props := model.MapBoolFromJSON(r.Body) collapsedThreadsSupported := props["collapsed_threads_supported"] if c.AppContext.Session().UserId != c.Params.UserId && !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { @@ -777,7 +775,12 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) { return } + js, jsonErr := json.Marshal(infos) + if jsonErr != nil { + c.Err = model.NewAppError("getFileInfosForPost", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } w.Header().Set("Cache-Control", "max-age=2592000, private") w.Header().Set(model.HeaderEtagServer, model.GetEtagForFileInfos(infos)) - w.Write([]byte(model.FileInfosToJson(infos))) + w.Write(js) } diff --git a/api4/post_test.go b/api4/post_test.go index 646cdd2355..6d8a42e887 100644 --- a/api4/post_test.go +++ b/api4/post_test.go @@ -4,6 +4,7 @@ package api4 import ( + "bytes" "context" "encoding/json" "errors" @@ -341,7 +342,9 @@ func testCreatePostWithOutgoingHook( ResponseType: respPostType, } - fmt.Fprint(w, outGoingHookResponse.ToJson()) + hookJSON, jsonErr := json.Marshal(outGoingHookResponse) + require.NoError(t, jsonErr) + w.Write(hookJSON) success <- true })) defer ts.Close() @@ -578,7 +581,9 @@ func TestCreatePostSendOutOfChannelMentions(t *testing.T) { continue } - wpost := model.PostFromJson(strings.NewReader(event.GetData()["post"].(string))) + var wpost model.Post + err := json.Unmarshal([]byte(event.GetData()["post"].(string)), &wpost) + require.NoError(t, err) acm, ok := wpost.GetProp(model.PropsAddChannelMember).(map[string]interface{}) require.True(t, ok, "should have received ephemeral post with 'add_channel_member' in props") @@ -634,7 +639,9 @@ func TestCreatePostCheckOnlineStatus(t *testing.T) { Message: "some message", } - req := httptest.NewRequest("POST", "/api/v4/posts?set_online=false", strings.NewReader(post.ToJson())) + postJSON, jsonErr := json.Marshal(post) + require.NoError(t, jsonErr) + req := httptest.NewRequest("POST", "/api/v4/posts?set_online=false", bytes.NewReader(postJSON)) req.Header.Set(model.HeaderAuth, "Bearer "+session.Token) handler.ServeHTTP(resp, req) @@ -645,7 +652,9 @@ func TestCreatePostCheckOnlineStatus(t *testing.T) { require.NotNil(t, appErr) assert.Equal(t, "app.status.get.missing.app_error", appErr.Id) - req = httptest.NewRequest("POST", "/api/v4/posts", strings.NewReader(post.ToJson())) + postJSON, jsonErr = json.Marshal(post) + require.NoError(t, jsonErr) + req = httptest.NewRequest("POST", "/api/v4/posts", bytes.NewReader(postJSON)) req.Header.Set(model.HeaderAuth, "Bearer "+session.Token) handler.ServeHTTP(resp, req) @@ -1945,7 +1954,8 @@ func TestGetPost(t *testing.T) { require.Equal(t, th.BasicPost.Id, post.Id, "post ids don't match") - post, resp, _ = c.GetPost(th.BasicPost.Id, resp.Etag) + post, resp, err = c.GetPost(th.BasicPost.Id, resp.Etag) + require.NoError(t, err) CheckEtag(t, post, resp) _, resp, err = c.GetPost("", "") diff --git a/api4/preference.go b/api4/preference.go index 80459df02b..c76d2febcc 100644 --- a/api4/preference.go +++ b/api4/preference.go @@ -100,8 +100,8 @@ func updatePreferences(c *Context, w http.ResponseWriter, r *http.Request) { return } - preferences, err := model.PreferencesFromJson(r.Body) - if err != nil { + var preferences model.Preferences + if jsonErr := json.NewDecoder(r.Body).Decode(&preferences); jsonErr != nil { c.SetInvalidParam("preferences") return } @@ -148,8 +148,8 @@ func deletePreferences(c *Context, w http.ResponseWriter, r *http.Request) { return } - preferences, err := model.PreferencesFromJson(r.Body) - if err != nil { + var preferences model.Preferences + if jsonErr := json.NewDecoder(r.Body).Decode(&preferences); jsonErr != nil { c.SetInvalidParam("preferences") return } diff --git a/api4/preference_test.go b/api4/preference_test.go index cd5b17d385..d5b7ff1568 100644 --- a/api4/preference_test.go +++ b/api4/preference_test.go @@ -4,7 +4,7 @@ package api4 import ( - "strings" + "encoding/json" "testing" "time" @@ -297,8 +297,9 @@ func TestUpdatePreferencesWebsocket(t *testing.T) { continue } - received, err := model.PreferencesFromJson(strings.NewReader(event.GetData()["preferences"].(string))) - require.NoError(t, err) + var received model.Preferences + jsonErr := json.Unmarshal([]byte(event.GetData()["preferences"].(string)), &received) + require.NoError(t, jsonErr) for i, p := range preferences { require.Equal(t, received[i].UserId, p.UserId, "received incorrect UserId") @@ -629,8 +630,9 @@ func TestDeletePreferencesWebsocket(t *testing.T) { continue } - received, err := model.PreferencesFromJson(strings.NewReader(event.GetData()["preferences"].(string))) - require.NoError(t, err) + var received model.Preferences + jsonErr := json.Unmarshal([]byte(event.GetData()["preferences"].(string)), &received) + require.NoError(t, jsonErr) for i, preference := range preferences { require.Equal(t, preference.UserId, received[i].UserId) diff --git a/api4/reaction.go b/api4/reaction.go index 2f8369071c..ac19502d92 100644 --- a/api4/reaction.go +++ b/api4/reaction.go @@ -19,8 +19,8 @@ func (api *API) InitReaction() { } func saveReaction(c *Context, w http.ResponseWriter, r *http.Request) { - reaction := model.ReactionFromJson(r.Body) - if reaction == nil { + var reaction model.Reaction + if jsonErr := json.NewDecoder(r.Body).Decode(&reaction); jsonErr != nil { c.SetInvalidParam("reaction") return } @@ -40,13 +40,13 @@ func saveReaction(c *Context, w http.ResponseWriter, r *http.Request) { return } - reaction, err := c.App.SaveReactionForPost(c.AppContext, reaction) + re, err := c.App.SaveReactionForPost(c.AppContext, &reaction) if err != nil { c.Err = err return } - if err := json.NewEncoder(w).Encode(reaction); err != nil { + if err := json.NewEncoder(w).Encode(re); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } @@ -68,7 +68,12 @@ func getReactions(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.ReactionsToJson(reactions))) + js, jsonErr := json.Marshal(reactions) + if jsonErr != nil { + c.Err = model.NewAppError("getReactions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func deleteReaction(c *Context, w http.ResponseWriter, r *http.Request) { @@ -113,7 +118,7 @@ func deleteReaction(c *Context, w http.ResponseWriter, r *http.Request) { } func getBulkReactions(c *Context, w http.ResponseWriter, r *http.Request) { - postIds := model.ArrayFromJson(r.Body) + postIds := model.ArrayFromJSON(r.Body) for _, postId := range postIds { if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), postId, model.PermissionReadChannel) { c.SetPermissionError(model.PermissionReadChannel) @@ -126,5 +131,10 @@ func getBulkReactions(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.MapPostIdToReactionsToJson(reactions))) + js, jsonErr := json.Marshal(reactions) + if jsonErr != nil { + c.Err = model.NewAppError("getBulkReactions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } diff --git a/api4/remote_cluster.go b/api4/remote_cluster.go index 4d03ce9a70..62565a20a7 100644 --- a/api4/remote_cluster.go +++ b/api4/remote_cluster.go @@ -31,13 +31,13 @@ func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { return } - frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) - if appErr != nil { - c.Err = appErr + var frame model.RemoteClusterFrame + if jsonErr := json.NewDecoder(r.Body).Decode(&frame); jsonErr != nil { + c.Err = model.NewAppError("remoteClusterPing", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) return } - if appErr = frame.IsValid(); appErr != nil { + if appErr := frame.IsValid(); appErr != nil { c.Err = appErr return } @@ -54,8 +54,8 @@ func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { return } - ping, err := model.RemoteClusterPingFromRawJSON(frame.Msg.Payload) - if err != nil { + var ping model.RemoteClusterPing + if jsonErr := json.Unmarshal(frame.Msg.Payload, &ping); jsonErr != nil { c.SetInvalidParam("msg.payload") return } @@ -65,7 +65,7 @@ func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { metrics.IncrementRemoteClusterMsgReceivedCounter(rc.RemoteId) } - resp, _ := json.Marshal(ping) + resp, _ := json.Marshal(&ping) w.Write(resp) } @@ -77,13 +77,13 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque return } - frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) - if appErr != nil { - c.Err = appErr + var frame model.RemoteClusterFrame + if jsonErr := json.NewDecoder(r.Body).Decode(&frame); jsonErr != nil { + c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) return } - if appErr = frame.IsValid(); appErr != nil { + if appErr := frame.IsValid(); appErr != nil { c.Err = appErr return } @@ -122,13 +122,13 @@ func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Reque return } - frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) - if appErr != nil { - c.Err = appErr + var frame model.RemoteClusterFrame + if jsonErr := json.NewDecoder(r.Body).Decode(&frame); jsonErr != nil { + c.Err = model.NewAppError("remoteClusterConfirmInvite", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) return } - if appErr = frame.IsValid(); appErr != nil { + if appErr := frame.IsValid(); appErr != nil { c.Err = appErr return } @@ -154,9 +154,9 @@ func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Reque return } - confirm, appErr := model.RemoteClusterInviteFromRawJSON(frame.Msg.Payload) - if appErr != nil { - c.Err = appErr + var confirm model.RemoteClusterInvite + if jsonErr := json.Unmarshal(frame.Msg.Payload, &confirm); jsonErr != nil { + c.SetInvalidParam("msg.payload") return } diff --git a/api4/role.go b/api4/role.go index 9df05f43b4..d579ba8330 100644 --- a/api4/role.go +++ b/api4/role.go @@ -60,7 +60,7 @@ func getRoleByName(c *Context, w http.ResponseWriter, r *http.Request) { } func getRolesByNames(c *Context, w http.ResponseWriter, r *http.Request) { - rolenames := model.ArrayFromJson(r.Body) + rolenames := model.ArrayFromJSON(r.Body) if len(rolenames) == 0 { c.SetInvalidParam("rolenames") @@ -79,7 +79,12 @@ func getRolesByNames(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.RoleListToJson(roles))) + js, jsonErr := json.Marshal(roles) + if jsonErr != nil { + c.Err = model.NewAppError("getRolesByNames", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { @@ -88,8 +93,8 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { return } - patch := model.RolePatchFromJson(r.Body) - if patch == nil { + var patch model.RolePatch + if jsonErr := json.NewDecoder(r.Body).Decode(&patch); jsonErr != nil { c.SetInvalidParam("role") return } @@ -127,7 +132,7 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { // Licensed instances can not change permissions in the blacklist set. if patch.Permissions != nil { - deltaPermissions := model.PermissionsChangedByPatch(oldRole, patch) + deltaPermissions := model.PermissionsChangedByPatch(oldRole, &patch) for _, permission := range deltaPermissions { notAllowed := false @@ -163,7 +168,7 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { } } - role, err := c.App.PatchRole(oldRole, patch) + role, err := c.App.PatchRole(oldRole, &patch) if err != nil { c.Err = err return diff --git a/api4/saml.go b/api4/saml.go index 2c2f2d8981..27a313e45d 100644 --- a/api4/saml.go +++ b/api4/saml.go @@ -242,7 +242,7 @@ func getSamlMetadataFromIdp(c *Context, w http.ResponseWriter, r *http.Request) return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) url := props["saml_metadata_url"] if url == "" { c.SetInvalidParam("saml_metadata_url") diff --git a/api4/scheme.go b/api4/scheme.go index 8eea49c4e0..293d08f632 100644 --- a/api4/scheme.go +++ b/api4/scheme.go @@ -23,8 +23,8 @@ func (api *API) InitScheme() { } func createScheme(c *Context, w http.ResponseWriter, r *http.Request) { - scheme := model.SchemeFromJson(r.Body) - if scheme == nil { + var scheme model.Scheme + if jsonErr := json.NewDecoder(r.Body).Decode(&scheme); jsonErr != nil { c.SetInvalidParam("scheme") return } @@ -43,17 +43,17 @@ func createScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - scheme, err := c.App.CreateScheme(scheme) + returnedScheme, err := c.App.CreateScheme(&scheme) if err != nil { c.Err = err return } auditRec.Success() - auditRec.AddMeta("scheme", scheme) // overwrite meta + auditRec.AddMeta("scheme", returnedScheme) // overwrite meta w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(scheme); err != nil { + if err := json.NewEncoder(w).Encode(returnedScheme); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } @@ -98,7 +98,12 @@ func getSchemes(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.SchemesToJson(schemes))) + js, jsonErr := json.Marshal(schemes) + if jsonErr != nil { + c.Err = model.NewAppError("getSchemes", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getTeamsForScheme(c *Context, w http.ResponseWriter, r *http.Request) { @@ -129,7 +134,12 @@ func getTeamsForScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.TeamListToJson(teams))) + js, jsonErr := json.Marshal(teams) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamsForScheme", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getChannelsForScheme(c *Context, w http.ResponseWriter, r *http.Request) { @@ -171,8 +181,8 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - patch := model.SchemePatchFromJson(r.Body) - if patch == nil { + var patch model.SchemePatch + if jsonErr := json.NewDecoder(r.Body).Decode(&patch); jsonErr != nil { c.SetInvalidParam("scheme") return } @@ -197,7 +207,7 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - scheme, err = c.App.PatchScheme(scheme, patch) + scheme, err = c.App.PatchScheme(scheme, &patch) if err != nil { c.Err = err return diff --git a/api4/status.go b/api4/status.go index 3247c9cce5..8bca2eb83a 100644 --- a/api4/status.go +++ b/api4/status.go @@ -49,7 +49,7 @@ func getUserStatus(c *Context, w http.ResponseWriter, r *http.Request) { } func getUserStatusesByIds(c *Context, w http.ResponseWriter, r *http.Request) { - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) if len(userIds) == 0 { c.SetInvalidParam("user_ids") @@ -64,14 +64,18 @@ func getUserStatusesByIds(c *Context, w http.ResponseWriter, r *http.Request) { } // No permission check required - - statusMap, err := c.App.GetUserStatusesByIds(userIds) + statuses, err := c.App.GetUserStatusesByIds(userIds) if err != nil { c.Err = err return } - w.Write([]byte(model.StatusListToJson(statusMap))) + js, jsonErr := json.Marshal(statuses) + if jsonErr != nil { + c.Err = model.NewAppError("getUserStatusesByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func updateUserStatus(c *Context, w http.ResponseWriter, r *http.Request) { @@ -80,8 +84,8 @@ func updateUserStatus(c *Context, w http.ResponseWriter, r *http.Request) { return } - status := model.StatusFromJson(r.Body) - if status == nil { + var status model.Status + if jsonErr := json.NewDecoder(r.Body).Decode(&status); jsonErr != nil { c.SetInvalidParam("status") return } @@ -134,8 +138,9 @@ func updateUserCustomStatus(c *Context, w http.ResponseWriter, r *http.Request) return } - customStatus := model.CustomStatusFromJson(r.Body) - if customStatus == nil || (customStatus.Emoji == "" && customStatus.Text == "") || !customStatus.AreDurationAndExpirationTimeValid() { + var customStatus model.CustomStatus + jsonErr := json.NewDecoder(r.Body).Decode(&customStatus) + if jsonErr != nil || (customStatus.Emoji == "" && customStatus.Text == "") || !customStatus.AreDurationAndExpirationTimeValid() { c.SetInvalidParam("custom_status") return } @@ -146,7 +151,7 @@ func updateUserCustomStatus(c *Context, w http.ResponseWriter, r *http.Request) } customStatus.PreSave() - err := c.App.SetCustomStatus(c.Params.UserId, customStatus) + err := c.App.SetCustomStatus(c.Params.UserId, &customStatus) if err != nil { c.Err = err return @@ -190,8 +195,8 @@ func removeUserRecentCustomStatus(c *Context, w http.ResponseWriter, r *http.Req return } - recentCustomStatus := model.CustomStatusFromJson(r.Body) - if recentCustomStatus == nil { + var recentCustomStatus model.CustomStatus + if jsonErr := json.NewDecoder(r.Body).Decode(&recentCustomStatus); jsonErr != nil { c.SetInvalidParam("recent_custom_status") return } @@ -201,7 +206,7 @@ func removeUserRecentCustomStatus(c *Context, w http.ResponseWriter, r *http.Req return } - if err := c.App.RemoveRecentCustomStatus(c.Params.UserId, recentCustomStatus); err != nil { + if err := c.App.RemoveRecentCustomStatus(c.Params.UserId, &recentCustomStatus); err != nil { c.Err = err return } diff --git a/api4/system.go b/api4/system.go index 25b0da4866..34ac01c236 100644 --- a/api4/system.go +++ b/api4/system.go @@ -186,11 +186,11 @@ func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) { if s[model.STATUS] != model.StatusOk { w.WriteHeader(http.StatusInternalServerError) } - w.Write([]byte(model.MapToJson(s))) + w.Write([]byte(model.MapToJSON(s))) } func testEmail(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { cfg = c.App.Config() } @@ -225,7 +225,7 @@ func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) siteURL := props["site_url"] if siteURL == "" { c.SetInvalidParam("site_url") @@ -334,7 +334,7 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("page", c.Params.Page) auditRec.AddMeta("logs_per_page", c.Params.LogsPerPage) - w.Write([]byte(model.ArrayToJson(lines))) + w.Write([]byte(model.ArrayToJSON(lines))) } func postLog(c *Context, w http.ResponseWriter, r *http.Request) { @@ -351,7 +351,7 @@ func postLog(c *Context, w http.ResponseWriter, r *http.Request) { } } - m := model.MapFromJson(r.Body) + m := model.MapFromJSON(r.Body) lvl := m["level"] msg := m["message"] @@ -372,7 +372,7 @@ func postLog(c *Context, w http.ResponseWriter, r *http.Request) { } m["message"] = msg - w.Write([]byte(model.MapToJson(m))) + w.Write([]byte(model.MapToJSON(m))) } func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { @@ -420,7 +420,7 @@ func getSupportedTimezones(c *Context, w http.ResponseWriter, r *http.Request) { } func testS3(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJson(r.Body) + cfg := model.ConfigFromJSON(r.Body) if cfg == nil { cfg = c.App.Config() } @@ -459,7 +459,7 @@ func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) { m["location"] = "" if !*c.App.Config().ServiceSettings.EnableLinkPreviews { - w.Write([]byte(model.MapToJson(m))) + w.Write([]byte(model.MapToJSON(m))) return } @@ -472,7 +472,7 @@ func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) { var location string if err := redirectLocationDataCache.Get(url, &location); err == nil { m["location"] = location - w.Write([]byte(model.MapToJson(m))) + w.Write([]byte(model.MapToJSON(m))) return } @@ -486,7 +486,7 @@ func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) { // Cache failures to prevent retries. redirectLocationDataCache.SetWithExpiry(url, "", 1*time.Hour) // Always return a success status and a JSON string to limit information returned to client. - w.Write([]byte(model.MapToJson(m))) + w.Write([]byte(model.MapToJSON(m))) return } defer func() { @@ -498,16 +498,16 @@ func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) { redirectLocationDataCache.SetWithExpiry(url, location, 1*time.Hour) m["location"] = location - w.Write([]byte(model.MapToJson(m))) + w.Write([]byte(model.MapToJSON(m))) } func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) { - ack, err := model.PushNotificationAckFromJson(r.Body) - if err != nil { + var ack model.PushNotificationAck + if jsonErr := json.NewDecoder(r.Body).Decode(&ack); jsonErr != nil { c.Err = model.NewAppError("pushNotificationAck", "api.push_notifications_ack.message.parse.app_error", nil, - err.Error(), + jsonErr.Error(), http.StatusBadRequest, ) return @@ -523,7 +523,7 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) { return } - err = c.App.SendAckToPushProxy(ack) + err := c.App.SendAckToPushProxy(&ack) if ack.IsIdLoaded { if err != nil { // Log the error only, then continue to fetch notification message @@ -542,7 +542,7 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) { return } - msg, appError := notificationInterface.GetNotificationMessage(ack, c.AppContext.Session().UserId) + msg, appError := notificationInterface.GetNotificationMessage(&ack, c.AppContext.Session().UserId) if appError != nil { c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.id_loaded.fetch.app_error", nil, appError.Error(), http.StatusInternalServerError) return @@ -612,9 +612,14 @@ func getServerBusyExpires(c *Context, w http.ResponseWriter, r *http.Request) { return } - // We call to ToJson because it actually returns a different struct + // We call to ToJSON because it actually returns a different struct // along with doing some computations. - if _, err := w.Write([]byte(c.App.Srv().Busy.ToJson())); err != nil { + sbsJSON, jsonErr := c.App.Srv().Busy.ToJSON() + if jsonErr != nil { + mlog.Warn(jsonErr.Error()) + } + + if _, err := w.Write(sbsJSON); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } @@ -700,7 +705,7 @@ func upgradeToEnterpriseStatus(c *Context, w http.ResponseWriter, r *http.Reques s = map[string]interface{}{"percentage": percentage, "error": nil} } - w.Write([]byte(model.StringInterfaceToJson(s))) + w.Write([]byte(model.StringInterfaceToJSON(s))) } func restart(c *Context, w http.ResponseWriter, r *http.Request) { @@ -739,7 +744,12 @@ func getWarnMetricsStatus(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.MapWarnMetricStatusToJson(status))) + js, jsonErr := json.Marshal(status) + if jsonErr != nil { + c.Err = model.NewAppError("getWarnMetricsStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func sendWarnMetricAckEmail(c *Context, w http.ResponseWriter, r *http.Request) { @@ -764,8 +774,8 @@ func sendWarnMetricAckEmail(c *Context, w http.ResponseWriter, r *http.Request) return } - ack := model.SendWarnMetricAckFromJson(r.Body) - if ack == nil { + var ack model.SendWarnMetricAck + if jsonErr := json.NewDecoder(r.Body).Decode(&ack); jsonErr != nil { c.SetInvalidParam("ack") return } @@ -838,7 +848,7 @@ func updateViewedProductNotices(c *Context, w http.ResponseWriter, r *http.Reque defer c.LogAuditRec(auditRec) c.LogAudit("attempt") - ids := model.ArrayFromJson(r.Body) + ids := model.ArrayFromJSON(r.Body) err := c.App.UpdateViewedProductNotices(c.AppContext.Session().UserId, ids) if err != nil { c.Err = err diff --git a/api4/team.go b/api4/team.go index 9ce00a67c8..c5fd6b003c 100644 --- a/api4/team.go +++ b/api4/team.go @@ -78,8 +78,8 @@ func (api *API) InitTeam() { } func createTeam(c *Context, w http.ResponseWriter, r *http.Request) { - team := model.TeamFromJson(r.Body) - if team == nil { + var team model.Team + if jsonErr := json.NewDecoder(r.Body).Decode(&team); jsonErr != nil { c.SetInvalidParam("team") return } @@ -94,7 +94,7 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } - rteam, err := c.App.CreateTeamWithUser(c.AppContext, team, c.AppContext.Session().UserId) + rteam, err := c.App.CreateTeamWithUser(c.AppContext, &team, c.AppContext.Session().UserId) if err != nil { c.Err = err return @@ -163,12 +163,12 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } - team := model.TeamFromJson(r.Body) - - if team == nil { + var team model.Team + if jsonErr := json.NewDecoder(r.Body).Decode(&team); jsonErr != nil { c.SetInvalidParam("team") return } + team.Email = strings.ToLower(team.Email) // The team being updated in the payload must be the same one as indicated in the URL. @@ -186,7 +186,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } - updatedTeam, err := c.App.UpdateTeam(team) + updatedTeam, err := c.App.UpdateTeam(&team) if err != nil { c.Err = err return @@ -207,9 +207,8 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } - team := model.TeamPatchFromJson(r.Body) - - if team == nil { + var team model.TeamPatch + if jsonErr := json.NewDecoder(r.Body).Decode(&team); jsonErr != nil { c.SetInvalidParam("team") return } @@ -226,7 +225,7 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("team", oldTeam) } - patchedTeam, err := c.App.PatchTeam(c.Params.TeamId, team) + patchedTeam, err := c.App.PatchTeam(c.Params.TeamId, &team) if err != nil { c.Err = err @@ -286,7 +285,7 @@ func updateTeamPrivacy(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) privacy, ok := props["privacy"].(string) if !ok { c.SetInvalidParam("privacy") @@ -421,7 +420,13 @@ func getTeamsForUser(c *Context, w http.ResponseWriter, r *http.Request) { } c.App.SanitizeTeams(*c.AppContext.Session(), teams) - w.Write([]byte(model.TeamListToJson(teams))) + + js, jsonErr := json.Marshal(teams) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getTeamsUnreadForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -445,7 +450,12 @@ func getTeamsUnreadForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.TeamsUnreadToJson(unreadTeamsList))) + js, jsonErr := json.Marshal(unreadTeamsList) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamsUnreadForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { @@ -514,7 +524,12 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.TeamMembersToJson(members))) + js, jsonErr := json.Marshal(members) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -545,7 +560,12 @@ func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.TeamMembersToJson(members))) + js, jsonErr := json.Marshal(members) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamMembersForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { @@ -554,7 +574,7 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { return } - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) if len(userIds) == 0 { c.SetInvalidParam("user_ids") @@ -578,7 +598,12 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.TeamMembersToJson(members))) + js, jsonErr := json.Marshal(members) + if jsonErr != nil { + c.Err = model.NewAppError("getTeamMembersByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { @@ -588,9 +613,9 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { } var err *model.AppError - member := model.TeamMemberFromJson(r.Body) - if member == nil { - c.Err = model.NewAppError("addTeamMember", "api.team.add_team_member.invalid_body.app_error", nil, "Error in model.TeamMemberFromJson()", http.StatusBadRequest) + var member model.TeamMember + if jsonErr := json.NewDecoder(r.Body).Decode(&member); jsonErr != nil { + c.Err = model.NewAppError("addTeamMember", "api.team.add_team_member.invalid_body.app_error", nil, "Error in model.TeamMemberFromJSON()", http.StatusBadRequest) return } if member.TeamId != c.Params.TeamId { @@ -653,8 +678,8 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { } } - member, err = c.App.AddTeamMember(c.AppContext, member.TeamId, member.UserId) - + var tm *model.TeamMember + tm, err = c.App.AddTeamMember(c.AppContext, member.TeamId, member.UserId) if err != nil { c.Err = err return @@ -663,7 +688,7 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(member); err != nil { + if err := json.NewEncoder(w).Encode(tm); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } @@ -717,7 +742,11 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } var err *model.AppError - members := model.TeamMembersFromJson(r.Body) + var members []*model.TeamMember + if jsonErr := json.NewDecoder(r.Body).Decode(&members); jsonErr != nil { + c.SetInvalidParam("members") + return + } if len(members) > MaxAddMembersBatch { c.SetInvalidParam("too many members in batch") @@ -798,17 +827,23 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } + var js []byte + var jsonErr error + if graceful { + // in 'graceful' mode we allow a different return value, notifying the client which users were not added + js, jsonErr = json.Marshal(membersWithErrors) + } else { + js, jsonErr = json.Marshal(model.TeamMembersWithErrorToTeamMembers(membersWithErrors)) + } + if jsonErr != nil { + c.Err = model.NewAppError("addTeamMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + auditRec.Success() w.WriteHeader(http.StatusCreated) - - if graceful { - // in 'graceful' mode we allow a different return value, notifying the client which users were not added - w.Write([]byte(model.TeamMembersWithErrorToJson(membersWithErrors))) - } else { - w.Write([]byte(model.TeamMembersToJson(model.TeamMembersWithErrorToTeamMembers(membersWithErrors)))) - } - + w.Write(js) } func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { @@ -916,7 +951,7 @@ func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) newRoles := props["roles"] if !model.IsValidUserRoles(newRoles) { @@ -951,8 +986,8 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ return } - schemeRoles := model.SchemeRolesFromJson(r.Body) - if schemeRoles == nil { + var schemeRoles model.SchemeRoles + if jsonErr := json.NewDecoder(r.Body).Decode(&schemeRoles); jsonErr != nil { c.SetInvalidParam("scheme_roles") return } @@ -1022,20 +1057,24 @@ func getAllTeams(c *Context, w http.ResponseWriter, r *http.Request) { c.App.SanitizeTeams(*c.AppContext.Session(), teams) - var resBody []byte - + var js []byte + var jsonErr error if c.Params.IncludeTotalCount { - resBody = model.TeamsWithCountToJson(teamsWithCount) + js, jsonErr = json.Marshal(teamsWithCount) } else { - resBody = model.ToJson(teams) + js, jsonErr = json.Marshal(teams) + } + if jsonErr != nil { + c.Err = model.NewAppError("getAllTeams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return } - w.Write(resBody) + w.Write(js) } func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.TeamSearchFromJson(r.Body) - if props == nil { + var props model.TeamSearch + if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { c.SetInvalidParam("team_search") return } @@ -1055,19 +1094,19 @@ func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) { var err *model.AppError if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPrivateTeams) && c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPublicTeams) { - teams, totalCount, err = c.App.SearchAllTeams(props) + teams, totalCount, err = c.App.SearchAllTeams(&props) } else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPrivateTeams) { if props.Page != nil || props.PerPage != nil { c.Err = model.NewAppError("searchTeams", "api.team.search_teams.pagination_not_implemented.private_team_search", nil, "", http.StatusNotImplemented) return } - teams, err = c.App.SearchPrivateTeams(props) + teams, err = c.App.SearchPrivateTeams(&props) } else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPublicTeams) { if props.Page != nil || props.PerPage != nil { c.Err = model.NewAppError("searchTeams", "api.team.search_teams.pagination_not_implemented.public_team_search", nil, "", http.StatusNotImplemented) return } - teams, err = c.App.SearchPublicTeams(props) + teams, err = c.App.SearchPublicTeams(&props) } else { teams = []*model.Team{} } @@ -1082,9 +1121,14 @@ func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) { var payload []byte if props.Page != nil && props.PerPage != nil { twc := map[string]interface{}{"teams": teams, "total_count": totalCount} - payload = model.ToJson(twc) + payload = model.ToJSON(twc) } else { - payload = []byte(model.TeamListToJson(teams)) + js, jsonErr := json.Marshal(teams) + if jsonErr != nil { + c.Err = model.NewAppError("searchTeams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + payload = js } w.Write(payload) @@ -1121,7 +1165,7 @@ func teamExists(c *Context, w http.ResponseWriter, r *http.Request) { } resp := map[string]bool{"exists": exists} - w.Write([]byte(model.MapBoolToJson(resp))) + w.Write([]byte(model.MapBoolToJSON(resp))) } func importTeam(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1210,7 +1254,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } auditRec.Success() - w.Write([]byte(model.MapToJson(data))) + w.Write([]byte(model.MapToJSON(data))) } func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1231,7 +1275,7 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } - emailList := model.ArrayFromJson(r.Body) + emailList := model.ArrayFromJSON(r.Body) for i := range emailList { emailList[i] = strings.ToLower(emailList[i]) @@ -1271,7 +1315,7 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { scheduledAt := model.GetMillis() jobData := map[string]string{ - "emailList": model.ArrayToJson(emailList), + "emailList": model.ArrayToJSON(emailList), "teamID": c.Params.TeamId, "senderID": c.AppContext.Session().UserId, "scheduledAt": strconv.FormatInt(scheduledAt, 10), @@ -1308,7 +1352,12 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } // in graceful mode we return both the successful ones and the failed ones - w.Write([]byte(model.EmailInviteWithErrorToJson(invitesWithError))) + js, jsonErr := json.Marshal(invitesWithError) + if jsonErr != nil { + c.Err = model.NewAppError("inviteUsersToTeam", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } else { err := c.App.InviteNewUsersToTeam(emailList, c.Params.TeamId, c.AppContext.Session().UserId) if err != nil { @@ -1346,9 +1395,9 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) return } - guestsInvite := model.GuestsInviteFromJson(r.Body) - if guestsInvite == nil { - c.Err = model.NewAppError("Api4.inviteGuestsToChannels", "api.team.invite_guests_to_channels.invalid_body.app_error", nil, "", http.StatusBadRequest) + var guestsInvite model.GuestsInvite + if jsonErr := json.NewDecoder(r.Body).Decode(&guestsInvite); jsonErr != nil { + c.Err = model.NewAppError("Api4.inviteGuestsToChannels", "api.team.invite_guests_to_channels.invalid_body.app_error", nil, jsonErr.Error(), http.StatusBadRequest) return } @@ -1387,7 +1436,7 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) var err *model.AppError if guestsInvite.Emails != nil { - invitesWithError, err = c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, guestsInvite, c.AppContext.Session().UserId) + invitesWithError, err = c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId) } if len(invitesOverLimit) > 0 { @@ -1404,9 +1453,14 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) return } // in graceful mode we return both the successful ones and the failed ones - w.Write([]byte(model.EmailInviteWithErrorToJson(invitesWithError))) + js, jsonErr := json.Marshal(invitesWithError) + if jsonErr != nil { + c.Err = model.NewAppError("inviteGuestsToChannel", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } else { - err := c.App.InviteGuestsToChannels(c.Params.TeamId, guestsInvite, c.AppContext.Session().UserId) + err := c.App.InviteGuestsToChannels(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId) if err != nil { c.Err = err return @@ -1438,7 +1492,7 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) { result["description"] = team.Description result["name"] = team.Name result["id"] = team.Id - w.Write([]byte(model.MapToJson(result))) + w.Write([]byte(model.MapToJSON(result))) } func invalidateAllEmailInvites(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1581,8 +1635,14 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - schemeID := model.SchemeIDFromJson(r.Body) - if schemeID == nil || (!model.IsValidId(*schemeID) && *schemeID != "") { + var p model.SchemeIDPatch + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + c.SetInvalidParam("scheme_id") + return + } + + schemeID := p.SchemeID + if p.SchemeID == nil || (!model.IsValidId(*p.SchemeID) && *p.SchemeID != "") { c.SetInvalidParam("scheme_id") return } diff --git a/api4/team_local.go b/api4/team_local.go index 95f1aef1cb..c0e923dbb4 100644 --- a/api4/team_local.go +++ b/api4/team_local.go @@ -76,7 +76,7 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) return } - emailList := model.ArrayFromJson(r.Body) + emailList := model.ArrayFromJSON(r.Body) if len(emailList) == 0 { c.SetInvalidParam("user_email") return @@ -142,7 +142,12 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) } } // in graceful mode we return both the successful ones and the failed ones - w.Write([]byte(model.EmailInviteWithErrorToJson(invitesWithErrors))) + js, jsonErr := json.Marshal(invitesWithErrors) + if jsonErr != nil { + c.Err = model.NewAppError("localInviteUsersToTeam", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } else { var invalidEmailList []string @@ -200,18 +205,19 @@ func normalizeDomains(domains string) []string { } func localCreateTeam(c *Context, w http.ResponseWriter, r *http.Request) { - team := model.TeamFromJson(r.Body) - if team == nil { + var team model.Team + if jsonErr := json.NewDecoder(r.Body).Decode(&team); jsonErr != nil { c.SetInvalidParam("team") return } + team.Email = strings.ToLower(team.Email) auditRec := c.MakeAuditRecord("localCreateTeam", audit.Fail) defer c.LogAuditRec(auditRec) auditRec.AddMeta("team", team) - rteam, err := c.App.CreateTeam(c.AppContext, team) + rteam, err := c.App.CreateTeam(c.AppContext, &team) if err != nil { c.Err = err return diff --git a/api4/team_test.go b/api4/team_test.go index 7395da6bb4..d36ca60f3f 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -6,6 +6,7 @@ package api4 import ( "encoding/base64" "encoding/binary" + "encoding/json" "fmt" "net/http" "strconv" @@ -343,7 +344,9 @@ func TestUpdateTeam(t *testing.T) { originalTeamId := team.Id team.Id = model.NewId() - r, err := th.Client.DoAPIPut("/teams/"+originalTeamId, team.ToJson()) + teamJSON, jsonErr := json.Marshal(team) + require.NoError(t, jsonErr) + r, err := th.Client.DoAPIPut("/teams/"+originalTeamId, string(teamJSON)) assert.Error(t, err) assert.Equal(t, http.StatusBadRequest, r.StatusCode) @@ -2038,7 +2041,7 @@ func TestAddTeamMember(t *testing.T) { token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": team.Id}), + model.MapToJSON(map[string]string{"teamId": team.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -2074,7 +2077,7 @@ func TestAddTeamMember(t *testing.T) { testId := GenerateTestId() token = model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": testId}), + model.MapToJSON(map[string]string{"teamId": testId}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -2119,7 +2122,7 @@ func TestAddTeamMember(t *testing.T) { // Attempt to use a token on a group-constrained team token = model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": team.Id}), + model.MapToJSON(map[string]string{"teamId": team.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) _, _, err = client.AddTeamMemberFromInvite(token.Token, "") diff --git a/api4/terms_of_service.go b/api4/terms_of_service.go index 6070ef1a3e..be914b5f3d 100644 --- a/api4/terms_of_service.go +++ b/api4/terms_of_service.go @@ -44,7 +44,7 @@ func createTermsOfService(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createTermsOfService", audit.Fail) defer c.LogAuditRec(auditRec) - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) text := props["text"] userId := c.AppContext.Session().UserId diff --git a/api4/upload.go b/api4/upload.go index 4ba35279db..bac31f2790 100644 --- a/api4/upload.go +++ b/api4/upload.go @@ -29,8 +29,8 @@ func createUpload(c *Context, w http.ResponseWriter, r *http.Request) { return } - us := model.UploadSessionFromJson(r.Body) - if us == nil { + var us model.UploadSession + if jsonErr := json.NewDecoder(r.Body).Decode(&us); jsonErr != nil { c.SetInvalidParam("upload") return } @@ -60,7 +60,7 @@ func createUpload(c *Context, w http.ResponseWriter, r *http.Request) { if c.AppContext.Session().UserId != "" { us.UserId = c.AppContext.Session().UserId } - us, err := c.App.CreateUploadSession(us) + rus, err := c.App.CreateUploadSession(&us) if err != nil { c.Err = err return @@ -68,7 +68,7 @@ func createUpload(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(us); err != nil { + if err := json.NewEncoder(w).Encode(rus); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } diff --git a/api4/upload_test.go b/api4/upload_test.go index d08342279e..19a786daf7 100644 --- a/api4/upload_test.go +++ b/api4/upload_test.go @@ -5,6 +5,7 @@ package api4 import ( "bytes" + "encoding/json" "io" "mime/multipart" "net/http" @@ -326,8 +327,10 @@ func TestUploadDataMultipart(t *testing.T) { req.Header.Set(model.HeaderAuth, th.Client.AuthType+" "+th.Client.AuthToken) res, err := th.Client.HTTPClient.Do(req) require.NoError(t, err) - info := model.FileInfoFromJson(res.Body) + var info model.FileInfo + err = json.NewDecoder(res.Body).Decode(&info) res.Body.Close() + require.NoError(t, err) require.NotEmpty(t, info) require.Equal(t, us.Filename, info.Name) @@ -361,8 +364,10 @@ func TestUploadDataMultipart(t *testing.T) { req.Header.Set(model.HeaderAuth, th.Client.AuthType+" "+th.Client.AuthToken) res, err = th.Client.HTTPClient.Do(req) require.NoError(t, err) - info := model.FileInfoFromJson(res.Body) + var info model.FileInfo + err = json.NewDecoder(res.Body).Decode(&info) res.Body.Close() + require.NoError(t, err) require.NotEmpty(t, info) require.Equal(t, u.Filename, info.Name) diff --git a/api4/user.go b/api4/user.go index 0166efc656..a32683febc 100644 --- a/api4/user.go +++ b/api4/user.go @@ -102,8 +102,8 @@ func (api *API) InitUser() { } func createUser(c *Context, w http.ResponseWriter, r *http.Request) { - user := model.UserFromJson(r.Body) - if user == nil { + var user model.User + if jsonErr := json.NewDecoder(r.Body).Decode(&user); jsonErr != nil { c.SetInvalidParam("user") return } @@ -148,14 +148,14 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) { return } } - ruser, err = c.App.CreateUserWithToken(c.AppContext, user, token) + ruser, err = c.App.CreateUserWithToken(c.AppContext, &user, token) } else if inviteId != "" { - ruser, err = c.App.CreateUserWithInviteId(c.AppContext, user, inviteId, redirect) + ruser, err = c.App.CreateUserWithInviteId(c.AppContext, &user, inviteId, redirect) } else if c.IsSystemAdmin() { - ruser, err = c.App.CreateUserAsAdmin(c.AppContext, user, redirect) + ruser, err = c.App.CreateUserAsAdmin(c.AppContext, &user, redirect) auditRec.AddMeta("admin", true) } else { - ruser, err = c.App.CreateUserFromSignup(c.AppContext, user, redirect) + ruser, err = c.App.CreateUserFromSignup(c.AppContext, &user, redirect) } if err != nil { @@ -624,7 +624,7 @@ func getFilteredUsersStats(c *Context, w http.ResponseWriter, r *http.Request) { } func getUsersByGroupChannelIds(c *Context, w http.ResponseWriter, r *http.Request) { - channelIds := model.ArrayFromJson(r.Body) + channelIds := model.ArrayFromJSON(r.Body) if len(channelIds) == 0 { c.SetInvalidParam("channel_ids") @@ -830,11 +830,18 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { w.Header().Set(model.HeaderEtagServer, etag) } c.App.UpdateLastActivityAtIfNeeded(*c.AppContext.Session()) - w.Write([]byte(model.UserListToJson(profiles))) + + js, jsonErr := json.Marshal(profiles) + if jsonErr != nil { + c.Err = model.NewAppError("getUsers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) if len(userIds) == 0 { c.SetInvalidParam("user_ids") @@ -869,11 +876,17 @@ func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.UserListToJson(users))) + js, jsonErr := json.Marshal(users) + if jsonErr != nil { + c.Err = model.NewAppError("getUsersByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func getUsersByNames(c *Context, w http.ResponseWriter, r *http.Request) { - usernames := model.ArrayFromJson(r.Body) + usernames := model.ArrayFromJSON(r.Body) if len(usernames) == 0 { c.SetInvalidParam("usernames") @@ -892,7 +905,13 @@ func getUsersByNames(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.UserListToJson(users))) + js, jsonErr := json.Marshal(users) + if jsonErr != nil { + c.Err = model.NewAppError("getUsersByNames", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func getKnownUsers(c *Context, w http.ResponseWriter, r *http.Request) { @@ -908,12 +927,16 @@ func getKnownUsers(c *Context, w http.ResponseWriter, r *http.Request) { } func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.UserSearchFromJson(r.Body) - if props == nil { + var props model.UserSearch + if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { c.SetInvalidParam("") return } + if props.Limit == 0 { + props.Limit = model.UserSearchDefaultLimit + } + if props.Term == "" { c.SetInvalidParam("term") return @@ -986,13 +1009,19 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - profiles, err := c.App.SearchUsers(props, options) + profiles, err := c.App.SearchUsers(&props, options) if err != nil { c.Err = err return } - w.Write([]byte(model.UserListToJson(profiles))) + js, jsonErr := json.Marshal(profiles) + if jsonErr != nil { + c.Err = model.NewAppError("searchUsers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1092,8 +1121,8 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - user := model.UserFromJson(r.Body) - if user == nil { + var user model.User + if jsonErr := json.NewDecoder(r.Body).Decode(&user); jsonErr != nil { c.SetInvalidParam("user") return } @@ -1151,7 +1180,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) { } } - ruser, err := c.App.UpdateUserAsUser(user, c.IsSystemAdmin()) + ruser, err := c.App.UpdateUserAsUser(&user, c.IsSystemAdmin()) if err != nil { c.Err = err return @@ -1172,8 +1201,8 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - patch := model.UserPatchFromJson(r.Body) - if patch == nil { + var patch model.UserPatch + if jsonErr := json.NewDecoder(r.Body).Decode(&patch); jsonErr != nil { c.SetInvalidParam("user") return } @@ -1207,7 +1236,7 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) { } } - conflictField := c.App.CheckProviderAttributes(ouser, patch) + conflictField := c.App.CheckProviderAttributes(ouser, &patch) if conflictField != "" { c.Err = model.NewAppError( "patchUser", "api.user.patch_user.login_provider_attribute_set.app_error", @@ -1228,7 +1257,7 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) { } } - ruser, err := c.App.PatchUser(c.Params.UserId, patch, c.IsSystemAdmin()) + ruser, err := c.App.PatchUser(c.Params.UserId, &patch, c.IsSystemAdmin()) if err != nil { c.Err = err return @@ -1304,7 +1333,7 @@ func updateUserRoles(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) newRoles := props["roles"] if !model.IsValidUserRoles(newRoles) { @@ -1352,7 +1381,7 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) active, ok := props["active"].(bool) if !ok { @@ -1451,8 +1480,8 @@ func updateUserAuth(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateUserAuth", audit.Fail) defer c.LogAuditRec(auditRec) - userAuth := model.UserAuthFromJson(r.Body) - if userAuth == nil { + var userAuth model.UserAuth + if jsonErr := json.NewDecoder(r.Body).Decode(&userAuth); jsonErr != nil { c.SetInvalidParam("user") return } @@ -1466,7 +1495,7 @@ func updateUserAuth(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("user", user) } - user, err := c.App.UpdateUserAuth(c.Params.UserId, userAuth) + user, err := c.App.UpdateUserAuth(c.Params.UserId, &userAuth) if err != nil { c.Err = err return @@ -1490,7 +1519,7 @@ func checkUserMfa(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) loginId := props["login_id"] if loginId == "" { @@ -1502,7 +1531,7 @@ func checkUserMfa(c *Context, w http.ResponseWriter, r *http.Request) { resp["mfa_required"] = false if !*c.App.Config().ServiceSettings.EnableMultifactorAuthentication { - w.Write([]byte(model.StringInterfaceToJson(resp))) + w.Write([]byte(model.StringInterfaceToJSON(resp))) return } @@ -1512,7 +1541,7 @@ func checkUserMfa(c *Context, w http.ResponseWriter, r *http.Request) { resp["mfa_required"] = user.MfaActive } - w.Write([]byte(model.StringInterfaceToJson(resp))) + w.Write([]byte(model.StringInterfaceToJSON(resp))) } func updateUserMfa(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1539,7 +1568,7 @@ func updateUserMfa(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("user", user) } - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) activate, ok := props["activate"].(bool) if !ok { c.SetInvalidParam("activate") @@ -1606,7 +1635,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) newPassword := props["new_password"] auditRec := c.MakeAuditRecord("updatePassword", audit.Fail) @@ -1665,7 +1694,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) { } func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) token := props["token"] if len(token) != model.TokenSize { @@ -1693,7 +1722,7 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { } func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) email := props["email"] email = strings.ToLower(email) @@ -1782,7 +1811,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = model.NewAppError("login", "api.user.login.invalid_credentials_email_username", nil, "", http.StatusUnauthorized) }() - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) id := props["id"] loginId := props["login_id"] password := props["password"] @@ -1952,7 +1981,12 @@ func getSessions(c *Context, w http.ResponseWriter, r *http.Request) { session.Sanitize() } - w.Write([]byte(model.SessionsToJson(sessions))) + js, jsonErr := json.Marshal(sessions) + if jsonErr != nil { + c.Err = model.NewAppError("getSessions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1969,7 +2003,7 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) { return } - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) sessionId := props["session_id"] if sessionId == "" { c.SetInvalidParam("session_id") @@ -2046,7 +2080,7 @@ func revokeAllSessionsAllUsers(c *Context, w http.ResponseWriter, r *http.Reques } func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) deviceId := props["device_id"] if deviceId == "" { @@ -2135,7 +2169,7 @@ func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) { } func verifyUserEmail(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) token := props["token"] if len(token) != model.TokenSize { @@ -2158,7 +2192,7 @@ func verifyUserEmail(c *Context, w http.ResponseWriter, r *http.Request) { } func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) email := props["email"] email = strings.ToLower(email) @@ -2192,8 +2226,8 @@ func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) { } func switchAccountType(c *Context, w http.ResponseWriter, r *http.Request) { - switchRequest := model.SwitchRequestFromJson(r.Body) - if switchRequest == nil { + var switchRequest model.SwitchRequest + if jsonErr := json.NewDecoder(r.Body).Decode(&switchRequest); jsonErr != nil { c.SetInvalidParam("switch_request") return } @@ -2233,7 +2267,7 @@ func switchAccountType(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() c.LogAudit("success") - w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link}))) + w.Write([]byte(model.MapToJSON(map[string]string{"follow_link": link}))) } func createUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { @@ -2255,8 +2289,8 @@ func createUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { return } - accessToken := model.UserAccessTokenFromJson(r.Body) - if accessToken == nil { + var accessToken model.UserAccessToken + if jsonErr := json.NewDecoder(r.Body).Decode(&accessToken); jsonErr != nil { c.SetInvalidParam("user_access_token") return } @@ -2281,17 +2315,17 @@ func createUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { accessToken.UserId = c.Params.UserId accessToken.Token = "" - accessToken, err := c.App.CreateUserAccessToken(accessToken) + token, err := c.App.CreateUserAccessToken(&accessToken) if err != nil { c.Err = err return } auditRec.Success() - auditRec.AddMeta("token_id", accessToken.Id) - c.LogAudit("success - token_id=" + accessToken.Id) + auditRec.AddMeta("token_id", token.Id) + c.LogAudit("success - token_id=" + token.Id) - if err := json.NewEncoder(w).Encode(accessToken); err != nil { + if err := json.NewEncoder(w).Encode(token); err != nil { mlog.Warn("Error while writing response", mlog.Err(err)) } } @@ -2301,8 +2335,9 @@ func searchUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) c.SetPermissionError(model.PermissionManageSystem) return } - props := model.UserAccessTokenSearchFromJson(r.Body) - if props == nil { + + var props model.UserAccessTokenSearch + if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { c.SetInvalidParam("user_access_token_search") return } @@ -2318,7 +2353,13 @@ func searchUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) return } - w.Write([]byte(model.UserAccessTokenListToJson(accessTokens))) + js, jsonErr := json.Marshal(accessTokens) + if jsonErr != nil { + c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func getUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) { @@ -2333,7 +2374,13 @@ func getUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.UserAccessTokenListToJson(accessTokens))) + js, jsonErr := json.Marshal(accessTokens) + if jsonErr != nil { + c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func getUserAccessTokensForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -2358,7 +2405,13 @@ func getUserAccessTokensForUser(c *Context, w http.ResponseWriter, r *http.Reque return } - w.Write([]byte(model.UserAccessTokenListToJson(accessTokens))) + js, jsonErr := json.Marshal(accessTokens) + if jsonErr != nil { + c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func getUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { @@ -2389,7 +2442,7 @@ func getUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { } func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) tokenId := props["token_id"] if tokenId == "" { @@ -2433,7 +2486,7 @@ func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { } func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) tokenId := props["token_id"] if tokenId == "" { @@ -2478,7 +2531,7 @@ func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) } func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.MapFromJson(r.Body) + props := model.MapFromJSON(r.Body) tokenId := props["token_id"] if tokenId == "" { @@ -2523,7 +2576,7 @@ func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { } func saveUserTermsOfService(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) userId := c.AppContext.Session().UserId termsOfServiceId, ok := props["termsOfServiceId"].(string) @@ -2666,8 +2719,8 @@ func publishUserTyping(c *Context, w http.ResponseWriter, r *http.Request) { return } - typingRequest := model.TypingRequestFromJson(r.Body) - if typingRequest == nil { + var typingRequest model.TypingRequest + if jsonErr := json.NewDecoder(r.Body).Decode(&typingRequest); jsonErr != nil { c.SetInvalidParam("typing_request") return } @@ -2751,10 +2804,17 @@ func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.Success() auditRec.AddMeta("convertedTo", bot) - w.Write(bot.ToJson()) + js, jsonErr := json.Marshal(bot) + if jsonErr != nil { + c.Err = model.NewAppError("convertUserToBot", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + auditRec.Success() + + w.Write(js) } func getUploadsForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -2774,11 +2834,16 @@ func getUploadsForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.UploadSessionsToJson(uss))) + js, jsonErr := json.Marshal(uss) + if jsonErr != nil { + c.Err = model.NewAppError("getUploadsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func migrateAuthToLDAP(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) from, ok := props["from"].(string) if !ok { c.SetInvalidParam("from") @@ -2837,7 +2902,7 @@ func migrateAuthToLDAP(c *Context, w http.ResponseWriter, r *http.Request) { } func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) { - props := model.StringInterfaceFromJson(r.Body) + props := model.StringInterfaceFromJSON(r.Body) from, ok := props["from"].(string) if !ok { c.SetInvalidParam("from") @@ -2858,7 +2923,7 @@ func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidParam("matches") return } - usersMap := model.MapFromJson(strings.NewReader(model.StringInterfaceToJson(matches))) + usersMap := model.MapFromJSON(strings.NewReader(model.StringInterfaceToJSON(matches))) auditRec := c.MakeAuditRecord("migrateAuthToSaml", audit.Fail) defer c.LogAuditRec(auditRec) diff --git a/api4/user_local.go b/api4/user_local.go index 38fa2b3668..a227fa137a 100644 --- a/api4/user_local.go +++ b/api4/user_local.go @@ -145,11 +145,18 @@ func localGetUsers(c *Context, w http.ResponseWriter, r *http.Request) { if etag != "" { w.Header().Set(model.HeaderEtagServer, etag) } - w.Write([]byte(model.UserListToJson(profiles))) + + js, jsonErr := json.Marshal(profiles) + if jsonErr != nil { + c.Err = model.NewAppError("localGetUsers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func localGetUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { - userIds := model.ArrayFromJson(r.Body) + userIds := model.ArrayFromJSON(r.Body) if len(userIds) == 0 { c.SetInvalidParam("user_ids") @@ -177,7 +184,13 @@ func localGetUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.UserListToJson(users))) + js, jsonErr := json.Marshal(users) + if jsonErr != nil { + c.Err = model.NewAppError("localGetUsersByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(js) } func localGetUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -335,5 +348,10 @@ func localGetUploadsForUser(c *Context, w http.ResponseWriter, r *http.Request) return } - w.Write([]byte(model.UploadSessionsToJson(uss))) + js, jsonErr := json.Marshal(uss) + if jsonErr != nil { + c.Err = model.NewAppError("localGetUploadsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } diff --git a/api4/user_test.go b/api4/user_test.go index fe6730c3be..99d9fbdb25 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -4,6 +4,7 @@ package api4 import ( + "encoding/json" "fmt" "net/http" "os" @@ -221,7 +222,7 @@ func TestCreateUserWithToken(t *testing.T) { user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SystemAdminRoleId + " " + model.SystemUserRoleId} token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -246,7 +247,7 @@ func TestCreateUserWithToken(t *testing.T) { user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SystemAdminRoleId + " " + model.SystemUserRoleId} token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -271,7 +272,7 @@ func TestCreateUserWithToken(t *testing.T) { user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SystemAdminRoleId + " " + model.SystemUserRoleId} token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -287,7 +288,7 @@ func TestCreateUserWithToken(t *testing.T) { past49Hours := timeNow.Add(-49*time.Hour).UnixNano() / int64(time.Millisecond) token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) token.CreateAt = past49Hours require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -319,7 +320,7 @@ func TestCreateUserWithToken(t *testing.T) { token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -340,7 +341,7 @@ func TestCreateUserWithToken(t *testing.T) { token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -358,7 +359,7 @@ func TestCreateUserWithToken(t *testing.T) { token := model.NewToken( app.TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -5761,8 +5762,9 @@ func TestThreadSocketEvents(t *testing.T) { case ev := <-userWSClient.EventChannel: if ev.EventType() == model.WebsocketEventThreadUpdated { caught = true - thread, err2 := model.ThreadResponseFromJson(ev.GetData()["thread"].(string)) - require.NoError(t, err2) + var thread model.ThreadResponse + jsonErr := json.Unmarshal([]byte(ev.GetData()["thread"].(string)), &thread) + require.NoError(t, jsonErr) for _, p := range thread.Participants { if p.Id != th.BasicUser.Id && p.Id != th.BasicUser2.Id { require.Fail(t, "invalid participants") diff --git a/api4/webhook.go b/api4/webhook.go index 355f9ad3ff..7845684806 100644 --- a/api4/webhook.go +++ b/api4/webhook.go @@ -28,8 +28,8 @@ func (api *API) InitWebhook() { } func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { - hook := model.IncomingWebhookFromJson(r.Body) - if hook == nil { + var hook model.IncomingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&hook); jsonErr != nil { c.SetInvalidParam("incoming_webhook") return } @@ -72,7 +72,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { userId = hook.UserId } - incomingHook, err := c.App.CreateIncomingWebhookForChannel(userId, channel, hook) + incomingHook, err := c.App.CreateIncomingWebhookForChannel(userId, channel, &hook) if err != nil { c.Err = err return @@ -94,8 +94,8 @@ func updateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { return } - updatedHook := model.IncomingWebhookFromJson(r.Body) - if updatedHook == nil { + var updatedHook model.IncomingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&updatedHook); jsonErr != nil { c.SetInvalidParam("incoming_webhook") return } @@ -157,7 +157,7 @@ func updateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { return } - incomingHook, err := c.App.UpdateIncomingWebhook(oldHook, updatedHook) + incomingHook, err := c.App.UpdateIncomingWebhook(oldHook, &updatedHook) if err != nil { c.Err = err return @@ -210,7 +210,12 @@ func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.IncomingWebhookListToJson(hooks))) + js, jsonErr := json.Marshal(hooks) + if jsonErr != nil { + c.Err = model.NewAppError("getIncomingHooks", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { @@ -326,8 +331,8 @@ func updateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { return } - updatedHook := model.OutgoingWebhookFromJson(r.Body) - if updatedHook == nil { + var updatedHook model.OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&updatedHook); jsonErr != nil { c.SetInvalidParam("outgoing_webhook") return } @@ -374,7 +379,7 @@ func updateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { updatedHook.CreatorId = c.AppContext.Session().UserId - rhook, err := c.App.UpdateOutgoingWebhook(oldHook, updatedHook) + rhook, err := c.App.UpdateOutgoingWebhook(oldHook, &updatedHook) if err != nil { c.Err = err return @@ -389,8 +394,8 @@ func updateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { } func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { - hook := model.OutgoingWebhookFromJson(r.Body) - if hook == nil { + var hook model.OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&hook); jsonErr != nil { c.SetInvalidParam("outgoing_webhook") return } @@ -421,7 +426,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { } } - rhook, err := c.App.CreateOutgoingWebhook(hook) + rhook, err := c.App.CreateOutgoingWebhook(&hook) if err != nil { c.LogAudit("fail") c.Err = err @@ -491,7 +496,12 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) { return } - w.Write([]byte(model.OutgoingWebhookListToJson(hooks))) + js, jsonErr := json.Marshal(hooks) + if jsonErr != nil { + c.Err = model.NewAppError("getOutgoingHooks", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return + } + w.Write(js) } func getOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api4/webhook_local.go b/api4/webhook_local.go index 765af76679..b9a45a2d34 100644 --- a/api4/webhook_local.go +++ b/api4/webhook_local.go @@ -27,8 +27,8 @@ func (api *API) InitWebhookLocal() { } func localCreateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { - hook := model.IncomingWebhookFromJson(r.Body) - if hook == nil { + var hook model.IncomingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&hook); jsonErr != nil { c.SetInvalidParam("incoming_webhook") return } @@ -54,7 +54,7 @@ func localCreateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) auditRec.AddMeta("channel", channel) c.LogAudit("attempt") - incomingHook, err := c.App.CreateIncomingWebhookForChannel(hook.UserId, channel, hook) + incomingHook, err := c.App.CreateIncomingWebhookForChannel(hook.UserId, channel, &hook) if err != nil { c.Err = err return @@ -71,8 +71,8 @@ func localCreateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) } func localCreateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { - hook := model.OutgoingWebhookFromJson(r.Body) - if hook == nil { + var hook model.OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&hook); jsonErr != nil { c.SetInvalidParam("outgoing_webhook") return } @@ -93,7 +93,7 @@ func localCreateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) return } - rhook, err := c.App.CreateOutgoingWebhook(hook) + rhook, err := c.App.CreateOutgoingWebhook(&hook) if err != nil { c.LogAudit("fail") c.Err = err diff --git a/app/busy.go b/app/busy.go index 98b22024e8..8341b91079 100644 --- a/app/busy.go +++ b/app/busy.go @@ -5,6 +5,7 @@ package app import ( "encoding/json" + "fmt" "sync" "sync/atomic" "time" @@ -136,7 +137,7 @@ func (b *Busy) ClusterEventChanged(sbs *model.ServerBusyState) { } } -func (b *Busy) ToJson() string { +func (b *Busy) ToJSON() ([]byte, error) { b.mux.RLock() defer b.mux.RUnlock() @@ -145,5 +146,10 @@ func (b *Busy) ToJson() string { Expires: b.expires.Unix(), ExpiresTS: b.expires.UTC().Format(TimestampFormat), } - return sbs.ToJson() + sbsJSON, jsonErr := json.Marshal(sbs) + if jsonErr != nil { + return []byte{}, fmt.Errorf("failed to encode server busy state to JSON: %w", jsonErr) + } + + return sbsJSON, nil } diff --git a/app/busy_test.go b/app/busy_test.go index 99be6ea4d1..7d8fc638dd 100644 --- a/app/busy_test.go +++ b/app/busy_test.go @@ -4,7 +4,7 @@ package app import ( - "bytes" + "encoding/json" "testing" "time" @@ -100,11 +100,15 @@ func TestBusyRace(t *testing.T) { func compareBusyState(t *testing.T, busy1 *Busy, busy2 *Busy) bool { t.Helper() if busy1.IsBusy() != busy2.IsBusy() { - t.Logf("busy1:%s; busy2:%s\n", busy1.ToJson(), busy2.ToJson()) + busy1JSON, _ := busy1.ToJSON() + busy2JSON, _ := busy2.ToJSON() + t.Logf("busy1:%s; busy2:%s\n", busy1JSON, busy2JSON) return false } if busy1.Expires().Unix() != busy2.Expires().Unix() { - t.Logf("busy1:%s; busy2:%s\n", busy1.ToJson(), busy2.ToJson()) + busy1JSON, _ := busy1.ToJSON() + busy2JSON, _ := busy2.ToJSON() + t.Logf("busy1:%s; busy2:%s\n", busy1JSON, busy2JSON) return false } return true @@ -116,8 +120,9 @@ type ClusterMock struct { } func (c *ClusterMock) SendClusterMessage(msg *model.ClusterMessage) { - sbs := model.ServerBusyStateFromJson(bytes.NewReader(msg.Data)) - c.Busy.ClusterEventChanged(sbs) + var sbs model.ServerBusyState + json.Unmarshal(msg.Data, &sbs) + c.Busy.ClusterEventChanged(&sbs) } func (c *ClusterMock) SendClusterMessageToNode(nodeID string, msg *model.ClusterMessage) error { diff --git a/app/channel.go b/app/channel.go index 832d7a6bc1..171fe48ff9 100644 --- a/app/channel.go +++ b/app/channel.go @@ -5,6 +5,7 @@ package app import ( "context" + "encoding/json" "errors" "fmt" "net/http" @@ -510,7 +511,7 @@ func (a *App) CreateGroupChannel(userIDs []string, creatorId string) (*model.Cha } message := model.NewWebSocketEvent(model.WebsocketEventGroupAdded, "", channel.Id, "", nil) - message.Add("teammate_ids", model.ArrayToJson(userIDs)) + message.Add("teammate_ids", model.ArrayToJSON(userIDs)) a.Publish(message) return channel, nil @@ -527,7 +528,7 @@ func (a *App) createGroupChannel(userIDs []string) (*model.Channel, *model.AppEr } if len(users) != len(userIDs) { - return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIDs), http.StatusBadRequest) + return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJSON(userIDs), http.StatusBadRequest) } group := &model.Channel{ @@ -606,7 +607,7 @@ func (a *App) GetGroupChannel(userIDs []string) (*model.Channel, *model.AppError } if len(users) != len(userIDs) { - return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIDs), http.StatusBadRequest) + return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJSON(userIDs), http.StatusBadRequest) } channel, appErr := a.GetChannelByName(model.GetGroupNameFromUserIds(userIDs), "", true) @@ -636,7 +637,11 @@ func (a *App) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppE a.invalidateCacheForChannel(channel) messageWs := model.NewWebSocketEvent(model.WebsocketEventChannelUpdated, "", channel.Id, "", nil) - messageWs.Add("channel", channel.ToJson()) + channelJSON, jsonErr := json.Marshal(channel) + if jsonErr != nil { + mlog.Warn("Failed to encode channel to JSON", mlog.Err(jsonErr)) + } + messageWs.Add("channel", string(channelJSON)) a.Publish(messageWs) return channel, nil @@ -1248,7 +1253,11 @@ func (a *App) UpdateChannelMemberNotifyProps(data map[string]string, channelID s // Notify the clients that the member notify props changed evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil) - evt.Add("channelMember", member.ToJson()) + memberJSON, jsonErr := json.Marshal(member) + if jsonErr != nil { + mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + } + evt.Add("channelMember", string(memberJSON)) a.Publish(evt) return member, nil @@ -1273,7 +1282,11 @@ func (a *App) updateChannelMember(member *model.ChannelMember) (*model.ChannelMe // Notify the clients that the member notify props changed evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil) - evt.Add("channelMember", member.ToJson()) + memberJSON, jsonErr := json.Marshal(member) + if jsonErr != nil { + mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + } + evt.Add("channelMember", string(memberJSON)) a.Publish(evt) return member, nil @@ -2545,10 +2558,12 @@ func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string, collapse } a.sanitizeProfiles(thread.Participants, false) thread.Post.SanitizeProps() - - payload := thread.ToJson() + payload, jsonErr := json.Marshal(thread) + if jsonErr != nil { + mlog.Warn("Failed to encode thread to JSON") + } message := model.NewWebSocketEvent(model.WebsocketEventThreadUpdated, channel.TeamId, "", userID, nil) - message.Add("thread", payload) + message.Add("thread", string(payload)) a.Publish(message) } } else if !threadMembership.Following && followThread { @@ -2661,10 +2676,13 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(postID string, userID st a.sanitizeProfiles(thread.Participants, false) thread.Post.SanitizeProps() - payload := thread.ToJson() if a.isCRTEnabledForUser(userID) { + payload, jsonErr := json.Marshal(thread) + if jsonErr != nil { + mlog.Warn("Failed to encode thread to JSON") + } message := model.NewWebSocketEvent(model.WebsocketEventThreadUpdated, channel.TeamId, "", userID, nil) - message.Add("thread", payload) + message.Add("thread", string(payload)) a.Publish(message) } channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, 0, false, false) @@ -3190,7 +3208,13 @@ func (a *App) setChannelsMuted(channelIDs []string, userID string, muted bool) ( a.invalidateCacheForChannelMembersNotifyProps(member.ChannelId) evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil) - evt.Add("channelMember", member.ToJson()) + + memberJSON, jsonErr := json.Marshal(member) + if jsonErr != nil { + mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + } + + evt.Add("channelMember", string(memberJSON)) a.Publish(evt) } @@ -3292,7 +3316,11 @@ func (a *App) ClearChannelMembersCache(channelID string) { clearSessionCache := func(channelMember model.ChannelMember) error { a.ClearSessionCacheForUser(channelMember.UserId) message := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", channelMember.UserId, nil) - message.Add("channelMember", channelMember.ToJson()) + memberJSON, jsonErr := json.Marshal(channelMember) + if jsonErr != nil { + mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + } + message.Add("channelMember", string(memberJSON)) a.Publish(message) return nil } diff --git a/app/cluster_handlers.go b/app/cluster_handlers.go index 01be8af6a3..f1f82eae33 100644 --- a/app/cluster_handlers.go +++ b/app/cluster_handlers.go @@ -5,6 +5,7 @@ package app import ( "bytes" + "encoding/json" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/plugin" @@ -12,11 +13,19 @@ import ( ) func (s *Server) clusterInstallPluginHandler(msg *model.ClusterMessage) { - s.installPluginFromData(model.PluginEventDataFromJson(bytes.NewReader(msg.Data))) + var data model.PluginEventData + if jsonErr := json.Unmarshal(msg.Data, &data); jsonErr != nil { + mlog.Warn("Failed to decode from JSON", mlog.Err(jsonErr)) + } + s.installPluginFromData(data) } func (s *Server) clusterRemovePluginHandler(msg *model.ClusterMessage) { - s.removePluginFromData(model.PluginEventDataFromJson(bytes.NewReader(msg.Data))) + var data model.PluginEventData + if jsonErr := json.Unmarshal(msg.Data, &data); jsonErr != nil { + mlog.Warn("Failed to decode from JSON", mlog.Err(jsonErr)) + } + s.removePluginFromData(data) } func (s *Server) clusterPluginEventHandler(msg *model.ClusterMessage) { @@ -69,15 +78,19 @@ func (s *Server) registerClusterHandlers() { } func (s *Server) clusterPublishHandler(msg *model.ClusterMessage) { - event := model.WebSocketEventFromJson(bytes.NewReader(msg.Data)) - if event == nil { + event, err := model.WebSocketEventFromJSON(bytes.NewReader(msg.Data)) + if err != nil { + mlog.Warn("Failed to decode event from JSON", mlog.Err(err)) return } s.PublishSkipClusterSend(event) } func (s *Server) clusterUpdateStatusHandler(msg *model.ClusterMessage) { - status := model.StatusFromJson(bytes.NewReader(msg.Data)) + var status model.Status + if jsonErr := json.Unmarshal(msg.Data, &status); jsonErr != nil { + mlog.Warn("Failed to decode status from JSON") + } s.statusCache.Set(status.UserId, status) } @@ -120,7 +133,11 @@ func (s *Server) clusterClearSessionCacheForAllUsersHandler(msg *model.ClusterMe } func (s *Server) clusterBusyStateChgHandler(msg *model.ClusterMessage) { - s.serverBusyStateChanged(model.ServerBusyStateFromJson(bytes.NewReader(msg.Data))) + var sbs model.ServerBusyState + if jsonErr := json.Unmarshal(msg.Data, &sbs); jsonErr != nil { + mlog.Warn("Failed to decode server busy state from JSON", mlog.Err(jsonErr)) + } + s.serverBusyStateChanged(&sbs) } func (s *Server) invalidateCacheForChannelMembersNotifyPropsSkipClusterSend(channelID string) { diff --git a/app/command_autocomplete.go b/app/command_autocomplete.go index ae3b3fc216..56fd45d6f5 100644 --- a/app/command_autocomplete.go +++ b/app/command_autocomplete.go @@ -4,6 +4,7 @@ package app import ( + "encoding/json" "errors" "fmt" "net/url" @@ -277,7 +278,10 @@ func (a *App) getDynamicListArgument(c *request.Context, commandArgs *model.Comm return false, parsed, toBeParsed, []model.AutocompleteSuggestion{} } - listItems := model.AutocompleteStaticListItemsFromJSON(resp.Body) + var listItems []model.AutocompleteListItem + if jsonErr := json.NewDecoder(resp.Body).Decode(&listItems); jsonErr != nil { + mlog.Warn("Failed to decode from JSON", mlog.Err(jsonErr)) + } return parseListItems(listItems, parsed, toBeParsed) } diff --git a/app/email/email.go b/app/email/email.go index ffc19ae847..e38e522eb5 100644 --- a/app/email/email.go +++ b/app/email/email.go @@ -460,14 +460,14 @@ func (es *Service) SendInviteEmails(team *model.Team, senderName string, senderU token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": team.Id, "email": invite}), + model.MapToJSON(map[string]string{"teamId": team.Id, "email": invite}), ) tokenProps := make(map[string]string) tokenProps["email"] = invite tokenProps["display_name"] = team.DisplayName tokenProps["name"] = team.Name - tokenData := model.MapToJson(tokenProps) + tokenData := model.MapToJSON(tokenProps) if err := es.store.Token().Save(token); err != nil { mlog.Error("Failed to send invite email successfully ", mlog.Err(err)) @@ -531,7 +531,7 @@ func (es *Service) SendGuestInviteEmails(team *model.Team, channels []*model.Cha token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{ + model.MapToJSON(map[string]string{ "teamId": team.Id, "channels": strings.Join(channelIDs, " "), "email": invite, @@ -543,7 +543,7 @@ func (es *Service) SendGuestInviteEmails(team *model.Team, channels []*model.Cha tokenProps["email"] = invite tokenProps["display_name"] = team.DisplayName tokenProps["name"] = team.Name - tokenData := model.MapToJson(tokenProps) + tokenData := model.MapToJSON(tokenProps) if err := es.store.Token().Save(token); err != nil { mlog.Error("Failed to send invite email successfully ", mlog.Err(err)) diff --git a/app/emoji.go b/app/emoji.go index 80c67a073e..f319e26bb7 100644 --- a/app/emoji.go +++ b/app/emoji.go @@ -6,6 +6,7 @@ package app import ( "bytes" "context" + "encoding/json" "errors" "fmt" "image" @@ -78,7 +79,11 @@ func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartIma } message := model.NewWebSocketEvent(model.WebsocketEventEmojiAdded, "", "", "", nil) - message.Add("emoji", emoji.ToJson()) + emojiJSON, jsonErr := json.Marshal(emoji) + if jsonErr != nil { + mlog.Warn("Failed to encode emoji to JSON", mlog.Err(jsonErr)) + } + message.Add("emoji", string(emojiJSON)) a.Publish(message) return emoji, nil } diff --git a/app/group.go b/app/group.go index 4483929da5..cb960f9248 100644 --- a/app/group.go +++ b/app/group.go @@ -4,10 +4,12 @@ package app import ( + "encoding/json" "errors" "net/http" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/store" ) @@ -97,7 +99,11 @@ func (a *App) UpdateGroup(group *model.Group) (*model.Group, *model.AppError) { if err == nil { messageWs := model.NewWebSocketEvent(model.WebsocketEventReceivedGroup, "", "", "", nil) - messageWs.Add("group", updatedGroup.ToJson()) + groupJSON, jsonErr := json.Marshal(updatedGroup) + if jsonErr != nil { + mlog.Warn("Failed to encode group to JSON", mlog.Err(jsonErr)) + } + messageWs.Add("group", string(groupJSON)) a.Publish(messageWs) } @@ -122,7 +128,11 @@ func (a *App) DeleteGroup(groupID string) (*model.Group, *model.AppError) { if err == nil { messageWs := model.NewWebSocketEvent(model.WebsocketEventReceivedGroup, "", "", "", nil) - messageWs.Add("group", deletedGroup.ToJson()) + groupJSON, jsonErr := json.Marshal(deletedGroup) + if jsonErr != nil { + mlog.Warn("Failed to encode group to JSON", mlog.Err(jsonErr)) + } + messageWs.Add("group", string(groupJSON)) a.Publish(messageWs) } diff --git a/app/import_validators.go b/app/import_validators.go index 5df7887b30..9cc37cf265 100644 --- a/app/import_validators.go +++ b/app/import_validators.go @@ -457,7 +457,7 @@ func validatePostImportData(data *PostImportData, maxPostSize int) *model.AppErr } } - if data.Props != nil && utf8.RuneCountInString(model.StringInterfaceToJson(*data.Props)) > model.PostPropsMaxRunes { + if data.Props != nil && utf8.RuneCountInString(model.StringInterfaceToJSON(*data.Props)) > model.PostPropsMaxRunes { return model.NewAppError("BulkImport", "app.import.validate_post_import_data.props_too_large.error", nil, "", http.StatusBadRequest) } diff --git a/app/integration_action.go b/app/integration_action.go index f8cdf3ea5d..941a276875 100644 --- a/app/integration_action.go +++ b/app/integration_action.go @@ -242,7 +242,11 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI } return "", nil } - resp, appErr = a.DoActionRequest(c, upstreamURL, upstreamRequest.ToJson()) + requestJSON, jsonErr := json.Marshal(upstreamRequest) + if jsonErr != nil { + return "", model.NewAppError("DoPostActionWithCookie", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + resp, appErr = a.DoActionRequest(c, upstreamURL, requestJSON) if appErr != nil { return "", appErr } @@ -530,7 +534,7 @@ type MailToLinkContent struct { MailBody string `json:"mail_body"` } -func (mlc *MailToLinkContent) ToJson() string { +func (mlc *MailToLinkContent) ToJSON() string { b, _ := json.Marshal(mlc) return string(b) } @@ -569,7 +573,7 @@ func (a *App) buildWarnMetricMailtoLink(warnMetricId string, user *model.User) s MailBody: mailBody, } - return mailToLinkContent.ToJson() + return mailToLinkContent.ToJSON() } func (a *App) DoLocalRequest(c *request.Context, rawURL string, body []byte) (*http.Response, *model.AppError) { diff --git a/app/integration_action_test.go b/app/integration_action_test.go index 8cb29061ff..7b2f04a346 100644 --- a/app/integration_action_test.go +++ b/app/integration_action_test.go @@ -29,8 +29,9 @@ func TestPostActionInvalidURL(t *testing.T) { }) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - request := model.PostActionIntegrationRequestFromJson(r.Body) - assert.NotNil(t, request) + var request model.PostActionIntegrationRequest + jsonErr := json.NewDecoder(r.Body).Decode(&request) + assert.NoError(t, jsonErr) })) defer ts.Close() @@ -155,8 +156,9 @@ func TestPostAction(t *testing.T) { }) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - request := model.PostActionIntegrationRequestFromJson(r.Body) - assert.NotNil(t, request) + var request model.PostActionIntegrationRequest + jsonErr := json.NewDecoder(r.Body).Decode(&request) + assert.NoError(t, jsonErr) assert.Equal(t, request.UserId, th.BasicUser.Id) assert.Equal(t, request.UserName, th.BasicUser.Username) @@ -410,8 +412,9 @@ func TestPostActionProps(t *testing.T) { }) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - request := model.PostActionIntegrationRequestFromJson(r.Body) - assert.NotNil(t, request) + var request model.PostActionIntegrationRequest + jsonErr := json.NewDecoder(r.Body).Decode(&request) + assert.NoError(t, jsonErr) fmt.Fprintf(w, `{ "update": { @@ -536,6 +539,8 @@ func TestSubmitInteractiveDialog(t *testing.T) { import ( "net/http" + "encoding/json" + "github.com/mattermost/mattermost-server/v6/plugin" "github.com/mattermost/mattermost-server/v6/model" ) @@ -553,7 +558,8 @@ func TestSubmitInteractiveDialog(t *testing.T) { Errors: map[string]string{"name1": errReply}, } w.WriteHeader(http.StatusOK) - _, _ = w.Write(response.ToJson()) + responseJSON, _ := json.Marshal(response) + _, _ = w.Write(responseJSON) } func main() { @@ -606,8 +612,9 @@ func TestPostActionRelativeURL(t *testing.T) { defer th.TearDown() ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - request := model.PostActionIntegrationRequestFromJson(r.Body) - assert.NotNil(t, request) + var request model.PostActionIntegrationRequest + jsonErr := json.NewDecoder(r.Body).Decode(&request) + assert.NoError(t, jsonErr) fmt.Fprintf(w, `{"post": {"message": "updated"}, "ephemeral_text": "foo"}`) })) defer ts.Close() @@ -824,6 +831,8 @@ func TestPostActionRelativePluginURL(t *testing.T) { import ( "net/http" + "encoding/json" + "github.com/mattermost/mattermost-server/v6/plugin" "github.com/mattermost/mattermost-server/v6/model" ) @@ -835,7 +844,8 @@ func TestPostActionRelativePluginURL(t *testing.T) { func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { response := &model.PostActionIntegrationResponse{} w.WriteHeader(http.StatusOK) - _, _ = w.Write(response.ToJson()) + responseJSON, _ := json.Marshal(response) + _, _ = w.Write(responseJSON) } func main() { diff --git a/app/license.go b/app/license.go index 0e7424b1f7..7907b1c0fe 100644 --- a/app/license.go +++ b/app/license.go @@ -5,9 +5,9 @@ package app import ( "bytes" + "encoding/json" "net/http" "os" - "strings" "time" "github.com/dgrijalva/jwt-go" @@ -100,7 +100,11 @@ func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppErr if !success { return nil, model.NewAppError("addLicense", model.InvalidLicenseError, nil, "", http.StatusBadRequest) } - license := model.LicenseFromJson(strings.NewReader(licenseStr)) + + var license model.License + if jsonErr := json.Unmarshal([]byte(licenseStr), &license); jsonErr != nil { + return nil, model.NewAppError("addLicense", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } uniqueUserCount, err := s.Store.User().Count(model.UserCountOptions{}) if err != nil { @@ -111,11 +115,11 @@ func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppErr return nil, model.NewAppError("addLicense", "api.license.add_license.unique_users.app_error", map[string]interface{}{"Users": *license.Features.Users, "Count": uniqueUserCount}, "", http.StatusBadRequest) } - if license != nil && license.IsExpired() { + if license.IsExpired() { return nil, model.NewAppError("addLicense", model.ExpiredLicenseError, nil, "", http.StatusBadRequest) } - if ok := s.SetLicense(license); !ok { + if ok := s.SetLicense(&license); !ok { return nil, model.NewAppError("addLicense", model.ExpiredLicenseError, nil, "", http.StatusBadRequest) } @@ -165,7 +169,7 @@ func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppErr } } - return license, nil + return &license, nil } func (s *Server) SetLicense(license *model.License) bool { @@ -196,8 +200,12 @@ func (s *Server) SetLicense(license *model.License) bool { func (s *Server) ValidateAndSetLicenseBytes(b []byte) bool { if success, licenseStr := utils.LicenseValidator.ValidateLicense(b); success { - license := model.LicenseFromJson(strings.NewReader(licenseStr)) - s.SetLicense(license) + var license model.License + if jsonErr := json.Unmarshal([]byte(licenseStr), &license); jsonErr != nil { + mlog.Warn("Failed to decode license from JSON", mlog.Err(jsonErr)) + return false + } + s.SetLicense(&license) return true } @@ -254,12 +262,17 @@ func (s *Server) GetSanitizedClientLicense() map[string]string { // RequestTrialLicense request a trial license from the mattermost official license server func (s *Server) RequestTrialLicense(trialRequest *model.TrialLicenseRequest) *model.AppError { - resp, err := http.Post(RequestTrialURL, "application/json", bytes.NewBuffer([]byte(trialRequest.ToJson()))) + trialRequestJSON, jsonErr := json.Marshal(trialRequest) + if jsonErr != nil { + return model.NewAppError("RequestTrialLicense", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + + resp, err := http.Post(RequestTrialURL, "application/json", bytes.NewBuffer(trialRequestJSON)) if err != nil { return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, err.Error(), http.StatusBadRequest) } defer resp.Body.Close() - licenseResponse := model.MapFromJson(resp.Body) + licenseResponse := model.MapFromJSON(resp.Body) if _, ok := licenseResponse["license"]; !ok { return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, licenseResponse["message"], http.StatusBadRequest) diff --git a/app/notification.go b/app/notification.go index a7d0319f10..89fb598cbc 100644 --- a/app/notification.go +++ b/app/notification.go @@ -5,6 +5,7 @@ package app import ( "context" + "encoding/json" "net/http" "sort" "strings" @@ -524,7 +525,11 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod message := model.NewWebSocketEvent(model.WebsocketEventPosted, "", post.ChannelId, "", nil) // Note that PreparePostForClient should've already been called by this point - message.Add("post", post.ToJson()) + postJSON, jsonErr := post.ToJSON() + if jsonErr != nil { + return nil, errors.Wrapf(jsonErr, "failed to encode post to JSON") + } + message.Add("post", postJSON) message.Add("channel_type", channel.Type) message.Add("channel_display_name", notification.GetChannelName(model.ShowUsername, "")) @@ -552,11 +557,11 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } if len(mentionedUsersList) != 0 { - message.Add("mentions", model.ArrayToJson(mentionedUsersList)) + message.Add("mentions", model.ArrayToJSON(mentionedUsersList)) } if len(notificationsForCRT.Desktop) != 0 { - message.Add("followers", model.ArrayToJson(notificationsForCRT.Desktop)) + message.Add("followers", model.ArrayToJSON(notificationsForCRT.Desktop)) } published, err := a.publishWebsocketEventForPermalinkPost(post, message) @@ -607,7 +612,12 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } } - message.Add("thread", userThread.ToJson()) + payload, jsonErr := json.Marshal(userThread) + if jsonErr != nil { + mlog.Warn("Failed to encode thread to JSON") + } + message.Add("thread", string(payload)) + a.Publish(message) } } diff --git a/app/notification_push.go b/app/notification_push.go index 7fa8ec0da3..cd80f2b815 100644 --- a/app/notification_push.go +++ b/app/notification_push.go @@ -4,6 +4,8 @@ package app import ( + "bytes" + "encoding/json" "io" "io/ioutil" "net/http" @@ -367,8 +369,13 @@ func (a *App) sendToPushProxy(msg *model.PushNotification, session *model.Sessio mlog.String("status", model.PushSendPrepare), ) + msgJSON, jsonErr := json.Marshal(msg) + if jsonErr != nil { + return errors.Wrap(jsonErr, "failed to encode to JSON") + } + url := strings.TrimRight(*a.Config().EmailSettings.PushNotificationServer, "/") + model.APIURLSuffixV1 + "/send_push" - request, err := http.NewRequest("POST", url, strings.NewReader(msg.ToJson())) + request, err := http.NewRequest("POST", url, bytes.NewReader(msgJSON)) if err != nil { return err } @@ -379,7 +386,10 @@ func (a *App) sendToPushProxy(msg *model.PushNotification, session *model.Sessio } defer resp.Body.Close() - pushResponse := model.PushResponseFromJson(resp.Body) + var pushResponse model.PushResponse + if jsonErr := json.NewDecoder(resp.Body).Decode(&pushResponse); jsonErr != nil { + return errors.Wrap(jsonErr, "failed to decode from JSON") + } switch pushResponse[model.PushStatus] { case model.PushStatusRemove: @@ -405,10 +415,15 @@ func (a *App) SendAckToPushProxy(ack *model.PushNotificationAck) error { mlog.String("status", model.PushReceived), ) + ackJSON, jsonErr := json.Marshal(ack) + if jsonErr != nil { + return errors.Wrap(jsonErr, "failed to encode to JSON") + } + request, err := http.NewRequest( "POST", strings.TrimRight(*a.Config().EmailSettings.PushNotificationServer, "/")+model.APIURLSuffixV1+"/ack", - strings.NewReader(ack.ToJson()), + bytes.NewReader(ackJSON), ) if err != nil { diff --git a/app/notification_push_test.go b/app/notification_push_test.go index 69f2da4658..044882897c 100644 --- a/app/notification_push_test.go +++ b/app/notification_push_test.go @@ -4,6 +4,7 @@ package app import ( + "encoding/json" "fmt" "net/http" "net/http/httptest" @@ -1024,18 +1025,19 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R // Don't do any checking if it's a benchmark if _, ok := h.t.(*testing.B); ok { resp := model.NewOkPushResponse() - fmt.Fprintln(w, (&resp).ToJson()) + jsonData, _ := json.Marshal(&resp) + fmt.Fprintln(w, jsonData) return } - var notification *model.PushNotification - var notificationAck *model.PushNotificationAck + var notification model.PushNotification + var notificationAck model.PushNotificationAck var err error if r.URL.Path == "/api/v1/send_push" { - notification, err = model.PushNotificationFromJson(r.Body) - if err != nil { + if err = json.NewDecoder(r.Body).Decode(¬ification); err != nil { resp := model.NewErrorPushResponse("fail") - fmt.Fprintln(w, (&resp).ToJson()) + jsonData, _ := json.Marshal(&resp) + fmt.Fprintln(w, jsonData) return } // We verify that messages are being sent in order per-device. @@ -1047,10 +1049,10 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R defer h.serialUserMap.Delete(notification.DeviceId) } } else { - notificationAck, err = model.PushNotificationAckFromJson(r.Body) - if err != nil { + if err = json.NewDecoder(r.Body).Decode(¬ificationAck); err != nil { resp := model.NewErrorPushResponse("fail") - fmt.Fprintln(w, (&resp).ToJson()) + jsonData, _ := json.Marshal(&resp) + fmt.Fprintln(w, jsonData) return } } @@ -1061,9 +1063,9 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R // Little bit of duplicate condition check so that we can check the in-order property // first. if r.URL.Path == "/api/v1/send_push" { - h._notifications = append(h._notifications, notification) + h._notifications = append(h._notifications, ¬ification) } else { - h._notificationAcks = append(h._notificationAcks, notificationAck) + h._notificationAcks = append(h._notificationAcks, ¬ificationAck) } var resp model.PushResponse @@ -1077,7 +1079,8 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R resp = model.NewRemovePushResponse() } } - fmt.Fprintln(w, (&resp).ToJson()) + jsonData, _ := json.Marshal(&resp) + fmt.Fprintln(w, jsonData) } } diff --git a/app/oauth.go b/app/oauth.go index b298996bc6..12c4de5fd0 100644 --- a/app/oauth.go +++ b/app/oauth.go @@ -582,7 +582,7 @@ func (a *App) LoginByOAuth(c *request.Context, service string, userData io.Reade map[string]interface{}{"Service": service}, "", http.StatusBadRequest) } - authUser, err1 := provider.GetUserFromJson(bytes.NewReader(buf.Bytes()), tokenUser) + authUser, err1 := provider.GetUserFromJSON(bytes.NewReader(buf.Bytes()), tokenUser) if err1 != nil { return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest) @@ -633,7 +633,7 @@ func (a *App) CompleteSwitchWithOAuth(service string, userData io.Reader, email return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "", http.StatusBadRequest) } - ssoUser, err1 := provider.GetUserFromJson(userData, tokenUser) + ssoUser, err1 := provider.GetUserFromJSON(userData, tokenUser) if err1 != nil { return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest) @@ -744,7 +744,7 @@ func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, servi } props["token"] = stateToken.Token - state := b64.StdEncoding.EncodeToString([]byte(model.MapToJson(props))) + state := b64.StdEncoding.EncodeToString([]byte(model.MapToJSON(props))) siteURL := a.GetSiteURL() if strings.TrimSpace(siteURL) == "" { @@ -783,7 +783,7 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service } stateStr := string(b) - stateProps := model.MapFromJson(strings.NewReader(stateStr)) + stateProps := model.MapFromJSON(strings.NewReader(stateStr)) expectedToken, appErr := a.GetOAuthStateToken(stateProps["token"]) if appErr != nil { diff --git a/app/oauth_test.go b/app/oauth_test.go index b128fbdee6..2dae3859e8 100644 --- a/app/oauth_test.go +++ b/app/oauth_test.go @@ -152,7 +152,7 @@ func TestAuthorizeOAuthUser(t *testing.T) { } makeState := func(token *model.Token) string { - return base64.StdEncoding.EncodeToString([]byte(model.MapToJson(map[string]string{ + return base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(map[string]string{ "token": token.Token, }))) } @@ -199,7 +199,7 @@ func TestAuthorizeOAuthUser(t *testing.T) { th := setup(t, true, true, true, "") defer th.TearDown() - state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(map[string]string{ + state := base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(map[string]string{ "token": model.NewId(), }))) @@ -235,7 +235,7 @@ func TestAuthorizeOAuthUser(t *testing.T) { token, err := th.App.CreateOAuthStateToken(generateOAuthStateTokenExtra(email, action, cookie)) require.Nil(t, err) - state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(map[string]string{ + state := base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(map[string]string{ "action": action, "email": email, "token": token.Token, @@ -489,7 +489,7 @@ func TestAuthorizeOAuthUser(t *testing.T) { "team_id": model.NewId(), "token": makeToken(th, cookie).Token, } - state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state := base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) recorder := httptest.ResponseRecorder{} body, receivedTeamId, receivedStateProps, _, err := th.App.AuthorizeOAuthUser(&recorder, request, model.ServiceGitlab, "", state, "") diff --git a/app/plugin_api_tests/manual.test_http_upgrade_websocket_plugin/main.go b/app/plugin_api_tests/manual.test_http_upgrade_websocket_plugin/main.go index 60cb3850b9..99a1ecac11 100644 --- a/app/plugin_api_tests/manual.test_http_upgrade_websocket_plugin/main.go +++ b/app/plugin_api_tests/manual.test_http_upgrade_websocket_plugin/main.go @@ -4,7 +4,7 @@ package main import ( - "bytes" + "encoding/json" "net/http" "github.com/gorilla/websocket" @@ -32,9 +32,17 @@ func (p *Plugin) ServeHTTP(_ *plugin.Context, w http.ResponseWriter, r *http.Req if err != nil { break } - req := model.WebSocketRequestFromJson(bytes.NewReader(msg)) + var req model.WebSocketRequest + err = json.Unmarshal(msg, &req) + if err != nil { + break + } resp := model.NewWebSocketResponse("OK", req.Seq, map[string]interface{}{"action": req.Action, "value": req.Data["value"]}) - if err = ws.WriteMessage(mt, resp.ToJson()); err != nil { + respJSON, err := resp.ToJSON() + if err != nil { + break + } + if err = ws.WriteMessage(mt, respJSON); err != nil { break } } diff --git a/app/plugin_install_test.go b/app/plugin_install_test.go index a1b9a8fc28..69abe2ae66 100644 --- a/app/plugin_install_test.go +++ b/app/plugin_install_test.go @@ -7,6 +7,7 @@ import ( "archive/tar" "bytes" "compress/gzip" + "encoding/json" "io" "os" "path/filepath" @@ -99,8 +100,10 @@ func TestInstallPluginLocally(t *testing.T) { Id: id, Version: version, } + manifestJSON, jsonErr := json.Marshal(manifest) + require.NoError(t, jsonErr) reader := makeInMemoryGzipTarFile(t, []testFile{ - {"plugin.json", manifest.ToJson()}, + {"plugin.json", string(manifestJSON)}, }) actualManifest, appError := th.App.installPluginLocally(reader, nil, installationStrategy) diff --git a/app/plugin_requests.go b/app/plugin_requests.go index 1beefcbfb3..4006a32301 100644 --- a/app/plugin_requests.go +++ b/app/plugin_requests.go @@ -27,7 +27,7 @@ func (s *Server) ServePluginRequest(w http.ResponseWriter, r *http.Request) { s.Log.Error(err.Error()) w.WriteHeader(err.StatusCode) w.Header().Set("Content-Type", "application/json") - w.Write([]byte(err.ToJson())) + w.Write([]byte(err.ToJSON())) return } @@ -52,7 +52,7 @@ func (a *App) ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, so a.Log().Error(err.Error()) w.WriteHeader(err.StatusCode) w.Header().Set("Content-Type", "application/json") - w.Write([]byte(err.ToJson())) + w.Write([]byte(err.ToJSON())) return } diff --git a/app/post.go b/app/post.go index b64def6ff1..0f07b7e57b 100644 --- a/app/post.go +++ b/app/post.go @@ -522,7 +522,12 @@ func (a *App) SendEphemeralPost(userID string, post *model.Post) *model.Post { message := model.NewWebSocketEvent(model.WebsocketEventEphemeralMessage, "", post.ChannelId, userID, nil) post = a.PreparePostForClient(post, true, false) post = model.AddPostActionCookies(post, a.PostActionCookieSecret()) - message.Add("post", post.ToJson()) + + postJSON, jsonErr := post.ToJSON() + if jsonErr != nil { + mlog.Warn("Failed to encode post to JSON", mlog.Err(jsonErr)) + } + message.Add("post", postJSON) a.Publish(message) return post @@ -540,7 +545,11 @@ func (a *App) UpdateEphemeralPost(userID string, post *model.Post) *model.Post { message := model.NewWebSocketEvent(model.WebsocketEventPostEdited, "", post.ChannelId, userID, nil) post = a.PreparePostForClient(post, true, false) post = model.AddPostActionCookies(post, a.PostActionCookieSecret()) - message.Add("post", post.ToJson()) + postJSON, jsonErr := post.ToJSON() + if jsonErr != nil { + mlog.Warn("Failed to encode post to JSON", mlog.Err(jsonErr)) + } + message.Add("post", postJSON) a.Publish(message) return post @@ -556,7 +565,11 @@ func (a *App) DeleteEphemeralPost(userID, postID string) { } message := model.NewWebSocketEvent(model.WebsocketEventPostDeleted, "", "", userID, nil) - message.Add("post", post.ToJson()) + postJSON, jsonErr := post.ToJSON() + if jsonErr != nil { + mlog.Warn("Failed to encode post to JSON", mlog.Err(jsonErr)) + } + message.Add("post", postJSON) a.Publish(message) } @@ -684,7 +697,11 @@ func (a *App) UpdatePost(c *request.Context, post *model.Post, safeUpdate bool) } message := model.NewWebSocketEvent(model.WebsocketEventPostEdited, "", rpost.ChannelId, "", nil) - message.Add("post", rpost.ToJson()) + postJSON, jsonErr := rpost.ToJSON() + if jsonErr != nil { + return nil, model.NewAppError("UpdatePost", "app.post.marshal.app_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + message.Add("post", postJSON) published, err := a.publishWebsocketEventForPermalinkPost(rpost, message) if err != nil { @@ -744,7 +761,12 @@ func (a *App) publishWebsocketEventForPermalinkPost(post *model.Post, message *m broadcastCopy := messageCopy.GetBroadcast() broadcastCopy.UserId = cm.UserId messageCopy.SetBroadcast(broadcastCopy) - messageCopy.Add("post", postForUser.ToJson()) + + postJSON, jsonErr := postForUser.ToJSON() + if jsonErr != nil { + mlog.Warn("Failed to encode post to JSON", mlog.Err(jsonErr)) + } + messageCopy.Add("post", postJSON) a.Publish(messageCopy) } diff --git a/app/preference.go b/app/preference.go index 2af9217160..23df83426c 100644 --- a/app/preference.go +++ b/app/preference.go @@ -4,10 +4,12 @@ package app import ( + "encoding/json" "errors" "net/http" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/shared/mlog" ) func (a *App) GetPreferencesForUser(userID string) (model.Preferences, *model.AppError) { @@ -65,7 +67,11 @@ func (a *App) UpdatePreferences(userID string, preferences model.Preferences) *m a.Publish(message) message = model.NewWebSocketEvent(model.WebsocketEventPreferencesChanged, "", "", userID, nil) - message.Add("preferences", preferences.ToJson()) + prefsJSON, jsonErr := json.Marshal(preferences) + if jsonErr != nil { + mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + } + message.Add("preferences", string(prefsJSON)) a.Publish(message) return nil @@ -95,7 +101,11 @@ func (a *App) DeletePreferences(userID string, preferences model.Preferences) *m a.Publish(message) message = model.NewWebSocketEvent(model.WebsocketEventPreferencesDeleted, "", "", userID, nil) - message.Add("preferences", preferences.ToJson()) + prefsJSON, jsonErr := json.Marshal(preferences) + if jsonErr != nil { + mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + } + message.Add("preferences", string(prefsJSON)) a.Publish(message) return nil diff --git a/app/reaction.go b/app/reaction.go index b826a9e7d9..74382decd6 100644 --- a/app/reaction.go +++ b/app/reaction.go @@ -4,12 +4,14 @@ package app import ( + "encoding/json" "errors" "net/http" "github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/plugin" + "github.com/mattermost/mattermost-server/v6/shared/mlog" ) func (a *App) SaveReactionForPost(c *request.Context, reaction *model.Reaction) (*model.Reaction, *model.AppError) { @@ -159,6 +161,10 @@ func (a *App) DeleteReactionForPost(c *request.Context, reaction *model.Reaction func (a *App) sendReactionEvent(event string, reaction *model.Reaction, post *model.Post) { // send out that a reaction has been added/removed message := model.NewWebSocketEvent(event, "", post.ChannelId, "", nil) - message.Add("reaction", reaction.ToJson()) + reactionJSON, jsonErr := json.Marshal(reaction) + if jsonErr != nil { + mlog.Warn("Failed to encode reaction to JSON") + } + message.Add("reaction", string(reactionJSON)) a.Publish(message) } diff --git a/app/role.go b/app/role.go index dd3459d12f..51633c1c80 100644 --- a/app/role.go +++ b/app/role.go @@ -5,12 +5,14 @@ package app import ( "context" + "encoding/json" "errors" "net/http" "reflect" "strings" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/store" "github.com/mattermost/mattermost-server/v6/utils" ) @@ -240,7 +242,11 @@ func (a *App) CheckRolesExist(roleNames []string) *model.AppError { func (a *App) sendUpdatedRoleEvent(role *model.Role) { message := model.NewWebSocketEvent(model.WebsocketEventRoleUpdated, "", "", "", nil) - message.Add("role", role.ToJson()) + roleJSON, jsonErr := json.Marshal(role) + if jsonErr != nil { + mlog.Warn("Failed to encode role to JSON", mlog.Err(jsonErr)) + } + message.Add("role", string(roleJSON)) a.Srv().Go(func() { a.Publish(message) diff --git a/app/security_update_check.go b/app/security_update_check.go index 17e409d365..2ed2334e76 100644 --- a/app/security_update_check.go +++ b/app/security_update_check.go @@ -4,6 +4,7 @@ package app import ( + "encoding/json" "io/ioutil" "net/http" "net/url" @@ -88,7 +89,11 @@ func (s *Server) DoSecurityUpdateCheck() { defer res.Body.Close() - bulletins := model.SecurityBulletinsFromJson(res.Body) + var bulletins model.SecurityBulletins + if jsonErr := json.NewDecoder(res.Body).Decode(&bulletins); jsonErr != nil { + mlog.Error("Failed to decode JSON", mlog.Err(jsonErr)) + return + } for _, bulletin := range bulletins { if bulletin.AppliesToVersion == model.CurrentVersion { diff --git a/app/slashcommands/command_expand_collapse.go b/app/slashcommands/command_expand_collapse.go index 08b324c283..056725e440 100644 --- a/app/slashcommands/command_expand_collapse.go +++ b/app/slashcommands/command_expand_collapse.go @@ -4,12 +4,14 @@ package slashcommands import ( + "encoding/json" "strconv" "github.com/mattermost/mattermost-server/v6/app" "github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/i18n" + "github.com/mattermost/mattermost-server/v6/shared/mlog" ) type ExpandProvider struct { @@ -75,7 +77,12 @@ func setCollapsePreference(a *app.App, args *model.CommandArgs, isCollapse bool) } socketMessage := model.NewWebSocketEvent(model.WebsocketEventPreferenceChanged, "", "", args.UserId, nil) - socketMessage.Add("preference", pref.ToJson()) + + prefJSON, jsonErr := json.Marshal(pref) + if jsonErr != nil { + mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + } + socketMessage.Add("preference", string(prefJSON)) a.Publish(socketMessage) var rmsg string diff --git a/app/slashcommands/command_loadtest.go b/app/slashcommands/command_loadtest.go index b1f16cd58b..a71a524039 100644 --- a/app/slashcommands/command_loadtest.go +++ b/app/slashcommands/command_loadtest.go @@ -4,6 +4,7 @@ package slashcommands import ( + "encoding/json" "io" "io/ioutil" "net/http" @@ -542,8 +543,8 @@ func (*LoadTestProvider) JsonCommand(a *app.App, c *request.Context, args *model r.Body.Close() }() - post := model.PostFromJson(r.Body) - if post == nil { + var post model.Post + if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { return &model.CommandResponse{Text: "Unable to decode post", ResponseType: model.CommandResponseTypeEphemeral}, errors.Errorf("could not decode post from json") } post.ChannelId = args.ChannelId @@ -552,7 +553,7 @@ func (*LoadTestProvider) JsonCommand(a *app.App, c *request.Context, args *model post.Message = message } - if _, err := a.CreatePostMissingChannel(c, post, false); err != nil { + if _, err := a.CreatePostMissingChannel(c, &post, false); err != nil { return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.CommandResponseTypeEphemeral}, err } diff --git a/app/slashcommands/command_share_test.go b/app/slashcommands/command_share_test.go index c64d29e1df..36b7ce3423 100644 --- a/app/slashcommands/command_share_test.go +++ b/app/slashcommands/command_share_test.go @@ -50,8 +50,8 @@ func TestShareProviderDoCommand(t *testing.T) { require.Equal(t, "##### "+args.T("api.command_share.channel_shared"), response.Text) channelConvertedMessages := testCluster.SelectMessages(func(msg *model.ClusterMessage) bool { - event := model.WebSocketEventFromJson(bytes.NewReader(msg.Data)) - return event != nil && event.EventType() == model.WebsocketEventChannelConverted + event, err := model.WebSocketEventFromJSON(bytes.NewReader(msg.Data)) + return err == nil && event.EventType() == model.WebsocketEventChannelConverted }) assert.Len(t, channelConvertedMessages, 1) }) @@ -85,8 +85,8 @@ func TestShareProviderDoCommand(t *testing.T) { require.Equal(t, "##### "+args.T("api.command_share.shared_channel_unavailable"), response.Text) channelConvertedMessages := testCluster.SelectMessages(func(msg *model.ClusterMessage) bool { - event := model.WebSocketEventFromJson(bytes.NewReader(msg.Data)) - return event != nil && event.EventType() == model.WebsocketEventChannelConverted + event, err := model.WebSocketEventFromJSON(bytes.NewReader(msg.Data)) + return err == nil && event.EventType() == model.WebsocketEventChannelConverted }) require.Len(t, channelConvertedMessages, 1) }) diff --git a/app/status.go b/app/status.go index 94fdf41f4e..9ed25614f3 100644 --- a/app/status.go +++ b/app/status.go @@ -4,9 +4,9 @@ package app import ( + "encoding/json" "errors" "net/http" - "strings" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -21,10 +21,14 @@ func (a *App) AddStatusCache(status *model.Status) { a.AddStatusCacheSkipClusterSend(status) if a.Cluster() != nil { + statusJSON, jsonErr := json.Marshal(status) + if jsonErr != nil { + mlog.Warn("Failed to encode status to JSON") + } msg := &model.ClusterMessage{ Event: model.ClusterEventUpdateStatus, SendType: model.ClusterSendBestEffort, - Data: []byte(status.ToClusterJson()), + Data: statusJSON, } a.Cluster().SendClusterMessage(msg) } @@ -443,15 +447,22 @@ func (a *App) addRecentCustomStatus(userID string, status *model.CustomStatus) * if err != nil || pref.Value == "" { newRCS = model.RecentCustomStatuses{*status} } else { - existingRCS := model.RecentCustomStatusesFromJson(strings.NewReader(pref.Value)) + var existingRCS model.RecentCustomStatuses + if jsonErr := json.Unmarshal([]byte(pref.Value), &existingRCS); jsonErr != nil { + return model.NewAppError("addRecentCustomStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + } newRCS = existingRCS.Add(status) } + newRCSJSON, jsonErr := json.Marshal(newRCS) + if jsonErr != nil { + return model.NewAppError("addRecentCustomStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + } pref = &model.Preference{ UserId: userID, Category: model.PreferenceCategoryCustomStatus, Name: model.PreferenceNameRecentCustomStatuses, - Value: newRCS.ToJson(), + Value: string(newRCSJSON), } if err := a.UpdatePreferences(userID, model.Preferences{*pref}); err != nil { return err @@ -470,14 +481,25 @@ func (a *App) RemoveRecentCustomStatus(userID string, status *model.CustomStatus return model.NewAppError("RemoveRecentCustomStatus", "api.custom_status.recent_custom_statuses.delete.app_error", nil, "", http.StatusBadRequest) } - existingRCS := model.RecentCustomStatusesFromJson(strings.NewReader(pref.Value)) - if !existingRCS.Contains(status) { + var existingRCS model.RecentCustomStatuses + if jsonErr := json.Unmarshal([]byte(pref.Value), &existingRCS); jsonErr != nil { + return model.NewAppError("RemoveRecentCustomStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + } + + if ok, err := existingRCS.Contains(status); !ok || err != nil { return model.NewAppError("RemoveRecentCustomStatus", "api.custom_status.recent_custom_statuses.delete.app_error", nil, "", http.StatusBadRequest) } - newRCS := existingRCS.Remove(status) - pref.Value = newRCS.ToJson() + newRCS, removeErr := existingRCS.Remove(status) + if removeErr != nil { + return model.NewAppError("RemoveRecentCustomStatus", "api.custom_status.recent_custom_statuses.delete.app_error", nil, removeErr.Error(), http.StatusBadRequest) + } + newRCSJSON, jsonErr := json.Marshal(newRCS) + if jsonErr != nil { + return model.NewAppError("RemoveRecentCustomStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + } + pref.Value = string(newRCSJSON) if err := a.UpdatePreferences(userID, model.Preferences{*pref}); err != nil { return err } diff --git a/app/team.go b/app/team.go index 0086463e06..34fd60c278 100644 --- a/app/team.go +++ b/app/team.go @@ -6,6 +6,7 @@ package app import ( "bytes" "context" + "encoding/json" "errors" "fmt" "image" @@ -337,7 +338,11 @@ func (a *App) sendTeamEvent(team *model.Team, event string) { teamID = team.Id } message := model.NewWebSocketEvent(event, teamID, "", "", nil) - message.Add("team", sanitizedTeam.ToJson()) + teamJSON, jsonErr := json.Marshal(team) + if jsonErr != nil { + mlog.Warn("Failed to encode team to JSON", mlog.Err(jsonErr)) + } + message.Add("team", string(teamJSON)) a.Publish(message) } @@ -479,7 +484,11 @@ func (a *App) UpdateTeamMemberSchemeRoles(teamID string, userID string, isScheme func (a *App) sendUpdatedMemberRoleEvent(userID string, member *model.TeamMember) { message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", userID, nil) - message.Add("member", member.ToJson()) + tmJSON, jsonErr := json.Marshal(member) + if jsonErr != nil { + mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr)) + } + message.Add("member", string(tmJSON)) a.Publish(message) } @@ -563,7 +572,7 @@ func (a *App) AddUserToTeamByToken(c *request.Context, userID string, tokenID st return nil, nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest) } - tokenData := model.MapFromJson(strings.NewReader(token.Extra)) + tokenData := model.MapFromJSON(strings.NewReader(token.Extra)) tchan := make(chan store.StoreResult, 1) go func() { @@ -1862,7 +1871,7 @@ func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) { return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest) } - tokenData := model.MapFromJson(strings.NewReader(token.Extra)) + tokenData := model.MapFromJSON(strings.NewReader(token.Extra)) return tokenData["teamId"], nil } @@ -2027,7 +2036,11 @@ func (a *App) ClearTeamMembersCache(teamID string) { a.ClearSessionCacheForUser(teamMember.UserId) message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", teamMember.UserId, nil) - message.Add("member", teamMember.ToJson()) + tmJSON, jsonErr := json.Marshal(teamMember) + if jsonErr != nil { + mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr)) + } + message.Add("member", string(tmJSON)) a.Publish(message) } diff --git a/app/team_test.go b/app/team_test.go index 3de0107a69..99296ceb80 100644 --- a/app/team_test.go +++ b/app/team_test.go @@ -202,7 +202,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("invalid token type", func(t *testing.T) { token := model.NewToken( TokenTypeVerifyEmail, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -215,7 +215,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("expired token", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) token.CreateAt = model.GetMillis() - InvitationExpiryTime - 1 @@ -229,7 +229,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("invalid team id", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": model.NewId()}), + model.MapToJSON(map[string]string{"teamId": model.NewId()}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -241,7 +241,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("invalid user id", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -253,7 +253,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("valid request", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) _, _, err := th.App.AddUserToTeamByToken(th.Context, ruser.Id, token.Token) @@ -270,7 +270,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("invalid add a guest using a regular invite", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) _, _, err := th.App.AddUserToTeamByToken(th.Context, rguest.Id, token.Token) @@ -280,7 +280,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("invalid add a regular user using a guest invite", func(t *testing.T) { token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) _, _, err := th.App.AddUserToTeamByToken(th.Context, ruser.Id, token.Token) @@ -295,7 +295,7 @@ func TestAddUserToTeamByToken(t *testing.T) { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.RestrictCreationToDomains = "restricted.com" }) token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) _, _, err := th.App.AddUserToTeamByToken(th.Context, rguest.Id, token.Token) @@ -311,7 +311,7 @@ func TestAddUserToTeamByToken(t *testing.T) { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.RestrictCreationToDomains = "restricted.com" }) token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), ) guestEmail := rguest.Email rguest.Email = "test@restricted.com" @@ -337,7 +337,7 @@ func TestAddUserToTeamByToken(t *testing.T) { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictCreationToDomains = "restricted.com" }) token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), ) _, err = th.App.Srv().Store.User().Update(rguest, false) require.NoError(t, err) @@ -352,7 +352,7 @@ func TestAddUserToTeamByToken(t *testing.T) { t.Run("valid request from guest invite", func(t *testing.T) { token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -375,7 +375,7 @@ func TestAddUserToTeamByToken(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -399,7 +399,7 @@ func TestAddUserToTeamByToken(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -414,7 +414,7 @@ func TestAddUserToTeamByToken(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": team.Id}), + model.MapToJSON(map[string]string{"teamId": team.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) diff --git a/app/user.go b/app/user.go index 6ed290238e..fe2c57cc19 100644 --- a/app/user.go +++ b/app/user.go @@ -54,7 +54,7 @@ func (a *App) CreateUserWithToken(c *request.Context, user *model.User, token *m return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest) } - tokenData := model.MapFromJson(strings.NewReader(token.Extra)) + tokenData := model.MapFromJSON(strings.NewReader(token.Extra)) team, nErr := a.Srv().Store.Team().Get(tokenData["teamId"]) if nErr != nil { @@ -294,7 +294,7 @@ func (a *App) CreateOAuthUser(c *request.Context, service string, userData io.Re if e != nil { return nil, e } - user, err1 := provider.GetUserFromJson(userData, tokenUser) + user, err1 := provider.GetUserFromJSON(userData, tokenUser) if err1 != nil { return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.create.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusInternalServerError) } @@ -1816,7 +1816,7 @@ func (a *App) AutocompleteUsersInTeam(teamID string, term string, options *model } func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OAuthProvider, service string, tokenUser *model.User) *model.AppError { - oauthUser, err1 := provider.GetUserFromJson(userData, tokenUser) + oauthUser, err1 := provider.GetUserFromJSON(userData, tokenUser) if err1 != nil { return model.NewAppError("UpdateOAuthUserAttrs", "api.user.update_oauth_user_attrs.get_user.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest) } @@ -2060,7 +2060,11 @@ func (a *App) PromoteGuestToUser(c *request.Context, user *model.User, requestor a.invalidateCacheForChannelMembers(member.ChannelId) evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil) - evt.Add("channelMember", member.ToJson()) + memberJSON, jsonErr := json.Marshal(member) + if jsonErr != nil { + mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + } + evt.Add("channelMember", string(memberJSON)) a.Publish(evt) } } @@ -2101,7 +2105,11 @@ func (a *App) DemoteUserToGuest(user *model.User) *model.AppError { a.invalidateCacheForChannelMembers(member.ChannelId) evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil) - evt.Add("channelMember", member.ToJson()) + memberJSON, jsonErr := json.Marshal(member) + if jsonErr != nil { + mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + } + evt.Add("channelMember", string(memberJSON)) a.Publish(evt) } } diff --git a/app/user_test.go b/app/user_test.go index 5233cf794b..7c497463b6 100644 --- a/app/user_test.go +++ b/app/user_test.go @@ -38,9 +38,10 @@ func TestCreateOAuthUser(t *testing.T) { t.Run("create user successfully", func(t *testing.T) { glUser := oauthgitlab.GitLabUser{Id: 42, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"} - json := glUser.ToJson() + js, jsonErr := json.Marshal(glUser) + require.NoError(t, jsonErr) - user, err := th.App.CreateOAuthUser(th.Context, model.UserAuthServiceGitlab, strings.NewReader(json), th.BasicTeam.Id, nil) + user, err := th.App.CreateOAuthUser(th.Context, model.UserAuthServiceGitlab, bytes.NewReader(js), th.BasicTeam.Id, nil) require.Nil(t, err) require.Equal(t, glUser.Username, user.Username, "usernames didn't match") @@ -59,7 +60,7 @@ func TestCreateOAuthUser(t *testing.T) { mockUser := &model.User{Id: "abcdef", AuthData: model.NewString("e7110007-64be-43d8-9840-4a7e9c26b710"), Email: dbUser.Email} providerMock := &mocks.OAuthProvider{} providerMock.On("IsSameUser", mock.Anything, mock.Anything).Return(true) - providerMock.On("GetUserFromJson", mock.Anything, mock.Anything).Return(mockUser, nil) + providerMock.On("GetUserFromJSON", mock.Anything, mock.Anything).Return(mockUser, nil) einterfaces.RegisterOAuthProvider(model.ServiceOffice365, providerMock) // Update user to be OAuth, formatting to match Office365 OAuth data @@ -734,7 +735,7 @@ func TestCreateUserWithToken(t *testing.T) { t.Run("invalid token type", func(t *testing.T) { token := model.NewToken( TokenTypeVerifyEmail, - model.MapToJson(map[string]string{"teamID": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamID": th.BasicTeam.Id, "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -745,7 +746,7 @@ func TestCreateUserWithToken(t *testing.T) { t.Run("expired token", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}), ) token.CreateAt = model.GetMillis() - InvitationExpiryTime - 1 require.NoError(t, th.App.Srv().Store.Token().Save(token)) @@ -757,7 +758,7 @@ func TestCreateUserWithToken(t *testing.T) { t.Run("invalid team id", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": model.NewId(), "email": user.Email}), + model.MapToJSON(map[string]string{"teamId": model.NewId(), "email": user.Email}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) defer th.App.DeleteToken(token) @@ -769,7 +770,7 @@ func TestCreateUserWithToken(t *testing.T) { invitationEmail := model.NewId() + "other-email@test.com" token := model.NewToken( TokenTypeTeamInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) newUser, err := th.App.CreateUserWithToken(th.Context, &user, token) @@ -789,7 +790,7 @@ func TestCreateUserWithToken(t *testing.T) { invitationEmail := model.NewId() + "other-email@test.com" token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) guest := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} @@ -819,11 +820,11 @@ func TestCreateUserWithToken(t *testing.T) { grantedInvitationEmail := model.NewId() + "other-email@restricted.com" forbiddenDomainToken := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": forbiddenInvitationEmail, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": forbiddenInvitationEmail, "channels": th.BasicChannel.Id}), ) grantedDomainToken := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": grantedInvitationEmail, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": grantedInvitationEmail, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(forbiddenDomainToken)) require.NoError(t, th.App.Srv().Store.Token().Save(grantedDomainToken)) @@ -866,7 +867,7 @@ func TestCreateUserWithToken(t *testing.T) { invitationEmail := model.NewId() + "other-email@test.com" token := model.NewToken( TokenTypeGuestInvitation, - model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail, "channels": th.BasicChannel.Id}), + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) guest := model.User{ diff --git a/app/web_conn_test.go b/app/web_conn_test.go index 5917b73af6..89bee5b1b5 100644 --- a/app/web_conn_test.go +++ b/app/web_conn_test.go @@ -254,10 +254,13 @@ func TestWebConnDrainDeadQueue(t *testing.T) { i := seqNum for err == nil { _, buf, err = conn.ReadMessage() - ev := model.WebSocketEventFromJson(bytes.NewReader(buf)) - require.LessOrEqual(t, int(i), limit) - assert.Equal(t, i, ev.GetSequence()) - i++ + if err != nil && len(buf) > 0 { + ev, jsonErr := model.WebSocketEventFromJSON(bytes.NewReader(buf)) + require.NoError(t, jsonErr) + require.LessOrEqual(t, int(i), limit) + assert.Equal(t, i, ev.GetSequence()) + i++ + } } if _, ok := err.(*websocket.CloseError); !ok { require.NoError(t, err) diff --git a/app/web_hub.go b/app/web_hub.go index 2fc212ea25..a6785d7be0 100644 --- a/app/web_hub.go +++ b/app/web_hub.go @@ -168,10 +168,14 @@ func (s *Server) Publish(message *model.WebSocketEvent) { s.PublishSkipClusterSend(message) if s.Cluster != nil { + data, err := message.ToJSON() + if err != nil { + mlog.Warn("Failed to encode message to JSON", mlog.Err(err)) + } cm := &model.ClusterMessage{ Event: model.ClusterEventPublish, SendType: model.ClusterSendBestEffort, - Data: message.ToJson(), + Data: data, } if message.EventType() == model.WebsocketEventPosted || diff --git a/app/webhook.go b/app/webhook.go index e45d46a4bb..25d0fa69ae 100644 --- a/app/webhook.go +++ b/app/webhook.go @@ -4,7 +4,9 @@ package app import ( + "bytes" "context" + "encoding/json" "errors" "io" "net/http" @@ -96,7 +98,11 @@ func (a *App) TriggerWebhook(c *request.Context, payload *model.OutgoingWebhookP var body io.Reader var contentType string if hook.ContentType == "application/json" { - body = strings.NewReader(payload.ToJSON()) + js, jsonErr := json.Marshal(payload) + if jsonErr != nil { + mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + } + body = bytes.NewReader(js) contentType = "application/json" } else { body = strings.NewReader(payload.ToFormValues()) @@ -164,7 +170,15 @@ func (a *App) doOutgoingWebhookRequest(url string, body io.Reader, contentType s defer resp.Body.Close() - return model.OutgoingWebhookResponseFromJson(io.LimitReader(resp.Body, MaxIntegrationResponseSize)) + var hookResp model.OutgoingWebhookResponse + if jsonErr := json.NewDecoder(io.LimitReader(resp.Body, MaxIntegrationResponseSize)).Decode(&hookResp); jsonErr != nil { + if jsonErr == io.EOF { + return nil, nil + } + return nil, model.NewAppError("doOutgoingWebhookRequest", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + + return &hookResp, nil } func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model.AppError) { @@ -180,7 +194,7 @@ func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model. } } - if utf8.RuneCountInString(model.StringInterfaceToJson(base.GetProps())) > model.PostPropsMaxUserRunes { + if utf8.RuneCountInString(model.StringInterfaceToJSON(base.GetProps())) > model.PostPropsMaxUserRunes { return nil, model.NewAppError("SplitWebhookPost", "web.incoming_webhook.split_props_length.app_error", map[string]interface{}{"Max": model.PostPropsMaxUserRunes}, "", http.StatusBadRequest) } @@ -213,7 +227,7 @@ func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model. } origAttachments, _ := newProps["attachments"].([]*model.SlackAttachment) newProps["attachments"] = append(origAttachments, &newAttachment) - newPropsString := model.StringInterfaceToJson(newProps) + newPropsString := model.StringInterfaceToJSON(newProps) runeCount := utf8.RuneCountInString(newPropsString) if runeCount <= model.PostPropsMaxUserRunes { diff --git a/app/webhook_test.go b/app/webhook_test.go index 3f0dffc753..f453e0c720 100644 --- a/app/webhook_test.go +++ b/app/webhook_test.go @@ -673,7 +673,9 @@ func TestTriggerOutGoingWebhookWithUsernameAndIconURL(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if testCase.WebhookResponse != nil { - w.Write([]byte(testCase.WebhookResponse.ToJson())) + js, jsonErr := json.Marshal(testCase.WebhookResponse) + require.NoError(t, jsonErr) + w.Write(js) } else { w.Write([]byte(`{"text": "sample response text from test server"}`)) } @@ -755,7 +757,7 @@ func TestDoOutgoingWebhookRequest(t *testing.T) { _, err := th.App.doOutgoingWebhookRequest(server.URL, strings.NewReader(""), "application/json") require.Error(t, err) - require.IsType(t, &json.SyntaxError{}, err) + require.Equal(t, "api.unmarshal_error", err.(*model.AppError).Id) }) t.Run("with a large, valid response", func(t *testing.T) { @@ -766,7 +768,7 @@ func TestDoOutgoingWebhookRequest(t *testing.T) { _, err := th.App.doOutgoingWebhookRequest(server.URL, strings.NewReader(""), "application/json") require.Error(t, err) - require.Equal(t, io.ErrUnexpectedEOF, err) + require.Equal(t, "api.unmarshal_error", err.(*model.AppError).Id) }) t.Run("with a large, invalid response", func(t *testing.T) { @@ -777,7 +779,7 @@ func TestDoOutgoingWebhookRequest(t *testing.T) { _, err := th.App.doOutgoingWebhookRequest(server.URL, strings.NewReader(""), "application/json") require.Error(t, err) - require.IsType(t, &json.SyntaxError{}, err) + require.Equal(t, "api.unmarshal_error", err.(*model.AppError).Id) }) t.Run("with a slow response", func(t *testing.T) { diff --git a/einterfaces/mocks/OAuthProvider.go b/einterfaces/mocks/OAuthProvider.go index 31c4ecbc4a..b83a0b928d 100644 --- a/einterfaces/mocks/OAuthProvider.go +++ b/einterfaces/mocks/OAuthProvider.go @@ -62,8 +62,8 @@ func (_m *OAuthProvider) GetUserFromIdToken(idToken string) (*model.User, error) return r0, r1 } -// GetUserFromJson provides a mock function with given fields: data, tokenUser -func (_m *OAuthProvider) GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) { +// GetUserFromJSON provides a mock function with given fields: data, tokenUser +func (_m *OAuthProvider) GetUserFromJSON(data io.Reader, tokenUser *model.User) (*model.User, error) { ret := _m.Called(data, tokenUser) var r0 *model.User diff --git a/einterfaces/oauthproviders.go b/einterfaces/oauthproviders.go index 1c1bab563f..de60c9459f 100644 --- a/einterfaces/oauthproviders.go +++ b/einterfaces/oauthproviders.go @@ -10,7 +10,7 @@ import ( ) type OAuthProvider interface { - GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) + GetUserFromJSON(data io.Reader, tokenUser *model.User) (*model.User, error) GetSSOSettings(config *model.Config, service string) (*model.SSOSettings, error) GetUserFromIdToken(idToken string) (*model.User, error) IsSameUser(dbUser, oAuthUser *model.User) bool diff --git a/i18n/en.json b/i18n/en.json index 47ccd74c6d..26880dc000 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1970,7 +1970,7 @@ }, { "id": "api.marshal_error", - "translation": "marshal error" + "translation": "Failed to marshal." }, { "id": "api.migrate_to_saml.error", @@ -3722,6 +3722,10 @@ "id": "api.unable_to_read_file_from_backend", "translation": "Error reading file from backend" }, + { + "id": "api.unmarshal_error", + "translation": "Failed to unmarshal." + }, { "id": "api.upgrade_to_enterprise.already-done.app_error", "translation": "You have already upgraded to Mattermost Enterprise Edition. Please restart the server to finish the upgrade." @@ -5810,6 +5814,10 @@ "id": "app.post.get_root_posts.app_error", "translation": "Unable to get the posts for the channel." }, + { + "id": "app.post.marshal.app_error", + "translation": "Failed to marshal post." + }, { "id": "app.post.overwrite.app_error", "translation": "Unable to overwrite the Post." diff --git a/migrations/advanced_permissions_phase_2.go b/migrations/advanced_permissions_phase_2.go index cb0e33345b..037a138d45 100644 --- a/migrations/advanced_permissions_phase_2.go +++ b/migrations/advanced_permissions_phase_2.go @@ -19,12 +19,12 @@ type AdvancedPermissionsPhase2Progress struct { LastUserId string `json:"last_user"` } -func (p *AdvancedPermissionsPhase2Progress) ToJson() string { +func (p *AdvancedPermissionsPhase2Progress) ToJSON() string { b, _ := json.Marshal(p) return string(b) } -func AdvancedPermissionsPhase2ProgressFromJson(data io.Reader) *AdvancedPermissionsPhase2Progress { +func AdvancedPermissionsPhase2ProgressFromJSON(data io.Reader) *AdvancedPermissionsPhase2Progress { var o *AdvancedPermissionsPhase2Progress json.NewDecoder(data).Decode(&o) return o @@ -63,9 +63,9 @@ func (worker *Worker) runAdvancedPermissionsPhase2Migration(lastDone string) (bo progress.LastTeamId = strings.Repeat("0", 26) progress.LastUserId = strings.Repeat("0", 26) } else { - progress = AdvancedPermissionsPhase2ProgressFromJson(strings.NewReader(lastDone)) + progress = AdvancedPermissionsPhase2ProgressFromJSON(strings.NewReader(lastDone)) if !progress.IsValid() { - return false, "", model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "migrations.worker.run_advanced_permissions_phase_2_migration.invalid_progress", map[string]interface{}{"progress": progress.ToJson()}, "", http.StatusInternalServerError) + return false, "", model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "migrations.worker.run_advanced_permissions_phase_2_migration.invalid_progress", map[string]interface{}{"progress": progress.ToJSON()}, "", http.StatusInternalServerError) } } @@ -73,13 +73,13 @@ func (worker *Worker) runAdvancedPermissionsPhase2Migration(lastDone string) (bo // Run a TeamMembers migration batch. result, err := worker.srv.Store.Team().MigrateTeamMembers(progress.LastTeamId, progress.LastUserId) if err != nil { - return false, progress.ToJson(), model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "app.team.migrate_team_members.update.app_error", nil, err.Error(), http.StatusInternalServerError) + return false, progress.ToJSON(), model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "app.team.migrate_team_members.update.app_error", nil, err.Error(), http.StatusInternalServerError) } if result == nil { // We haven't progressed. That means that we've reached the end of this stage of the migration, and should now advance to the next stage. progress.LastUserId = strings.Repeat("0", 26) progress.CurrentTable = "ChannelMembers" - return false, progress.ToJson(), nil + return false, progress.ToJSON(), nil } progress.LastTeamId = result["TeamId"] @@ -88,17 +88,17 @@ func (worker *Worker) runAdvancedPermissionsPhase2Migration(lastDone string) (bo // Run a ChannelMembers migration batch. data, err := worker.srv.Store.Channel().MigrateChannelMembers(progress.LastChannelId, progress.LastUserId) if err != nil { - return false, progress.ToJson(), model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "app.channel.migrate_channel_members.select.app_error", nil, err.Error(), http.StatusInternalServerError) + return false, progress.ToJSON(), model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "app.channel.migrate_channel_members.select.app_error", nil, err.Error(), http.StatusInternalServerError) } if data == nil { // We haven't progressed. That means we've reached the end of this final stage of the migration. - return true, progress.ToJson(), nil + return true, progress.ToJSON(), nil } progress.LastChannelId = data["ChannelId"] progress.LastUserId = data["UserId"] } - return false, progress.ToJson(), nil + return false, progress.ToJSON(), nil } diff --git a/model/bot.go b/model/bot.go index c985fd89ee..fe9b907870 100644 --- a/model/bot.go +++ b/model/bot.go @@ -4,7 +4,6 @@ package model import ( - "encoding/json" "fmt" "net/http" "strings" @@ -114,12 +113,6 @@ func (b *Bot) Etag() string { return Etag(b.UserId, b.UpdateAt) } -// ToJson serializes the bot to json. -func (b *Bot) ToJson() []byte { - data, _ := json.Marshal(b) - return data -} - // Patch modifies an existing bot with optional fields from the given patch. // TODO 6.0: consider returning a boolean to indicate whether or not the patch // applied any changes. @@ -154,16 +147,6 @@ func (b *Bot) WouldPatch(patch *BotPatch) bool { return false } -// ToJson serializes the bot patch to json. -func (b *BotPatch) ToJson() []byte { - data, err := json.Marshal(b) - if err != nil { - return nil - } - - return data -} - // UserFromBot returns a user model describing the bot fields stored in the User store. func UserFromBot(b *Bot) *User { return &User{ @@ -185,12 +168,6 @@ func BotFromUser(u *User) *Bot { } } -// ToJson serializes a list of bots to json. -func (l *BotList) ToJson() []byte { - b, _ := json.Marshal(l) - return b -} - // Etag computes the etag for a list of bots. func (l *BotList) Etag() string { id := "0" diff --git a/model/channel.go b/model/channel.go index 0ad8314a40..75fc2680df 100644 --- a/model/channel.go +++ b/model/channel.go @@ -6,7 +6,6 @@ package model import ( "crypto/sha1" "encoding/hex" - "encoding/json" "io" "net/http" "sort" @@ -165,11 +164,6 @@ func (o *Channel) DeepCopy() *Channel { return © } -func (o *Channel) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - func (o *Channel) Etag() string { return Etag(o.Id, o.UpdateAt) } diff --git a/model/channel_list.go b/model/channel_list.go index 918ed51ef2..7b86b56028 100644 --- a/model/channel_list.go +++ b/model/channel_list.go @@ -3,20 +3,8 @@ package model -import ( - "encoding/json" -) - type ChannelList []*Channel -func (o *ChannelList) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - func (o *ChannelList) Etag() string { id := "0" @@ -41,14 +29,6 @@ func (o *ChannelList) Etag() string { type ChannelListWithTeamData []*ChannelWithTeamData -func (o *ChannelListWithTeamData) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - func (o *ChannelListWithTeamData) Etag() string { id := "0" diff --git a/model/channel_member.go b/model/channel_member.go index ef9be2cfeb..82bc84aec9 100644 --- a/model/channel_member.go +++ b/model/channel_member.go @@ -4,7 +4,6 @@ package model import ( - "encoding/json" "net/http" "strings" ) @@ -69,11 +68,6 @@ type ChannelMemberForExport struct { Username string } -func (o *ChannelMember) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - func (o *ChannelMember) IsValid() *AppError { if !IsValidId(o.ChannelId) { diff --git a/model/channel_search.go b/model/channel_search.go index 6bde45abed..530deb2022 100644 --- a/model/channel_search.go +++ b/model/channel_search.go @@ -3,10 +3,6 @@ package model -import ( - "encoding/json" -) - const ChannelSearchDefaultLimit = 50 type ChannelSearch struct { @@ -24,9 +20,3 @@ type ChannelSearch struct { Page *int `json:"page,omitempty"` PerPage *int `json:"per_page,omitempty"` } - -// ToJson convert a Channel to a json string -func (c *ChannelSearch) ToJson() string { - b, _ := json.Marshal(c) - return string(b) -} diff --git a/model/channel_sidebar.go b/model/channel_sidebar.go index e2038b6b88..fd4d44caaa 100644 --- a/model/channel_sidebar.go +++ b/model/channel_sidebar.go @@ -4,7 +4,6 @@ package model import ( - "encoding/json" "regexp" ) @@ -73,27 +72,6 @@ type SidebarChannel struct { type SidebarChannels []*SidebarChannel type SidebarCategoriesWithChannels []*SidebarCategoryWithChannels -func (o SidebarCategoryWithChannels) ToJson() []byte { - b, _ := json.Marshal(o) - return b -} - -func SidebarCategoriesWithChannelsToJson(o []*SidebarCategoryWithChannels) []byte { - b, err := json.Marshal(o) - if err != nil { - return []byte("[]") - } - return b -} - -func (o OrderedSidebarCategories) ToJson() []byte { - b, err := json.Marshal(o) - if err != nil { - return []byte("[]") - } - return b -} - var categoryIdPattern = regexp.MustCompile("(favorites|channels|direct_messages)_[a-z0-9]{26}_[a-z0-9]{26}") func IsValidCategoryId(s string) bool { diff --git a/model/channel_stats.go b/model/channel_stats.go index 37c1206fc6..cf44d5416c 100644 --- a/model/channel_stats.go +++ b/model/channel_stats.go @@ -3,20 +3,9 @@ package model -import ( - "encoding/json" - "io" -) - type ChannelStats struct { ChannelId string `json:"channel_id"` MemberCount int64 `json:"member_count"` GuestCount int64 `json:"guest_count"` PinnedPostCount int64 `json:"pinnedpost_count"` } - -func ChannelStatsFromJson(data io.Reader) *ChannelStats { - var o *ChannelStats - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/channel_view.go b/model/channel_view.go index cb62e42dfd..c34c438dc2 100644 --- a/model/channel_view.go +++ b/model/channel_view.go @@ -3,30 +3,13 @@ package model -import ( - "encoding/json" - "io" -) - type ChannelView struct { ChannelId string `json:"channel_id"` PrevChannelId string `json:"prev_channel_id"` CollapsedThreadsSupported bool `json:"collapsed_threads_supported"` } -func ChannelViewFromJson(data io.Reader) *ChannelView { - var o *ChannelView - json.NewDecoder(data).Decode(&o) - return o -} - type ChannelViewResponse struct { Status string `json:"status"` LastViewedAtTimes map[string]int64 `json:"last_viewed_at_times"` } - -func ChannelViewResponseFromJson(data io.Reader) *ChannelViewResponse { - var o *ChannelViewResponse - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/client4.go b/model/client4.go index afe48000b8..615b1264da 100644 --- a/model/client4.go +++ b/model/client4.go @@ -622,7 +622,7 @@ func (c *Client4) DoAPIRequestReader(method, url string, data io.Reader, headers if rp.StatusCode >= 300 { defer closeBody(rp) - return rp, AppErrorFromJson(rp.Body) + return rp, AppErrorFromJSON(rp.Body) } return rp, nil @@ -653,10 +653,14 @@ func (c *Client4) doUploadFile(url string, body io.Reader, contentType string, c defer closeBody(rp) if rp.StatusCode >= 300 { - return nil, BuildResponse(rp), AppErrorFromJson(rp.Body) + return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } - return FileUploadResponseFromJson(rp.Body), BuildResponse(rp), nil + var res FileUploadResponse + if jsonErr := json.NewDecoder(rp.Body).Decode(&res); jsonErr != nil { + return nil, nil, NewAppError("doUploadFile", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &res, BuildResponse(rp), nil } func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response, error) { @@ -677,10 +681,14 @@ func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) defer closeBody(rp) if rp.StatusCode >= 300 { - return nil, BuildResponse(rp), AppErrorFromJson(rp.Body) + return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } - return EmojiFromJson(rp.Body), BuildResponse(rp), nil + var e Emoji + if jsonErr := json.NewDecoder(rp.Body).Decode(&e); jsonErr != nil { + return nil, nil, NewAppError("DoEmojiUploadFile", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &e, BuildResponse(rp), nil } func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) (map[string]string, *Response, error) { @@ -701,10 +709,10 @@ func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string defer closeBody(rp) if rp.StatusCode >= 300 { - return nil, BuildResponse(rp), AppErrorFromJson(rp.Body) + return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } - return MapFromJson(rp.Body), BuildResponse(rp), nil + return MapFromJSON(rp.Body), BuildResponse(rp), nil } // Authentication Section @@ -756,14 +764,19 @@ func (c *Client4) LoginWithMFA(loginId, password, mfaToken string) (*User, *Resp } func (c *Client4) login(m map[string]string) (*User, *Response, error) { - r, err := c.DoAPIPost("/users/login", MapToJson(m)) + r, err := c.DoAPIPost("/users/login", MapToJSON(m)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) c.AuthToken = r.Header.Get(HeaderToken) c.AuthType = HeaderBearer - return UserFromJson(r.Body), BuildResponse(r), nil + + var user User + if jsonErr := json.NewDecoder(r.Body).Decode(&user); jsonErr != nil { + return nil, nil, NewAppError("login", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &user, BuildResponse(r), nil } // Logout terminates the current user's session. @@ -789,19 +802,28 @@ func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Resp return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["follow_link"], BuildResponse(r), nil + return MapFromJSON(r.Body)["follow_link"], BuildResponse(r), nil } // User Section // CreateUser creates a user in the system based on the provided user struct. func (c *Client4) CreateUser(user *User) (*User, *Response, error) { - r, err := c.DoAPIPost(c.usersRoute(), user.ToJson()) + userJSON, jsonErr := json.Marshal(user) + if jsonErr != nil { + return nil, nil, NewAppError("CreateUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + + r, err := c.DoAPIPost(c.usersRoute(), string(userJSON)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("CreateUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // CreateUserWithToken creates a user in the system based on the provided tokenId. @@ -821,7 +843,11 @@ func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Respo } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("CreateUserWithToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // CreateUserWithInviteId creates a user in the system based on the provided invited id. @@ -841,7 +867,11 @@ func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *R } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("CreateUserWithInviteId", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // GetMe returns the logged in user. @@ -851,7 +881,14 @@ func (c *Client4) GetMe(etag string) (*User, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("GetMe", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // GetUser returns a user based on the provided user id string. @@ -861,7 +898,14 @@ func (c *Client4) GetUser(userId, etag string) (*User, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("GetUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // GetUserByUsername returns a user based on the provided user name string. @@ -871,7 +915,14 @@ func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response, er return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("GetUserByUsername", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // GetUserByEmail returns a user based on the provided user email string. @@ -881,7 +932,14 @@ func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("GetUserByEmail", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // AutocompleteUsersInTeam returns the users on a team based on search term. @@ -892,7 +950,14 @@ func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, limit return nil, BuildResponse(r), err } defer closeBody(r) - return UserAutocompleteFromJson(r.Body), BuildResponse(r), nil + var u UserAutocomplete + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("AutocompleteUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // AutocompleteUsersInChannel returns the users in a channel based on search term. @@ -903,7 +968,14 @@ func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, us return nil, BuildResponse(r), err } defer closeBody(r) - return UserAutocompleteFromJson(r.Body), BuildResponse(r), nil + var u UserAutocomplete + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("AutocompleteUsersInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // AutocompleteUsers returns the users in the system based on search term. @@ -914,7 +986,14 @@ func (c *Client4) AutocompleteUsers(username string, limit int, etag string) (*U return nil, BuildResponse(r), err } defer closeBody(r) - return UserAutocompleteFromJson(r.Body), BuildResponse(r), nil + var u UserAutocomplete + if r.StatusCode == http.StatusNotModified { + return &u, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("AutocompleteUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // GetDefaultProfileImage gets the default user's profile image. Must be logged in. @@ -956,7 +1035,14 @@ func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Respon return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersInTeam returns a page of users on a team. Page counting starts at 0. @@ -967,7 +1053,14 @@ func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag stri return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetNewUsersInTeam returns a page of users on a team. Page counting starts at 0. @@ -978,7 +1071,14 @@ func (c *Client4) GetNewUsersInTeam(teamId string, page int, perPage int, etag s return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetNewUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetRecentlyActiveUsersInTeam returns a page of users on a team. Page counting starts at 0. @@ -989,7 +1089,14 @@ func (c *Client4) GetRecentlyActiveUsersInTeam(teamId string, page int, perPage return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetRecentlyActiveUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetActiveUsersInTeam returns a page of users on a team. Page counting starts at 0. @@ -1000,7 +1107,14 @@ func (c *Client4) GetActiveUsersInTeam(teamId string, page int, perPage int, eta return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetActiveUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersNotInTeam returns a page of users who are not in a team. Page counting starts at 0. @@ -1011,7 +1125,14 @@ func (c *Client4) GetUsersNotInTeam(teamId string, page int, perPage int, etag s return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersNotInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersInChannel returns a page of users in a channel. Page counting starts at 0. @@ -1022,7 +1143,14 @@ func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, eta return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersInChannelByStatus returns a page of users in a channel. Page counting starts at 0. Sorted by Status @@ -1033,7 +1161,14 @@ func (c *Client4) GetUsersInChannelByStatus(channelId string, page int, perPage return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersInChannelByStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersNotInChannel returns a page of users not in a channel. Page counting starts at 0. @@ -1044,7 +1179,14 @@ func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPa return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersNotInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersWithoutTeam returns a page of users on the system that aren't on any teams. Page counting starts at 0. @@ -1055,7 +1197,14 @@ func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*Us return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersWithoutTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersInGroup returns a page of users in a group. Page counting starts at 0. @@ -1066,17 +1215,28 @@ func (c *Client4) GetUsersInGroup(groupID string, page int, perPage int, etag st return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersInGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersByIds returns a list of users based on the provided user ids. func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response, error) { - r, err := c.DoAPIPost(c.usersRoute()+"/ids", ArrayToJson(userIds)) + r, err := c.DoAPIPost(c.usersRoute()+"/ids", ArrayToJSON(userIds)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersByIds returns a list of users based on the provided user ids. @@ -1091,28 +1251,36 @@ func (c *Client4) GetUsersByIdsWithOptions(userIds []string, options *UserGetByI url += "?" + v.Encode() } - r, err := c.DoAPIPost(url, ArrayToJson(userIds)) + r, err := c.DoAPIPost(url, ArrayToJSON(userIds)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersByIdsWithOptions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersByUsernames returns a list of users based on the provided usernames. func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response, error) { - r, err := c.DoAPIPost(c.usersRoute()+"/usernames", ArrayToJson(usernames)) + r, err := c.DoAPIPost(c.usersRoute()+"/usernames", ArrayToJSON(usernames)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersByUsernames", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUsersByGroupChannelIds returns a map with channel ids as keys // and a list of users as values based on the provided user ids. func (c *Client4) GetUsersByGroupChannelIds(groupChannelIds []string) (map[string][]*User, *Response, error) { - r, err := c.DoAPIPost(c.usersRoute()+"/group_channels", ArrayToJson(groupChannelIds)) + r, err := c.DoAPIPost(c.usersRoute()+"/group_channels", ArrayToJSON(groupChannelIds)) if err != nil { return nil, BuildResponse(r), err } @@ -1134,7 +1302,11 @@ func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return UserListFromJson(r.Body), BuildResponse(r), nil + var list []*User + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("SearchUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // UpdateUser updates a user in the system based on the provided user struct. @@ -1148,7 +1320,11 @@ func (c *Client4) UpdateUser(user *User) (*User, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("UpdateUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // PatchUser partially updates a user in the system. Any missing fields are not updated. @@ -1162,7 +1338,11 @@ func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("PatchUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // UpdateUserAuth updates a user AuthData (uthData, authService and password) in the system. @@ -1176,7 +1356,11 @@ func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, return nil, BuildResponse(r), err } defer closeBody(r) - return UserAuthFromJson(r.Body), BuildResponse(r), nil + var ua UserAuth + if jsonErr := json.NewDecoder(r.Body).Decode(&ua); jsonErr != nil { + return nil, nil, NewAppError("UpdateUserAuth", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &ua, BuildResponse(r), nil } // UpdateUserMfa activates multi-factor authentication for a user if activate @@ -1187,7 +1371,7 @@ func (c *Client4) UpdateUserMfa(userId, code string, activate bool) (*Response, requestBody["activate"] = activate requestBody["code"] = code - r, err := c.DoAPIPut(c.userRoute(userId)+"/mfa", StringInterfaceToJson(requestBody)) + r, err := c.DoAPIPut(c.userRoute(userId)+"/mfa", StringInterfaceToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1203,13 +1387,17 @@ func (c *Client4) GenerateMfaSecret(userId string) (*MfaSecret, *Response, error return nil, BuildResponse(r), err } defer closeBody(r) - return MfaSecretFromJson(r.Body), BuildResponse(r), nil + var secret MfaSecret + if jsonErr := json.NewDecoder(r.Body).Decode(&secret); jsonErr != nil { + return nil, nil, NewAppError("GenerateMfaSecret", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &secret, BuildResponse(r), nil } // UpdateUserPassword updates a user's password. Must be logged in as the user or be a system administrator. func (c *Client4) UpdateUserPassword(userId, currentPassword, newPassword string) (*Response, error) { requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword} - r, err := c.DoAPIPut(c.userRoute(userId)+"/password", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.userRoute(userId)+"/password", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1220,7 +1408,7 @@ func (c *Client4) UpdateUserPassword(userId, currentPassword, newPassword string // UpdateUserHashedPassword updates a user's password with an already-hashed password. Must be a system administrator. func (c *Client4) UpdateUserHashedPassword(userId, newHashedPassword string) (*Response, error) { requestBody := map[string]string{"already_hashed": "true", "new_password": newHashedPassword} - r, err := c.DoAPIPut(c.userRoute(userId)+"/password", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.userRoute(userId)+"/password", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1251,7 +1439,7 @@ func (c *Client4) DemoteUserToGuest(guestId string) (*Response, error) { // UpdateUserRoles updates a user's roles in the system. A user can have "system_user" and "system_admin" roles. func (c *Client4) UpdateUserRoles(userId, roles string) (*Response, error) { requestBody := map[string]string{"roles": roles} - r, err := c.DoAPIPut(c.userRoute(userId)+"/roles", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.userRoute(userId)+"/roles", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1263,7 +1451,7 @@ func (c *Client4) UpdateUserRoles(userId, roles string) (*Response, error) { func (c *Client4) UpdateUserActive(userId string, active bool) (*Response, error) { requestBody := make(map[string]interface{}) requestBody["active"] = active - r, err := c.DoAPIPut(c.userRoute(userId)+"/active", StringInterfaceToJson(requestBody)) + r, err := c.DoAPIPut(c.userRoute(userId)+"/active", StringInterfaceToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1322,7 +1510,11 @@ func (c *Client4) ConvertBotToUser(userId string, userPatch *UserPatch, setSyste return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("ConvertBotToUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // PermanentDeleteAll permanently deletes all users in the system. This is a local only endpoint @@ -1339,7 +1531,7 @@ func (c *Client4) PermanentDeleteAllUsers() (*Response, error) { // provided email. func (c *Client4) SendPasswordResetEmail(email string) (*Response, error) { requestBody := map[string]string{"email": email} - r, err := c.DoAPIPost(c.usersRoute()+"/password/reset/send", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/password/reset/send", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1350,7 +1542,7 @@ func (c *Client4) SendPasswordResetEmail(email string) (*Response, error) { // ResetPassword uses a recovery code to update reset a user's password. func (c *Client4) ResetPassword(token, newPassword string) (*Response, error) { requestBody := map[string]string{"token": token, "new_password": newPassword} - r, err := c.DoAPIPost(c.usersRoute()+"/password/reset", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/password/reset", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1365,13 +1557,17 @@ func (c *Client4) GetSessions(userId, etag string) ([]*Session, *Response, error return nil, BuildResponse(r), err } defer closeBody(r) - return SessionsFromJson(r.Body), BuildResponse(r), nil + var list []*Session + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetSessions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // RevokeSession revokes a user session based on the provided user id and session id strings. func (c *Client4) RevokeSession(userId, sessionId string) (*Response, error) { requestBody := map[string]string{"session_id": sessionId} - r, err := c.DoAPIPost(c.userRoute(userId)+"/sessions/revoke", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.userRoute(userId)+"/sessions/revoke", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1402,7 +1598,7 @@ func (c *Client4) RevokeSessionsFromAllUsers() (*Response, error) { // AttachDeviceId attaches a mobile device ID to the current session. func (c *Client4) AttachDeviceId(deviceId string) (*Response, error) { requestBody := map[string]string{"device_id": deviceId} - r, err := c.DoAPIPut(c.usersRoute()+"/sessions/device", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.usersRoute()+"/sessions/device", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1430,7 +1626,12 @@ func (c *Client4) GetTeamsUnreadForUser(userId, teamIdToExclude string, includeC return nil, BuildResponse(r), err } defer closeBody(r) - return TeamsUnreadFromJson(r.Body), BuildResponse(r), nil + + var list []*TeamUnread + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetTeamsUnreadForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUserAudits returns a list of audit based on the provided user id string. @@ -1453,7 +1654,7 @@ func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag strin // VerifyUserEmail will verify a user's email using the supplied token. func (c *Client4) VerifyUserEmail(token string) (*Response, error) { requestBody := map[string]string{"token": token} - r, err := c.DoAPIPost(c.usersRoute()+"/email/verify", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/email/verify", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1468,7 +1669,11 @@ func (c *Client4) VerifyUserEmailWithoutToken(userId string) (*User, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return UserFromJson(r.Body), BuildResponse(r), nil + var u User + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("VerifyUserEmailWithoutToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // SendVerificationEmail will send an email to the user with the provided email address, if @@ -1476,7 +1681,7 @@ func (c *Client4) VerifyUserEmailWithoutToken(userId string) (*User, *Response, // email address. func (c *Client4) SendVerificationEmail(email string) (*Response, error) { requestBody := map[string]string{"email": email} - r, err := c.DoAPIPost(c.usersRoute()+"/email/verify/send", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/email/verify/send", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1528,7 +1733,7 @@ func (c *Client4) SetProfileImage(userId string, data []byte) (*Response, error) defer closeBody(rp) if rp.StatusCode >= 300 { - return BuildResponse(rp), AppErrorFromJson(rp.Body) + return BuildResponse(rp), AppErrorFromJSON(rp.Body) } return BuildResponse(rp), nil @@ -1540,12 +1745,16 @@ func (c *Client4) SetProfileImage(userId string, data []byte) (*Response, error) // permission. A non-blank description is required. func (c *Client4) CreateUserAccessToken(userId, description string) (*UserAccessToken, *Response, error) { requestBody := map[string]string{"description": description} - r, err := c.DoAPIPost(c.userRoute(userId)+"/tokens", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.userRoute(userId)+"/tokens", MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return UserAccessTokenFromJson(r.Body), BuildResponse(r), nil + var uat UserAccessToken + if jsonErr := json.NewDecoder(r.Body).Decode(&uat); jsonErr != nil { + return nil, nil, NewAppError("CreateUserAccessToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &uat, BuildResponse(r), nil } // GetUserAccessTokens will get a page of access tokens' id, description, is_active @@ -1558,7 +1767,11 @@ func (c *Client4) GetUserAccessTokens(page int, perPage int) ([]*UserAccessToken return nil, BuildResponse(r), err } defer closeBody(r) - return UserAccessTokenListFromJson(r.Body), BuildResponse(r), nil + var list []*UserAccessToken + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUserAccessTokens", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetUserAccessToken will get a user access tokens' id, description, is_active @@ -1571,7 +1784,11 @@ func (c *Client4) GetUserAccessToken(tokenId string) (*UserAccessToken, *Respons return nil, BuildResponse(r), err } defer closeBody(r) - return UserAccessTokenFromJson(r.Body), BuildResponse(r), nil + var uat UserAccessToken + if jsonErr := json.NewDecoder(r.Body).Decode(&uat); jsonErr != nil { + return nil, nil, NewAppError("GetUserAccessToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &uat, BuildResponse(r), nil } // GetUserAccessTokensForUser will get a paged list of user access tokens showing id, @@ -1585,7 +1802,11 @@ func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ( return nil, BuildResponse(r), err } defer closeBody(r) - return UserAccessTokenListFromJson(r.Body), BuildResponse(r), nil + var list []*UserAccessToken + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUserAccessTokensForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // RevokeUserAccessToken will revoke a user access token by id. Must have the @@ -1593,7 +1814,7 @@ func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ( // 'edit_other_users' permission. func (c *Client4) RevokeUserAccessToken(tokenId string) (*Response, error) { requestBody := map[string]string{"token_id": tokenId} - r, err := c.DoAPIPost(c.usersRoute()+"/tokens/revoke", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/tokens/revoke", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1612,7 +1833,11 @@ func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*User return nil, BuildResponse(r), err } defer closeBody(r) - return UserAccessTokenListFromJson(r.Body), BuildResponse(r), nil + var list []*UserAccessToken + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("SearchUserAccessTokens", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // DisableUserAccessToken will disable a user access token by id. Must have the @@ -1620,7 +1845,7 @@ func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*User // 'edit_other_users' permission. func (c *Client4) DisableUserAccessToken(tokenId string) (*Response, error) { requestBody := map[string]string{"token_id": tokenId} - r, err := c.DoAPIPost(c.usersRoute()+"/tokens/disable", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/tokens/disable", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1633,7 +1858,7 @@ func (c *Client4) DisableUserAccessToken(tokenId string) (*Response, error) { // 'edit_other_users' permission. func (c *Client4) EnableUserAccessToken(tokenId string) (*Response, error) { requestBody := map[string]string{"token_id": tokenId} - r, err := c.DoAPIPost(c.usersRoute()+"/tokens/enable", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.usersRoute()+"/tokens/enable", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1645,7 +1870,11 @@ func (c *Client4) EnableUserAccessToken(tokenId string) (*Response, error) { // CreateBot creates a bot in the system based on the provided bot struct. func (c *Client4) CreateBot(bot *Bot) (*Bot, *Response, error) { - r, err := c.DoAPIPostBytes(c.botsRoute(), bot.ToJson()) + buf, err := json.Marshal(bot) + if err != nil { + return nil, nil, NewAppError("CreateBot", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPostBytes(c.botsRoute(), buf) if err != nil { return nil, BuildResponse(r), err } @@ -1662,7 +1891,11 @@ func (c *Client4) CreateBot(bot *Bot) (*Bot, *Response, error) { // PatchBot partially updates a bot. Any missing fields are not updated. func (c *Client4) PatchBot(userId string, patch *BotPatch) (*Bot, *Response, error) { - r, err := c.DoAPIPutBytes(c.botRoute(userId), patch.ToJson()) + buf, err := json.Marshal(patch) + if err != nil { + return nil, nil, NewAppError("PatchBot", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPutBytes(c.botRoute(userId), buf) if err != nil { return nil, BuildResponse(r), err } @@ -1826,7 +2059,11 @@ func (c *Client4) CreateTeam(team *Team) (*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("CreateTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // GetTeam returns a team based on the provided team id string. @@ -1836,7 +2073,11 @@ func (c *Client4) GetTeam(teamId, etag string) (*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("GetTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // GetAllTeams returns all teams based on permissions. @@ -1847,7 +2088,11 @@ func (c *Client4) GetAllTeams(etag string, page int, perPage int) ([]*Team, *Res return nil, BuildResponse(r), err } defer closeBody(r) - return TeamListFromJson(r.Body), BuildResponse(r), nil + var list []*Team + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetAllTeams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetAllTeamsWithTotalCount returns all teams based on permissions. @@ -1858,8 +2103,11 @@ func (c *Client4) GetAllTeamsWithTotalCount(etag string, page int, perPage int) return nil, 0, BuildResponse(r), err } defer closeBody(r) - teamsListWithCount := TeamsWithCountFromJson(r.Body) - return teamsListWithCount.Teams, teamsListWithCount.TotalCount, BuildResponse(r), nil + var listWithCount TeamsWithCount + if jsonErr := json.NewDecoder(r.Body).Decode(&listWithCount); jsonErr != nil { + return nil, 0, nil, NewAppError("GetAllTeamsWithTotalCount", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return listWithCount.Teams, listWithCount.TotalCount, BuildResponse(r), nil } // GetAllTeamsExcludePolicyConstrained returns all teams which are not part of a data retention policy. @@ -1871,7 +2119,11 @@ func (c *Client4) GetAllTeamsExcludePolicyConstrained(etag string, page int, per return nil, BuildResponse(r), err } defer closeBody(r) - return TeamListFromJson(r.Body), BuildResponse(r), nil + var list []*Team + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetAllTeamsExcludePolicyConstrained", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetTeamByName returns a team based on the provided team name string. @@ -1881,7 +2133,11 @@ func (c *Client4) GetTeamByName(name, etag string) (*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("GetTeamByName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // SearchTeams returns teams matching the provided search term. @@ -1895,7 +2151,11 @@ func (c *Client4) SearchTeams(search *TeamSearch) ([]*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamListFromJson(r.Body), BuildResponse(r), nil + var list []*Team + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("SearchTeams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // SearchTeamsPaged returns a page of teams and the total count matching the provided search term. @@ -1915,8 +2175,11 @@ func (c *Client4) SearchTeamsPaged(search *TeamSearch) ([]*Team, int64, *Respons return nil, 0, BuildResponse(r), err } defer closeBody(r) - twc := TeamsWithCountFromJson(r.Body) - return twc.Teams, twc.TotalCount, BuildResponse(r), nil + var listWithCount TeamsWithCount + if jsonErr := json.NewDecoder(r.Body).Decode(&listWithCount); jsonErr != nil { + return nil, 0, nil, NewAppError("GetAllTeamsWithTotalCount", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return listWithCount.Teams, listWithCount.TotalCount, BuildResponse(r), nil } // TeamExists returns true or false if the team exist or not. @@ -1926,7 +2189,7 @@ func (c *Client4) TeamExists(name, etag string) (bool, *Response, error) { return false, BuildResponse(r), err } defer closeBody(r) - return MapBoolFromJson(r.Body)["exists"], BuildResponse(r), nil + return MapBoolFromJSON(r.Body)["exists"], BuildResponse(r), nil } // GetTeamsForUser returns a list of teams a user is on. Must be logged in as the user @@ -1937,7 +2200,11 @@ func (c *Client4) GetTeamsForUser(userId, etag string) ([]*Team, *Response, erro return nil, BuildResponse(r), err } defer closeBody(r) - return TeamListFromJson(r.Body), BuildResponse(r), nil + var list []*Team + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetTeamsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetTeamMember returns a team member based on the provided team and user id strings. @@ -1947,13 +2214,20 @@ func (c *Client4) GetTeamMember(teamId, userId, etag string) (*TeamMember, *Resp return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMemberFromJson(r.Body), BuildResponse(r), nil + var tm TeamMember + if r.StatusCode == http.StatusNotModified { + return &tm, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&tm); jsonErr != nil { + return nil, nil, NewAppError("GetTeamMember", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &tm, BuildResponse(r), nil } // UpdateTeamMemberRoles will update the roles on a team for a user. func (c *Client4) UpdateTeamMemberRoles(teamId, userId, newRoles string) (*Response, error) { requestBody := map[string]string{"roles": newRoles} - r, err := c.DoAPIPut(c.teamMemberRoute(teamId, userId)+"/roles", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.teamMemberRoute(teamId, userId)+"/roles", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -1986,7 +2260,11 @@ func (c *Client4) UpdateTeam(team *Team) (*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("UpdateTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // PatchTeam partially updates a team. Any missing fields are not updated. @@ -2000,7 +2278,11 @@ func (c *Client4) PatchTeam(teamId string, patch *TeamPatch) (*Team, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("PatchTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // RestoreTeam restores a previously deleted team. @@ -2010,7 +2292,11 @@ func (c *Client4) RestoreTeam(teamId string) (*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("RestoreTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // RegenerateTeamInviteId requests a new invite ID to be generated. @@ -2020,7 +2306,11 @@ func (c *Client4) RegenerateTeamInviteId(teamId string) (*Team, *Response, error return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("RegenerateTeamInviteId", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // SoftDeleteTeam deletes the team softly (archive only, not permanent delete). @@ -2048,12 +2338,16 @@ func (c *Client4) PermanentDeleteTeam(teamId string) (*Response, error) { // the corresponding AllowOpenInvite appropriately. func (c *Client4) UpdateTeamPrivacy(teamId string, privacy string) (*Team, *Response, error) { requestBody := map[string]string{"privacy": privacy} - r, err := c.DoAPIPut(c.teamRoute(teamId)+"/privacy", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.teamRoute(teamId)+"/privacy", MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("UpdateTeamPrivacy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // GetTeamMembers returns team members based on the provided team id string. @@ -2064,7 +2358,14 @@ func (c *Client4) GetTeamMembers(teamId string, page int, perPage int, etag stri return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMembersFromJson(r.Body), BuildResponse(r), nil + var tms []*TeamMember + if r.StatusCode == http.StatusNotModified { + return tms, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { + return nil, nil, NewAppError("GetTeamMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return tms, BuildResponse(r), nil } // GetTeamMembersWithoutDeletedUsers returns team members based on the provided team id string. Additional parameters of sort and exclude_deleted_users accepted as well @@ -2076,7 +2377,14 @@ func (c *Client4) GetTeamMembersSortAndWithoutDeletedUsers(teamId string, page i return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMembersFromJson(r.Body), BuildResponse(r), nil + var tms []*TeamMember + if r.StatusCode == http.StatusNotModified { + return tms, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { + return nil, nil, NewAppError("GetTeamMembersSortAndWithoutDeletedUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return tms, BuildResponse(r), nil } // GetTeamMembersForUser returns the team members for a user. @@ -2086,18 +2394,29 @@ func (c *Client4) GetTeamMembersForUser(userId string, etag string) ([]*TeamMemb return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMembersFromJson(r.Body), BuildResponse(r), nil + var tms []*TeamMember + if r.StatusCode == http.StatusNotModified { + return tms, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { + return nil, nil, NewAppError("GetTeamMembersForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return tms, BuildResponse(r), nil } // GetTeamMembersByIds will return an array of team members based on the // team id and a list of user ids provided. Must be authenticated. func (c *Client4) GetTeamMembersByIds(teamId string, userIds []string) ([]*TeamMember, *Response, error) { - r, err := c.DoAPIPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds)) + r, err := c.DoAPIPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJSON(userIds)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMembersFromJson(r.Body), BuildResponse(r), nil + var tms []*TeamMember + if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { + return nil, nil, NewAppError("GetTeamMembersByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return tms, BuildResponse(r), nil } // AddTeamMember adds user to a team and return a team member. @@ -2112,7 +2431,11 @@ func (c *Client4) AddTeamMember(teamId, userId string) (*TeamMember, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMemberFromJson(r.Body), BuildResponse(r), nil + var tm TeamMember + if jsonErr := json.NewDecoder(r.Body).Decode(&tm); jsonErr != nil { + return nil, nil, NewAppError("AddTeamMember", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &tm, BuildResponse(r), nil } // AddTeamMemberFromInvite adds a user to a team and return a team member using an invite id @@ -2133,7 +2456,11 @@ func (c *Client4) AddTeamMemberFromInvite(token, inviteId string) (*TeamMember, return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMemberFromJson(r.Body), BuildResponse(r), nil + var tm TeamMember + if jsonErr := json.NewDecoder(r.Body).Decode(&tm); jsonErr != nil { + return nil, nil, NewAppError("AddTeamMemberFromInvite", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &tm, BuildResponse(r), nil } // AddTeamMembers adds a number of users to a team and returns the team members. @@ -2143,13 +2470,20 @@ func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember member := &TeamMember{TeamId: teamId, UserId: userId} members = append(members, member) } - - r, err := c.DoAPIPost(c.teamMembersRoute(teamId)+"/batch", TeamMembersToJson(members)) + js, jsonErr := json.Marshal(members) + if jsonErr != nil { + return nil, nil, NewAppError("AddTeamMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.teamMembersRoute(teamId)+"/batch", string(js)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMembersFromJson(r.Body), BuildResponse(r), nil + var tms []*TeamMember + if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { + return nil, nil, NewAppError("AddTeamMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return tms, BuildResponse(r), nil } // AddTeamMembers adds a number of users to a team and returns the team members. @@ -2159,13 +2493,21 @@ func (c *Client4) AddTeamMembersGracefully(teamId string, userIds []string) ([]* member := &TeamMember{TeamId: teamId, UserId: userId} members = append(members, member) } + js, jsonErr := json.Marshal(members) + if jsonErr != nil { + return nil, nil, NewAppError("AddTeamMembersGracefully", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } - r, err := c.DoAPIPost(c.teamMembersRoute(teamId)+"/batch?graceful="+c.boolString(true), TeamMembersToJson(members)) + r, err := c.DoAPIPost(c.teamMembersRoute(teamId)+"/batch?graceful="+c.boolString(true), string(js)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamMembersWithErrorFromJson(r.Body), BuildResponse(r), nil + var tms []*TeamMemberWithError + if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { + return nil, nil, NewAppError("AddTeamMembersGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return tms, BuildResponse(r), nil } // RemoveTeamMember will remove a user from a team. @@ -2186,7 +2528,11 @@ func (c *Client4) GetTeamStats(teamId, etag string) (*TeamStats, *Response, erro return nil, BuildResponse(r), err } defer closeBody(r) - return TeamStatsFromJson(r.Body), BuildResponse(r), nil + var ts TeamStats + if jsonErr := json.NewDecoder(r.Body).Decode(&ts); jsonErr != nil { + return nil, nil, NewAppError("GetTeamStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &ts, BuildResponse(r), nil } // GetTotalUsersStats returns a total system user stats. @@ -2197,7 +2543,11 @@ func (c *Client4) GetTotalUsersStats(etag string) (*UsersStats, *Response, error return nil, BuildResponse(r), err } defer closeBody(r) - return UsersStatsFromJson(r.Body), BuildResponse(r), nil + var stats UsersStats + if jsonErr := json.NewDecoder(r.Body).Decode(&stats); jsonErr != nil { + return nil, nil, NewAppError("GetTotalUsersStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &stats, BuildResponse(r), nil } // GetTeamUnread will return a TeamUnread object that contains the amount of @@ -2209,7 +2559,11 @@ func (c *Client4) GetTeamUnread(teamId, userId string) (*TeamUnread, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return TeamUnreadFromJson(r.Body), BuildResponse(r), nil + var tu TeamUnread + if jsonErr := json.NewDecoder(r.Body).Decode(&tu); jsonErr != nil { + return nil, nil, NewAppError("GetTeamUnread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &tu, BuildResponse(r), nil } // ImportTeam will import an exported team from other app into a existing team. @@ -2253,7 +2607,7 @@ func (c *Client4) ImportTeam(data []byte, filesize int, importFrom, filename, te // InviteUsersToTeam invite users by email to the team. func (c *Client4) InviteUsersToTeam(teamId string, userEmails []string) (*Response, error) { - r, err := c.DoAPIPost(c.teamRoute(teamId)+"/invite/email", ArrayToJson(userEmails)) + r, err := c.DoAPIPost(c.teamRoute(teamId)+"/invite/email", ArrayToJSON(userEmails)) if err != nil { return BuildResponse(r), err } @@ -2282,12 +2636,16 @@ func (c *Client4) InviteGuestsToTeam(teamId string, userEmails []string, channel // InviteUsersToTeam invite users by email to the team. func (c *Client4) InviteUsersToTeamGracefully(teamId string, userEmails []string) ([]*EmailInviteWithError, *Response, error) { - r, err := c.DoAPIPost(c.teamRoute(teamId)+"/invite/email?graceful="+c.boolString(true), ArrayToJson(userEmails)) + r, err := c.DoAPIPost(c.teamRoute(teamId)+"/invite/email?graceful="+c.boolString(true), ArrayToJSON(userEmails)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return EmailInviteWithErrorFromJson(r.Body), BuildResponse(r), nil + var list []*EmailInviteWithError + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("InviteUsersToTeamGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // InviteGuestsToTeam invite guest by email to some channels in a team. @@ -2306,7 +2664,11 @@ func (c *Client4) InviteGuestsToTeamGracefully(teamId string, userEmails []strin return nil, BuildResponse(r), err } defer closeBody(r) - return EmailInviteWithErrorFromJson(r.Body), BuildResponse(r), nil + var list []*EmailInviteWithError + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("InviteGuestsToTeamGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // InvalidateEmailInvites will invalidate active email invitations that have not been accepted by the user. @@ -2326,7 +2688,11 @@ func (c *Client4) GetTeamInviteInfo(inviteId string) (*Team, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return TeamFromJson(r.Body), BuildResponse(r), nil + var t Team + if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { + return nil, nil, NewAppError("GetTeamInviteInfo", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &t, BuildResponse(r), nil } // SetTeamIcon sets team icon of the team. @@ -2364,7 +2730,7 @@ func (c *Client4) SetTeamIcon(teamId string, data []byte) (*Response, error) { defer closeBody(rp) if rp.StatusCode >= 300 { - return BuildResponse(rp), AppErrorFromJson(rp.Body) + return BuildResponse(rp), AppErrorFromJSON(rp.Body) } return BuildResponse(rp), nil @@ -2449,7 +2815,11 @@ func (c *Client4) GetAllChannelsWithCount(page int, perPage int, etag string) (C // CreateChannel creates a channel based on the provided channel struct. func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response, error) { - r, err := c.DoAPIPost(c.channelsRoute(), channel.ToJson()) + channelJSON, jsonErr := json.Marshal(channel) + if jsonErr != nil { + return nil, nil, NewAppError("CreateChannel", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.channelsRoute(), string(channelJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2465,7 +2835,11 @@ func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response, error) { // UpdateChannel updates a channel based on the provided channel struct. func (c *Client4) UpdateChannel(channel *Channel) (*Channel, *Response, error) { - r, err := c.DoAPIPut(c.channelRoute(channel.Id), channel.ToJson()) + channelJSON, jsonErr := json.Marshal(channel) + if jsonErr != nil { + return nil, nil, NewAppError("UpdateChannel", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPut(c.channelRoute(channel.Id), string(channelJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2502,7 +2876,7 @@ func (c *Client4) PatchChannel(channelId string, patch *ChannelPatch) (*Channel, // UpdateChannelPrivacy updates channel privacy func (c *Client4) UpdateChannelPrivacy(channelId string, privacy ChannelType) (*Channel, *Response, error) { requestBody := map[string]string{"privacy": string(privacy)} - r, err := c.DoAPIPut(c.channelRoute(channelId)+"/privacy", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.channelRoute(channelId)+"/privacy", MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } @@ -2536,7 +2910,7 @@ func (c *Client4) RestoreChannel(channelId string) (*Channel, *Response, error) // ids provided. func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response, error) { requestBody := []string{userId1, userId2} - r, err := c.DoAPIPost(c.channelsRoute()+"/direct", ArrayToJson(requestBody)) + r, err := c.DoAPIPost(c.channelsRoute()+"/direct", ArrayToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } @@ -2552,7 +2926,7 @@ func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Respo // CreateGroupChannel creates a group message channel based on userIds provided. func (c *Client4) CreateGroupChannel(userIds []string) (*Channel, *Response, error) { - r, err := c.DoAPIPost(c.channelsRoute()+"/group", ArrayToJson(userIds)) + r, err := c.DoAPIPost(c.channelsRoute()+"/group", ArrayToJSON(userIds)) if err != nil { return nil, BuildResponse(r), err } @@ -2589,7 +2963,11 @@ func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, return nil, BuildResponse(r), err } defer closeBody(r) - return ChannelStatsFromJson(r.Body), BuildResponse(r), nil + var stats ChannelStats + if jsonErr := json.NewDecoder(r.Body).Decode(&stats); jsonErr != nil { + return nil, nil, NewAppError("GetChannelStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &stats, BuildResponse(r), nil } // GetChannelMembersTimezones gets a list of timezones for a channel. @@ -2599,7 +2977,7 @@ func (c *Client4) GetChannelMembersTimezones(channelId string) ([]string, *Respo return nil, BuildResponse(r), err } defer closeBody(r) - return ArrayFromJson(r.Body), BuildResponse(r), nil + return ArrayFromJSON(r.Body), BuildResponse(r), nil } // GetPinnedPosts gets a list of pinned posts. @@ -2609,7 +2987,16 @@ func (c *Client4) GetPinnedPosts(channelId string, etag string) (*PostList, *Res return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPinnedPosts", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetPrivateChannelsForTeam returns a list of private channels based on the provided team id string. @@ -2665,7 +3052,7 @@ func (c *Client4) GetDeletedChannelsForTeam(teamId string, page int, perPage int // GetPublicChannelsByIdsForTeam returns a list of public channels based on provided team id string. func (c *Client4) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) ([]*Channel, *Response, error) { - r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/ids", ArrayToJson(channelIds)) + r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/ids", ArrayToJSON(channelIds)) if err != nil { return nil, BuildResponse(r), err } @@ -2715,7 +3102,11 @@ func (c *Client4) GetChannelsForTeamAndUserWithLastDeleteAt(teamId, userId strin // SearchChannels returns the channels on a team matching the provided search term. func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response, error) { - r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/search", search.ToJson()) + searchJSON, jsonErr := json.Marshal(search) + if jsonErr != nil { + return nil, nil, NewAppError("SearchChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/search", string(searchJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2731,7 +3122,11 @@ func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Chann // SearchArchivedChannels returns the archived channels on a team matching the provided search term. func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response, error) { - r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/search_archived", search.ToJson()) + searchJSON, jsonErr := json.Marshal(search) + if jsonErr != nil { + return nil, nil, NewAppError("SearchArchivedChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/search_archived", string(searchJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2747,7 +3142,11 @@ func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ( // SearchAllChannels search in all the channels. Must be a system administrator. func (c *Client4) SearchAllChannels(search *ChannelSearch) (ChannelListWithTeamData, *Response, error) { - r, err := c.DoAPIPost(c.channelsRoute()+"/search", search.ToJson()) + searchJSON, jsonErr := json.Marshal(search) + if jsonErr != nil { + return nil, nil, NewAppError("SearchAllChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.channelsRoute()+"/search", string(searchJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2763,7 +3162,11 @@ func (c *Client4) SearchAllChannels(search *ChannelSearch) (ChannelListWithTeamD // SearchAllChannelsPaged searches all the channels and returns the results paged with the total count. func (c *Client4) SearchAllChannelsPaged(search *ChannelSearch) (*ChannelsWithCount, *Response, error) { - r, err := c.DoAPIPost(c.channelsRoute()+"/search", search.ToJson()) + searchJSON, jsonErr := json.Marshal(search) + if jsonErr != nil { + return nil, nil, NewAppError("SearchAllChannelsPaged", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.channelsRoute()+"/search", string(searchJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2779,7 +3182,11 @@ func (c *Client4) SearchAllChannelsPaged(search *ChannelSearch) (*ChannelsWithCo // SearchGroupChannels returns the group channels of the user whose members' usernames match the search term. func (c *Client4) SearchGroupChannels(search *ChannelSearch) ([]*Channel, *Response, error) { - r, err := c.DoAPIPost(c.channelsRoute()+"/group/search", search.ToJson()) + searchJSON, jsonErr := json.Marshal(search) + if jsonErr != nil { + return nil, nil, NewAppError("SearchGroupChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.channelsRoute()+"/group/search", string(searchJSON)) if err != nil { return nil, BuildResponse(r), err } @@ -2819,7 +3226,7 @@ func (c *Client4) MoveChannel(channelId, teamId string, force bool) (*Channel, * "team_id": teamId, "force": force, } - r, err := c.DoAPIPost(c.channelRoute(channelId)+"/move", StringInterfaceToJson(requestBody)) + r, err := c.DoAPIPost(c.channelRoute(channelId)+"/move", StringInterfaceToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } @@ -2916,7 +3323,7 @@ func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag st // GetChannelMembersByIds gets the channel members in a channel for a list of user ids. func (c *Client4) GetChannelMembersByIds(channelId string, userIds []string) (ChannelMembers, *Response, error) { - r, err := c.DoAPIPost(c.channelMembersRoute(channelId)+"/ids", ArrayToJson(userIds)) + r, err := c.DoAPIPost(c.channelMembersRoute(channelId)+"/ids", ArrayToJSON(userIds)) if err != nil { return nil, BuildResponse(r), err } @@ -3003,7 +3410,7 @@ func (c *Client4) GetChannelUnread(channelId, userId string) (*ChannelUnread, *R // UpdateChannelRoles will update the roles on a channel for a user. func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (*Response, error) { requestBody := map[string]string{"roles": roles} - r, err := c.DoAPIPut(c.channelMemberRoute(channelId, userId)+"/roles", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.channelMemberRoute(channelId, userId)+"/roles", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -3027,7 +3434,7 @@ func (c *Client4) UpdateChannelMemberSchemeRoles(channelId string, userId string // UpdateChannelNotifyProps will update the notification properties on a channel for a user. func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[string]string) (*Response, error) { - r, err := c.DoAPIPut(c.channelMemberRoute(channelId, userId)+"/notify_props", MapToJson(props)) + r, err := c.DoAPIPut(c.channelMemberRoute(channelId, userId)+"/notify_props", MapToJSON(props)) if err != nil { return BuildResponse(r), err } @@ -3038,7 +3445,7 @@ func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[s // AddChannelMember adds user to channel and return a channel member. func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *Response, error) { requestBody := map[string]string{"user_id": userId} - r, err := c.DoAPIPost(c.channelMembersRoute(channelId)+"", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.channelMembersRoute(channelId)+"", MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } @@ -3055,7 +3462,7 @@ func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *R // AddChannelMemberWithRootId adds user to channel and return a channel member. Post add to channel message has the postRootId. func (c *Client4) AddChannelMemberWithRootId(channelId, userId, postRootId string) (*ChannelMember, *Response, error) { requestBody := map[string]string{"user_id": userId, "post_root_id": postRootId} - r, err := c.DoAPIPost(c.channelMembersRoute(channelId)+"", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.channelMembersRoute(channelId)+"", MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } @@ -3117,32 +3524,65 @@ func (c *Client4) AutocompleteChannelsForTeamForSearch(teamId, name string) (Cha // CreatePost creates a post based on the provided post struct. func (c *Client4) CreatePost(post *Post) (*Post, *Response, error) { - r, err := c.DoAPIPost(c.postsRoute(), post.ToUnsanitizedJson()) + postJSON, jsonErr := json.Marshal(post) + if jsonErr != nil { + return nil, nil, NewAppError("CreatePost", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.postsRoute(), string(postJSON)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return PostFromJson(r.Body), BuildResponse(r), nil + var p Post + if r.StatusCode == http.StatusNotModified { + return &p, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("CreatePost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &p, BuildResponse(r), nil } // CreatePostEphemeral creates a ephemeral post based on the provided post struct which is send to the given user id. func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response, error) { - r, err := c.DoAPIPost(c.postsEphemeralRoute(), post.ToUnsanitizedJson()) + postJSON, jsonErr := json.Marshal(post) + if jsonErr != nil { + return nil, nil, NewAppError("CreatePostEphemeral", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.postsEphemeralRoute(), string(postJSON)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return PostFromJson(r.Body), BuildResponse(r), nil + var p Post + if r.StatusCode == http.StatusNotModified { + return &p, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("CreatePostEphemeral", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &p, BuildResponse(r), nil } // UpdatePost updates a post based on the provided post struct. func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response, error) { - r, err := c.DoAPIPut(c.postRoute(postId), post.ToUnsanitizedJson()) + postJSON, jsonErr := json.Marshal(post) + if jsonErr != nil { + return nil, nil, NewAppError("UpdatePost", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPut(c.postRoute(postId), string(postJSON)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return PostFromJson(r.Body), BuildResponse(r), nil + var p Post + if r.StatusCode == http.StatusNotModified { + return &p, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("UpdatePost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &p, BuildResponse(r), nil } // PatchPost partially updates a post. Any missing fields are not updated. @@ -3156,7 +3596,14 @@ func (c *Client4) PatchPost(postId string, patch *PostPatch) (*Post, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return PostFromJson(r.Body), BuildResponse(r), nil + var p Post + if r.StatusCode == http.StatusNotModified { + return &p, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("PatchPost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &p, BuildResponse(r), nil } // SetPostUnread marks channel where post belongs as unread on the time of the provided post. @@ -3200,7 +3647,15 @@ func (c *Client4) GetPost(postId string, etag string) (*Post, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return PostFromJson(r.Body), BuildResponse(r), nil + + var post Post + if r.StatusCode == http.StatusNotModified { + return &post, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { + return nil, nil, NewAppError("GetPost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &post, BuildResponse(r), nil } // DeletePost deletes a post from the provided post id string. @@ -3224,7 +3679,14 @@ func (c *Client4) GetPostThread(postId string, etag string, collapsedThreads boo return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPostThread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetPostsForChannel gets a page of posts with an array for ordering for a channel. @@ -3238,7 +3700,14 @@ func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag s return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPostsForChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetFlaggedPostsForUser returns flagged posts of a user based on user id string. @@ -3249,7 +3718,14 @@ func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) ( return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetFlaggedPostsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetFlaggedPostsForUserInTeam returns flagged posts in team of a user based on user id string. @@ -3264,7 +3740,14 @@ func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, pag return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetFlaggedPostsForUserInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetFlaggedPostsForUserInChannel returns flagged posts in channel of a user based on user id string. @@ -3279,7 +3762,14 @@ func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId strin return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetFlaggedPostsForUserInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetPostsSince gets posts created after a specified time as Unix time in milliseconds. @@ -3293,7 +3783,14 @@ func (c *Client4) GetPostsSince(channelId string, time int64, collapsedThreads b return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPostsSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetPostsAfter gets a page of posts that were posted after the post provided. @@ -3307,7 +3804,14 @@ func (c *Client4) GetPostsAfter(channelId, postId string, page, perPage int, eta return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPostsAfter", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetPostsBefore gets a page of posts that were posted before the post provided. @@ -3321,7 +3825,14 @@ func (c *Client4) GetPostsBefore(channelId, postId string, page, perPage int, et return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPostsBefore", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // GetPostsAroundLastUnread gets a list of posts around last unread post by a user in a channel. @@ -3335,7 +3846,14 @@ func (c *Client4) GetPostsAroundLastUnread(userId, channelId string, limitBefore return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPostsAroundLastUnread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // SearchFiles returns any posts with matching terms string. @@ -3349,12 +3867,21 @@ func (c *Client4) SearchFiles(teamId string, terms string, isOrSearch bool) (*Fi // SearchFilesWithParams returns any posts with matching terms string. func (c *Client4) SearchFilesWithParams(teamId string, params *SearchParameter) (*FileInfoList, *Response, error) { - r, err := c.DoAPIPost(c.teamRoute(teamId)+"/files/search", params.SearchParameterToJson()) + js, jsonErr := json.Marshal(params) + if jsonErr != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.teamRoute(teamId)+"/files/search", string(js)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return FileInfoListFromJson(r.Body), BuildResponse(r), nil + + var list FileInfoList + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // SearchPosts returns any posts with matching terms string. @@ -3368,23 +3895,38 @@ func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*Po // SearchPostsWithParams returns any posts with matching terms string. func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) (*PostList, *Response, error) { - r, err := c.DoAPIPost(c.teamRoute(teamId)+"/posts/search", params.SearchParameterToJson()) + js, jsonErr := json.Marshal(params) + if jsonErr != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPost(c.teamRoute(teamId)+"/posts/search", string(js)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return PostListFromJson(r.Body), BuildResponse(r), nil + var list PostList + if r.StatusCode == http.StatusNotModified { + return &list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &list, BuildResponse(r), nil } // SearchPostsWithMatches returns any posts with matching terms string, including. func (c *Client4) SearchPostsWithMatches(teamId string, terms string, isOrSearch bool) (*PostSearchResults, *Response, error) { requestBody := map[string]interface{}{"terms": terms, "is_or_search": isOrSearch} - r, err := c.DoAPIPost(c.teamRoute(teamId)+"/posts/search", StringInterfaceToJson(requestBody)) + r, err := c.DoAPIPost(c.teamRoute(teamId)+"/posts/search", StringInterfaceToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return PostSearchResultsFromJson(r.Body), BuildResponse(r), nil + var psr PostSearchResults + if jsonErr := json.NewDecoder(r.Body).Decode(&psr); jsonErr != nil { + return nil, nil, NewAppError("SearchPostsWithMatches", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &psr, BuildResponse(r), nil } // DoPostAction performs a post action. @@ -3549,7 +4091,7 @@ func (c *Client4) GetFileLink(fileId string) (string, *Response, error) { return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["link"], BuildResponse(r), nil + return MapFromJSON(r.Body)["link"], BuildResponse(r), nil } // GetFilePreview gets the bytes for a file by id. @@ -3589,7 +4131,12 @@ func (c *Client4) GetFileInfo(fileId string) (*FileInfo, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return FileInfoFromJson(r.Body), BuildResponse(r), nil + + var fi FileInfo + if jsonErr := json.NewDecoder(r.Body).Decode(&fi); jsonErr != nil { + return nil, nil, NewAppError("GetFileInfo", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &fi, BuildResponse(r), nil } // GetFileInfosForPost gets all the file info objects attached to a post. @@ -3599,7 +4146,15 @@ func (c *Client4) GetFileInfosForPost(postId string, etag string) ([]*FileInfo, return nil, BuildResponse(r), err } defer closeBody(r) - return FileInfosFromJson(r.Body), BuildResponse(r), nil + + var list []*FileInfo + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetFileInfosForPost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // General/System Section @@ -3630,7 +4185,7 @@ func (c *Client4) GetPing() (string, *Response, error) { return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["status"], BuildResponse(r), nil + return MapFromJSON(r.Body)["status"], BuildResponse(r), nil } // GetPingWithServerStatus will return ok if several basic server health checks @@ -3645,7 +4200,7 @@ func (c *Client4) GetPingWithServerStatus() (string, *Response, error) { return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["status"], BuildResponse(r), nil + return MapFromJSON(r.Body)["status"], BuildResponse(r), nil } // GetPingWithFullServerStatus will return the full status if several basic server @@ -3660,7 +4215,7 @@ func (c *Client4) GetPingWithFullServerStatus() (map[string]string, *Response, e return nil, BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body), BuildResponse(r), nil + return MapFromJSON(r.Body), BuildResponse(r), nil } // TestEmail will attempt to connect to the configured SMTP server. @@ -3681,7 +4236,7 @@ func (c *Client4) TestEmail(config *Config) (*Response, error) { func (c *Client4) TestSiteURL(siteURL string) (*Response, error) { requestBody := make(map[string]string) requestBody["site_url"] = siteURL - r, err := c.DoAPIPost(c.testSiteURLRoute(), MapToJson(requestBody)) + r, err := c.DoAPIPost(c.testSiteURLRoute(), MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -3710,7 +4265,7 @@ func (c *Client4) GetConfig() (*Config, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ConfigFromJson(r.Body), BuildResponse(r), nil + return ConfigFromJSON(r.Body), BuildResponse(r), nil } // ReloadConfig will reload the server configuration. @@ -3731,7 +4286,7 @@ func (c *Client4) GetOldClientConfig(etag string) (map[string]string, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body), BuildResponse(r), nil + return MapFromJSON(r.Body), BuildResponse(r), nil } // GetEnvironmentConfig will retrieve a map mirroring the server configuration where fields @@ -3743,7 +4298,7 @@ func (c *Client4) GetEnvironmentConfig() (map[string]interface{}, *Response, err return nil, BuildResponse(r), err } defer closeBody(r) - return StringInterfaceFromJson(r.Body), BuildResponse(r), nil + return StringInterfaceFromJSON(r.Body), BuildResponse(r), nil } // GetOldClientLicense will retrieve the parts of the server license needed by the @@ -3754,7 +4309,7 @@ func (c *Client4) GetOldClientLicense(etag string) (map[string]string, *Response return nil, BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body), BuildResponse(r), nil + return MapFromJSON(r.Body), BuildResponse(r), nil } // DatabaseRecycle will recycle the connections. Discard current connection and get new one. @@ -3788,7 +4343,7 @@ func (c *Client4) UpdateConfig(config *Config) (*Config, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ConfigFromJson(r.Body), BuildResponse(r), nil + return ConfigFromJSON(r.Body), BuildResponse(r), nil } // MigrateConfig will migrate existing config to the new one. @@ -3796,7 +4351,7 @@ func (c *Client4) MigrateConfig(from, to string) (*Response, error) { m := make(map[string]string, 2) m["from"] = from m["to"] = to - r, err := c.DoAPIPost(c.configRoute()+"/migrate", MapToJson(m)) + r, err := c.DoAPIPost(c.configRoute()+"/migrate", MapToJSON(m)) if err != nil { return BuildResponse(r), err } @@ -3839,7 +4394,7 @@ func (c *Client4) UploadLicenseFile(data []byte) (*Response, error) { defer closeBody(rp) if rp.StatusCode >= 300 { - return BuildResponse(rp), AppErrorFromJson(rp.Body) + return BuildResponse(rp), AppErrorFromJSON(rp.Body) } return BuildResponse(rp), nil @@ -3889,7 +4444,12 @@ func (c *Client4) CreateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook return nil, BuildResponse(r), err } defer closeBody(r) - return IncomingWebhookFromJson(r.Body), BuildResponse(r), nil + + var iw IncomingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&iw); jsonErr != nil { + return nil, nil, NewAppError("CreateIncomingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &iw, BuildResponse(r), nil } // UpdateIncomingWebhook updates an incoming webhook for a channel. @@ -3903,7 +4463,12 @@ func (c *Client4) UpdateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook return nil, BuildResponse(r), err } defer closeBody(r) - return IncomingWebhookFromJson(r.Body), BuildResponse(r), nil + + var iw IncomingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&iw); jsonErr != nil { + return nil, nil, NewAppError("UpdateIncomingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &iw, BuildResponse(r), nil } // GetIncomingWebhooks returns a page of incoming webhooks on the system. Page counting starts at 0. @@ -3914,7 +4479,14 @@ func (c *Client4) GetIncomingWebhooks(page int, perPage int, etag string) ([]*In return nil, BuildResponse(r), err } defer closeBody(r) - return IncomingWebhookListFromJson(r.Body), BuildResponse(r), nil + var iwl []*IncomingWebhook + if r.StatusCode == http.StatusNotModified { + return iwl, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&iwl); jsonErr != nil { + return nil, nil, NewAppError("GetIncomingWebhooks", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return iwl, BuildResponse(r), nil } // GetIncomingWebhooksForTeam returns a page of incoming webhooks for a team. Page counting starts at 0. @@ -3925,7 +4497,14 @@ func (c *Client4) GetIncomingWebhooksForTeam(teamId string, page int, perPage in return nil, BuildResponse(r), err } defer closeBody(r) - return IncomingWebhookListFromJson(r.Body), BuildResponse(r), nil + var iwl []*IncomingWebhook + if r.StatusCode == http.StatusNotModified { + return iwl, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&iwl); jsonErr != nil { + return nil, nil, NewAppError("GetIncomingWebhooksForTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return iwl, BuildResponse(r), nil } // GetIncomingWebhook returns an Incoming webhook given the hook ID. @@ -3935,7 +4514,14 @@ func (c *Client4) GetIncomingWebhook(hookID string, etag string) (*IncomingWebho return nil, BuildResponse(r), err } defer closeBody(r) - return IncomingWebhookFromJson(r.Body), BuildResponse(r), nil + var iw IncomingWebhook + if r.StatusCode == http.StatusNotModified { + return &iw, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&iw); jsonErr != nil { + return nil, nil, NewAppError("GetIncomingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &iw, BuildResponse(r), nil } // DeleteIncomingWebhook deletes and Incoming Webhook given the hook ID. @@ -3959,7 +4545,11 @@ func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookFromJson(r.Body), BuildResponse(r), nil + var ow OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { + return nil, nil, NewAppError("CreateOutgoingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &ow, BuildResponse(r), nil } // UpdateOutgoingWebhook creates an outgoing webhook for a team or channel. @@ -3973,7 +4563,11 @@ func (c *Client4) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookFromJson(r.Body), BuildResponse(r), nil + var ow OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { + return nil, nil, NewAppError("UpdateOutgoingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &ow, BuildResponse(r), nil } // GetOutgoingWebhooks returns a page of outgoing webhooks on the system. Page counting starts at 0. @@ -3984,7 +4578,14 @@ func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*Ou return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookListFromJson(r.Body), BuildResponse(r), nil + var owl []*OutgoingWebhook + if r.StatusCode == http.StatusNotModified { + return owl, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&owl); jsonErr != nil { + return nil, nil, NewAppError("GetOutgoingWebhooks", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return owl, BuildResponse(r), nil } // GetOutgoingWebhook outgoing webhooks on the system requested by Hook Id. @@ -3994,7 +4595,11 @@ func (c *Client4) GetOutgoingWebhook(hookId string) (*OutgoingWebhook, *Response return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookFromJson(r.Body), BuildResponse(r), nil + var ow OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { + return nil, nil, NewAppError("GetOutgoingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &ow, BuildResponse(r), nil } // GetOutgoingWebhooksForChannel returns a page of outgoing webhooks for a channel. Page counting starts at 0. @@ -4005,7 +4610,14 @@ func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perP return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookListFromJson(r.Body), BuildResponse(r), nil + var owl []*OutgoingWebhook + if r.StatusCode == http.StatusNotModified { + return owl, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&owl); jsonErr != nil { + return nil, nil, NewAppError("GetOutgoingWebhooksForChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return owl, BuildResponse(r), nil } // GetOutgoingWebhooksForTeam returns a page of outgoing webhooks for a team. Page counting starts at 0. @@ -4016,7 +4628,14 @@ func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage in return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookListFromJson(r.Body), BuildResponse(r), nil + var owl []*OutgoingWebhook + if r.StatusCode == http.StatusNotModified { + return owl, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&owl); jsonErr != nil { + return nil, nil, NewAppError("GetOutgoingWebhooksForTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return owl, BuildResponse(r), nil } // RegenOutgoingHookToken regenerate the outgoing webhook token. @@ -4026,7 +4645,11 @@ func (c *Client4) RegenOutgoingHookToken(hookId string) (*OutgoingWebhook, *Resp return nil, BuildResponse(r), err } defer closeBody(r) - return OutgoingWebhookFromJson(r.Body), BuildResponse(r), nil + var ow OutgoingWebhook + if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { + return nil, nil, NewAppError("RegenOutgoingHookToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &ow, BuildResponse(r), nil } // DeleteOutgoingWebhook delete the outgoing webhook on the system requested by Hook Id. @@ -4048,8 +4671,12 @@ func (c *Client4) GetPreferences(userId string) (Preferences, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - preferences, _ := PreferencesFromJson(r.Body) - return preferences, BuildResponse(r), nil + + var prefs Preferences + if jsonErr := json.NewDecoder(r.Body).Decode(&prefs); jsonErr != nil { + return nil, nil, NewAppError("GetPreferences", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return prefs, BuildResponse(r), nil } // UpdatePreferences saves the user's preferences. @@ -4088,8 +4715,11 @@ func (c *Client4) GetPreferencesByCategory(userId string, category string) (Pref return nil, BuildResponse(r), err } defer closeBody(r) - preferences, _ := PreferencesFromJson(r.Body) - return preferences, BuildResponse(r), nil + var prefs Preferences + if jsonErr := json.NewDecoder(r.Body).Decode(&prefs); jsonErr != nil { + return nil, nil, NewAppError("GetPreferencesByCategory", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return prefs, BuildResponse(r), nil } // GetPreferenceByCategoryAndName returns the user's preferences from the provided category and preference name string. @@ -4100,7 +4730,12 @@ func (c *Client4) GetPreferenceByCategoryAndName(userId string, category string, return nil, BuildResponse(r), err } defer closeBody(r) - return PreferenceFromJson(r.Body), BuildResponse(r), nil + + var pref Preference + if jsonErr := json.NewDecoder(r.Body).Decode(&pref); jsonErr != nil { + return nil, nil, NewAppError("GetPreferenceByCategoryAndName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &pref, BuildResponse(r), nil } // SAML Section @@ -4215,19 +4850,28 @@ func (c *Client4) GetSamlCertificateStatus() (*SamlCertificateStatus, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return SamlCertificateStatusFromJson(r.Body), BuildResponse(r), nil + + var status SamlCertificateStatus + if jsonErr := json.NewDecoder(r.Body).Decode(&status); jsonErr != nil { + return nil, nil, NewAppError("GetSamlCertificateStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &status, BuildResponse(r), nil } func (c *Client4) GetSamlMetadataFromIdp(samlMetadataURL string) (*SamlMetadataResponse, *Response, error) { requestBody := make(map[string]string) requestBody["saml_metadata_url"] = samlMetadataURL - r, err := c.DoAPIPost(c.samlRoute()+"/metadatafromidp", MapToJson(requestBody)) + r, err := c.DoAPIPost(c.samlRoute()+"/metadatafromidp", MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return SamlMetadataResponseFromJson(r.Body), BuildResponse(r), nil + var resp SamlMetadataResponse + if jsonErr := json.NewDecoder(r.Body).Decode(&resp); jsonErr != nil { + return nil, nil, NewAppError("GetSamlMetadataFromIdp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &resp, BuildResponse(r), nil } // ResetSamlAuthDataToEmail resets the AuthData field of SAML users to their Email. @@ -4264,7 +4908,11 @@ func (c *Client4) CreateComplianceReport(report *Compliance) (*Compliance, *Resp return nil, BuildResponse(r), err } defer closeBody(r) - return ComplianceFromJson(r.Body), BuildResponse(r), nil + var comp Compliance + if jsonErr := json.NewDecoder(r.Body).Decode(&comp); jsonErr != nil { + return nil, nil, NewAppError("CreateComplianceReport", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &comp, BuildResponse(r), nil } // GetComplianceReports returns list of compliance reports. @@ -4275,7 +4923,11 @@ func (c *Client4) GetComplianceReports(page, perPage int) (Compliances, *Respons return nil, BuildResponse(r), err } defer closeBody(r) - return CompliancesFromJson(r.Body), BuildResponse(r), nil + var comp Compliances + if jsonErr := json.NewDecoder(r.Body).Decode(&comp); jsonErr != nil { + return nil, nil, NewAppError("GetComplianceReports", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return comp, BuildResponse(r), nil } // GetComplianceReport returns a compliance report. @@ -4285,7 +4937,11 @@ func (c *Client4) GetComplianceReport(reportId string) (*Compliance, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return ComplianceFromJson(r.Body), BuildResponse(r), nil + var comp Compliance + if jsonErr := json.NewDecoder(r.Body).Decode(&comp); jsonErr != nil { + return nil, nil, NewAppError("GetComplianceReport", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &comp, BuildResponse(r), nil } // DownloadComplianceReport returns a full compliance report as a file. @@ -4306,7 +4962,7 @@ func (c *Client4) DownloadComplianceReport(reportId string) ([]byte, *Response, defer closeBody(rp) if rp.StatusCode >= 300 { - return nil, BuildResponse(rp), AppErrorFromJson(rp.Body) + return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } data, err := ioutil.ReadAll(rp.Body) @@ -4326,7 +4982,11 @@ func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ClusterInfosFromJson(r.Body), BuildResponse(r), nil + var list []*ClusterInfo + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetClusterStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // LDAP Section @@ -4391,7 +5051,11 @@ func (c *Client4) LinkLdapGroup(dn string) (*Group, *Response, error) { } defer closeBody(r) - return GroupFromJson(r.Body), BuildResponse(r), nil + var g Group + if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { + return nil, nil, NewAppError("LinkLdapGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &g, BuildResponse(r), nil } // UnlinkLdapGroup deletes the Mattermost group associated with the given LDAP group DN. @@ -4404,12 +5068,16 @@ func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response, error) { } defer closeBody(r) - return GroupFromJson(r.Body), BuildResponse(r), nil + var g Group + if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { + return nil, nil, NewAppError("UnlinkLdapGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &g, BuildResponse(r), nil } // MigrateIdLdap migrates the LDAP enabled users to given attribute func (c *Client4) MigrateIdLdap(toAttribute string) (*Response, error) { - r, err := c.DoAPIPost(c.ldapRoute()+"/migrateid", MapToJson(map[string]string{ + r, err := c.DoAPIPost(c.ldapRoute()+"/migrateid", MapToJSON(map[string]string{ "toAttribute": toAttribute, })) if err != nil { @@ -4511,7 +5179,11 @@ func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response, error) { } defer closeBody(r) - return GroupsFromJson(r.Body), BuildResponse(r), nil + var list []*Group + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetGroups", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetGroupsByUserId retrieves Mattermost Groups for a user @@ -4527,11 +5199,15 @@ func (c *Client4) GetGroupsByUserId(userId string) ([]*Group, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return GroupsFromJson(r.Body), BuildResponse(r), nil + var list []*Group + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetGroupsByUserId", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } func (c *Client4) MigrateAuthToLdap(fromAuthService string, matchField string, force bool) (*Response, error) { - r, err := c.DoAPIPost(c.usersRoute()+"/migrate_auth/ldap", StringInterfaceToJson(map[string]interface{}{ + r, err := c.DoAPIPost(c.usersRoute()+"/migrate_auth/ldap", StringInterfaceToJSON(map[string]interface{}{ "from": fromAuthService, "force": force, "match_field": matchField, @@ -4544,7 +5220,7 @@ func (c *Client4) MigrateAuthToLdap(fromAuthService string, matchField string, f } func (c *Client4) MigrateAuthToSaml(fromAuthService string, usersMap map[string]string, auto bool) (*Response, error) { - r, err := c.DoAPIPost(c.usersRoute()+"/migrate_auth/saml", StringInterfaceToJson(map[string]interface{}{ + r, err := c.DoAPIPost(c.usersRoute()+"/migrate_auth/saml", StringInterfaceToJSON(map[string]interface{}{ "from": fromAuthService, "auto": auto, "matches": usersMap, @@ -4628,7 +5304,7 @@ func (c *Client4) GetBrandImage() ([]byte, *Response, error) { defer closeBody(r) if r.StatusCode >= 300 { - return nil, BuildResponse(r), AppErrorFromJson(r.Body) + return nil, BuildResponse(r), AppErrorFromJSON(r.Body) } data, err := ioutil.ReadAll(r.Body) @@ -4683,7 +5359,7 @@ func (c *Client4) UploadBrandImage(data []byte) (*Response, error) { defer closeBody(rp) if rp.StatusCode >= 300 { - return BuildResponse(rp), AppErrorFromJson(rp.Body) + return BuildResponse(rp), AppErrorFromJSON(rp.Body) } return BuildResponse(rp), nil @@ -4699,19 +5375,19 @@ func (c *Client4) GetLogs(page, perPage int) ([]string, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ArrayFromJson(r.Body), BuildResponse(r), nil + return ArrayFromJSON(r.Body), BuildResponse(r), nil } // PostLog is a convenience Web Service call so clients can log messages into // the server-side logs. For example we typically log javascript error messages // into the server-side. It returns the log message if the logging was successful. func (c *Client4) PostLog(message map[string]string) (map[string]string, *Response, error) { - r, err := c.DoAPIPost("/logs", MapToJson(message)) + r, err := c.DoAPIPost("/logs", MapToJSON(message)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body), BuildResponse(r), nil + return MapFromJSON(r.Body), BuildResponse(r), nil } // OAuth Section @@ -4727,7 +5403,12 @@ func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppFromJson(r.Body), BuildResponse(r), nil + + var oapp OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { + return nil, nil, NewAppError("CreateOAuthApp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &oapp, BuildResponse(r), nil } // UpdateOAuthApp updates a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider. @@ -4741,7 +5422,11 @@ func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppFromJson(r.Body), BuildResponse(r), nil + var oapp OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { + return nil, nil, NewAppError("UpdateOAuthApp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &oapp, BuildResponse(r), nil } // GetOAuthApps gets a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider. @@ -4752,7 +5437,11 @@ func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response, error return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppListFromJson(r.Body), BuildResponse(r), nil + var list []*OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetOAuthApps", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetOAuthApp gets a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. @@ -4762,7 +5451,11 @@ func (c *Client4) GetOAuthApp(appId string) (*OAuthApp, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppFromJson(r.Body), BuildResponse(r), nil + var oapp OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { + return nil, nil, NewAppError("GetOAuthApp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &oapp, BuildResponse(r), nil } // GetOAuthAppInfo gets a sanitized version of a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. @@ -4772,7 +5465,11 @@ func (c *Client4) GetOAuthAppInfo(appId string) (*OAuthApp, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppFromJson(r.Body), BuildResponse(r), nil + var oapp OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { + return nil, nil, NewAppError("GetOAuthAppInfo", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &oapp, BuildResponse(r), nil } // DeleteOAuthApp deletes a registered OAuth 2.0 client application. @@ -4792,7 +5489,11 @@ func (c *Client4) RegenerateOAuthAppSecret(appId string) (*OAuthApp, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppFromJson(r.Body), BuildResponse(r), nil + var oapp OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { + return nil, nil, NewAppError("RegenerateOAuthAppSecret", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &oapp, BuildResponse(r), nil } // GetAuthorizedOAuthAppsForUser gets a page of OAuth 2.0 client applications the user has authorized to use access their account. @@ -4803,7 +5504,11 @@ func (c *Client4) GetAuthorizedOAuthAppsForUser(userId string, page, perPage int return nil, BuildResponse(r), err } defer closeBody(r) - return OAuthAppListFromJson(r.Body), BuildResponse(r), nil + var list []*OAuthApp + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetAuthorizedOAuthAppsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // AuthorizeOAuthApp will authorize an OAuth 2.0 client application to access a user's account and provide a redirect link to follow. @@ -4817,13 +5522,13 @@ func (c *Client4) AuthorizeOAuthApp(authRequest *AuthorizeRequest) (string, *Res return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["redirect"], BuildResponse(r), nil + return MapFromJSON(r.Body)["redirect"], BuildResponse(r), nil } // DeauthorizeOAuthApp will deauthorize an OAuth 2.0 client application from accessing a user's account. func (c *Client4) DeauthorizeOAuthApp(appId string) (*Response, error) { requestData := map[string]string{"client_id": appId} - r, err := c.DoAPIRequest(http.MethodPost, c.URL+"/oauth/deauthorize", MapToJson(requestData), "") + r, err := c.DoAPIRequest(http.MethodPost, c.URL+"/oauth/deauthorize", MapToJSON(requestData), "") if err != nil { return BuildResponse(r), err } @@ -4851,7 +5556,7 @@ func (c *Client4) GetOAuthAccessToken(data url.Values) (*AccessResponse, *Respon defer closeBody(rp) if rp.StatusCode >= 300 { - return nil, BuildResponse(rp), AppErrorFromJson(rp.Body) + return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } var ar *AccessResponse @@ -4907,7 +5612,11 @@ func (c *Client4) GetDataRetentionPolicy() (*GlobalRetentionPolicy, *Response, e return nil, BuildResponse(r), err } defer closeBody(r) - return GlobalRetentionPolicyFromJson(r.Body), BuildResponse(r), nil + var p GlobalRetentionPolicy + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("GetDataRetentionPolicy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &p, BuildResponse(r), nil } // GetDataRetentionPolicyByID will get the details for the granular data retention policy with the specified ID. @@ -4917,11 +5626,12 @@ func (c *Client4) GetDataRetentionPolicyByID(policyID string) (*RetentionPolicyW return nil, BuildResponse(r), err } defer closeBody(r) - policy, err := RetentionPolicyWithTeamAndChannelCountsFromJson(r.Body) - if err != nil { - return nil, BuildResponse(r), NewAppError("Client4.GetDataRetentionPolicyByID", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode) + + var p RetentionPolicyWithTeamAndChannelCounts + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("GetDataRetentionPolicyByID", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) } - return policy, BuildResponse(r), nil + return &p, BuildResponse(r), nil } // GetDataRetentionPoliciesCount will get the total number of granular data retention policies. @@ -4949,26 +5659,31 @@ func (c *Client4) GetDataRetentionPolicies(page, perPage int) (*RetentionPolicyW return nil, BuildResponse(r), err } defer closeBody(r) - policies, err := RetentionPolicyWithTeamAndChannelCountsListFromJson(r.Body) - if err != nil { - return nil, BuildResponse(r), NewAppError("Client4.GetDataRetentionPolicies", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode) + + var p RetentionPolicyWithTeamAndChannelCountsList + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("GetDataRetentionPolicies", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) } - return policies, BuildResponse(r), nil + return &p, BuildResponse(r), nil } // CreateDataRetentionPolicy will create a new granular data retention policy which will be applied to // the specified teams and channels. The Id field of `policy` must be empty. func (c *Client4) CreateDataRetentionPolicy(policy *RetentionPolicyWithTeamAndChannelIDs) (*RetentionPolicyWithTeamAndChannelCounts, *Response, error) { - r, err := c.DoAPIPostBytes(c.dataRetentionRoute()+"/policies", policy.ToJson()) + policyJSON, jsonErr := json.Marshal(policy) + if jsonErr != nil { + return nil, nil, NewAppError("CreateDataRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPostBytes(c.dataRetentionRoute()+"/policies", policyJSON) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - newPolicy, err := RetentionPolicyWithTeamAndChannelCountsFromJson(r.Body) - if err != nil { - return nil, BuildResponse(r), NewAppError("Client4.CreateDataRetentionPolicy", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode) + var p RetentionPolicyWithTeamAndChannelCounts + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("CreateDataRetentionPolicy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) } - return newPolicy, BuildResponse(r), nil + return &p, BuildResponse(r), nil } // DeleteDataRetentionPolicy will delete the granular data retention policy with the specified ID. @@ -4984,16 +5699,20 @@ func (c *Client4) DeleteDataRetentionPolicy(policyID string) (*Response, error) // PatchDataRetentionPolicy will patch the granular data retention policy with the specified ID. // The Id field of `patch` must be non-empty. func (c *Client4) PatchDataRetentionPolicy(patch *RetentionPolicyWithTeamAndChannelIDs) (*RetentionPolicyWithTeamAndChannelCounts, *Response, error) { - r, err := c.DoAPIPatchBytes(c.dataRetentionPolicyRoute(patch.ID), patch.ToJson()) + patchJSON, jsonErr := json.Marshal(patch) + if jsonErr != nil { + return nil, nil, NewAppError("PatchDataRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + r, err := c.DoAPIPatchBytes(c.dataRetentionPolicyRoute(patch.ID), patchJSON) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - policy, err := RetentionPolicyWithTeamAndChannelCountsFromJson(r.Body) - if err != nil { - return nil, BuildResponse(r), NewAppError("Client4.PatchDataRetentionPolicy", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode) + var p RetentionPolicyWithTeamAndChannelCounts + if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { + return nil, nil, NewAppError("PatchDataRetentionPolicy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) } - return policy, BuildResponse(r), nil + return &p, BuildResponse(r), nil } // GetTeamsForRetentionPolicy will get the teams to which the specified policy is currently applied. @@ -5145,7 +5864,12 @@ func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return CommandFromJson(r.Body), BuildResponse(r), nil + + var command Command + if jsonErr := json.NewDecoder(r.Body).Decode(&command); jsonErr != nil { + return nil, nil, NewAppError("CreateCommand", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &command, BuildResponse(r), nil } // UpdateCommand updates a command based on the provided Command struct. @@ -5159,7 +5883,11 @@ func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return CommandFromJson(r.Body), BuildResponse(r), nil + var command Command + if jsonErr := json.NewDecoder(r.Body).Decode(&command); jsonErr != nil { + return nil, nil, NewAppError("UpdateCommand", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &command, BuildResponse(r), nil } // MoveCommand moves a command to a different team. @@ -5195,7 +5923,12 @@ func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Res return nil, BuildResponse(r), err } defer closeBody(r) - return CommandListFromJson(r.Body), BuildResponse(r), nil + + var list []*Command + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("ListCommands", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // ListCommandAutocompleteSuggestions will retrieve a list of suggestions for a userInput. @@ -5206,7 +5939,11 @@ func (c *Client4) ListCommandAutocompleteSuggestions(userInput, teamId string) ( return nil, BuildResponse(r), err } defer closeBody(r) - return AutocompleteSuggestionsFromJSON(r.Body), BuildResponse(r), nil + var list []AutocompleteSuggestion + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("ListCommandAutocompleteSuggestions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetCommandById will retrieve a command by id. @@ -5217,7 +5954,11 @@ func (c *Client4) GetCommandById(cmdId string) (*Command, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return CommandFromJson(r.Body), BuildResponse(r), nil + var command Command + if jsonErr := json.NewDecoder(r.Body).Decode(&command); jsonErr != nil { + return nil, nil, NewAppError("GetCommandById", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &command, BuildResponse(r), nil } // ExecuteCommand executes a given slash command. @@ -5236,7 +5977,7 @@ func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, * } defer closeBody(r) - response, err := CommandResponseFromJson(r.Body) + response, err := CommandResponseFromJSON(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("ExecuteCommand", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } @@ -5261,7 +6002,7 @@ func (c *Client4) ExecuteCommandWithTeam(channelId, teamId, command string) (*Co } defer closeBody(r) - response, err := CommandResponseFromJson(r.Body) + response, err := CommandResponseFromJSON(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("ExecuteCommandWithTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } @@ -5275,7 +6016,11 @@ func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response return nil, BuildResponse(r), err } defer closeBody(r) - return CommandListFromJson(r.Body), BuildResponse(r), nil + var list []*Command + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("ListAutocompleteCommands", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // RegenCommandToken will create a new token if the user have the right permissions. @@ -5285,7 +6030,7 @@ func (c *Client4) RegenCommandToken(commandId string) (string, *Response, error) return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["token"], BuildResponse(r), nil + return MapFromJSON(r.Body)["token"], BuildResponse(r), nil } // Status Section @@ -5297,17 +6042,28 @@ func (c *Client4) GetUserStatus(userId, etag string) (*Status, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return StatusFromJson(r.Body), BuildResponse(r), nil + var s Status + if r.StatusCode == http.StatusNotModified { + return &s, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("GetUserStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } // GetUsersStatusesByIds returns a list of users status based on the provided user ids. func (c *Client4) GetUsersStatusesByIds(userIds []string) ([]*Status, *Response, error) { - r, err := c.DoAPIPost(c.userStatusesRoute()+"/ids", ArrayToJson(userIds)) + r, err := c.DoAPIPost(c.userStatusesRoute()+"/ids", ArrayToJSON(userIds)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return StatusListFromJson(r.Body), BuildResponse(r), nil + var list []*Status + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUsersStatusesByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // UpdateUserStatus sets a user's status based on the provided user id string. @@ -5321,7 +6077,11 @@ func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status, return nil, BuildResponse(r), err } defer closeBody(r) - return StatusFromJson(r.Body), BuildResponse(r), nil + var s Status + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("UpdateUserStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } // Emoji Section @@ -5342,7 +6102,12 @@ func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emo return nil, nil, err } - if err := writer.WriteField("emoji", emoji.ToJson()); err != nil { + emojiJSON, jsonErr := json.Marshal(emoji) + if jsonErr != nil { + return nil, nil, NewAppError("CreateEmoji", "api.marshal_error", nil, jsonErr.Error(), 0) + } + + if err := writer.WriteField("emoji", string(emojiJSON)); err != nil { return nil, nil, err } @@ -5361,7 +6126,12 @@ func (c *Client4) GetEmojiList(page, perPage int) ([]*Emoji, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return EmojiListFromJson(r.Body), BuildResponse(r), nil + + var list []*Emoji + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetEmojiList", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetSortedEmojiList returns a page of custom emoji on the system sorted based on the sort @@ -5373,7 +6143,11 @@ func (c *Client4) GetSortedEmojiList(page, perPage int, sort string) ([]*Emoji, return nil, BuildResponse(r), err } defer closeBody(r) - return EmojiListFromJson(r.Body), BuildResponse(r), nil + var list []*Emoji + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetSortedEmojiList", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // DeleteEmoji delete an custom emoji on the provided emoji id string. @@ -5393,7 +6167,11 @@ func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return EmojiFromJson(r.Body), BuildResponse(r), nil + var e Emoji + if jsonErr := json.NewDecoder(r.Body).Decode(&e); jsonErr != nil { + return nil, nil, NewAppError("GetEmoji", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &e, BuildResponse(r), nil } // GetEmojiByName returns a custom emoji based on the name string. @@ -5403,7 +6181,11 @@ func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return EmojiFromJson(r.Body), BuildResponse(r), nil + var e Emoji + if jsonErr := json.NewDecoder(r.Body).Decode(&e); jsonErr != nil { + return nil, nil, NewAppError("GetEmojiByName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &e, BuildResponse(r), nil } // GetEmojiImage returns the emoji image. @@ -5433,7 +6215,11 @@ func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return EmojiListFromJson(r.Body), BuildResponse(r), nil + var list []*Emoji + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("SearchEmoji", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // AutocompleteEmoji returns a list of emoji starting with or matching name. @@ -5444,7 +6230,11 @@ func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Respon return nil, BuildResponse(r), err } defer closeBody(r) - return EmojiListFromJson(r.Body), BuildResponse(r), nil + var list []*Emoji + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("AutocompleteEmoji", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // Reaction Section @@ -5460,7 +6250,11 @@ func (c *Client4) SaveReaction(reaction *Reaction) (*Reaction, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return ReactionFromJson(r.Body), BuildResponse(r), nil + var re Reaction + if jsonErr := json.NewDecoder(r.Body).Decode(&re); jsonErr != nil { + return nil, nil, NewAppError("SaveReaction", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &re, BuildResponse(r), nil } // GetReactions returns a list of reactions to a post. @@ -5470,7 +6264,11 @@ func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ReactionsFromJson(r.Body), BuildResponse(r), nil + var list []*Reaction + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetReactions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // DeleteReaction deletes reaction of a user in a post. @@ -5485,12 +6283,16 @@ func (c *Client4) DeleteReaction(reaction *Reaction) (*Response, error) { // FetchBulkReactions returns a map of postIds and corresponding reactions func (c *Client4) GetBulkReactions(postIds []string) (map[string][]*Reaction, *Response, error) { - r, err := c.DoAPIPost(c.postsRoute()+"/ids/reactions", ArrayToJson(postIds)) + r, err := c.DoAPIPost(c.postsRoute()+"/ids/reactions", ArrayToJSON(postIds)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return MapPostIdToReactionsFromJson(r.Body), BuildResponse(r), nil + reactions := map[string][]*Reaction{} + if jsonErr := json.NewDecoder(r.Body).Decode(&reactions); jsonErr != nil { + return nil, nil, NewAppError("GetBulkReactions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return reactions, BuildResponse(r), nil } // Timezone Section @@ -5514,12 +6316,12 @@ func (c *Client4) OpenGraph(url string) (map[string]string, *Response, error) { requestBody := make(map[string]string) requestBody["url"] = url - r, err := c.DoAPIPost(c.openGraphRoute(), MapToJson(requestBody)) + r, err := c.DoAPIPost(c.openGraphRoute(), MapToJSON(requestBody)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body), BuildResponse(r), nil + return MapFromJSON(r.Body), BuildResponse(r), nil } // Jobs Section @@ -5531,7 +6333,11 @@ func (c *Client4) GetJob(id string) (*Job, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return JobFromJson(r.Body), BuildResponse(r), nil + var j Job + if jsonErr := json.NewDecoder(r.Body).Decode(&j); jsonErr != nil { + return nil, nil, NewAppError("GetJob", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &j, BuildResponse(r), nil } // GetJobs gets all jobs, sorted with the job that was created most recently first. @@ -5541,7 +6347,11 @@ func (c *Client4) GetJobs(page int, perPage int) ([]*Job, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return JobsFromJson(r.Body), BuildResponse(r), nil + var list []*Job + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetJobs", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetJobsByType gets all jobs of a given type, sorted with the job that was created most recently first. @@ -5551,7 +6361,11 @@ func (c *Client4) GetJobsByType(jobType string, page int, perPage int) ([]*Job, return nil, BuildResponse(r), err } defer closeBody(r) - return JobsFromJson(r.Body), BuildResponse(r), nil + var list []*Job + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetJobsByType", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // CreateJob creates a job based on the provided job struct. @@ -5565,7 +6379,11 @@ func (c *Client4) CreateJob(job *Job) (*Job, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return JobFromJson(r.Body), BuildResponse(r), nil + var j Job + if jsonErr := json.NewDecoder(r.Body).Decode(&j); jsonErr != nil { + return nil, nil, NewAppError("CreateJob", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &j, BuildResponse(r), nil } // CancelJob requests the cancellation of the job with the provided Id. @@ -5602,7 +6420,11 @@ func (c *Client4) GetRole(id string) (*Role, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return RoleFromJson(r.Body), BuildResponse(r), nil + var role Role + if jsonErr := json.NewDecoder(r.Body).Decode(&role); jsonErr != nil { + return nil, nil, NewAppError("GetRole", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &role, BuildResponse(r), nil } // GetRoleByName gets a single role by Name. @@ -5612,17 +6434,25 @@ func (c *Client4) GetRoleByName(name string) (*Role, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return RoleFromJson(r.Body), BuildResponse(r), nil + var role Role + if jsonErr := json.NewDecoder(r.Body).Decode(&role); jsonErr != nil { + return nil, nil, NewAppError("GetRoleByName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &role, BuildResponse(r), nil } // GetRolesByNames returns a list of roles based on the provided role names. func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response, error) { - r, err := c.DoAPIPost(c.rolesRoute()+"/names", ArrayToJson(roleNames)) + r, err := c.DoAPIPost(c.rolesRoute()+"/names", ArrayToJSON(roleNames)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return RoleListFromJson(r.Body), BuildResponse(r), nil + var list []*Role + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetRolesByNames", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // PatchRole partially updates a role in the system. Any missing fields are not updated. @@ -5636,7 +6466,11 @@ func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return RoleFromJson(r.Body), BuildResponse(r), nil + var role Role + if jsonErr := json.NewDecoder(r.Body).Decode(&role); jsonErr != nil { + return nil, nil, NewAppError("PatchRole", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &role, BuildResponse(r), nil } // Schemes Section @@ -5652,7 +6486,11 @@ func (c *Client4) CreateScheme(scheme *Scheme) (*Scheme, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return SchemeFromJson(r.Body), BuildResponse(r), nil + var s Scheme + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("CreateScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } // GetScheme gets a single scheme by ID. @@ -5662,17 +6500,25 @@ func (c *Client4) GetScheme(id string) (*Scheme, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return SchemeFromJson(r.Body), BuildResponse(r), nil + var s Scheme + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("GetScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } -// GetSchemes gets all schemes, sorted with the most recently created first, optionally filtered by scope. +// GetSchemes ets all schemes, sorted with the most recently created first, optionally filtered by scope. func (c *Client4) GetSchemes(scope string, page int, perPage int) ([]*Scheme, *Response, error) { r, err := c.DoAPIGet(c.schemesRoute()+fmt.Sprintf("?scope=%v&page=%v&per_page=%v", scope, page, perPage), "") if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return SchemesFromJson(r.Body), BuildResponse(r), nil + var list []*Scheme + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetSchemes", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // DeleteScheme deletes a single scheme by ID. @@ -5696,7 +6542,11 @@ func (c *Client4) PatchScheme(id string, patch *SchemePatch) (*Scheme, *Response return nil, BuildResponse(r), err } defer closeBody(r) - return SchemeFromJson(r.Body), BuildResponse(r), nil + var s Scheme + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("PatchScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } // GetTeamsForScheme gets the teams using this scheme, sorted alphabetically by display name. @@ -5706,7 +6556,11 @@ func (c *Client4) GetTeamsForScheme(schemeId string, page int, perPage int) ([]* return nil, BuildResponse(r), err } defer closeBody(r) - return TeamListFromJson(r.Body), BuildResponse(r), nil + var list []*Team + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetTeamsForScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // GetChannelsForScheme gets the channels using this scheme, sorted alphabetically by display name. @@ -5777,10 +6631,14 @@ func (c *Client4) uploadPlugin(file io.Reader, force bool) (*Manifest, *Response defer closeBody(rp) if rp.StatusCode >= 300 { - return nil, BuildResponse(rp), AppErrorFromJson(rp.Body) + return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } - return ManifestFromJson(rp.Body), BuildResponse(rp), nil + var m Manifest + if jsonErr := json.NewDecoder(rp.Body).Decode(&m); jsonErr != nil { + return nil, nil, NewAppError("uploadPlugin", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &m, BuildResponse(rp), nil } func (c *Client4) InstallPluginFromURL(downloadURL string, force bool) (*Manifest, *Response, error) { @@ -5792,21 +6650,31 @@ func (c *Client4) InstallPluginFromURL(downloadURL string, force bool) (*Manifes return nil, BuildResponse(r), err } defer closeBody(r) - return ManifestFromJson(r.Body), BuildResponse(r), nil + + var m Manifest + if jsonErr := json.NewDecoder(r.Body).Decode(&m); jsonErr != nil { + return nil, nil, NewAppError("InstallPluginFromUrl", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &m, BuildResponse(r), nil } // InstallMarketplacePlugin will install marketplace plugin. func (c *Client4) InstallMarketplacePlugin(request *InstallMarketplacePluginRequest) (*Manifest, *Response, error) { - json, err := request.ToJson() + buf, err := json.Marshal(request) if err != nil { - return nil, nil, err + return nil, nil, NewAppError("InstallMarketplacePlugin", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } - r, err := c.DoAPIPost(c.pluginsRoute()+"/marketplace", json) + r, err := c.DoAPIPost(c.pluginsRoute()+"/marketplace", string(buf)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return ManifestFromJson(r.Body), BuildResponse(r), nil + + var m Manifest + if jsonErr := json.NewDecoder(r.Body).Decode(&m); jsonErr != nil { + return nil, nil, NewAppError("InstallMarketplacePlugin", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &m, BuildResponse(r), nil } // GetPlugins will return a list of plugin manifests for currently active plugins. @@ -5816,7 +6684,12 @@ func (c *Client4) GetPlugins() (*PluginsResponse, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return PluginsResponseFromJson(r.Body), BuildResponse(r), nil + + var resp PluginsResponse + if jsonErr := json.NewDecoder(r.Body).Decode(&resp); jsonErr != nil { + return nil, nil, NewAppError("GetPlugins", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &resp, BuildResponse(r), nil } // GetPluginStatuses will return the plugins installed on any server in the cluster, for reporting @@ -5827,7 +6700,11 @@ func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return PluginStatusesFromJson(r.Body), BuildResponse(r), nil + var list PluginStatuses + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetPluginStatuses", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // RemovePlugin will disable and delete a plugin. @@ -5847,7 +6724,12 @@ func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ManifestListFromJson(r.Body), BuildResponse(r), nil + + var list []*Manifest + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetWebappPlugins", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // EnablePlugin will enable an plugin installed. @@ -5932,7 +6814,7 @@ func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response, return "", BuildResponse(r), err } defer closeBody(r) - return MapFromJson(r.Body)["location"], BuildResponse(r), nil + return MapFromJSON(r.Body)["location"], BuildResponse(r), nil } // SetServerBusy will mark the server as busy, which disables non-critical services for `secs` seconds. @@ -5965,15 +6847,18 @@ func (c *Client4) GetServerBusy() (*ServerBusyState, *Response, error) { } defer closeBody(r) - sbs := ServerBusyStateFromJson(r.Body) - return sbs, BuildResponse(r), nil + var sbs ServerBusyState + if jsonErr := json.NewDecoder(r.Body).Decode(&sbs); jsonErr != nil { + return nil, nil, NewAppError("GetServerBusy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &sbs, BuildResponse(r), nil } // RegisterTermsOfServiceAction saves action performed by a user against a specific terms of service. func (c *Client4) RegisterTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) (*Response, error) { url := c.userTermsOfServiceRoute(userId) data := map[string]interface{}{"termsOfServiceId": termsOfServiceId, "accepted": accepted} - r, err := c.DoAPIPost(url, StringInterfaceToJson(data)) + r, err := c.DoAPIPost(url, StringInterfaceToJSON(data)) if err != nil { return BuildResponse(r), err } @@ -5989,7 +6874,11 @@ func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response, er return nil, BuildResponse(r), err } defer closeBody(r) - return TermsOfServiceFromJson(r.Body), BuildResponse(r), nil + var tos TermsOfService + if jsonErr := json.NewDecoder(r.Body).Decode(&tos); jsonErr != nil { + return nil, nil, NewAppError("GetTermsOfService", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &tos, BuildResponse(r), nil } // GetUserTermsOfService fetches user's latest terms of service action if the latest action was for acceptance. @@ -6000,19 +6889,27 @@ func (c *Client4) GetUserTermsOfService(userId, etag string) (*UserTermsOfServic return nil, BuildResponse(r), err } defer closeBody(r) - return UserTermsOfServiceFromJson(r.Body), BuildResponse(r), nil + var u UserTermsOfService + if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { + return nil, nil, NewAppError("GetUserTermsOfService", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &u, BuildResponse(r), nil } // CreateTermsOfService creates new terms of service. func (c *Client4) CreateTermsOfService(text, userId string) (*TermsOfService, *Response, error) { url := c.termsOfServiceRoute() data := map[string]interface{}{"text": text} - r, err := c.DoAPIPost(url, StringInterfaceToJson(data)) + r, err := c.DoAPIPost(url, StringInterfaceToJSON(data)) if err != nil { return nil, BuildResponse(r), err } defer closeBody(r) - return TermsOfServiceFromJson(r.Body), BuildResponse(r), nil + var tos TermsOfService + if jsonErr := json.NewDecoder(r.Body).Decode(&tos); jsonErr != nil { + return nil, nil, NewAppError("CreateTermsOfService", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &tos, BuildResponse(r), nil } func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response, error) { @@ -6021,7 +6918,11 @@ func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return GroupFromJson(r.Body), BuildResponse(r), nil + var g Group + if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { + return nil, nil, NewAppError("GetGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &g, BuildResponse(r), nil } func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Response, error) { @@ -6031,7 +6932,11 @@ func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Respon return nil, BuildResponse(r), err } defer closeBody(r) - return GroupFromJson(r.Body), BuildResponse(r), nil + var g Group + if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { + return nil, nil, NewAppError("PatchGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &g, BuildResponse(r), nil } func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response, error) { @@ -6042,7 +6947,11 @@ func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType Gro return nil, BuildResponse(r), err } defer closeBody(r) - return GroupSyncableFromJson(r.Body), BuildResponse(r), nil + var gs GroupSyncable + if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { + return nil, nil, NewAppError("LinkGroupSyncable", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &gs, BuildResponse(r), nil } func (c *Client4) UnlinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType) (*Response, error) { @@ -6061,7 +6970,11 @@ func (c *Client4) GetGroupSyncable(groupID, syncableID string, syncableType Grou return nil, BuildResponse(r), err } defer closeBody(r) - return GroupSyncableFromJson(r.Body), BuildResponse(r), nil + var gs GroupSyncable + if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { + return nil, nil, NewAppError("GetGroupSyncable", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &gs, BuildResponse(r), nil } func (c *Client4) GetGroupSyncables(groupID string, syncableType GroupSyncableType, etag string) ([]*GroupSyncable, *Response, error) { @@ -6070,7 +6983,11 @@ func (c *Client4) GetGroupSyncables(groupID string, syncableType GroupSyncableTy return nil, BuildResponse(r), err } defer closeBody(r) - return GroupSyncablesFromJson(r.Body), BuildResponse(r), nil + var list []*GroupSyncable + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetGroupSyncables", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response, error) { @@ -6080,7 +6997,11 @@ func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType Gr return nil, BuildResponse(r), err } defer closeBody(r) - return GroupSyncableFromJson(r.Body), BuildResponse(r), nil + var gs GroupSyncable + if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { + return nil, nil, NewAppError("PatchGroupSyncable", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &gs, BuildResponse(r), nil } func (c *Client4) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int, etag string) ([]*UserWithGroups, int64, *Response, error) { @@ -6091,7 +7012,11 @@ func (c *Client4) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, return nil, 0, BuildResponse(r), err } defer closeBody(r) - ugc := UsersWithGroupsAndCountFromJson(r.Body) + + var ugc UsersWithGroupsAndCount + if jsonErr := json.NewDecoder(r.Body).Decode(&ugc); jsonErr != nil { + return nil, 0, nil, NewAppError("TeamMembersMinusGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } return ugc.Users, ugc.Count, BuildResponse(r), nil } @@ -6103,7 +7028,10 @@ func (c *Client4) ChannelMembersMinusGroupMembers(channelID string, groupIDs []s return nil, 0, BuildResponse(r), err } defer closeBody(r) - ugc := UsersWithGroupsAndCountFromJson(r.Body) + var ugc UsersWithGroupsAndCount + if jsonErr := json.NewDecoder(r.Body).Decode(&ugc); jsonErr != nil { + return nil, 0, nil, NewAppError("ChannelMembersMinusGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } return ugc.Users, ugc.Count, BuildResponse(r), nil } @@ -6117,7 +7045,7 @@ func (c *Client4) PatchConfig(config *Config) (*Config, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ConfigFromJson(r.Body), BuildResponse(r), nil + return ConfigFromJSON(r.Body), BuildResponse(r), nil } func (c *Client4) GetChannelModerations(channelID string, etag string) ([]*ChannelModeration, *Response, error) { @@ -6213,7 +7141,11 @@ func (c *Client4) GetGroupStats(groupID string) (*GroupStats, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return GroupStatsFromJson(r.Body), BuildResponse(r), nil + var gs GroupStats + if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { + return nil, nil, NewAppError("GetGroupStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &gs, BuildResponse(r), nil } func (c *Client4) GetSidebarCategoriesForTeamForUser(userID, teamID, etag string) (*OrderedSidebarCategories, *Response, error) { @@ -6273,7 +7205,7 @@ func (c *Client4) GetSidebarCategoryOrderForTeamForUser(userID, teamID, etag str return nil, BuildResponse(r), err } defer closeBody(r) - return ArrayFromJson(r.Body), BuildResponse(r), nil + return ArrayFromJSON(r.Body), BuildResponse(r), nil } func (c *Client4) UpdateSidebarCategoryOrderForTeamForUser(userID, teamID string, order []string) ([]string, *Response, error) { @@ -6284,7 +7216,7 @@ func (c *Client4) UpdateSidebarCategoryOrderForTeamForUser(userID, teamID string return nil, BuildResponse(r), err } defer closeBody(r) - return ArrayFromJson(r.Body), BuildResponse(r), nil + return ArrayFromJSON(r.Body), BuildResponse(r), nil } func (c *Client4) GetSidebarCategoryForTeamForUser(userID, teamID, categoryID, etag string) (*SidebarCategoryWithChannels, *Response, error) { @@ -6349,7 +7281,7 @@ func (c *Client4) GetNotices(lastViewed int64, teamId string, client NoticeClien } func (c *Client4) MarkNoticesViewed(ids []string) (*Response, error) { - r, err := c.DoAPIPut("/system/notices/view", ArrayToJson(ids)) + r, err := c.DoAPIPut("/system/notices/view", ArrayToJSON(ids)) if err != nil { return BuildResponse(r), err } @@ -6368,7 +7300,12 @@ func (c *Client4) CreateUpload(us *UploadSession) (*UploadSession, *Response, er return nil, BuildResponse(r), err } defer closeBody(r) - return UploadSessionFromJson(r.Body), BuildResponse(r), nil + + var s UploadSession + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("CreateUpload", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } // GetUpload returns the upload session for the specified uploadId. @@ -6378,7 +7315,11 @@ func (c *Client4) GetUpload(uploadId string) (*UploadSession, *Response, error) return nil, BuildResponse(r), err } defer closeBody(r) - return UploadSessionFromJson(r.Body), BuildResponse(r), nil + var s UploadSession + if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { + return nil, nil, NewAppError("GetUpload", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &s, BuildResponse(r), nil } // GetUploadsForUser returns the upload sessions created by the specified @@ -6389,7 +7330,11 @@ func (c *Client4) GetUploadsForUser(userId string) ([]*UploadSession, *Response, return nil, BuildResponse(r), err } defer closeBody(r) - return UploadSessionsFromJson(r.Body), BuildResponse(r), nil + var list []*UploadSession + if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { + return nil, nil, NewAppError("GetUploadsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return list, BuildResponse(r), nil } // UploadData performs an upload. On success it returns @@ -6401,12 +7346,19 @@ func (c *Client4) UploadData(uploadId string, data io.Reader) (*FileInfo, *Respo return nil, BuildResponse(r), err } defer closeBody(r) - return FileInfoFromJson(r.Body), BuildResponse(r), nil + var fi FileInfo + if r.StatusCode == http.StatusNoContent { + return nil, BuildResponse(r), nil + } + if jsonErr := json.NewDecoder(r.Body).Decode(&fi); jsonErr != nil { + return nil, nil, NewAppError("UploadData", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + return &fi, BuildResponse(r), nil } func (c *Client4) UpdatePassword(userId, currentPassword, newPassword string) (*Response, error) { requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword} - r, err := c.DoAPIPut(c.userRoute(userId)+"/password", MapToJson(requestBody)) + r, err := c.DoAPIPut(c.userRoute(userId)+"/password", MapToJSON(requestBody)) if err != nil { return BuildResponse(r), err } @@ -6541,7 +7493,7 @@ func (c *Client4) ListImports() ([]string, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ArrayFromJson(r.Body), BuildResponse(r), nil + return ArrayFromJSON(r.Body), BuildResponse(r), nil } func (c *Client4) ListExports() ([]string, *Response, error) { @@ -6550,7 +7502,7 @@ func (c *Client4) ListExports() ([]string, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ArrayFromJson(r.Body), BuildResponse(r), nil + return ArrayFromJSON(r.Body), BuildResponse(r), nil } func (c *Client4) DeleteExport(name string) (*Response, error) { diff --git a/model/client4_test.go b/model/client4_test.go index 5df300fbcc..5f9bd828cf 100644 --- a/model/client4_test.go +++ b/model/client4_test.go @@ -4,6 +4,7 @@ package model import ( + "encoding/json" "net/http" "net/http/httptest" "strings" @@ -48,7 +49,10 @@ func TestClient4CreatePost(t *testing.T) { } server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - attachments := PostFromJson(r.Body).Attachments() + var post Post + err := json.NewDecoder(r.Body).Decode(&post) + assert.NoError(t, err) + attachments := post.Attachments() assert.Equal(t, []*SlackAttachment{ { Actions: []*PostAction{ @@ -64,6 +68,8 @@ func TestClient4CreatePost(t *testing.T) { }, }, }, attachments) + err = json.NewEncoder(w).Encode(&post) + assert.NoError(t, err) })) client := NewAPIv4Client(server.URL) @@ -85,6 +91,10 @@ func TestClient4SetToken(t *testing.T) { } assert.Equal(t, expected, strings.TrimSpace(token[1])) + + var user User + err := json.NewEncoder(w).Encode(&user) + assert.NoError(t, err) })) client := NewAPIv4Client(server.URL) diff --git a/model/cluster_discovery.go b/model/cluster_discovery.go index ad07def68a..160a59170a 100644 --- a/model/cluster_discovery.go +++ b/model/cluster_discovery.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "os" ) @@ -115,14 +113,3 @@ func (o *ClusterDiscovery) IsValid() *AppError { return nil } - -func ClusterDiscoveryFromJson(data io.Reader) *ClusterDiscovery { - decoder := json.NewDecoder(data) - var me ClusterDiscovery - err := decoder.Decode(&me) - if err == nil { - return &me - } - - return nil -} diff --git a/model/cluster_discovery_test.go b/model/cluster_discovery_test.go index ae99c0daa4..3fe221c28b 100644 --- a/model/cluster_discovery_test.go +++ b/model/cluster_discovery_test.go @@ -4,12 +4,9 @@ package model import ( - "encoding/json" - "strings" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestClusterDiscovery(t *testing.T) { @@ -19,16 +16,9 @@ func TestClusterDiscovery(t *testing.T) { Hostname: "test_hostname", } - buf, err := json.Marshal(o) - require.NoError(t, err) - json := string(buf) - result1 := ClusterDiscoveryFromJson(strings.NewReader(json)) - - assert.NotNil(t, result1) - assert.Equal(t, "cluster_name", result1.ClusterName) - - result2 := ClusterDiscoveryFromJson(strings.NewReader(json)) - result3 := ClusterDiscoveryFromJson(strings.NewReader(json)) + result1 := o + result2 := o + result3 := o o.Id = "0" result1.Id = "1" @@ -36,13 +26,13 @@ func TestClusterDiscovery(t *testing.T) { result3.Id = "3" result3.Hostname = "something_diff" - assert.True(t, o.IsEqual(result1)) + assert.True(t, o.IsEqual(&result1)) list := make([]*ClusterDiscovery, 0) list = append(list, &o) - list = append(list, result1) - list = append(list, result2) - list = append(list, result3) + list = append(list, &result1) + list = append(list, &result2) + list = append(list, &result3) rlist := FilterClusterDiscovery(list, func(in *ClusterDiscovery) bool { return !o.IsEqual(in) diff --git a/model/cluster_info.go b/model/cluster_info.go index 12852a022a..48d11d2fb1 100644 --- a/model/cluster_info.go +++ b/model/cluster_info.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type ClusterInfo struct { Id string `json:"id"` Version string `json:"version"` @@ -15,24 +10,3 @@ type ClusterInfo struct { IPAddress string `json:"ipaddress"` Hostname string `json:"hostname"` } - -func ClusterInfoFromJson(data io.Reader) *ClusterInfo { - var ci *ClusterInfo - json.NewDecoder(data).Decode(&ci) - return ci -} - -func ClusterInfosToJson(objmap []*ClusterInfo) string { - b, _ := json.Marshal(objmap) - return string(b) -} - -func ClusterInfosFromJson(data io.Reader) []*ClusterInfo { - decoder := json.NewDecoder(data) - - var objmap []*ClusterInfo - if err := decoder.Decode(&objmap); err != nil { - return make([]*ClusterInfo, 0) - } - return objmap -} diff --git a/model/cluster_info_test.go b/model/cluster_info_test.go deleted file mode 100644 index c7e432e328..0000000000 --- a/model/cluster_info_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestClusterInfosJson(t *testing.T) { - cluster := ClusterInfo{IPAddress: NewId(), Hostname: NewId()} - clusterInfos := make([]*ClusterInfo, 1) - clusterInfos[0] = &cluster - json := ClusterInfosToJson(clusterInfos) - result := ClusterInfosFromJson(strings.NewReader(json)) - - assert.Equal(t, clusterInfos[0].IPAddress, result[0].IPAddress, "Ids do not match") -} diff --git a/model/cluster_stats.go b/model/cluster_stats.go index 011f41f754..3b41cb6eee 100644 --- a/model/cluster_stats.go +++ b/model/cluster_stats.go @@ -3,20 +3,9 @@ package model -import ( - "encoding/json" - "io" -) - type ClusterStats struct { Id string `json:"id"` TotalWebsocketConnections int `json:"total_websocket_connections"` TotalReadDbConnections int `json:"total_read_db_connections"` TotalMasterDbConnections int `json:"total_master_db_connections"` } - -func ClusterStatsFromJson(data io.Reader) *ClusterStats { - var cs *ClusterStats - json.NewDecoder(data).Decode(&cs) - return cs -} diff --git a/model/command.go b/model/command.go index 923ed590de..4bb9529820 100644 --- a/model/command.go +++ b/model/command.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "strings" ) @@ -43,20 +41,7 @@ type Command struct { AutocompleteIconData string `db:"-" json:"autocomplete_icon_data,omitempty"` } -func CommandFromJson(data io.Reader) *Command { - var o *Command - json.NewDecoder(data).Decode(&o) - return o -} - -func CommandListFromJson(data io.Reader) []*Command { - var o []*Command - json.NewDecoder(data).Decode(&o) - return o -} - func (o *Command) IsValid() *AppError { - if !IsValidId(o.Id) { return NewAppError("Command.IsValid", "model.command.is_valid.id.app_error", nil, "", http.StatusBadRequest) } diff --git a/model/command_args.go b/model/command_args.go index e60d249661..c8333acbde 100644 --- a/model/command_args.go +++ b/model/command_args.go @@ -4,9 +4,6 @@ package model import ( - "encoding/json" - "io" - "github.com/mattermost/mattermost-server/v6/shared/i18n" ) @@ -27,12 +24,6 @@ type CommandArgs struct { Session Session `json:"-"` } -func CommandArgsFromJson(data io.Reader) *CommandArgs { - var o *CommandArgs - json.NewDecoder(data).Decode(&o) - return o -} - // AddUserMention adds or overrides an entry in UserMentions with name username // and identifier userId func (o *CommandArgs) AddUserMention(username, userId string) { diff --git a/model/command_autocomplete.go b/model/command_autocomplete.go index 649e8e3732..a71a08c6ec 100644 --- a/model/command_autocomplete.go +++ b/model/command_autocomplete.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io" "net/url" "path" "reflect" @@ -291,24 +290,6 @@ func (ad *AutocompleteData) IsValid() error { return nil } -// ToJSON encodes AutocompleteData struct to the json -func (ad *AutocompleteData) ToJSON() ([]byte, error) { - b, err := json.Marshal(ad) - if err != nil { - return nil, errors.Wrapf(err, "can't marshal slash command %s", ad.Trigger) - } - return b, nil -} - -// AutocompleteDataFromJSON decodes AutocompleteData struct from the json -func AutocompleteDataFromJSON(data []byte) (*AutocompleteData, error) { - var ad AutocompleteData - if err := json.Unmarshal(data, &ad); err != nil { - return nil, errors.Wrap(err, "can't unmarshal AutocompleteData") - } - return &ad, nil -} - // Equals method checks if argument is the same. func (a *AutocompleteArg) Equals(arg *AutocompleteArg) bool { if a.Name != arg.Name || @@ -419,32 +400,6 @@ func (a *AutocompleteArg) UnmarshalJSON(b []byte) error { return nil } -// AutocompleteSuggestionsToJSON returns json for a list of AutocompleteSuggestion objects -func AutocompleteSuggestionsToJSON(suggestions []AutocompleteSuggestion) []byte { - b, _ := json.Marshal(suggestions) - return b -} - -// AutocompleteSuggestionsFromJSON returns list of AutocompleteSuggestions from json. -func AutocompleteSuggestionsFromJSON(data io.Reader) []AutocompleteSuggestion { - var o []AutocompleteSuggestion - json.NewDecoder(data).Decode(&o) - return o -} - -// AutocompleteStaticListItemsToJSON returns json for a list of AutocompleteStaticListItem objects -func AutocompleteStaticListItemsToJSON(items []AutocompleteListItem) []byte { - b, _ := json.Marshal(items) - return b -} - -// AutocompleteStaticListItemsFromJSON returns list of AutocompleteStaticListItem from json. -func AutocompleteStaticListItemsFromJSON(data io.Reader) []AutocompleteListItem { - var o []AutocompleteListItem - json.NewDecoder(data).Decode(&o) - return o -} - func stringNotInSlice(a string, slice []string) bool { for _, b := range slice { if b == a { diff --git a/model/command_autocomplete_test.go b/model/command_autocomplete_test.go index 3da7d7dea8..18a0d70eea 100644 --- a/model/command_autocomplete_test.go +++ b/model/command_autocomplete_test.go @@ -65,15 +65,6 @@ func TestAutocompleteData(t *testing.T) { assert.Error(t, ad.IsValid()) } -func TestAutocompleteDataJSON(t *testing.T) { - ad := getAutocompleteData() - b, err := ad.ToJSON() - assert.NoError(t, err) - ad2, err := AutocompleteDataFromJSON(b) - assert.NoError(t, err) - assert.True(t, ad2.Equals(ad)) -} - func getAutocompleteData() *AutocompleteData { ad := NewAutocompleteData("jira", "", "Available commands:") ad.RoleID = SystemUserRoleId diff --git a/model/command_request.go b/model/command_request.go index 5c6e206774..331394cbab 100644 --- a/model/command_request.go +++ b/model/command_request.go @@ -3,21 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type CommandMoveRequest struct { TeamId string `json:"team_id"` } - -func CommandMoveRequestFromJson(data io.Reader) (*CommandMoveRequest, error) { - decoder := json.NewDecoder(data) - var cmr CommandMoveRequest - err := decoder.Decode(&cmr) - if err != nil { - return nil, err - } - return &cmr, nil -} diff --git a/model/command_response.go b/model/command_response.go index 432571bbec..b2521f8e0f 100644 --- a/model/command_response.go +++ b/model/command_response.go @@ -34,7 +34,7 @@ type CommandResponse struct { func CommandResponseFromHTTPBody(contentType string, body io.Reader) (*CommandResponse, error) { if strings.TrimSpace(strings.Split(contentType, ";")[0]) == "application/json" { - return CommandResponseFromJson(body) + return CommandResponseFromJSON(body) } if b, err := ioutil.ReadAll(body); err == nil { return CommandResponseFromPlainText(string(b)), nil @@ -48,7 +48,7 @@ func CommandResponseFromPlainText(text string) *CommandResponse { } } -func CommandResponseFromJson(data io.Reader) (*CommandResponse, error) { +func CommandResponseFromJSON(data io.Reader) (*CommandResponse, error) { b, err := ioutil.ReadAll(data) if err != nil { return nil, err diff --git a/model/command_response_test.go b/model/command_response_test.go index 5c470e649d..264951a19a 100644 --- a/model/command_response_test.go +++ b/model/command_response_test.go @@ -35,7 +35,7 @@ func TestCommandResponseFromPlainText(t *testing.T) { assert.Equal(t, "foo", response.Text) } -func TestCommandResponseFromJson(t *testing.T) { +func TestCommandResponseFromJSON(t *testing.T) { t.Parallel() testCases := []struct { @@ -208,7 +208,7 @@ func TestCommandResponseFromJson(t *testing.T) { t.Run(testCase.Description, func(t *testing.T) { t.Parallel() - response, err := CommandResponseFromJson(strings.NewReader(testCase.Json)) + response, err := CommandResponseFromJSON(strings.NewReader(testCase.Json)) if testCase.ShouldError { assert.Nil(t, response) } else { diff --git a/model/compliance.go b/model/compliance.go index 9da215bcdb..b46a0d1038 100644 --- a/model/compliance.go +++ b/model/compliance.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "strings" ) @@ -83,7 +81,6 @@ func (c *Compliance) JobName() string { } func (c *Compliance) IsValid() *AppError { - if !IsValidId(c.Id) { return NewAppError("Compliance.IsValid", "model.compliance.is_valid.id.app_error", nil, "", http.StatusBadRequest) } @@ -110,15 +107,3 @@ func (c *Compliance) IsValid() *AppError { return nil } - -func ComplianceFromJson(data io.Reader) *Compliance { - var c *Compliance - json.NewDecoder(data).Decode(&c) - return c -} - -func CompliancesFromJson(data io.Reader) Compliances { - var o Compliances - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/config.go b/model/config.go index c7f070c325..540e4226cc 100644 --- a/model/config.go +++ b/model/config.go @@ -3197,7 +3197,7 @@ func (o *Config) Clone() *Config { return &ret } -func (o *Config) ToJsonFiltered(tagType, tagValue string) string { +func (o *Config) ToJSONFiltered(tagType, tagValue string) ([]byte, error) { filteredConfigMap := structToMapFilteredByTag(*o, tagType, tagValue) for key, value := range filteredConfigMap { v, ok := value.(map[string]interface{}) @@ -3205,8 +3205,7 @@ func (o *Config) ToJsonFiltered(tagType, tagValue string) string { delete(filteredConfigMap, key) } } - b, _ := json.Marshal(filteredConfigMap) - return string(b) + return json.Marshal(filteredConfigMap) } func (o *Config) GetSSOService(service string) *SSOSettings { @@ -3224,7 +3223,7 @@ func (o *Config) GetSSOService(service string) *SSOSettings { return nil } -func ConfigFromJson(data io.Reader) *Config { +func ConfigFromJSON(data io.Reader) *Config { var o *Config json.NewDecoder(data).Decode(&o) return o diff --git a/model/config_test.go b/model/config_test.go index 7dbd0db33c..bf200c7557 100644 --- a/model/config_test.go +++ b/model/config_test.go @@ -1338,10 +1338,11 @@ func TestConfigToJSONFiltered(t *testing.T) { c := Config{} c.SetDefaults() - jsonCfgFiltered := c.ToJsonFiltered(ConfigAccessTagType, ConfigAccessTagCloudRestrictable) + jsonCfgFiltered, err := c.ToJSONFiltered(ConfigAccessTagType, ConfigAccessTagCloudRestrictable) + require.NoError(t, err) unmarshaledCfg := make(map[string]json.RawMessage) - err := json.Unmarshal([]byte(jsonCfgFiltered), &unmarshaledCfg) + err = json.Unmarshal(jsonCfgFiltered, &unmarshaledCfg) require.NoError(t, err) _, ok := unmarshaledCfg["SqlSettings"] diff --git a/model/custom_status.go b/model/custom_status.go index 7b3d484b27..2f5084b867 100644 --- a/model/custom_status.go +++ b/model/custom_status.go @@ -4,9 +4,9 @@ package model import ( + "bytes" "encoding/json" "fmt" - "io" "time" ) @@ -49,12 +49,6 @@ func (cs *CustomStatus) PreSave() { } } -func (cs *CustomStatus) ToJson() string { - csCopy := *cs - b, _ := json.Marshal(csCopy) - return string(b) -} - func (cs *CustomStatus) AreDurationAndExpirationTimeValid() bool { if cs.Duration == "" && (cs.ExpiresAt.IsZero() || !cs.ExpiresAt.Before(time.Now())) { return true @@ -67,33 +61,38 @@ func (cs *CustomStatus) AreDurationAndExpirationTimeValid() bool { return false } -func CustomStatusFromJson(data io.Reader) *CustomStatus { - var cs *CustomStatus - _ = json.NewDecoder(data).Decode(&cs) - return cs -} - func RuneToHexadecimalString(r rune) string { return fmt.Sprintf("%04x", r) } type RecentCustomStatuses []CustomStatus -func (rcs RecentCustomStatuses) Contains(cs *CustomStatus) bool { - var csJSON = cs.ToJson() +func (rcs RecentCustomStatuses) Contains(cs *CustomStatus) (bool, error) { + if cs == nil { + return false, nil + } + + csJSON, jsonErr := json.Marshal(cs) + if jsonErr != nil { + return false, jsonErr + } // status is empty - if cs == nil || csJSON == "" || (cs.Emoji == "" && cs.Text == "") { - return false + if len(csJSON) == 0 || (cs.Emoji == "" && cs.Text == "") { + return false, nil } for _, status := range rcs { - if status.ToJson() == csJSON { - return true + js, jsonErr := json.Marshal(status) + if jsonErr != nil { + return false, jsonErr + } + if bytes.Equal(js, csJSON) { + return true, nil } } - return false + return false, nil } func (rcs RecentCustomStatuses) Add(cs *CustomStatus) RecentCustomStatuses { @@ -112,29 +111,30 @@ func (rcs RecentCustomStatuses) Add(cs *CustomStatus) RecentCustomStatuses { return newRCS } -func (rcs RecentCustomStatuses) Remove(cs *CustomStatus) RecentCustomStatuses { - var csJSON = cs.ToJson() - if csJSON == "" || (cs.Emoji == "" && cs.Text == "") { - return rcs +func (rcs RecentCustomStatuses) Remove(cs *CustomStatus) (RecentCustomStatuses, error) { + if cs == nil { + return rcs, nil + } + + csJSON, jsonErr := json.Marshal(cs) + if jsonErr != nil { + return rcs, jsonErr + } + + if len(csJSON) == 0 || (cs.Emoji == "" && cs.Text == "") { + return rcs, nil } newRCS := rcs[:0] for _, status := range rcs { - if status.ToJson() != csJSON { + js, jsonErr := json.Marshal(status) + if jsonErr != nil { + return rcs, jsonErr + } + if !bytes.Equal(js, csJSON) { newRCS = append(newRCS, status) } } - return newRCS -} - -func (rcs RecentCustomStatuses) ToJson() string { - b, _ := json.Marshal(rcs) - return string(b) -} - -func RecentCustomStatusesFromJson(data io.Reader) RecentCustomStatuses { - var rcs RecentCustomStatuses - _ = json.NewDecoder(data).Decode(&rcs) - return rcs + return newRCS, nil } diff --git a/model/data_retention_policy.go b/model/data_retention_policy.go index 3f984d1bcf..0a1d318e6e 100644 --- a/model/data_retention_policy.go +++ b/model/data_retention_policy.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type GlobalRetentionPolicy struct { MessageDeletionEnabled bool `json:"message_deletion_enabled"` FileDeletionEnabled bool `json:"file_deletion_enabled"` @@ -73,60 +68,3 @@ type RetentionPolicyCursor struct { TeamPoliciesDone bool GlobalPoliciesDone bool } - -func (rp *GlobalRetentionPolicy) ToJson() []byte { - b, _ := json.Marshal(rp) - return b -} - -func GlobalRetentionPolicyFromJson(data io.Reader) *GlobalRetentionPolicy { - var grp *GlobalRetentionPolicy - json.NewDecoder(data).Decode(&grp) - return grp -} - -func RetentionPolicyWithTeamAndChannelCountsFromJson(data io.Reader) (*RetentionPolicyWithTeamAndChannelCounts, error) { - var rp RetentionPolicyWithTeamAndChannelCounts - err := json.NewDecoder(data).Decode(&rp) - return &rp, err -} - -func (rp *RetentionPolicyWithTeamAndChannelCounts) ToJson() []byte { - b, _ := json.Marshal(rp) - return b -} - -func RetentionPolicyWithTeamAndChannelCountsListFromJson(data io.Reader) (*RetentionPolicyWithTeamAndChannelCountsList, error) { - var rpList *RetentionPolicyWithTeamAndChannelCountsList - err := json.NewDecoder(data).Decode(&rpList) - if err != nil { - return nil, err - } - return rpList, nil -} - -func (rpList *RetentionPolicyWithTeamAndChannelCountsList) ToJson() []byte { - b, _ := json.Marshal(rpList) - return b -} - -func RetentionPolicyWithTeamAndChannelIdsFromJson(data io.Reader) (*RetentionPolicyWithTeamAndChannelIDs, error) { - var rp *RetentionPolicyWithTeamAndChannelIDs - err := json.NewDecoder(data).Decode(&rp) - return rp, err -} - -func (rp *RetentionPolicyWithTeamAndChannelIDs) ToJson() []byte { - b, _ := json.Marshal(rp) - return b -} - -func (lst *RetentionPolicyForTeamList) ToJson() []byte { - b, _ := json.Marshal(lst) - return b -} - -func (lst *RetentionPolicyForChannelList) ToJson() []byte { - b, _ := json.Marshal(lst) - return b -} diff --git a/model/emoji.go b/model/emoji.go index c746598068..fd0e8ab369 100644 --- a/model/emoji.go +++ b/model/emoji.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "regexp" "sort" @@ -95,20 +93,3 @@ func (emoji *Emoji) PreSave() { emoji.CreateAt = GetMillis() emoji.UpdateAt = emoji.CreateAt } - -func (emoji *Emoji) ToJson() string { - b, _ := json.Marshal(emoji) - return string(b) -} - -func EmojiFromJson(data io.Reader) *Emoji { - var emoji *Emoji - json.NewDecoder(data).Decode(&emoji) - return emoji -} - -func EmojiListFromJson(data io.Reader) []*Emoji { - var emojiList []*Emoji - json.NewDecoder(data).Decode(&emojiList) - return emojiList -} diff --git a/model/emoji_search.go b/model/emoji_search.go index 71e2671cf2..4d947a11e5 100644 --- a/model/emoji_search.go +++ b/model/emoji_search.go @@ -3,23 +3,7 @@ package model -import ( - "encoding/json" - "io" -) - type EmojiSearch struct { Term string `json:"term"` PrefixOnly bool `json:"prefix_only"` } - -func (es *EmojiSearch) ToJson() string { - b, _ := json.Marshal(es) - return string(b) -} - -func EmojiSearchFromJson(data io.Reader) *EmojiSearch { - var es *EmojiSearch - json.NewDecoder(data).Decode(&es) - return es -} diff --git a/model/emoji_search_test.go b/model/emoji_search_test.go deleted file mode 100644 index aca109cd59..0000000000 --- a/model/emoji_search_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestEmojiSearchJson(t *testing.T) { - emojiSearch := EmojiSearch{Term: NewId()} - json := emojiSearch.ToJson() - remojiSearch := EmojiSearchFromJson(strings.NewReader(json)) - - require.Equal(t, emojiSearch.Term, remojiSearch.Term, "Terms do not match") -} diff --git a/model/file.go b/model/file.go index d2cb8f34d3..63d1ad333c 100644 --- a/model/file.go +++ b/model/file.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - const ( MaxImageSize = int64(6048 * 4032) // 24 megapixels, roughly 36MB as a raw image ) @@ -16,14 +11,3 @@ type FileUploadResponse struct { FileInfos []*FileInfo `json:"file_infos"` ClientIds []string `json:"client_ids"` } - -func FileUploadResponseFromJson(data io.Reader) *FileUploadResponse { - var o *FileUploadResponse - json.NewDecoder(data).Decode(&o) - return o -} - -func (o *FileUploadResponse) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} diff --git a/model/file_info.go b/model/file_info.go index 0285b2f8f5..9519ef45b9 100644 --- a/model/file_info.go +++ b/model/file_info.go @@ -4,7 +4,6 @@ package model import ( - "encoding/json" "image" "image/gif" "io" @@ -58,36 +57,6 @@ type FileInfo struct { RemoteId *string `json:"remote_id"` } -func (fi *FileInfo) ToJson() string { - b, _ := json.Marshal(fi) - return string(b) -} - -func FileInfoFromJson(data io.Reader) *FileInfo { - decoder := json.NewDecoder(data) - - var fi FileInfo - if err := decoder.Decode(&fi); err != nil { - return nil - } - return &fi -} - -func FileInfosToJson(infos []*FileInfo) string { - b, _ := json.Marshal(infos) - return string(b) -} - -func FileInfosFromJson(data io.Reader) []*FileInfo { - decoder := json.NewDecoder(data) - - var infos []*FileInfo - if err := decoder.Decode(&infos); err != nil { - return nil - } - return infos -} - func (fi *FileInfo) PreSave() { if fi.Id == "" { fi.Id = NewId() diff --git a/model/file_info_list.go b/model/file_info_list.go index fd87c3aa37..219b24f1dc 100644 --- a/model/file_info_list.go +++ b/model/file_info_list.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "sort" ) @@ -33,15 +31,6 @@ func (o *FileInfoList) ToSlice() []*FileInfo { return fileInfos } -func (o *FileInfoList) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } - - return string(b) -} - func (o *FileInfoList) MakeNonNil() { if o.Order == nil { o.Order = make([]string, 0) @@ -120,9 +109,3 @@ func (o *FileInfoList) Etag() string { return Etag(orderId, id, t) } - -func FileInfoListFromJson(data io.Reader) *FileInfoList { - var o *FileInfoList - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/file_info_search_results.go b/model/file_info_search_results.go index 90f2922b9c..fddbffd49a 100644 --- a/model/file_info_search_results.go +++ b/model/file_info_search_results.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type FileInfoSearchMatches map[string][]string type FileInfoSearchResults struct { @@ -21,17 +16,3 @@ func MakeFileInfoSearchResults(fileInfos *FileInfoList, matches FileInfoSearchMa matches, } } - -func (o *FileInfoSearchResults) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } - return string(b) -} - -func FileInfoSearchResultsFromJson(data io.Reader) *FileInfoSearchResults { - var o *FileInfoSearchResults - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/gitlab/gitlab.go b/model/gitlab/gitlab.go index a14844330a..ade599cb45 100644 --- a/model/gitlab/gitlab.go +++ b/model/gitlab/gitlab.go @@ -56,7 +56,7 @@ func userFromGitLabUser(glu *GitLabUser) *model.User { return user } -func gitLabUserFromJson(data io.Reader) (*GitLabUser, error) { +func gitLabUserFromJSON(data io.Reader) (*GitLabUser, error) { decoder := json.NewDecoder(data) var glu GitLabUser err := decoder.Decode(&glu) @@ -66,14 +66,6 @@ func gitLabUserFromJson(data io.Reader) (*GitLabUser, error) { return &glu, nil } -func (glu *GitLabUser) ToJson() string { - b, err := json.Marshal(glu) - if err != nil { - return "" - } - return string(b) -} - func (glu *GitLabUser) IsValid() error { if glu.Id == 0 { return errors.New("user id can't be 0") @@ -90,8 +82,8 @@ func (glu *GitLabUser) getAuthData() string { return strconv.FormatInt(glu.Id, 10) } -func (m *GitLabProvider) GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) { - glu, err := gitLabUserFromJson(data) +func (m *GitLabProvider) GetUserFromJSON(data io.Reader, tokenUser *model.User) (*model.User, error) { + glu, err := gitLabUserFromJSON(data) if err != nil { return nil, err } diff --git a/model/group.go b/model/group.go index c70b7aa150..566b23611a 100644 --- a/model/group.go +++ b/model/group.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "regexp" ) @@ -171,11 +169,6 @@ func (group *Group) IsValidForUpdate() *AppError { return nil } -func (group *Group) ToJson() string { - b, _ := json.Marshal(group) - return string(b) -} - var validGroupnameChars = regexp.MustCompile(`^[a-z0-9\.\-_]+$`) func (group *Group) IsValidName() *AppError { @@ -195,27 +188,3 @@ func (group *Group) IsValidName() *AppError { } return nil } - -func GroupFromJson(data io.Reader) *Group { - var group *Group - json.NewDecoder(data).Decode(&group) - return group -} - -func GroupsFromJson(data io.Reader) []*Group { - var groups []*Group - json.NewDecoder(data).Decode(&groups) - return groups -} - -func GroupPatchFromJson(data io.Reader) *GroupPatch { - var groupPatch *GroupPatch - json.NewDecoder(data).Decode(&groupPatch) - return groupPatch -} - -func GroupStatsFromJson(data io.Reader) *GroupStats { - var groupStats *GroupStats - json.NewDecoder(data).Decode(&groupStats) - return groupStats -} diff --git a/model/group_syncable.go b/model/group_syncable.go index eb3bdf0978..1f1bf60f69 100644 --- a/model/group_syncable.go +++ b/model/group_syncable.go @@ -6,8 +6,6 @@ package model import ( "encoding/json" "fmt" - "io" - "io/ioutil" "net/http" ) @@ -158,20 +156,6 @@ type UserChannelIDPair struct { ChannelID string } -func GroupSyncableFromJson(data io.Reader) *GroupSyncable { - groupSyncable := &GroupSyncable{} - bodyBytes, _ := ioutil.ReadAll(data) - json.Unmarshal(bodyBytes, groupSyncable) - return groupSyncable -} - -func GroupSyncablesFromJson(data io.Reader) []*GroupSyncable { - groupSyncables := []*GroupSyncable{} - bodyBytes, _ := ioutil.ReadAll(data) - json.Unmarshal(bodyBytes, &groupSyncables) - return groupSyncables -} - func NewGroupTeam(groupID, teamID string, autoAdd bool) *GroupSyncable { return &GroupSyncable{ GroupId: groupID, diff --git a/model/guest_invite.go b/model/guest_invite.go index 826aa74d94..5103ccd1b1 100644 --- a/model/guest_invite.go +++ b/model/guest_invite.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" ) @@ -39,15 +37,3 @@ func (i *GuestsInvite) IsValid() *AppError { } return nil } - -// GuestsInviteFromJson will decode the input and return a GuestsInvite -func GuestsInviteFromJson(data io.Reader) *GuestsInvite { - var i *GuestsInvite - json.NewDecoder(data).Decode(&i) - return i -} - -func (i *GuestsInvite) ToJson() string { - b, _ := json.Marshal(i) - return string(b) -} diff --git a/model/incoming_webhook.go b/model/incoming_webhook.go index e389bf5457..ce7828e4bc 100644 --- a/model/incoming_webhook.go +++ b/model/incoming_webhook.go @@ -41,30 +41,7 @@ type IncomingWebhookRequest struct { IconEmoji string `json:"icon_emoji"` } -func (o *IncomingWebhook) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func IncomingWebhookFromJson(data io.Reader) *IncomingWebhook { - var o *IncomingWebhook - json.NewDecoder(data).Decode(&o) - return o -} - -func IncomingWebhookListToJson(l []*IncomingWebhook) string { - b, _ := json.Marshal(l) - return string(b) -} - -func IncomingWebhookListFromJson(data io.Reader) []*IncomingWebhook { - var o []*IncomingWebhook - json.NewDecoder(data).Decode(&o) - return o -} - func (o *IncomingWebhook) IsValid() *AppError { - if !IsValidId(o.Id) { return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.id.app_error", nil, "", http.StatusBadRequest) @@ -186,7 +163,7 @@ func decodeIncomingWebhookRequest(by []byte) (*IncomingWebhookRequest, error) { return nil, err } -func IncomingWebhookRequestFromJson(data io.Reader) (*IncomingWebhookRequest, *AppError) { +func IncomingWebhookRequestFromJSON(data io.Reader) (*IncomingWebhookRequest, *AppError) { buf := new(bytes.Buffer) buf.ReadFrom(data) by := buf.Bytes() @@ -197,7 +174,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, err.Error(), http.StatusBadRequest) } } @@ -205,11 +182,3 @@ func IncomingWebhookRequestFromJson(data io.Reader) (*IncomingWebhookRequest, *A return o, nil } - -func (o *IncomingWebhookRequest) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } - return string(b) -} diff --git a/model/incoming_webhook_test.go b/model/incoming_webhook_test.go index 11f924f3c6..3aafbcc23c 100644 --- a/model/incoming_webhook_test.go +++ b/model/incoming_webhook_test.go @@ -10,14 +10,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestIncomingWebhookJson(t *testing.T) { - o := IncomingWebhook{Id: NewId()} - json := o.ToJson() - ro := IncomingWebhookFromJson(strings.NewReader(json)) - - require.Equal(t, o.Id, ro.Id) -} - func TestIncomingWebhookIsValid(t *testing.T) { o := IncomingWebhook{} @@ -85,7 +77,7 @@ func TestIncomingWebhookPreUpdate(t *testing.T) { o.PreUpdate() } -func TestIncomingWebhookRequestFromJson(t *testing.T) { +func TestIncomingWebhookRequestFromJSON(t *testing.T) { texts := []string{ `this is a test`, `this is a test @@ -139,7 +131,7 @@ func TestIncomingWebhookRequestFromJson(t *testing.T) { // try to create an IncomingWebhookRequest from the payload data := strings.NewReader(payload) - iwr, _ := IncomingWebhookRequestFromJson(data) + iwr, _ := IncomingWebhookRequestFromJSON(data) // After it has been decoded, the JSON string won't contain the escape char anymore expected := strings.Replace(text, `\"`, `"`, -1) @@ -153,7 +145,7 @@ func TestIncomingWebhookRequestFromJson(t *testing.T) { func TestIncomingWebhookNullArrayItems(t *testing.T) { payload := `{"attachments":[{"fields":[{"title":"foo","value":"bar","short":true}, null]}, null]}` - iwr, _ := IncomingWebhookRequestFromJson(strings.NewReader(payload)) + iwr, _ := IncomingWebhookRequestFromJSON(strings.NewReader(payload)) require.NotNil(t, iwr) require.Len(t, iwr.Attachments, 1) require.Len(t, iwr.Attachments[0].Fields, 1) diff --git a/model/initial_load.go b/model/initial_load.go index c533faa5da..5ecddda202 100644 --- a/model/initial_load.go +++ b/model/initial_load.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type InitialLoad struct { User *User `json:"user"` TeamMembers []*TeamMember `json:"team_members"` @@ -17,14 +12,3 @@ type InitialLoad struct { LicenseCfg map[string]string `json:"license_cfg"` NoAccounts bool `json:"no_accounts"` } - -func (il *InitialLoad) ToJson() string { - b, _ := json.Marshal(il) - return string(b) -} - -func InitialLoadFromJson(data io.Reader) *InitialLoad { - var il *InitialLoad - json.NewDecoder(data).Decode(&il) - return il -} diff --git a/model/initial_load_test.go b/model/initial_load_test.go deleted file mode 100644 index 56c446b714..0000000000 --- a/model/initial_load_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestInitialLoadJson(t *testing.T) { - u := &User{Id: NewId()} - o := InitialLoad{User: u} - json := o.ToJson() - ro := InitialLoadFromJson(strings.NewReader(json)) - - require.Equal(t, o.User.Id, ro.User.Id, "Ids do not match") -} diff --git a/model/integration_action.go b/model/integration_action.go index 375d29869b..c61cc6d457 100644 --- a/model/integration_action.go +++ b/model/integration_action.go @@ -323,62 +323,6 @@ func (r *OpenDialogRequest) DecodeAndVerifyTriggerId(s *ecdsa.PrivateKey) (strin return DecodeAndVerifyTriggerId(r.TriggerId, s) } -func (r *PostActionIntegrationRequest) ToJson() []byte { - b, _ := json.Marshal(r) - return b -} - -func PostActionIntegrationRequestFromJson(data io.Reader) *PostActionIntegrationRequest { - var o *PostActionIntegrationRequest - err := json.NewDecoder(data).Decode(&o) - if err != nil { - return nil - } - return o -} - -func (r *PostActionIntegrationResponse) ToJson() []byte { - b, _ := json.Marshal(r) - return b -} - -func PostActionIntegrationResponseFromJson(data io.Reader) *PostActionIntegrationResponse { - var o *PostActionIntegrationResponse - err := json.NewDecoder(data).Decode(&o) - if err != nil { - return nil - } - return o -} - -func SubmitDialogRequestFromJson(data io.Reader) *SubmitDialogRequest { - var o *SubmitDialogRequest - err := json.NewDecoder(data).Decode(&o) - if err != nil { - return nil - } - return o -} - -func (r *SubmitDialogRequest) ToJson() []byte { - b, _ := json.Marshal(r) - return b -} - -func SubmitDialogResponseFromJson(data io.Reader) *SubmitDialogResponse { - var o *SubmitDialogResponse - err := json.NewDecoder(data).Decode(&o) - if err != nil { - return nil - } - return o -} - -func (r *SubmitDialogResponse) ToJson() []byte { - b, _ := json.Marshal(r) - return b -} - func (o *Post) StripActionIntegrations() { attachments := o.Attachments() if o.GetProp("attachments") != nil { @@ -524,9 +468,3 @@ func DecryptPostActionCookie(encoded string, secret []byte) (string, error) { return string(plain), nil } - -func DoPostActionRequestFromJson(data io.Reader) *DoPostActionRequest { - var o *DoPostActionRequest - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/integration_action_test.go b/model/integration_action_test.go index 21f08b3de3..ac378bdd8f 100644 --- a/model/integration_action_test.go +++ b/model/integration_action_test.go @@ -4,12 +4,10 @@ package model import ( - "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "encoding/base64" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -17,7 +15,6 @@ import ( ) func TestTriggerIdDecodeAndVerification(t *testing.T) { - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) require.NoError(t, err) @@ -85,84 +82,6 @@ func TestTriggerIdDecodeAndVerification(t *testing.T) { }) } -func TestPostActionIntegrationRequestToJson(t *testing.T) { - o := PostActionIntegrationRequest{UserId: NewId(), Context: StringInterface{"a": "abc"}} - j := o.ToJson() - ro := PostActionIntegrationRequestFromJson(bytes.NewReader(j)) - - assert.NotNil(t, ro) - assert.Equal(t, o, *ro) -} - -func TestPostActionIntegrationRequestFromJsonError(t *testing.T) { - ro := PostActionIntegrationRequestFromJson(strings.NewReader("")) - assert.Nil(t, ro) -} - -func TestPostActionIntegrationResponseToJson(t *testing.T) { - o := PostActionIntegrationResponse{Update: &Post{Id: NewId(), Message: NewId()}, EphemeralText: NewId()} - j := o.ToJson() - ro := PostActionIntegrationResponseFromJson(bytes.NewReader(j)) - - assert.NotNil(t, ro) - assert.Equal(t, o, *ro) -} - -func TestPostActionIntegrationResponseFromJsonError(t *testing.T) { - ro := PostActionIntegrationResponseFromJson(strings.NewReader("")) - assert.Nil(t, ro) -} - -func TestSubmitDialogRequestToJson(t *testing.T) { - t.Run("all fine", func(t *testing.T) { - request := SubmitDialogRequest{ - URL: "http://example.org", - CallbackId: NewId(), - State: "some state", - UserId: NewId(), - ChannelId: NewId(), - TeamId: NewId(), - Submission: map[string]interface{}{ - "text": "some text", - "float": 1.2, - "bool": true, - }, - Cancelled: true, - } - jsonRequest := request.ToJson() - r := SubmitDialogRequestFromJson(bytes.NewReader(jsonRequest)) - - require.NotNil(t, r) - assert.Equal(t, request, *r) - }) - t.Run("error", func(t *testing.T) { - r := SubmitDialogRequestFromJson(strings.NewReader("")) - assert.Nil(t, r) - }) -} - -func TestSubmitDialogResponseToJson(t *testing.T) { - t.Run("all fine", func(t *testing.T) { - request := SubmitDialogResponse{ - Error: "some generic error", - Errors: map[string]string{ - "text": "some text", - "float": "1.2", - "bool": "true", - }, - } - jsonRequest := request.ToJson() - r := SubmitDialogResponseFromJson(bytes.NewReader(jsonRequest)) - - require.NotNil(t, r) - assert.Equal(t, request, *r) - }) - t.Run("error", func(t *testing.T) { - r := SubmitDialogResponseFromJson(strings.NewReader("")) - assert.Nil(t, r) - }) -} - func TestPostActionIntegrationEquals(t *testing.T) { t.Run("equal uncomparable types", func(t *testing.T) { pa1 := &PostAction{ diff --git a/model/job.go b/model/job.go index 5f0188df1f..13c6154f55 100644 --- a/model/job.go +++ b/model/job.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "time" ) @@ -117,37 +115,6 @@ func (j *Job) IsValid() *AppError { return nil } -func (j *Job) ToJson() string { - b, _ := json.Marshal(j) - return string(b) -} - -func JobFromJson(data io.Reader) *Job { - var job Job - if err := json.NewDecoder(data).Decode(&job); err == nil { - return &job - } - return nil -} - -func JobsToJson(jobs []*Job) string { - b, _ := json.Marshal(jobs) - return string(b) -} - -func JobsFromJson(data io.Reader) []*Job { - var jobs []*Job - if err := json.NewDecoder(data).Decode(&jobs); err == nil { - return jobs - } - return nil -} - -func (j *Job) DataToJson() string { - b, _ := json.Marshal(j.Data) - return string(b) -} - type Worker interface { Run() Stop() diff --git a/model/license.go b/model/license.go index cbdcf6d38c..d83a61f901 100644 --- a/model/license.go +++ b/model/license.go @@ -6,7 +6,6 @@ package model import ( "encoding/json" "fmt" - "io" "net/http" "time" ) @@ -73,11 +72,6 @@ type TrialLicenseRequest struct { ReceiveEmailsAccepted bool `json:"receive_emails_accepted"` } -func (tlr *TrialLicenseRequest) ToJson() string { - b, _ := json.Marshal(tlr) - return string(b) -} - type Features struct { Users *int `json:"users"` LDAP *bool `json:"ldap"` @@ -291,11 +285,6 @@ func (l *License) IsStarted() bool { return l.StartsAt < GetMillis() } -func (l *License) ToJson() string { - b, _ := json.Marshal(l) - return string(b) -} - func (l *License) IsTrialLicense() bool { return l.IsTrial || (l.ExpiresAt-l.StartsAt) == trialDuration.Milliseconds() || (l.ExpiresAt-l.StartsAt) == adminTrialDuration.Milliseconds() } @@ -333,12 +322,6 @@ func NewTestLicense(features ...string) *License { return ret } -func LicenseFromJson(data io.Reader) *License { - var o *License - json.NewDecoder(data).Decode(&o) - return o -} - func (lr *LicenseRecord) IsValid() *AppError { if !IsValidId(lr.Id) { return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.id.app_error", nil, "", http.StatusBadRequest) diff --git a/model/license_test.go b/model/license_test.go index f98e97dbb0..5a2dda7e55 100644 --- a/model/license_test.go +++ b/model/license_test.go @@ -143,70 +143,6 @@ func TestLicenseIsStarted(t *testing.T) { assert.False(t, l1.IsStarted()) } -func TestLicenseToFromJson(t *testing.T) { - f := Features{} - f.SetDefaults() - - l := License{ - Id: NewId(), - IssuedAt: GetMillis(), - StartsAt: GetMillis(), - ExpiresAt: GetMillis(), - Customer: &Customer{ - Id: NewId(), - Name: NewId(), - Email: NewId(), - Company: NewId(), - }, - Features: &f, - IsTrial: true, - } - - j := l.ToJson() - - l1 := LicenseFromJson(strings.NewReader(j)) - assert.NotNil(t, l1) - - CheckString(t, l1.Id, l.Id) - CheckInt64(t, l1.IssuedAt, l.IssuedAt) - CheckInt64(t, l1.StartsAt, l.StartsAt) - CheckInt64(t, l1.ExpiresAt, l.ExpiresAt) - CheckBool(t, l1.IsTrial, l.IsTrial) - - CheckString(t, l1.Customer.Id, l.Customer.Id) - CheckString(t, l1.Customer.Name, l.Customer.Name) - CheckString(t, l1.Customer.Email, l.Customer.Email) - CheckString(t, l1.Customer.Company, l.Customer.Company) - - f1 := l1.Features - - CheckInt(t, *f1.Users, *f.Users) - CheckBool(t, *f1.LDAP, *f.LDAP) - CheckBool(t, *f1.LDAPGroups, *f.LDAPGroups) - CheckBool(t, *f1.MFA, *f.MFA) - CheckBool(t, *f1.GoogleOAuth, *f.GoogleOAuth) - CheckBool(t, *f1.Office365OAuth, *f.Office365OAuth) - CheckBool(t, *f1.Compliance, *f.Compliance) - CheckBool(t, *f1.Cluster, *f.Cluster) - CheckBool(t, *f1.Metrics, *f.Metrics) - CheckBool(t, *f1.MHPNS, *f.MHPNS) - CheckBool(t, *f1.SAML, *f.SAML) - CheckBool(t, *f1.Elasticsearch, *f.Elasticsearch) - CheckBool(t, *f1.DataRetention, *f.DataRetention) - CheckBool(t, *f1.MessageExport, *f.MessageExport) - CheckBool(t, *f1.CustomPermissionsSchemes, *f.CustomPermissionsSchemes) - CheckBool(t, *f1.GuestAccounts, *f.GuestAccounts) - CheckBool(t, *f1.GuestAccountsPermissions, *f.GuestAccountsPermissions) - CheckBool(t, *f1.IDLoadedPushNotifications, *f.IDLoadedPushNotifications) - CheckBool(t, *f1.SharedChannels, *f.SharedChannels) - CheckBool(t, *f1.RemoteClusterService, *f.RemoteClusterService) - CheckBool(t, *f1.FutureFeatures, *f.FutureFeatures) - - invalid := `{"asdf` - l2 := LicenseFromJson(strings.NewReader(invalid)) - assert.Nil(t, l2) -} - func TestLicenseRecordIsValid(t *testing.T) { lr := LicenseRecord{ CreateAt: GetMillis(), diff --git a/model/link_metadata_test.go b/model/link_metadata_test.go index 19fbec8feb..81d390961e 100644 --- a/model/link_metadata_test.go +++ b/model/link_metadata_test.go @@ -160,14 +160,16 @@ func TestLinkMetadataDeserializeDataToConcreteType(t *testing.T) { Width: 500, } + js, err := json.Marshal(image) + assert.NoError(t, err) metadata := &LinkMetadata{ Type: LinkMetadataTypeImage, - Data: []byte(image.ToJson()), + Data: js, } require.IsType(t, []byte{}, metadata.Data) - err := metadata.DeserializeDataToConcreteType() + err = metadata.DeserializeDataToConcreteType() assert.NoError(t, err) assert.IsType(t, &PostImage{}, metadata.Data) diff --git a/model/manifest.go b/model/manifest.go index d37b8279fa..67b0d12091 100644 --- a/model/manifest.go +++ b/model/manifest.go @@ -6,7 +6,6 @@ package model import ( "encoding/json" "fmt" - "io" "io/ioutil" "os" "path/filepath" @@ -227,28 +226,6 @@ type ManifestWebapp struct { BundleHash []byte `json:"-"` } -func (m *Manifest) ToJson() string { - b, _ := json.Marshal(m) - return string(b) -} - -func ManifestListToJson(m []*Manifest) string { - b, _ := json.Marshal(m) - return string(b) -} - -func ManifestFromJson(data io.Reader) *Manifest { - var m *Manifest - json.NewDecoder(data).Decode(&m) - return m -} - -func ManifestListFromJson(data io.Reader) []*Manifest { - var manifests []*Manifest - json.NewDecoder(data).Decode(&manifests) - return manifests -} - func (m *Manifest) HasClient() bool { return m.Webapp != nil } diff --git a/model/manifest_test.go b/model/manifest_test.go index 43e4c0a668..ae816b340d 100644 --- a/model/manifest_test.go +++ b/model/manifest_test.go @@ -436,57 +436,6 @@ func TestFindManifest_FolderPermission(t *testing.T) { } } -func TestManifestJson(t *testing.T) { - manifest := &Manifest{ - Id: "theid", - Server: &ManifestServer{ - Executable: "theexecutable", - Executables: map[string]string{ - "linux-amd64": "linux-amd64/path/to/executable", - "darwin-amd64": "darwin-amd64/path/to/executable", - "windows-amd64": "windows-amd64/path/to/executable", - "linux-arm64": "linux-arm64/path/to/executable", - }, - }, - Webapp: &ManifestWebapp{ - BundlePath: "thebundlepath", - }, - SettingsSchema: &PluginSettingsSchema{ - Header: "theheadertext", - Footer: "thefootertext", - Settings: []*PluginSetting{ - { - Key: "thesetting", - DisplayName: "thedisplayname", - Type: "dropdown", - HelpText: "thehelptext", - RegenerateHelpText: "theregeneratehelptext", - Placeholder: "theplaceholder", - Options: []*PluginOption{ - { - DisplayName: "theoptiondisplayname", - Value: "thevalue", - }, - }, - Default: "thedefault", - }, - }, - }, - } - - json := manifest.ToJson() - newManifest := ManifestFromJson(strings.NewReader(json)) - assert.Equal(t, newManifest, manifest) - assert.Equal(t, newManifest.ToJson(), json) - assert.Equal(t, ManifestFromJson(strings.NewReader("junk")), (*Manifest)(nil)) - - manifestList := []*Manifest{manifest} - json = ManifestListToJson(manifestList) - newManifestList := ManifestListFromJson(strings.NewReader(json)) - assert.Equal(t, newManifestList, manifestList) - assert.Equal(t, ManifestListToJson(newManifestList), json) -} - func TestManifestHasClient(t *testing.T) { manifest := &Manifest{ Id: "theid", diff --git a/model/marketplace_plugin.go b/model/marketplace_plugin.go index cad93dfb03..8f0371b117 100644 --- a/model/marketplace_plugin.go +++ b/model/marketplace_plugin.go @@ -125,12 +125,3 @@ func PluginRequestFromReader(reader io.Reader) (*InstallMarketplacePluginRequest } return r, nil } - -// ToJson method will return json from plugin request. -func (r *InstallMarketplacePluginRequest) ToJson() (string, error) { - b, err := json.Marshal(r) - if err != nil { - return "", err - } - return string(b), nil -} diff --git a/model/mfa_secret.go b/model/mfa_secret.go index b229356617..8cfa675eb2 100644 --- a/model/mfa_secret.go +++ b/model/mfa_secret.go @@ -3,23 +3,7 @@ package model -import ( - "encoding/json" - "io" -) - type MfaSecret struct { Secret string `json:"secret"` QRCode string `json:"qr_code"` } - -func (mfa *MfaSecret) ToJson() string { - b, _ := json.Marshal(mfa) - return string(b) -} - -func MfaSecretFromJson(data io.Reader) *MfaSecret { - var mfa *MfaSecret - json.NewDecoder(data).Decode(&mfa) - return mfa -} diff --git a/model/mfa_secret_test.go b/model/mfa_secret_test.go deleted file mode 100644 index efe0027339..0000000000 --- a/model/mfa_secret_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMfaSecretJson(t *testing.T) { - secret := MfaSecret{Secret: NewId(), QRCode: NewId()} - json := secret.ToJson() - result := MfaSecretFromJson(strings.NewReader(json)) - - require.Equal(t, secret.Secret, result.Secret, "Secrets do not match") -} diff --git a/model/modeltestlib_test.go b/model/modeltestlib_test.go index 4705e88e7e..14c3f476b1 100644 --- a/model/modeltestlib_test.go +++ b/model/modeltestlib_test.go @@ -13,10 +13,6 @@ func CheckInt(t *testing.T, got int, expected int) { assert.Equal(t, got, expected) } -func CheckInt64(t *testing.T, got int64, expected int64) { - assert.Equal(t, got, expected) -} - func CheckString(t *testing.T, got string, expected string) { assert.Equal(t, got, expected) } @@ -28,7 +24,3 @@ func CheckTrue(t *testing.T, test bool) { func CheckFalse(t *testing.T, test bool) { assert.False(t, test) } - -func CheckBool(t *testing.T, got bool, expected bool) { - assert.Equal(t, got, expected) -} diff --git a/model/oauth.go b/model/oauth.go index 7e32908eb1..a3d7f95fac 100644 --- a/model/oauth.go +++ b/model/oauth.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" "unicode/utf8" ) @@ -108,11 +106,6 @@ func (a *OAuthApp) PreUpdate() { a.UpdateAt = GetMillis() } -func (a *OAuthApp) ToJson() string { - b, _ := json.Marshal(a) - return string(b) -} - // Generate a valid strong etag so the browser can cache the results func (a *OAuthApp) Etag() string { return Etag(a.Id, a.UpdateAt) @@ -132,20 +125,3 @@ func (a *OAuthApp) IsValidRedirectURL(url string) bool { return false } - -func OAuthAppFromJson(data io.Reader) *OAuthApp { - var app *OAuthApp - json.NewDecoder(data).Decode(&app) - return app -} - -func OAuthAppListToJson(l []*OAuthApp) string { - b, _ := json.Marshal(l) - return string(b) -} - -func OAuthAppListFromJson(data io.Reader) []*OAuthApp { - var o []*OAuthApp - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/oauth_test.go b/model/oauth_test.go index eeee7673ea..f3255865c8 100644 --- a/model/oauth_test.go +++ b/model/oauth_test.go @@ -4,27 +4,11 @@ package model import ( - "strings" "testing" "github.com/stretchr/testify/require" ) -func TestOAuthAppJson(t *testing.T) { - a1 := OAuthApp{} - a1.Id = NewId() - a1.Name = "TestOAuthApp" + NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - a1.IconURL = "https://nowhere.com/icon_image.png" - a1.ClientSecret = NewId() - - json := a1.ToJson() - ra1 := OAuthAppFromJson(strings.NewReader(json)) - - require.Equal(t, a1.Id, ra1.Id, "ids did not match") -} - func TestOAuthAppPreSave(t *testing.T) { a1 := OAuthApp{} a1.Id = NewId() diff --git a/model/outgoing_webhook.go b/model/outgoing_webhook.go index 10abbd52e0..b24aed67e1 100644 --- a/model/outgoing_webhook.go +++ b/model/outgoing_webhook.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" "net/url" "strconv" @@ -59,11 +57,6 @@ type OutgoingWebhookResponse struct { const OutgoingHookResponseTypeComment = "comment" -func (o *OutgoingWebhookPayload) ToJSON() string { - b, _ := json.Marshal(o) - return string(b) -} - func (o *OutgoingWebhookPayload) ToFormValues() string { v := url.Values{} v.Set("token", o.Token) @@ -82,42 +75,6 @@ func (o *OutgoingWebhookPayload) ToFormValues() string { return v.Encode() } -func (o *OutgoingWebhook) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func OutgoingWebhookFromJson(data io.Reader) *OutgoingWebhook { - var o *OutgoingWebhook - json.NewDecoder(data).Decode(&o) - return o -} - -func OutgoingWebhookListToJson(l []*OutgoingWebhook) string { - b, _ := json.Marshal(l) - return string(b) -} - -func OutgoingWebhookListFromJson(data io.Reader) []*OutgoingWebhook { - var o []*OutgoingWebhook - json.NewDecoder(data).Decode(&o) - return o -} - -func (o *OutgoingWebhookResponse) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func OutgoingWebhookResponseFromJson(data io.Reader) (*OutgoingWebhookResponse, error) { - var o *OutgoingWebhookResponse - err := json.NewDecoder(data).Decode(&o) - if err == io.EOF { - return nil, nil - } - return o, err -} - func (o *OutgoingWebhook) IsValid() *AppError { if !IsValidId(o.Id) { diff --git a/model/outgoing_webhook_test.go b/model/outgoing_webhook_test.go index 03d3ad7273..d4a8b0b73d 100644 --- a/model/outgoing_webhook_test.go +++ b/model/outgoing_webhook_test.go @@ -11,14 +11,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestOutgoingWebhookJson(t *testing.T) { - o := OutgoingWebhook{Id: NewId()} - json := o.ToJson() - ro := OutgoingWebhookFromJson(strings.NewReader(json)) - - assert.Equal(t, o.Id, ro.Id, "Ids do not match") -} - func TestOutgoingWebhookIsValid(t *testing.T) { o := OutgoingWebhook{} assert.NotNil(t, o.IsValid(), "empty declaration should be invalid") @@ -142,13 +134,3 @@ func TestOutgoingWebhookTriggerWordStartsWith(t *testing.T) { assert.True(t, o.TriggerWordStartsWith("foobar"), "Should return true") assert.False(t, o.TriggerWordStartsWith("barfoo"), "Should return false") } - -func TestOutgoingWebhookResponseJson(t *testing.T) { - o := OutgoingWebhookResponse{} - o.Text = NewString("some text") - - json := o.ToJson() - ro, _ := OutgoingWebhookResponseFromJson(strings.NewReader(json)) - - assert.Equal(t, *o.Text, *ro.Text, "Text does not match") -} diff --git a/model/permalink.go b/model/permalink.go index b6d3284ed3..6a19fb7576 100644 --- a/model/permalink.go +++ b/model/permalink.go @@ -3,8 +3,6 @@ package model -import "encoding/json" - type Permalink struct { PreviewPost *PreviewPost `json:"preview_post"` } @@ -27,8 +25,3 @@ func NewPreviewPost(post *Post, team *Team, channel *Channel) *PreviewPost { ChannelDisplayName: channel.DisplayName, } } - -func (o *Permalink) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} diff --git a/model/plugin_event_data.go b/model/plugin_event_data.go index c704c99339..1253533d11 100644 --- a/model/plugin_event_data.go +++ b/model/plugin_event_data.go @@ -3,23 +3,7 @@ package model -import ( - "encoding/json" - "io" -) - // PluginEventData used to notify peers about plugin changes. type PluginEventData struct { Id string `json:"id"` } - -func (p *PluginEventData) ToJson() string { - b, _ := json.Marshal(p) - return string(b) -} - -func PluginEventDataFromJson(data io.Reader) PluginEventData { - var m PluginEventData - json.NewDecoder(data).Decode(&m) - return m -} diff --git a/model/plugin_status.go b/model/plugin_status.go index b4ba2e7340..c206505be3 100644 --- a/model/plugin_status.go +++ b/model/plugin_status.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - const ( PluginStateNotRunning = 0 PluginStateStarting = 1 // unused by server @@ -29,14 +24,3 @@ type PluginStatus struct { } type PluginStatuses []*PluginStatus - -func (m *PluginStatuses) ToJson() string { - b, _ := json.Marshal(m) - return string(b) -} - -func PluginStatusesFromJson(data io.Reader) PluginStatuses { - var m PluginStatuses - json.NewDecoder(data).Decode(&m) - return m -} diff --git a/model/plugins_response.go b/model/plugins_response.go index 421ee2f545..5aed0b3c62 100644 --- a/model/plugins_response.go +++ b/model/plugins_response.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type PluginInfo struct { Manifest } @@ -16,14 +11,3 @@ type PluginsResponse struct { Active []*PluginInfo `json:"active"` Inactive []*PluginInfo `json:"inactive"` } - -func (m *PluginsResponse) ToJson() string { - b, _ := json.Marshal(m) - return string(b) -} - -func PluginsResponseFromJson(data io.Reader) *PluginsResponse { - var m *PluginsResponse - json.NewDecoder(data).Decode(&m) - return m -} diff --git a/model/plugins_response_test.go b/model/plugins_response_test.go deleted file mode 100644 index dbe6d3433c..0000000000 --- a/model/plugins_response_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPluginsResponseJson(t *testing.T) { - manifest := &Manifest{ - Id: "theid", - Server: &ManifestServer{ - Executable: "theexecutable", - }, - Webapp: &ManifestWebapp{ - BundlePath: "thebundlepath", - }, - } - - response := &PluginsResponse{ - Active: []*PluginInfo{{Manifest: *manifest}}, - Inactive: []*PluginInfo{}, - } - - json := response.ToJson() - newResponse := PluginsResponseFromJson(strings.NewReader(json)) - assert.Equal(t, newResponse, response) - assert.Equal(t, newResponse.ToJson(), json) - assert.Equal(t, PluginsResponseFromJson(strings.NewReader("junk")), (*PluginsResponse)(nil)) -} diff --git a/model/post.go b/model/post.go index 98303a509c..d889c86cb4 100644 --- a/model/post.go +++ b/model/post.go @@ -6,7 +6,6 @@ package model import ( "encoding/json" "errors" - "io" "net/http" "regexp" "sort" @@ -221,16 +220,11 @@ func (o *Post) Clone() *Post { return copy } -func (o *Post) ToJson() string { +func (o *Post) ToJSON() (string, error) { copy := o.Clone() copy.StripActionIntegrations() - b, _ := json.Marshal(copy) - return string(b) -} - -func (o *Post) ToUnsanitizedJson() string { - b, _ := json.Marshal(o) - return string(b) + b, err := json.Marshal(copy) + return string(b), err } type GetPostsSinceOptions struct { @@ -265,12 +259,6 @@ type GetPostsOptions struct { CollapsedThreadsExtended bool } -func PostFromJson(data io.Reader) *Post { - var o *Post - json.NewDecoder(data).Decode(&o) - return o -} - func (o *Post) Etag() string { return Etag(o.Id, o.UpdateAt) } @@ -347,15 +335,15 @@ func (o *Post) IsValid(maxPostSize int) *AppError { } } - if utf8.RuneCountInString(ArrayToJson(o.Filenames)) > PostFilenamesMaxRunes { + if utf8.RuneCountInString(ArrayToJSON(o.Filenames)) > PostFilenamesMaxRunes { return NewAppError("Post.IsValid", "model.post.is_valid.filenames.app_error", nil, "id="+o.Id, http.StatusBadRequest) } - if utf8.RuneCountInString(ArrayToJson(o.FileIds)) > PostFileidsMaxRunes { + if utf8.RuneCountInString(ArrayToJSON(o.FileIds)) > PostFileidsMaxRunes { return NewAppError("Post.IsValid", "model.post.is_valid.file_ids.app_error", nil, "id="+o.Id, http.StatusBadRequest) } - if utf8.RuneCountInString(StringInterfaceToJson(o.GetProps())) > PostPropsMaxRunes { + if utf8.RuneCountInString(StringInterfaceToJSON(o.GetProps())) > PostPropsMaxRunes { return NewAppError("Post.IsValid", "model.post.is_valid.props.app_error", nil, "id="+o.Id, http.StatusBadRequest) } @@ -513,45 +501,6 @@ func (o *Post) Patch(patch *PostPatch) { } } -func (o *PostPatch) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } - - return string(b) -} - -func PostPatchFromJson(data io.Reader) *PostPatch { - decoder := json.NewDecoder(data) - var post PostPatch - err := decoder.Decode(&post) - if err != nil { - return nil - } - - return &post -} - -func (o *SearchParameter) SearchParameterToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } - - return string(b) -} - -func SearchParameterFromJson(data io.Reader) (*SearchParameter, error) { - decoder := json.NewDecoder(data) - var searchParam SearchParameter - if err := decoder.Decode(&searchParam); err != nil { - return nil, err - } - - return &searchParam, nil -} - func (o *Post) ChannelMentions() []string { return ChannelMentions(o.Message) } @@ -660,11 +609,6 @@ func (o *Post) WithRewrittenImageURLs(f func(string) string) *Post { return copy } -func (o *PostEphemeral) ToUnsanitizedJson() string { - b, _ := json.Marshal(o) - return string(b) -} - // RewriteImageURLs takes a message and returns a copy that has all of the image URLs replaced // according to the function f. For each image URL, f will be invoked, and the resulting markdown // will contain the URL returned by that invocation instead. diff --git a/model/post_list.go b/model/post_list.go index 5236dd88d9..933d1f8fdb 100644 --- a/model/post_list.go +++ b/model/post_list.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io" "sort" ) @@ -74,14 +73,11 @@ func (o *PostList) StripActionIntegrations() { } } -func (o *PostList) ToJson() string { +func (o *PostList) ToJSON() (string, error) { copy := *o copy.StripActionIntegrations() b, err := json.Marshal(©) - if err != nil { - return "" - } - return string(b) + return string(b), err } func (o *PostList) MakeNonNil() { @@ -179,9 +175,3 @@ func (o *PostList) IsChannelId(channelId string) bool { return true } - -func PostListFromJson(data io.Reader) *PostList { - var o *PostList - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/post_list_test.go b/model/post_list_test.go index 7f0c4dfab8..1fc9476b64 100644 --- a/model/post_list_test.go +++ b/model/post_list_test.go @@ -4,14 +4,13 @@ package model import ( - "strings" + "encoding/json" "testing" "github.com/stretchr/testify/assert" ) func TestPostListJson(t *testing.T) { - pl := PostList{} p1 := &Post{Id: NewId(), Message: NewId()} pl.AddPost(p1) @@ -21,8 +20,12 @@ func TestPostListJson(t *testing.T) { pl.AddOrder(p1.Id) pl.AddOrder(p2.Id) - json := pl.ToJson() - rpl := PostListFromJson(strings.NewReader(json)) + js, err := pl.ToJSON() + assert.NoError(t, err) + + var rpl PostList + err = json.Unmarshal([]byte(js), &rpl) + assert.NoError(t, err) assert.Equal(t, p1.Message, rpl.Posts[p1.Id].Message, "failed to serialize p1 message") assert.Equal(t, p2.Message, rpl.Posts[p2.Id].Message, "failed to serialize p2 message") diff --git a/model/post_metadata.go b/model/post_metadata.go index 7b0687ca08..a316eb771f 100644 --- a/model/post_metadata.go +++ b/model/post_metadata.go @@ -3,10 +3,6 @@ package model -import ( - "encoding/json" -) - type PostMetadata struct { // Embeds holds information required to render content embedded in the post. This includes the OpenGraph metadata // for links in the post. @@ -38,8 +34,3 @@ type PostImage struct { // FrameCount stores the number of frames in this image, if it is an animated gif. It will be 0 for other formats. FrameCount int `json:"frame_count"` } - -func (o *PostImage) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} diff --git a/model/post_search_results.go b/model/post_search_results.go index fc9ba083df..92e044a7f8 100644 --- a/model/post_search_results.go +++ b/model/post_search_results.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io" ) type PostSearchMatches map[string][]string @@ -22,18 +21,9 @@ func MakePostSearchResults(posts *PostList, matches PostSearchMatches) *PostSear } } -func (o *PostSearchResults) ToJson() string { +func (o *PostSearchResults) ToJSON() (string, error) { copy := *o copy.PostList.StripActionIntegrations() b, err := json.Marshal(©) - if err != nil { - return "" - } - return string(b) -} - -func PostSearchResultsFromJson(data io.Reader) *PostSearchResults { - var o *PostSearchResults - json.NewDecoder(data).Decode(&o) - return o + return string(b), err } diff --git a/model/post_test.go b/model/post_test.go index 1b1649c0d7..d8e6fbd100 100644 --- a/model/post_test.go +++ b/model/post_test.go @@ -4,6 +4,7 @@ package model import ( + "encoding/json" "io/ioutil" "strings" "sync" @@ -13,20 +14,16 @@ import ( "github.com/stretchr/testify/require" ) -func TestPostToJson(t *testing.T) { +func TestPostToJSON(t *testing.T) { o := Post{Id: NewId(), Message: NewId()} - j := o.ToJson() - ro := PostFromJson(strings.NewReader(j)) - - assert.NotNil(t, ro) + j, err := o.ToJSON() + assert.NoError(t, err) + var ro Post + err = json.Unmarshal([]byte(j), &ro) + assert.NoError(t, err) assert.Equal(t, &o, ro.Clone()) } -func TestPostFromJsonError(t *testing.T) { - ro := PostFromJson(strings.NewReader("")) - assert.Nil(t, ro) -} - func TestPostIsValid(t *testing.T) { o := Post{} maxPostSize := 10000 @@ -849,34 +846,6 @@ func TestPostPatchDisableMentionHighlights(t *testing.T) { }) } -func TestSearchParameterFromJson(t *testing.T) { - t.Run("empty input", func(t *testing.T) { - params, err := SearchParameterFromJson(strings.NewReader("")) - require.Nil(t, params) - require.Error(t, err) - }) - - t.Run("invalid json", func(t *testing.T) { - params, err := SearchParameterFromJson(strings.NewReader("invalid")) - require.Nil(t, params) - require.Error(t, err) - }) - - t.Run("valid empty input", func(t *testing.T) { - params, err := SearchParameterFromJson(strings.NewReader("{}")) - require.NoError(t, err) - require.NotNil(t, params) - require.Equal(t, &SearchParameter{}, params) - }) - - t.Run("valid non-empty input", func(t *testing.T) { - params, err := SearchParameterFromJson(strings.NewReader("{\"terms\": \"test\"}")) - require.NoError(t, err) - require.NotNil(t, params) - require.Equal(t, "test", *params.Terms) - }) -} - func TestPostAttachments(t *testing.T) { p := &Post{ Props: map[string]interface{}{ diff --git a/model/preference.go b/model/preference.go index d1f8c2e9cf..41a5823528 100644 --- a/model/preference.go +++ b/model/preference.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io" "net/http" "regexp" "strings" @@ -65,16 +64,7 @@ type Preference struct { Value string `json:"value"` } -func (o *Preference) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func PreferenceFromJson(data io.Reader) *Preference { - var o *Preference - json.NewDecoder(data).Decode(&o) - return o -} +type Preferences []Preference func (o *Preference) IsValid() *AppError { if !IsValidId(o.UserId) { diff --git a/model/preferences.go b/model/preferences.go deleted file mode 100644 index c2d2486547..0000000000 --- a/model/preferences.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "encoding/json" - "io" -) - -type Preferences []Preference - -func (o *Preferences) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func PreferencesFromJson(data io.Reader) (Preferences, error) { - decoder := json.NewDecoder(data) - var o Preferences - err := decoder.Decode(&o) - if err != nil { - return nil, err - } - return o, nil -} diff --git a/model/push_notification.go b/model/push_notification.go index a8b214ff85..cad84f830e 100644 --- a/model/push_notification.go +++ b/model/push_notification.go @@ -4,9 +4,6 @@ package model import ( - "encoding/json" - "errors" - "io" "strings" ) @@ -70,18 +67,12 @@ type PushNotification struct { IsIdLoaded bool `json:"is_id_loaded"` } -func (pn *PushNotification) ToJson() string { - b, _ := json.Marshal(pn) - return string(b) -} - func (pn *PushNotification) DeepCopy() *PushNotification { copy := *pn return © } func (pn *PushNotification) SetDeviceIdAndPlatform(deviceId string) { - index := strings.Index(deviceId, ":") if index > -1 { @@ -89,30 +80,3 @@ func (pn *PushNotification) SetDeviceIdAndPlatform(deviceId string) { pn.DeviceId = deviceId[index+1:] } } - -func PushNotificationFromJson(data io.Reader) (*PushNotification, error) { - if data == nil { - return nil, errors.New("push notification data can't be nil") - } - var pn *PushNotification - if err := json.NewDecoder(data).Decode(&pn); err != nil { - return nil, err - } - return pn, nil -} - -func PushNotificationAckFromJson(data io.Reader) (*PushNotificationAck, error) { - if data == nil { - return nil, errors.New("push notification data can't be nil") - } - var ack *PushNotificationAck - if err := json.NewDecoder(data).Decode(&ack); err != nil { - return nil, err - } - return ack, nil -} - -func (ack *PushNotificationAck) ToJson() string { - b, _ := json.Marshal(ack) - return string(b) -} diff --git a/model/push_notification_test.go b/model/push_notification_test.go index 0fea71da57..d4876c0a0f 100644 --- a/model/push_notification_test.go +++ b/model/push_notification_test.go @@ -4,58 +4,11 @@ package model import ( - "strings" "testing" "github.com/stretchr/testify/require" ) -func TestPushNotification(t *testing.T) { - t.Run("should build a push notification from JSON", func(t *testing.T) { - msg := PushNotification{Platform: "test"} - json := msg.ToJson() - result, err := PushNotificationFromJson(strings.NewReader(json)) - - require.NoError(t, err) - require.Equal(t, msg.Platform, result.Platform, "ids do not match") - }) - - t.Run("should throw an error when the message is nil", func(t *testing.T) { - _, err := PushNotificationFromJson(nil) - require.Error(t, err) - require.Equal(t, "push notification data can't be nil", err.Error()) - }) - - t.Run("should throw an error when the message parsing fails", func(t *testing.T) { - _, err := PushNotificationFromJson(strings.NewReader("")) - require.Error(t, err) - require.Equal(t, "EOF", err.Error()) - }) -} - -func TestPushNotificationAck(t *testing.T) { - t.Run("should build a push notification ack from JSON", func(t *testing.T) { - msg := PushNotificationAck{ClientPlatform: "test"} - json := msg.ToJson() - result, err := PushNotificationAckFromJson(strings.NewReader(json)) - - require.NoError(t, err) - require.Equal(t, msg.ClientPlatform, result.ClientPlatform, "ids do not match") - }) - - t.Run("should throw an error when the message is nil", func(t *testing.T) { - _, err := PushNotificationAckFromJson(nil) - require.Error(t, err) - require.Equal(t, "push notification data can't be nil", err.Error()) - }) - - t.Run("should throw an error when the message parsing fails", func(t *testing.T) { - _, err := PushNotificationAckFromJson(strings.NewReader("")) - require.Error(t, err) - require.Equal(t, "EOF", err.Error()) - }) -} - func TestPushNotificationDeviceId(t *testing.T) { msg := PushNotification{Platform: "test"} diff --git a/model/push_response.go b/model/push_response.go index 85e6b44748..a88b43393a 100644 --- a/model/push_response.go +++ b/model/push_response.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - const ( PushStatus = "status" PushStatusOk = "OK" @@ -36,18 +31,3 @@ func NewErrorPushResponse(message string) PushResponse { m[PushStatusErrorMsg] = message return m } - -func (pr *PushResponse) ToJson() string { - b, _ := json.Marshal(pr) - return string(b) -} - -func PushResponseFromJson(data io.Reader) PushResponse { - decoder := json.NewDecoder(data) - - var objmap PushResponse - if err := decoder.Decode(&objmap); err != nil { - return make(map[string]string) - } - return objmap -} diff --git a/model/push_response_test.go b/model/push_response_test.go index 4660aa7232..aa41379454 100644 --- a/model/push_response_test.go +++ b/model/push_response_test.go @@ -4,7 +4,6 @@ package model import ( - "strings" "testing" ) @@ -23,12 +22,3 @@ func TestNewErrorPushResponse(t *testing.T) { CheckString(t, r["status"], "FAIL") CheckString(t, r["error"], "error message") } - -func TestPushResponseToFromJson(t *testing.T) { - r := NewErrorPushResponse("error message") - j := r.ToJson() - r1 := PushResponseFromJson(strings.NewReader(j)) - - CheckString(t, r1["status"], r["status"]) - CheckString(t, r1["error"], r["error"]) -} diff --git a/model/reaction.go b/model/reaction.go index d0497f33b2..335cb904b0 100644 --- a/model/reaction.go +++ b/model/reaction.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "regexp" ) @@ -20,49 +18,6 @@ type Reaction struct { RemoteId *string `json:"remote_id"` } -func (o *Reaction) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func ReactionFromJson(data io.Reader) *Reaction { - var o Reaction - - if err := json.NewDecoder(data).Decode(&o); err != nil { - return nil - } - return &o -} - -func ReactionsToJson(o []*Reaction) string { - b, _ := json.Marshal(o) - return string(b) -} - -func MapPostIdToReactionsToJson(o map[string][]*Reaction) string { - b, _ := json.Marshal(o) - return string(b) -} - -func MapPostIdToReactionsFromJson(data io.Reader) map[string][]*Reaction { - decoder := json.NewDecoder(data) - - var objmap map[string][]*Reaction - if err := decoder.Decode(&objmap); err != nil { - return make(map[string][]*Reaction) - } - return objmap -} - -func ReactionsFromJson(data io.Reader) []*Reaction { - var o []*Reaction - - if err := json.NewDecoder(data).Decode(&o); err != nil { - return nil - } - return o -} - func (o *Reaction) IsValid() *AppError { if !IsValidId(o.UserId) { return NewAppError("Reaction.IsValid", "model.reaction.is_valid.user_id.app_error", nil, "user_id="+o.UserId, http.StatusBadRequest) diff --git a/model/remote_cluster.go b/model/remote_cluster.go index 2ec0cc9b6c..44d11f1697 100644 --- a/model/remote_cluster.go +++ b/model/remote_cluster.go @@ -127,14 +127,6 @@ func (rc *RemoteCluster) fixTopics() { rc.Topics = sb.String() } -func (rc *RemoteCluster) ToJSON() (string, error) { - b, err := json.Marshal(rc) - if err != nil { - return "", err - } - return string(b), nil -} - func (rc *RemoteCluster) ToRemoteClusterInfo() RemoteClusterInfo { return RemoteClusterInfo{ Name: rc.Name, @@ -148,15 +140,6 @@ func NormalizeRemoteName(name string) string { return strings.ToLower(name) } -func RemoteClusterFromJSON(data io.Reader) (*RemoteCluster, *AppError) { - var rc RemoteCluster - err := json.NewDecoder(data).Decode(&rc) - if err != nil { - return nil, NewAppError("RemoteClusterFromJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return &rc, nil -} - // RemoteClusterInfo provides a subset of RemoteCluster fields suitable for sending to clients. type RemoteClusterInfo struct { Name string `json:"name"` @@ -183,15 +166,6 @@ func (f *RemoteClusterFrame) IsValid() *AppError { return nil } -func RemoteClusterFrameFromJSON(data io.Reader) (*RemoteClusterFrame, *AppError) { - var frame RemoteClusterFrame - err := json.NewDecoder(data).Decode(&frame) - if err != nil { - return nil, NewAppError("RemoteClusterFrameFromJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return &frame, nil -} - // RemoteClusterMsg represents a message that is sent and received between clusters. // These are processed and routed via the RemoteClusters service. type RemoteClusterMsg struct { @@ -226,15 +200,6 @@ func (m RemoteClusterMsg) IsValid() *AppError { return nil } -func RemoteClusterMsgFromJSON(data io.Reader) (RemoteClusterMsg, *AppError) { - var msg RemoteClusterMsg - err := json.NewDecoder(data).Decode(&msg) - if err != nil { - return RemoteClusterMsg{}, NewAppError("RemoteClusterMsgFromJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return msg, nil -} - // RemoteClusterPing represents a ping that is sent and received between clusters // to indicate a connection is alive. This is the payload for a `RemoteClusterMsg`. type RemoteClusterPing struct { @@ -242,15 +207,6 @@ type RemoteClusterPing struct { RecvAt int64 `json:"recv_at"` } -func RemoteClusterPingFromRawJSON(raw json.RawMessage) (RemoteClusterPing, *AppError) { - var ping RemoteClusterPing - err := json.Unmarshal(raw, &ping) - if err != nil { - return RemoteClusterPing{}, NewAppError("RemoteClusterPingFromRawJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return ping, nil -} - // RemoteClusterInvite represents an invitation to establish a simple trust with a remote cluster. type RemoteClusterInvite struct { RemoteId string `json:"remote_id"` @@ -259,15 +215,6 @@ type RemoteClusterInvite struct { Token string `json:"token"` } -func RemoteClusterInviteFromRawJSON(raw json.RawMessage) (*RemoteClusterInvite, *AppError) { - var invite RemoteClusterInvite - err := json.Unmarshal(raw, &invite) - if err != nil { - return nil, NewAppError("RemoteClusterInviteFromRawJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return &invite, nil -} - func (rci *RemoteClusterInvite) Encrypt(password string) ([]byte, error) { raw, err := json.Marshal(&rci) if err != nil { diff --git a/model/remote_cluster_test.go b/model/remote_cluster_test.go index 37a60c944c..6cc914d637 100644 --- a/model/remote_cluster_test.go +++ b/model/remote_cluster_test.go @@ -5,28 +5,13 @@ package model import ( "crypto/rand" - "encoding/json" "io" - "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestRemoteClusterJson(t *testing.T) { - o := RemoteCluster{RemoteId: NewId(), Name: "test"} - - json, err := o.ToJSON() - require.NoError(t, err) - - ro, appErr := RemoteClusterFromJSON(strings.NewReader(json)) - require.Nil(t, appErr) - - require.Equal(t, o.RemoteId, ro.RemoteId) - require.Equal(t, o.Name, ro.Name) -} - func TestRemoteClusterIsValid(t *testing.T) { id := NewId() creator := NewId() @@ -66,20 +51,6 @@ func TestRemoteClusterPreSave(t *testing.T) { require.GreaterOrEqual(t, o.CreateAt, now) } -func TestRemoteClusterMsgJson(t *testing.T) { - o := NewRemoteClusterMsg("shared_channel", []byte("{\"hello\":\"world\"}")) - - json, err := json.Marshal(o) - require.NoError(t, err) - - ro, appErr := RemoteClusterMsgFromJSON(strings.NewReader(string(json))) - require.Nil(t, appErr) - - require.Equal(t, o.Id, ro.Id) - require.Equal(t, o.CreateAt, ro.CreateAt) - require.Equal(t, o.Topic, ro.Topic) -} - func TestRemoteClusterMsgIsValid(t *testing.T) { id := NewId() now := GetMillis() diff --git a/model/role.go b/model/role.go index b0020e9e24..55c22b910f 100644 --- a/model/role.go +++ b/model/role.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "strings" ) @@ -399,39 +397,6 @@ type RolePermissions struct { Permissions []string } -func (r *Role) ToJson() string { - b, _ := json.Marshal(r) - return string(b) -} - -func RoleFromJson(data io.Reader) *Role { - var r *Role - json.NewDecoder(data).Decode(&r) - return r -} - -func RoleListToJson(r []*Role) string { - b, _ := json.Marshal(r) - return string(b) -} - -func RoleListFromJson(data io.Reader) []*Role { - var roles []*Role - json.NewDecoder(data).Decode(&roles) - return roles -} - -func (r *RolePatch) ToJson() string { - b, _ := json.Marshal(r) - return string(b) -} - -func RolePatchFromJson(data io.Reader) *RolePatch { - var rolePatch *RolePatch - json.NewDecoder(data).Decode(&rolePatch) - return rolePatch -} - func (r *Role) Patch(patch *RolePatch) { if patch.Permissions != nil { r.Permissions = *patch.Permissions diff --git a/model/saml.go b/model/saml.go index 2723e78537..e9e987d8ac 100644 --- a/model/saml.go +++ b/model/saml.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "encoding/xml" - "io" "time" ) @@ -176,25 +174,3 @@ type EntityDescriptor struct { Organization Organization `xml:"Organization"` ContactPerson ContactPerson `xml:"ContactPerson"` } - -func (s *SamlCertificateStatus) ToJson() string { - b, _ := json.Marshal(s) - return string(b) -} - -func SamlCertificateStatusFromJson(data io.Reader) *SamlCertificateStatus { - var status *SamlCertificateStatus - json.NewDecoder(data).Decode(&status) - return status -} - -func (s *SamlMetadataResponse) ToJson() string { - b, _ := json.Marshal(s) - return string(b) -} - -func SamlMetadataResponseFromJson(data io.Reader) *SamlMetadataResponse { - var status *SamlMetadataResponse - json.NewDecoder(data).Decode(&status) - return status -} diff --git a/model/saml_test.go b/model/saml_test.go deleted file mode 100644 index 26a5d8ee57..0000000000 --- a/model/saml_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestSamlCertificateStatusJson(t *testing.T) { - status := &SamlCertificateStatus{IdpCertificateFile: true, PrivateKeyFile: true, PublicCertificateFile: true} - json := status.ToJson() - rstatus := SamlCertificateStatusFromJson(strings.NewReader(json)) - - require.Equal(t, status.IdpCertificateFile, rstatus.IdpCertificateFile, "IdpCertificateFile do not match") - - rstatus = SamlCertificateStatusFromJson(strings.NewReader("junk")) - require.Nil(t, rstatus, "should be nil") -} diff --git a/model/scheme.go b/model/scheme.go index d77afca134..c861c1e66e 100644 --- a/model/scheme.go +++ b/model/scheme.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "regexp" ) @@ -81,30 +79,6 @@ type SchemeRoles struct { SchemeGuest bool `json:"scheme_guest"` } -func (scheme *Scheme) ToJson() string { - b, _ := json.Marshal(scheme) - return string(b) -} - -func SchemeFromJson(data io.Reader) *Scheme { - var scheme *Scheme - json.NewDecoder(data).Decode(&scheme) - return scheme -} - -func SchemesToJson(schemes []*Scheme) string { - b, _ := json.Marshal(schemes) - return string(b) -} - -func SchemesFromJson(data io.Reader) []*Scheme { - var schemes []*Scheme - if err := json.NewDecoder(data).Decode(&schemes); err == nil { - return schemes - } - return nil -} - func (scheme *Scheme) IsValid() bool { if !IsValidId(scheme.Id) { return false @@ -187,40 +161,7 @@ func (scheme *Scheme) Patch(patch *SchemePatch) { } } -func (patch *SchemePatch) ToJson() string { - b, _ := json.Marshal(patch) - return string(b) -} - -func SchemePatchFromJson(data io.Reader) *SchemePatch { - var patch *SchemePatch - json.NewDecoder(data).Decode(&patch) - return patch -} - -func SchemeIDFromJson(data io.Reader) *string { - var p *SchemeIDPatch - json.NewDecoder(data).Decode(&p) - return p.SchemeID -} - -func (p *SchemeIDPatch) ToJson() string { - b, _ := json.Marshal(p) - return string(b) -} - func IsValidSchemeName(name string) bool { re := regexp.MustCompile(fmt.Sprintf("^[a-z0-9_]{2,%d}$", SchemeNameMaxLength)) return re.MatchString(name) } - -func (schemeRoles *SchemeRoles) ToJson() string { - b, _ := json.Marshal(schemeRoles) - return string(b) -} - -func SchemeRolesFromJson(data io.Reader) *SchemeRoles { - var schemeRoles *SchemeRoles - json.NewDecoder(data).Decode(&schemeRoles) - return schemeRoles -} diff --git a/model/security_bulletin.go b/model/security_bulletin.go index 66a65812a5..fa5662cfdc 100644 --- a/model/security_bulletin.go +++ b/model/security_bulletin.go @@ -3,39 +3,9 @@ package model -import ( - "encoding/json" - "io" -) - type SecurityBulletin struct { Id string `json:"id"` AppliesToVersion string `json:"applies_to_version"` } type SecurityBulletins []SecurityBulletin - -func (sb *SecurityBulletin) ToJson() string { - b, _ := json.Marshal(sb) - return string(b) -} - -func SecurityBulletinFromJson(data io.Reader) *SecurityBulletin { - var o *SecurityBulletin - json.NewDecoder(data).Decode(&o) - return o -} - -func (sb SecurityBulletins) ToJson() string { - b, err := json.Marshal(sb) - if err != nil { - return "[]" - } - return string(b) -} - -func SecurityBulletinsFromJson(data io.Reader) SecurityBulletins { - var o SecurityBulletins - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/security_bulletin_test.go b/model/security_bulletin_test.go deleted file mode 100644 index ff2bbb1405..0000000000 --- a/model/security_bulletin_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestSecurityBulletinToFromJson(t *testing.T) { - b := SecurityBulletin{ - Id: NewId(), - AppliesToVersion: NewId(), - } - - j := b.ToJson() - b1 := SecurityBulletinFromJson(strings.NewReader(j)) - - require.Equal(t, b, *b1) - - // Malformed JSON - s2 := `{"wat"` - b2 := SecurityBulletinFromJson(strings.NewReader(s2)) - require.Nil(t, b2) -} - -func TestSecurityBulletinsToFromJson(t *testing.T) { - b := SecurityBulletins{ - { - Id: NewId(), - AppliesToVersion: NewId(), - }, - { - Id: NewId(), - AppliesToVersion: NewId(), - }, - } - - j := b.ToJson() - - b1 := SecurityBulletinsFromJson(strings.NewReader(j)) - - require.Len(t, b1, 2) - - // Malformed JSON - s2 := `{"wat"` - b2 := SecurityBulletinsFromJson(strings.NewReader(s2)) - - require.Empty(t, b2) -} diff --git a/model/session.go b/model/session.go index e5e51c4e07..d3bbc6e4c7 100644 --- a/model/session.go +++ b/model/session.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "strconv" "strings" @@ -80,17 +78,6 @@ func (s *Session) DeepCopy() *Session { return ©Session } -func (s *Session) ToJson() string { - b, _ := json.Marshal(s) - return string(b) -} - -func SessionFromJson(data io.Reader) *Session { - var s *Session - json.NewDecoder(data).Decode(&s) - return s -} - func (s *Session) PreSave() { if s.Id == "" { s.Id = NewId() @@ -208,17 +195,3 @@ func (s *Session) GetCSRF() string { return s.Props["csrf"] } - -func SessionsToJson(o []*Session) string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - -func SessionsFromJson(data io.Reader) []*Session { - var o []*Session - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/session_test.go b/model/session_test.go index e21654855d..086639ec8a 100644 --- a/model/session_test.go +++ b/model/session_test.go @@ -5,9 +5,7 @@ package model import ( "strconv" - "strings" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -41,24 +39,6 @@ func TestSessionDeepCopy(t *testing.T) { assert.Equal(t, 0, len(copySession.TeamMembers)) } -func TestSessionJson(t *testing.T) { - session := Session{} - session.PreSave() - json := session.ToJson() - rsession := SessionFromJson(strings.NewReader(json)) - - require.Equal(t, rsession.Id, session.Id, "Ids do not match") - - session.Sanitize() - - require.False(t, session.IsExpired(), "Shouldn't expire") - - session.ExpiresAt = GetMillis() - time.Sleep(10 * time.Millisecond) - - require.True(t, session.IsExpired(), "Should expire") -} - func TestSessionCSRF(t *testing.T) { s := Session{} token := s.GetCSRF() diff --git a/model/shared_channel.go b/model/shared_channel.go index 0e44c1f8af..08a2929249 100644 --- a/model/shared_channel.go +++ b/model/shared_channel.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" "unicode/utf8" ) @@ -31,17 +29,6 @@ type SharedChannel struct { Type ChannelType `db:"-"` } -func (sc *SharedChannel) ToJson() string { - b, _ := json.Marshal(sc) - return string(b) -} - -func SharedChannelFromJson(data io.Reader) (*SharedChannel, error) { - var sc *SharedChannel - err := json.NewDecoder(data).Decode(&sc) - return sc, err -} - func (sc *SharedChannel) IsValid() *AppError { if !IsValidId(sc.ChannelId) { return NewAppError("SharedChannel.IsValid", "model.channel.is_valid.id.app_error", nil, "ChannelId="+sc.ChannelId, http.StatusBadRequest) @@ -116,17 +103,6 @@ type SharedChannelRemote struct { LastPostId string `json:"last_post_id"` } -func (sc *SharedChannelRemote) ToJson() string { - b, _ := json.Marshal(sc) - return string(b) -} - -func SharedChannelRemoteFromJson(data io.Reader) (*SharedChannelRemote, error) { - var sc *SharedChannelRemote - err := json.NewDecoder(data).Decode(&sc) - return sc, err -} - func (sc *SharedChannelRemote) IsValid() *AppError { if !IsValidId(sc.Id) { return NewAppError("SharedChannelRemote.IsValid", "model.channel.is_valid.id.app_error", nil, "Id="+sc.Id, http.StatusBadRequest) diff --git a/model/shared_channel_test.go b/model/shared_channel_test.go index 10cc6bad06..c3a8e32bb6 100644 --- a/model/shared_channel_test.go +++ b/model/shared_channel_test.go @@ -11,16 +11,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestSharedChannelJson(t *testing.T) { - o := SharedChannel{ChannelId: NewId(), ShareName: NewId()} - json := o.ToJson() - ro, err := SharedChannelFromJson(strings.NewReader(json)) - - require.NoError(t, err) - require.Equal(t, o.ChannelId, ro.ChannelId) - require.Equal(t, o.ShareName, ro.ShareName) -} - func TestSharedChannelIsValid(t *testing.T) { id := NewId() now := GetMillis() @@ -74,13 +64,3 @@ func TestSharedChannelPreUpdate(t *testing.T) { require.GreaterOrEqual(t, o.UpdateAt, now) } - -func TestSharedChannelRemoteJson(t *testing.T) { - o := SharedChannelRemote{Id: NewId(), ChannelId: NewId()} - json := o.ToJson() - ro, err := SharedChannelRemoteFromJson(strings.NewReader(json)) - - require.NoError(t, err) - require.Equal(t, o.Id, ro.Id) - require.Equal(t, o.ChannelId, ro.ChannelId) -} diff --git a/model/status.go b/model/status.go index 167b38f1ba..45a6d5d289 100644 --- a/model/status.go +++ b/model/status.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io" ) const ( @@ -29,41 +28,19 @@ type Status struct { PrevStatus string `json:"-"` } -func (o *Status) ToJson() string { - oCopy := *o - oCopy.ActiveChannel = "" - b, _ := json.Marshal(oCopy) - return string(b) +func (s *Status) ToJSON() ([]byte, error) { + sCopy := *s + sCopy.ActiveChannel = "" + return json.Marshal(sCopy) } -func (o *Status) ToClusterJson() string { - oCopy := *o - b, _ := json.Marshal(oCopy) - return string(b) -} - -func StatusFromJson(data io.Reader) *Status { - var o *Status - json.NewDecoder(data).Decode(&o) - return o -} - -func StatusListToJson(u []*Status) string { - uCopy := make([]Status, len(u)) +func StatusListToJSON(u []*Status) ([]byte, error) { + list := make([]Status, len(u)) for i, s := range u { - sCopy := *s - sCopy.ActiveChannel = "" - uCopy[i] = sCopy + list[i] = *s + list[i].ActiveChannel = "" } - - b, _ := json.Marshal(uCopy) - return string(b) -} - -func StatusListFromJson(data io.Reader) []*Status { - var statuses []*Status - json.NewDecoder(data).Decode(&statuses) - return statuses + return json.Marshal(list) } func StatusMapToInterfaceMap(statusMap map[string]*Status) map[string]interface{} { diff --git a/model/status_test.go b/model/status_test.go index 82d0b96cb3..a741962189 100644 --- a/model/status_test.go +++ b/model/status_test.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -13,27 +12,26 @@ import ( func TestStatus(t *testing.T) { status := Status{NewId(), StatusOnline, true, 0, "123", 0, ""} - json := status.ToJson() - status2 := StatusFromJson(strings.NewReader(json)) + js, err := status.ToJSON() + assert.NoError(t, err) + var status2 Status + err = json.Unmarshal(js, &status2) + assert.NoError(t, err) assert.Equal(t, status.UserId, status2.UserId, "UserId should have matched") assert.Equal(t, status.Status, status2.Status, "Status should have matched") assert.Equal(t, status.LastActivityAt, status2.LastActivityAt, "LastActivityAt should have matched") assert.Equal(t, status.Manual, status2.Manual, "Manual should have matched") assert.Equal(t, "", status2.ActiveChannel) - - json = status.ToClusterJson() - status2 = StatusFromJson(strings.NewReader(json)) - - assert.Equal(t, status.ActiveChannel, status2.ActiveChannel) } -func TestStatusListToJson(t *testing.T) { +func TestStatusListToJSON(t *testing.T) { statuses := []*Status{{NewId(), StatusOnline, true, 0, "123", 0, ""}, {NewId(), StatusOffline, true, 0, "", 0, ""}} - jsonStatuses := StatusListToJson(statuses) + jsonStatuses, err := StatusListToJSON(statuses) + assert.NoError(t, err) var dat []map[string]interface{} - if err := json.Unmarshal([]byte(jsonStatuses), &dat); err != nil { + if err := json.Unmarshal(jsonStatuses, &dat); err != nil { panic(err) } @@ -45,19 +43,3 @@ func TestStatusListToJson(t *testing.T) { assert.Equal(t, statuses[0].UserId, dat[0]["user_id"]) assert.Equal(t, statuses[1].UserId, dat[1]["user_id"]) } - -func TestStatusListFromJson(t *testing.T) { - const jsonStream = ` - [{"user_id":"k39fowpzhfffjxeaw8ecyrygme","status":"online","manual":true,"last_activity_at":0},{"user_id":"e9f1bbg8wfno7b3k7yk79bbwfy","status":"offline","manual":true,"last_activity_at":0}] - ` - var dat []map[string]interface{} - if err := json.Unmarshal([]byte(jsonStream), &dat); err != nil { - panic(err) - } - - toDec := strings.NewReader(jsonStream) - statusesFromJson := StatusListFromJson(toDec) - - assert.Equal(t, statusesFromJson[0].UserId, dat[0]["user_id"], "UserId should be equal") - assert.Equal(t, statusesFromJson[1].UserId, dat[1]["user_id"], "UserId should be equal") -} diff --git a/model/suggest_command.go b/model/suggest_command.go index 45a7af38a8..7fb045fc0f 100644 --- a/model/suggest_command.go +++ b/model/suggest_command.go @@ -3,23 +3,7 @@ package model -import ( - "encoding/json" - "io" -) - type SuggestCommand struct { Suggestion string `json:"suggestion"` Description string `json:"description"` } - -func (o *SuggestCommand) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func SuggestCommandFromJson(data io.Reader) *SuggestCommand { - var o *SuggestCommand - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/suggest_command_test.go b/model/suggest_command_test.go deleted file mode 100644 index 202099758a..0000000000 --- a/model/suggest_command_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSuggestCommandJson(t *testing.T) { - command := &SuggestCommand{Suggestion: NewId()} - json := command.ToJson() - result := SuggestCommandFromJson(strings.NewReader(json)) - - assert.Equal(t, command.Suggestion, result.Suggestion, "Ids do not match") -} diff --git a/model/switch_request.go b/model/switch_request.go index 0a7f207808..70694cb1a4 100644 --- a/model/switch_request.go +++ b/model/switch_request.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type SwitchRequest struct { CurrentService string `json:"current_service"` NewService string `json:"new_service"` @@ -18,17 +13,6 @@ type SwitchRequest struct { LdapLoginId string `json:"ldap_id"` } -func (o *SwitchRequest) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func SwitchRequestFromJson(data io.Reader) *SwitchRequest { - var o *SwitchRequest - json.NewDecoder(data).Decode(&o) - return o -} - func (o *SwitchRequest) EmailToOAuth() bool { return o.CurrentService == UserAuthServiceEmail && (o.NewService == UserAuthServiceSaml || diff --git a/model/switch_request_test.go b/model/switch_request_test.go deleted file mode 100644 index b0b0f15e28..0000000000 --- a/model/switch_request_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestSwitchRequestJson(t *testing.T) { - o := SwitchRequest{Email: NewId(), Password: NewId()} - json := o.ToJson() - ro := SwitchRequestFromJson(strings.NewReader(json)) - - require.Equal(t, o.Email, ro.Email, "Emails do not match") -} diff --git a/model/system.go b/model/system.go index 0201abf831..c8bcaba2bb 100644 --- a/model/system.go +++ b/model/system.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "math/big" ) @@ -56,17 +54,6 @@ type System struct { Value string `json:"value"` } -func (o *System) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func SystemFromJson(data io.Reader) *System { - var o *System - json.NewDecoder(data).Decode(&o) - return o -} - type SystemPostActionCookieSecret struct { Secret []byte `json:"key,omitempty"` } @@ -105,17 +92,6 @@ type FileData struct { Body []byte } -func (sbs *ServerBusyState) ToJson() string { - b, _ := json.Marshal(sbs) - return string(b) -} - -func ServerBusyStateFromJson(r io.Reader) *ServerBusyState { - var sbs *ServerBusyState - json.NewDecoder(r).Decode(&sbs) - return sbs -} - var WarnMetricsTable = map[string]WarnMetric{ SystemWarnMetricMfa: { Id: SystemWarnMetricMfa, @@ -201,35 +177,6 @@ type WarnMetricStatus struct { StoreStatus string `json:"store_status,omitempty"` } -func (wms *WarnMetricStatus) ToJson() string { - b, _ := json.Marshal(wms) - return string(b) -} - -func WarnMetricStatusFromJson(data io.Reader) *WarnMetricStatus { - var o WarnMetricStatus - if err := json.NewDecoder(data).Decode(&o); err != nil { - return nil - } - return &o -} - -func MapWarnMetricStatusToJson(o map[string]*WarnMetricStatus) string { - b, _ := json.Marshal(o) - return string(b) -} - type SendWarnMetricAck struct { ForceAck bool `json:"forceAck"` } - -func (swma *SendWarnMetricAck) ToJson() string { - b, _ := json.Marshal(swma) - return string(b) -} - -func SendWarnMetricAckFromJson(r io.Reader) *SendWarnMetricAck { - var swma *SendWarnMetricAck - json.NewDecoder(r).Decode(&swma) - return swma -} diff --git a/model/system_test.go b/model/system_test.go deleted file mode 100644 index 07dce1cbd3..0000000000 --- a/model/system_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func TestSystemJson(t *testing.T) { - system := System{Name: "test", Value: NewId()} - json := system.ToJson() - result := SystemFromJson(strings.NewReader(json)) - - require.Equal(t, "test", result.Name, "ids do not match") -} - -func TestServerBusyJson(t *testing.T) { - now := time.Now() - sbs := ServerBusyState{Busy: true, Expires: now.Unix()} - json := sbs.ToJson() - result := ServerBusyStateFromJson(strings.NewReader(json)) - - require.Equal(t, sbs.Busy, result.Busy, "busy state does not match") - require.Equal(t, sbs.Expires, result.Expires, "expiry does not match") -} diff --git a/model/team.go b/model/team.go index e38a140758..d18d162078 100644 --- a/model/team.go +++ b/model/team.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" "regexp" "strings" @@ -68,12 +66,6 @@ type TeamsWithCount struct { TotalCount int64 `json:"total_count"` } -func InvitesFromJson(data io.Reader) *Invites { - var o *Invites - json.NewDecoder(data).Decode(&o) - return o -} - func (o *Invites) ToEmailList() []string { emailList := make([]string, len(o.Invites)) for _, invite := range o.Invites { @@ -82,61 +74,11 @@ func (o *Invites) ToEmailList() []string { return emailList } -func (o *Invites) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func (o *Team) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func TeamFromJson(data io.Reader) *Team { - var o *Team - json.NewDecoder(data).Decode(&o) - return o -} - -func TeamMapToJson(u map[string]*Team) string { - b, _ := json.Marshal(u) - return string(b) -} - -func TeamMapFromJson(data io.Reader) map[string]*Team { - var teams map[string]*Team - json.NewDecoder(data).Decode(&teams) - return teams -} - -func TeamListToJson(t []*Team) string { - b, _ := json.Marshal(t) - return string(b) -} - -func TeamsWithCountToJson(tlc *TeamsWithCount) []byte { - b, _ := json.Marshal(tlc) - return b -} - -func TeamsWithCountFromJson(data io.Reader) *TeamsWithCount { - var twc *TeamsWithCount - json.NewDecoder(data).Decode(&twc) - return twc -} - -func TeamListFromJson(data io.Reader) []*Team { - var teams []*Team - json.NewDecoder(data).Decode(&teams) - return teams -} - func (o *Team) Etag() string { return Etag(o.Id, o.UpdateAt) } func (o *Team) IsValid() *AppError { - if !IsValidId(o.Id) { return NewAppError("Team.IsValid", "model.team.is_valid.id.app_error", nil, "", http.StatusBadRequest) } @@ -309,23 +251,3 @@ func (o *Team) Patch(patch *TeamPatch) { func (o *Team) IsGroupConstrained() bool { return o.GroupConstrained != nil && *o.GroupConstrained } - -func (t *TeamPatch) ToJson() string { - b, err := json.Marshal(t) - if err != nil { - return "" - } - - return string(b) -} - -func TeamPatchFromJson(data io.Reader) *TeamPatch { - decoder := json.NewDecoder(data) - var team TeamPatch - err := decoder.Decode(&team) - if err != nil { - return nil - } - - return &team -} diff --git a/model/team_member.go b/model/team_member.go index f5f1cc6166..2c928d2dc4 100644 --- a/model/team_member.go +++ b/model/team_member.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" "strings" ) @@ -71,34 +69,6 @@ type TeamMembersGetOptions struct { ViewRestrictions *ViewUsersRestrictions } -func (o *TeamMember) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func (o *TeamUnread) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func TeamMemberFromJson(data io.Reader) *TeamMember { - var o *TeamMember - json.NewDecoder(data).Decode(&o) - return o -} - -func TeamUnreadFromJson(data io.Reader) *TeamUnread { - var o *TeamUnread - json.NewDecoder(data).Decode(&o) - return o -} - -func EmailInviteWithErrorFromJson(data io.Reader) []*EmailInviteWithError { - var o []*EmailInviteWithError - json.NewDecoder(data).Decode(&o) - return o -} - func EmailInviteWithErrorToEmails(o []*EmailInviteWithError) []string { var ret []string for _, o := range o { @@ -109,14 +79,6 @@ func EmailInviteWithErrorToEmails(o []*EmailInviteWithError) []string { return ret } -func EmailInviteWithErrorToJson(o []*EmailInviteWithError) string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - func EmailInviteWithErrorToString(o *EmailInviteWithError) string { return fmt.Sprintf("%s:%s", o.Email, o.Error.Error()) } @@ -131,52 +93,10 @@ func TeamMembersWithErrorToTeamMembers(o []*TeamMemberWithError) []*TeamMember { return ret } -func TeamMembersWithErrorToJson(o []*TeamMemberWithError) string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - func TeamMemberWithErrorToString(o *TeamMemberWithError) string { return fmt.Sprintf("%s:%s", o.UserId, o.Error.Error()) } -func TeamMembersWithErrorFromJson(data io.Reader) []*TeamMemberWithError { - var o []*TeamMemberWithError - json.NewDecoder(data).Decode(&o) - return o -} - -func TeamMembersToJson(o []*TeamMember) string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - -func TeamMembersFromJson(data io.Reader) []*TeamMember { - var o []*TeamMember - json.NewDecoder(data).Decode(&o) - return o -} - -func TeamsUnreadToJson(o []*TeamUnread) string { - b, err := json.Marshal(o) - if err != nil { - return "[]" - } - return string(b) -} - -func TeamsUnreadFromJson(data io.Reader) []*TeamUnread { - var o []*TeamUnread - json.NewDecoder(data).Decode(&o) - return o -} - func (o *TeamMember) IsValid() *AppError { if !IsValidId(o.TeamId) { diff --git a/model/team_member_test.go b/model/team_member_test.go index a02ed6bf67..c60681db99 100644 --- a/model/team_member_test.go +++ b/model/team_member_test.go @@ -4,37 +4,14 @@ package model import ( - "strings" "testing" "github.com/stretchr/testify/require" ) -func TestTeamMemberJson(t *testing.T) { - o := TeamMember{TeamId: NewId(), UserId: NewId()} - json := o.ToJson() - ro := TeamMemberFromJson(strings.NewReader(json)) - - require.Equal(t, o.TeamId, ro.TeamId, "Ids do not match") -} - func TestTeamMemberIsValid(t *testing.T) { o := TeamMember{} - require.NotNil(t, o.IsValid(), "should be invalid") - o.TeamId = NewId() - require.NotNil(t, o.IsValid(), "should be invalid") } - -func TestUnreadMemberJson(t *testing.T) { - o := TeamUnread{TeamId: NewId(), MsgCount: 5, MentionCount: 3} - json := o.ToJson() - - r := TeamUnreadFromJson(strings.NewReader(json)) - - require.Equal(t, o.TeamId, r.TeamId, "Ids do not match") - - require.Equal(t, o.MsgCount, r.MsgCount, "MsgCount do not match") -} diff --git a/model/team_search.go b/model/team_search.go index e24b84387c..c4a39275c0 100644 --- a/model/team_search.go +++ b/model/team_search.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type TeamSearch struct { Term string `json:"term"` Page *int `json:"page,omitempty"` @@ -25,25 +20,3 @@ type TeamSearch struct { func (t *TeamSearch) IsPaginated() bool { return t.Page != nil && t.PerPage != nil } - -// ToJson convert a TeamSearch to json string -func (t *TeamSearch) ToJson() string { - b, err := json.Marshal(t) - if err != nil { - return "" - } - - return string(b) -} - -// TeamSearchFromJson decodes the input and returns a TeamSearch -func TeamSearchFromJson(data io.Reader) *TeamSearch { - decoder := json.NewDecoder(data) - var cs TeamSearch - err := decoder.Decode(&cs) - if err == nil { - return &cs - } - - return nil -} diff --git a/model/team_search_test.go b/model/team_search_test.go deleted file mode 100644 index d66d1dc292..0000000000 --- a/model/team_search_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestTeamSearchJson(t *testing.T) { - teamSearch := TeamSearch{Term: NewId()} - var rteamSearch *ChannelSearch - err := json.Unmarshal([]byte(teamSearch.ToJson()), &rteamSearch) - require.NoError(t, err) - - assert.Equal(t, teamSearch.Term, rteamSearch.Term, "Terms do not match") -} diff --git a/model/team_stats.go b/model/team_stats.go index 9209a0cfe6..0a3a738761 100644 --- a/model/team_stats.go +++ b/model/team_stats.go @@ -3,24 +3,8 @@ package model -import ( - "encoding/json" - "io" -) - type TeamStats struct { TeamId string `json:"team_id"` TotalMemberCount int64 `json:"total_member_count"` ActiveMemberCount int64 `json:"active_member_count"` } - -func (o *TeamStats) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func TeamStatsFromJson(data io.Reader) *TeamStats { - var o *TeamStats - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/team_test.go b/model/team_test.go index c5cbb9ee61..f37a84a2dd 100644 --- a/model/team_test.go +++ b/model/team_test.go @@ -11,14 +11,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestTeamJson(t *testing.T) { - o := Team{Id: NewId(), DisplayName: NewId()} - json := o.ToJson() - ro := TeamFromJson(strings.NewReader(json)) - - require.Equal(t, o.Id, ro.Id, "Ids do not match") -} - func TestTeamIsValid(t *testing.T) { o := Team{} diff --git a/model/terms_of_service.go b/model/terms_of_service.go index 38f654a5d0..b6e531a22a 100644 --- a/model/terms_of_service.go +++ b/model/terms_of_service.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" "unicode/utf8" ) @@ -38,17 +36,6 @@ func (t *TermsOfService) IsValid() *AppError { return nil } -func (t *TermsOfService) ToJson() string { - b, _ := json.Marshal(t) - return string(b) -} - -func TermsOfServiceFromJson(data io.Reader) *TermsOfService { - var termsOfService *TermsOfService - json.NewDecoder(data).Decode(&termsOfService) - return termsOfService -} - func InvalidTermsOfServiceError(fieldName string, termsOfServiceId string) *AppError { id := fmt.Sprintf("model.terms_of_service.is_valid.%s.app_error", fieldName) details := "" diff --git a/model/terms_of_service_test.go b/model/terms_of_service_test.go index 3260011926..78a89b0a07 100644 --- a/model/terms_of_service_test.go +++ b/model/terms_of_service_test.go @@ -33,17 +33,3 @@ func TestTermsOfServiceIsValid(t *testing.T) { s.Text = "test" assert.Nil(t, s.IsValid(), "should be valid") } - -func TestTermsOfServiceJson(t *testing.T) { - o := TermsOfService{ - Id: NewId(), - Text: NewId(), - CreateAt: GetMillis(), - UserId: NewId(), - } - j := o.ToJson() - ro := TermsOfServiceFromJson(strings.NewReader(j)) - - assert.NotNil(t, ro) - assert.Equal(t, o, *ro) -} diff --git a/model/thread.go b/model/thread.go index fe4a40146a..e774e87a0f 100644 --- a/model/thread.go +++ b/model/thread.go @@ -3,10 +3,6 @@ package model -import ( - "encoding/json" -) - type Thread struct { PostId string `json:"id"` ChannelId string `json:"channel_id"` @@ -62,33 +58,6 @@ type GetUserThreadsOpts struct { TeamOnly bool } -func (o *ThreadResponse) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func ThreadResponseFromJson(s string) (*ThreadResponse, error) { - var t ThreadResponse - err := json.Unmarshal([]byte(s), &t) - return &t, err -} - -func (o *Threads) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func (o *Thread) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func ThreadFromJson(s string) (*Thread, error) { - var t Thread - err := json.Unmarshal([]byte(s), &t) - return &t, err -} - func (o *Thread) Etag() string { return Etag(o.PostId, o.LastReplyAt) } @@ -101,8 +70,3 @@ type ThreadMembership struct { LastUpdated int64 `json:"last_update_at"` UnreadMentions int64 `json:"unread_mentions"` } - -func (o *ThreadMembership) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} diff --git a/model/typing_request.go b/model/typing_request.go index e2e9d3bfba..f7a34341d4 100644 --- a/model/typing_request.go +++ b/model/typing_request.go @@ -3,23 +3,7 @@ package model -import ( - "encoding/json" - "io" -) - type TypingRequest struct { ChannelId string `json:"channel_id"` ParentId string `json:"parent_id"` } - -func (o *TypingRequest) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func TypingRequestFromJson(data io.Reader) *TypingRequest { - var o *TypingRequest - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/typing_request_test.go b/model/typing_request_test.go deleted file mode 100644 index 0e373744ca..0000000000 --- a/model/typing_request_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestTypingRequestJson(t *testing.T) { - o := TypingRequest{ChannelId: NewId(), ParentId: NewId()} - json := o.ToJson() - ro := TypingRequestFromJson(strings.NewReader(json)) - - require.Equal(t, o.ChannelId, ro.ChannelId, "ChannelIds do not match") - require.Equal(t, o.ParentId, ro.ParentId, "ParentIds do not match") -} diff --git a/model/upload_session.go b/model/upload_session.go index c5f09083e2..994e7fb32c 100644 --- a/model/upload_session.go +++ b/model/upload_session.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" ) @@ -48,39 +46,6 @@ type UploadSession struct { ReqFileId string `json:"req_file_id"` } -// ToJson serializes the UploadSession into JSON and returns it as string. -func (us *UploadSession) ToJson() string { - b, _ := json.Marshal(us) - return string(b) -} - -// UploadSessionsToJson serializes a list of UploadSession into JSON and -// returns it as string. -func UploadSessionsToJson(uss []*UploadSession) string { - b, _ := json.Marshal(uss) - return string(b) -} - -// UploadSessionsFromJson deserializes a list of UploadSession from JSON data. -func UploadSessionsFromJson(data io.Reader) []*UploadSession { - decoder := json.NewDecoder(data) - var uss []*UploadSession - if err := decoder.Decode(&uss); err != nil { - return nil - } - return uss -} - -// UploadSessionFromJson deserializes the UploadSession from JSON data. -func UploadSessionFromJson(data io.Reader) *UploadSession { - decoder := json.NewDecoder(data) - var us UploadSession - if err := decoder.Decode(&us); err != nil { - return nil - } - return &us -} - // PreSave is a utility function used to fill required information. func (us *UploadSession) PreSave() { if us.Id == "" { diff --git a/model/user.go b/model/user.go index 9922d818ec..ba0a8e934d 100644 --- a/model/user.go +++ b/model/user.go @@ -7,8 +7,6 @@ import ( "crypto/sha256" "encoding/json" "fmt" - "io" - "io/ioutil" "net/http" "regexp" "sort" @@ -533,22 +531,6 @@ func (u *User) Patch(patch *UserPatch) { } } -// ToJson convert a User to a json string -func (u *User) ToJson() string { - b, _ := json.Marshal(u) - return string(b) -} - -func (u *UserPatch) ToJson() string { - b, _ := json.Marshal(u) - return string(b) -} - -func (u *UserAuth) ToJson() string { - b, _ := json.Marshal(u) - return string(b) -} - // Generate a valid strong etag so the browser can cache the results func (u *User) Etag(showFullName, showEmail bool) string { return Etag(u.Id, u.UpdateAt, u.TermsOfServiceId, u.TermsOfServiceCreateAt, showFullName, showEmail, u.BotLastIconUpdate) @@ -623,9 +605,14 @@ func (u *User) AddNotifyProp(key string, value string) { u.NotifyProps[key] = value } -func (u *User) SetCustomStatus(cs *CustomStatus) { +func (u *User) SetCustomStatus(cs *CustomStatus) error { u.MakeNonNil() - u.Props[UserPropsKeyCustomStatus] = cs.ToJson() + statusJSON, jsonErr := json.Marshal(cs) + if jsonErr != nil { + return jsonErr + } + u.Props[UserPropsKeyCustomStatus] = string(statusJSON) + return nil } func (u *User) ClearCustomStatus() { @@ -809,47 +796,6 @@ func (u *UserPatch) SetField(fieldName string, fieldValue string) { } } -// UserFromJson will decode the input and return a User -func UserFromJson(data io.Reader) *User { - var user *User - json.NewDecoder(data).Decode(&user) - return user -} - -func UserPatchFromJson(data io.Reader) *UserPatch { - var user *UserPatch - json.NewDecoder(data).Decode(&user) - return user -} - -func UserAuthFromJson(data io.Reader) *UserAuth { - var user *UserAuth - json.NewDecoder(data).Decode(&user) - return user -} - -func UserMapToJson(u map[string]*User) string { - b, _ := json.Marshal(u) - return string(b) -} - -func UserMapFromJson(data io.Reader) map[string]*User { - var users map[string]*User - json.NewDecoder(data).Decode(&users) - return users -} - -func UserListToJson(u []*User) string { - b, _ := json.Marshal(u) - return string(b) -} - -func UserListFromJson(data io.Reader) []*User { - var users []*User - json.NewDecoder(data).Decode(&users) - return users -} - // HashPassword generates a hash using the bcrypt.GenerateFromPassword func HashPassword(password string) string { hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) @@ -963,10 +909,3 @@ type UsersWithGroupsAndCount struct { Users []*UserWithGroups `json:"users"` Count int64 `json:"total_count"` } - -func UsersWithGroupsAndCountFromJson(data io.Reader) *UsersWithGroupsAndCount { - uwg := &UsersWithGroupsAndCount{} - bodyBytes, _ := ioutil.ReadAll(data) - json.Unmarshal(bodyBytes, uwg) - return uwg -} diff --git a/model/user_access_token.go b/model/user_access_token.go index f458a6d92c..dee31f1837 100644 --- a/model/user_access_token.go +++ b/model/user_access_token.go @@ -4,8 +4,6 @@ package model import ( - "encoding/json" - "io" "net/http" ) @@ -41,25 +39,3 @@ func (t *UserAccessToken) PreSave() { t.Id = NewId() t.IsActive = true } - -func (t *UserAccessToken) ToJson() string { - b, _ := json.Marshal(t) - return string(b) -} - -func UserAccessTokenFromJson(data io.Reader) *UserAccessToken { - var t *UserAccessToken - json.NewDecoder(data).Decode(&t) - return t -} - -func UserAccessTokenListToJson(t []*UserAccessToken) string { - b, _ := json.Marshal(t) - return string(b) -} - -func UserAccessTokenListFromJson(data io.Reader) []*UserAccessToken { - var t []*UserAccessToken - json.NewDecoder(data).Decode(&t) - return t -} diff --git a/model/user_access_token_search.go b/model/user_access_token_search.go index a692f69297..97fcde12d3 100644 --- a/model/user_access_token_search.go +++ b/model/user_access_token_search.go @@ -3,33 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type UserAccessTokenSearch struct { Term string `json:"term"` } - -// ToJson convert a UserAccessTokenSearch to json string -func (c *UserAccessTokenSearch) ToJson() string { - b, err := json.Marshal(c) - if err != nil { - return "" - } - - return string(b) -} - -// UserAccessTokenSearchJson decodes the input and returns a UserAccessTokenSearch -func UserAccessTokenSearchFromJson(data io.Reader) *UserAccessTokenSearch { - decoder := json.NewDecoder(data) - var cs UserAccessTokenSearch - err := decoder.Decode(&cs) - if err == nil { - return &cs - } - - return nil -} diff --git a/model/user_access_token_search_test.go b/model/user_access_token_search_test.go deleted file mode 100644 index 289a98a129..0000000000 --- a/model/user_access_token_search_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestUserAccessTokenSearchJson(t *testing.T) { - userAccessTokenSearch := UserAccessTokenSearch{Term: NewId()} - json := userAccessTokenSearch.ToJson() - ruserAccessTokenSearch := UserAccessTokenSearchFromJson(strings.NewReader(json)) - require.Equal(t, userAccessTokenSearch.Term, ruserAccessTokenSearch.Term, "Terms do not match") -} diff --git a/model/user_access_token_test.go b/model/user_access_token_test.go index 351eac0b52..d733c52610 100644 --- a/model/user_access_token_test.go +++ b/model/user_access_token_test.go @@ -4,29 +4,11 @@ package model import ( - "strings" "testing" "github.com/stretchr/testify/require" ) -func TestUserAccessTokenJson(t *testing.T) { - a1 := UserAccessToken{} - a1.UserId = NewId() - a1.Token = NewId() - - json := a1.ToJson() - ra1 := UserAccessTokenFromJson(strings.NewReader(json)) - - require.Equal(t, a1.Token, ra1.Token, "tokens didn't match") - - tokens := []*UserAccessToken{&a1} - json = UserAccessTokenListToJson(tokens) - tokens = UserAccessTokenListFromJson(strings.NewReader(json)) - - require.Equal(t, tokens[0].Token, ra1.Token, "tokens didn't match") -} - func TestUserAccessTokenIsValid(t *testing.T) { ad := UserAccessToken{} diff --git a/model/user_autocomplete.go b/model/user_autocomplete.go index 118e138d3a..b07131b387 100644 --- a/model/user_autocomplete.go +++ b/model/user_autocomplete.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type UserAutocompleteInChannel struct { InChannel []*User `json:"in_channel"` OutOfChannel []*User `json:"out_of_channel"` @@ -21,40 +16,3 @@ type UserAutocomplete struct { Users []*User `json:"users"` OutOfChannel []*User `json:"out_of_channel,omitempty"` } - -func (o *UserAutocomplete) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func UserAutocompleteFromJson(data io.Reader) *UserAutocomplete { - decoder := json.NewDecoder(data) - autocomplete := new(UserAutocomplete) - err := decoder.Decode(&autocomplete) - if err != nil { - return nil - } - return autocomplete -} - -func (o *UserAutocompleteInChannel) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func UserAutocompleteInChannelFromJson(data io.Reader) *UserAutocompleteInChannel { - var o *UserAutocompleteInChannel - json.NewDecoder(data).Decode(&o) - return o -} - -func (o *UserAutocompleteInTeam) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func UserAutocompleteInTeamFromJson(data io.Reader) *UserAutocompleteInTeam { - var o *UserAutocompleteInTeam - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/user_search.go b/model/user_search.go index cefeb41a22..93bf600918 100644 --- a/model/user_search.go +++ b/model/user_search.go @@ -3,11 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - const UserSearchMaxLimit = 1000 const UserSearchDefaultLimit = 100 @@ -29,24 +24,6 @@ type UserSearch struct { TeamRoles []string `json:"team_roles"` } -// ToJson convert a User to a json string -func (u *UserSearch) ToJson() []byte { - b, _ := json.Marshal(u) - return b -} - -// UserSearchFromJson will decode the input and return a User -func UserSearchFromJson(data io.Reader) *UserSearch { - us := UserSearch{} - json.NewDecoder(data).Decode(&us) - - if us.Limit == 0 { - us.Limit = UserSearchDefaultLimit - } - - return &us -} - // UserSearchOptions captures internal parameters derived from the user's permissions and a // UserSearch request. type UserSearchOptions struct { diff --git a/model/user_search_test.go b/model/user_search_test.go deleted file mode 100644 index 948d683d39..0000000000 --- a/model/user_search_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestUserSearchJson(t *testing.T) { - userSearch := UserSearch{Term: NewId(), TeamId: NewId()} - json := userSearch.ToJson() - ruserSearch := UserSearchFromJson(bytes.NewReader(json)) - - assert.Equal(t, userSearch.Term, ruserSearch.Term, "Terms do not match") -} diff --git a/model/user_terms_of_service.go b/model/user_terms_of_service.go index 9a0f4f18bb..880c07866b 100644 --- a/model/user_terms_of_service.go +++ b/model/user_terms_of_service.go @@ -4,9 +4,7 @@ package model import ( - "encoding/json" "fmt" - "io" "net/http" ) @@ -32,11 +30,6 @@ func (ut *UserTermsOfService) IsValid() *AppError { return nil } -func (ut *UserTermsOfService) ToJson() string { - b, _ := json.Marshal(ut) - return string(b) -} - func (ut *UserTermsOfService) PreSave() { if ut.UserId == "" { ut.UserId = NewId() @@ -45,12 +38,6 @@ func (ut *UserTermsOfService) PreSave() { ut.CreateAt = GetMillis() } -func UserTermsOfServiceFromJson(data io.Reader) *UserTermsOfService { - var userTermsOfService *UserTermsOfService - json.NewDecoder(data).Decode(&userTermsOfService) - return userTermsOfService -} - func InvalidUserTermsOfServiceError(fieldName string, userTermsOfServiceId string) *AppError { id := fmt.Sprintf("model.user_terms_of_service.is_valid.%s.app_error", fieldName) details := "" diff --git a/model/user_terms_of_Service_test.go b/model/user_terms_of_service_test.go similarity index 62% rename from model/user_terms_of_Service_test.go rename to model/user_terms_of_service_test.go index 676f217714..c00f6df2df 100644 --- a/model/user_terms_of_Service_test.go +++ b/model/user_terms_of_service_test.go @@ -4,10 +4,8 @@ package model import ( - "strings" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -24,16 +22,3 @@ func TestUserTermsOfServiceIsValid(t *testing.T) { s.CreateAt = GetMillis() require.Nil(t, s.IsValid(), "should be valid") } - -func TestUserTermsOfServiceJson(t *testing.T) { - o := UserTermsOfService{ - UserId: NewId(), - TermsOfServiceId: NewId(), - CreateAt: GetMillis(), - } - j := o.ToJson() - ro := UserTermsOfServiceFromJson(strings.NewReader(j)) - - assert.NotNil(t, ro) - assert.Equal(t, o, *ro) -} diff --git a/model/user_test.go b/model/user_test.go index 0dc1cd9d13..31b8b819ed 100644 --- a/model/user_test.go +++ b/model/user_test.go @@ -43,14 +43,6 @@ func TestUserDeepCopy(t *testing.T) { assert.Equal(t, id, copyUser.Id) } -func TestUserJson(t *testing.T) { - user := User{Id: NewId(), Username: NewId()} - json := user.ToJson() - ruser := UserFromJson(strings.NewReader(json)) - - assert.Equal(t, user.Id, ruser.Id, "Ids do not match") -} - func TestUserPreSave(t *testing.T) { user := User{Password: "test"} user.PreSave() diff --git a/model/users_stats.go b/model/users_stats.go index 3e18296e13..1a7becf2f3 100644 --- a/model/users_stats.go +++ b/model/users_stats.go @@ -3,22 +3,6 @@ package model -import ( - "encoding/json" - "io" -) - type UsersStats struct { TotalUsersCount int64 `json:"total_users_count"` } - -func (o *UsersStats) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - -func UsersStatsFromJson(data io.Reader) *UsersStats { - var o *UsersStats - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/utils.go b/model/utils.go index aefa065544..fab3f49445 100644 --- a/model/utils.go +++ b/model/utils.go @@ -116,13 +116,13 @@ func (er *AppError) SystemMessage(T i18n.TranslateFunc) string { return T(er.Id, er.params) } -func (er *AppError) ToJson() string { +func (er *AppError) ToJSON() string { b, _ := json.Marshal(er) return string(b) } -// AppErrorFromJson will decode the input and return an AppError -func AppErrorFromJson(data io.Reader) *AppError { +// AppErrorFromJSON will decode the input and return an AppError +func AppErrorFromJSON(data io.Reader) *AppError { str := "" bytes, rerr := ioutil.ReadAll(data) if rerr != nil { @@ -135,7 +135,7 @@ func AppErrorFromJson(data io.Reader) *AppError { var er AppError err := decoder.Decode(&er) if err != nil { - return NewAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, "body: "+str, http.StatusInternalServerError) + return NewAppError("AppErrorFromJSON", "model.utils.decode_json.app_error", nil, "body: "+str, http.StatusInternalServerError) } return &er } @@ -233,20 +233,20 @@ func CopyStringMap(originalMap map[string]string) map[string]string { return copyMap } -// MapToJson converts a map to a json string -func MapToJson(objmap map[string]string) string { +// MapToJSON converts a map to a json string +func MapToJSON(objmap map[string]string) string { b, _ := json.Marshal(objmap) return string(b) } -// MapBoolToJson converts a map to a json string -func MapBoolToJson(objmap map[string]bool) string { +// MapBoolToJSON converts a map to a json string +func MapBoolToJSON(objmap map[string]bool) string { b, _ := json.Marshal(objmap) return string(b) } -// MapFromJson will decode the key/value pair map -func MapFromJson(data io.Reader) map[string]string { +// MapFromJSON will decode the key/value pair map +func MapFromJSON(data io.Reader) map[string]string { decoder := json.NewDecoder(data) var objmap map[string]string @@ -256,8 +256,8 @@ func MapFromJson(data io.Reader) map[string]string { return objmap } -// MapFromJson will decode the key/value pair map -func MapBoolFromJson(data io.Reader) map[string]bool { +// MapFromJSON will decode the key/value pair map +func MapBoolFromJSON(data io.Reader) map[string]bool { decoder := json.NewDecoder(data) var objmap map[string]bool @@ -267,12 +267,12 @@ func MapBoolFromJson(data io.Reader) map[string]bool { return objmap } -func ArrayToJson(objmap []string) string { +func ArrayToJSON(objmap []string) string { b, _ := json.Marshal(objmap) return string(b) } -func ArrayFromJson(data io.Reader) []string { +func ArrayFromJSON(data io.Reader) []string { decoder := json.NewDecoder(data) var objmap []string @@ -299,12 +299,12 @@ func ArrayFromInterface(data interface{}) []string { return stringArray } -func StringInterfaceToJson(objmap map[string]interface{}) string { +func StringInterfaceToJSON(objmap map[string]interface{}) string { b, _ := json.Marshal(objmap) return string(b) } -func StringInterfaceFromJson(data io.Reader) map[string]interface{} { +func StringInterfaceFromJSON(data io.Reader) map[string]interface{} { decoder := json.NewDecoder(data) var objmap map[string]interface{} @@ -314,8 +314,8 @@ func StringInterfaceFromJson(data io.Reader) map[string]interface{} { return objmap } -// ToJson serializes an arbitrary data type to JSON, discarding the error. -func ToJson(v interface{}) []byte { +// ToJSON serializes an arbitrary data type to JSON, discarding the error. +func ToJSON(v interface{}) []byte { b, _ := json.Marshal(v) return b } diff --git a/model/utils_test.go b/model/utils_test.go index d21957cd4d..3a9e909d5b 100644 --- a/model/utils_test.go +++ b/model/utils_test.go @@ -73,15 +73,15 @@ func TestPadDateStringZeros(t *testing.T) { func TestAppError(t *testing.T) { err := NewAppError("TestAppError", "message", nil, "", http.StatusInternalServerError) - json := err.ToJson() - rerr := AppErrorFromJson(strings.NewReader(json)) + json := err.ToJSON() + rerr := AppErrorFromJSON(strings.NewReader(json)) require.Equal(t, err.Message, rerr.Message) t.Log(err.Error()) } func TestAppErrorJunk(t *testing.T) { - rerr := AppErrorFromJson(strings.NewReader("This is a broken test")) + rerr := AppErrorFromJSON(strings.NewReader("This is a broken test")) require.Equal(t, "body: This is a broken test", rerr.DetailedError) } @@ -100,13 +100,13 @@ func TestMapJson(t *testing.T) { m := make(map[string]string) m["id"] = "test_id" - json := MapToJson(m) + json := MapToJSON(m) - rm := MapFromJson(strings.NewReader(json)) + rm := MapFromJSON(strings.NewReader(json)) require.Equal(t, rm["id"], "test_id", "map should be valid") - rm2 := MapFromJson(strings.NewReader("")) + rm2 := MapFromJSON(strings.NewReader("")) require.LessOrEqual(t, len(rm2), 0, "make should be ivalid") } diff --git a/model/websocket_client.go b/model/websocket_client.go index c1415fa9b9..2bd8a3b7cc 100644 --- a/model/websocket_client.go +++ b/model/websocket_client.go @@ -10,6 +10,8 @@ import ( "sync/atomic" "time" + "github.com/mattermost/mattermost-server/v6/shared/mlog" + "github.com/gorilla/websocket" ) @@ -224,8 +226,9 @@ func (wsc *WebSocketClient) Listen() { return } - event := WebSocketEventFromJson(bytes.NewReader(buf.Bytes())) - if event == nil { + event, jsonErr := WebSocketEventFromJSON(bytes.NewReader(buf.Bytes())) + if jsonErr != nil { + mlog.Warn("Failed to decode from JSON", mlog.Err(jsonErr)) continue } if event.IsValid() { diff --git a/model/websocket_message.go b/model/websocket_message.go index dcbd1cc73f..005eed3337 100644 --- a/model/websocket_message.go +++ b/model/websocket_message.go @@ -4,7 +4,6 @@ package model import ( - "bytes" "encoding/json" "fmt" "io" @@ -77,7 +76,7 @@ const ( ) type WebSocketMessage interface { - ToJson() []byte + ToJSON() ([]byte, error) IsValid() bool EventType() string } @@ -114,7 +113,7 @@ type WebSocketEvent struct { } // PrecomputeJSON precomputes and stores the serialized JSON for all fields other than Sequence. -// This makes ToJson much more efficient when sending the same event to multiple connections. +// This makes ToJSON much more efficient when sending the same event to multiple connections. func (ev *WebSocketEvent) PrecomputeJSON() *WebSocketEvent { copy := ev.Copy() event, _ := json.Marshal(copy.event) @@ -199,17 +198,16 @@ func (ev *WebSocketEvent) EventType() string { return ev.event } -func (ev *WebSocketEvent) ToJson() []byte { +func (ev *WebSocketEvent) ToJSON() ([]byte, error) { if ev.precomputedJSON != nil { - return []byte(fmt.Sprintf(`{"event": %s, "data": %s, "broadcast": %s, "seq": %d}`, ev.precomputedJSON.Event, ev.precomputedJSON.Data, ev.precomputedJSON.Broadcast, ev.GetSequence())) + return []byte(fmt.Sprintf(`{"event": %s, "data": %s, "broadcast": %s, "seq": %d}`, ev.precomputedJSON.Event, ev.precomputedJSON.Data, ev.precomputedJSON.Broadcast, ev.GetSequence())), nil } - b, _ := json.Marshal(webSocketEventJSON{ + return json.Marshal(webSocketEventJSON{ ev.event, ev.data, ev.broadcast, ev.sequence, }) - return b } // Encode encodes the event to the given encoder. @@ -228,11 +226,11 @@ func (ev *WebSocketEvent) Encode(enc *json.Encoder) error { }) } -func WebSocketEventFromJson(data io.Reader) *WebSocketEvent { +func WebSocketEventFromJSON(data io.Reader) (*WebSocketEvent, error) { var ev WebSocketEvent var o webSocketEventJSON if err := json.NewDecoder(data).Decode(&o); err != nil { - return nil + return nil, err } ev.event = o.Event if u, ok := o.Data["user"]; ok { @@ -240,14 +238,19 @@ func WebSocketEventFromJson(data io.Reader) *WebSocketEvent { // because the user is in the form of a map[string]interface{}. buf, err := json.Marshal(u) if err != nil { - return nil + return nil, err } - o.Data["user"] = UserFromJson(bytes.NewReader(buf)) + + var user User + if err = json.Unmarshal(buf, &user); err != nil { + return nil, err + } + o.Data["user"] = &user } ev.data = o.Data ev.broadcast = o.Broadcast ev.sequence = o.Sequence - return &ev + return &ev, nil } // WebSocketResponse represents a response received through the WebSocket @@ -280,13 +283,11 @@ func (m *WebSocketResponse) EventType() string { return WebsocketEventResponse } -func (m *WebSocketResponse) ToJson() []byte { - b, _ := json.Marshal(m) - return b +func (m *WebSocketResponse) ToJSON() ([]byte, error) { + return json.Marshal(m) } -func WebSocketResponseFromJson(data io.Reader) *WebSocketResponse { +func WebSocketResponseFromJSON(data io.Reader) (*WebSocketResponse, error) { var o *WebSocketResponse - json.NewDecoder(data).Decode(&o) - return o + return o, json.NewDecoder(data).Decode(&o) } diff --git a/model/websocket_message_test.go b/model/websocket_message_test.go index bd8ed03ec4..992dcce872 100644 --- a/model/websocket_message_test.go +++ b/model/websocket_message_test.go @@ -19,8 +19,11 @@ func TestWebSocketEvent(t *testing.T) { Id: userId, } m.Add("user", user) - json := m.ToJson() - result := WebSocketEventFromJson(bytes.NewReader(json)) + json, err := m.ToJSON() + require.NoError(t, err) + + result, err := WebSocketEventFromJSON(bytes.NewReader(json)) + require.NoError(t, err) require.True(t, m.IsValid(), "should be valid") require.Equal(t, m.GetBroadcast().TeamId, result.GetBroadcast().TeamId, "Team ids do not match") @@ -72,11 +75,13 @@ func TestWebSocketEventImmutable(t *testing.T) { require.Equal(t, m, copy) } -func TestWebSocketEventFromJson(t *testing.T) { - ev := WebSocketEventFromJson(bytes.NewReader([]byte("junk"))) +func TestWebSocketEventFromJSON(t *testing.T) { + ev, err := WebSocketEventFromJSON(bytes.NewReader([]byte("junk"))) + require.Error(t, err) require.Nil(t, ev, "should not have parsed") data := []byte(`{"event": "test", "data": {"key": "val"}, "seq": 45, "broadcast": {"user_id": "userid"}}`) - ev = WebSocketEventFromJson(bytes.NewReader(data)) + ev, err = WebSocketEventFromJSON(bytes.NewReader(data)) + require.NoError(t, err) require.NotNil(t, ev, "should have parsed") require.Equal(t, ev.EventType(), "test") require.Equal(t, ev.GetSequence(), int64(45)) @@ -88,12 +93,16 @@ func TestWebSocketResponse(t *testing.T) { m := NewWebSocketResponse("OK", 1, map[string]interface{}{}) e := NewWebSocketError(1, &AppError{}) m.Add("RootId", NewId()) - json := m.ToJson() - result := WebSocketResponseFromJson(bytes.NewReader(json)) - json2 := e.ToJson() - WebSocketResponseFromJson(bytes.NewReader(json2)) + json, err := m.ToJSON() + require.NoError(t, err) + result, err := WebSocketResponseFromJSON(bytes.NewReader(json)) + require.NoError(t, err) + json2, err := e.ToJSON() + require.NoError(t, err) + WebSocketResponseFromJSON(bytes.NewReader(json2)) - badresult := WebSocketResponseFromJson(bytes.NewReader([]byte("junk"))) + badresult, err := WebSocketResponseFromJSON(bytes.NewReader([]byte("junk"))) + require.Error(t, err) require.Nil(t, badresult, "should not have parsed") require.True(t, m.IsValid(), "should be valid") @@ -105,16 +114,18 @@ func TestWebSocketEvent_PrecomputeJSON(t *testing.T) { event := NewWebSocketEvent(WebsocketEventPosted, "foo", "bar", "baz", nil) event = event.SetSequence(7) - before := event.ToJson() + before, err := event.ToJSON() + require.NoError(t, err) event.PrecomputeJSON() - after := event.ToJson() + after, err := event.ToJSON() + require.NoError(t, err) assert.Equal(t, before, after) } var stringSink []byte -func BenchmarkWebSocketEvent_ToJson(b *testing.B) { +func BenchmarkWebSocketEvent_ToJSON(b *testing.B) { event := NewWebSocketEvent(WebsocketEventPosted, "foo", "bar", "baz", nil) for i := 0; i < 100; i++ { event.GetData()[NewId()] = NewId() @@ -122,7 +133,7 @@ func BenchmarkWebSocketEvent_ToJson(b *testing.B) { b.Run("SerializedNTimes", func(b *testing.B) { for i := 0; i < b.N; i++ { - stringSink = event.ToJson() + stringSink, _ = event.ToJSON() } }) @@ -135,14 +146,14 @@ func BenchmarkWebSocketEvent_ToJson(b *testing.B) { b.Run("PrecomputedAndSerializedNTimes", func(b *testing.B) { for i := 0; i < b.N; i++ { event.PrecomputeJSON() - stringSink = event.ToJson() + stringSink, _ = event.ToJSON() } }) event.PrecomputeJSON() b.Run("PrecomputedOnceAndSerializedNTimes", func(b *testing.B) { for i := 0; i < b.N; i++ { - stringSink = event.ToJson() + stringSink, _ = event.ToJSON() } }) } diff --git a/model/websocket_request.go b/model/websocket_request.go index cc5d417f01..9e86397833 100644 --- a/model/websocket_request.go +++ b/model/websocket_request.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io" "github.com/mattermost/mattermost-server/v6/shared/i18n" ) @@ -23,11 +22,6 @@ type WebSocketRequest struct { Locale string `json:"-"` } -func (o *WebSocketRequest) ToJson() string { - b, _ := json.Marshal(o) - return string(b) -} - func (o *WebSocketRequest) Clone() (*WebSocketRequest, error) { buf, err := json.Marshal(o) if err != nil { @@ -40,9 +34,3 @@ func (o *WebSocketRequest) Clone() (*WebSocketRequest, error) { } return &ret, nil } - -func WebSocketRequestFromJson(data io.Reader) *WebSocketRequest { - var o *WebSocketRequest - json.NewDecoder(data).Decode(&o) - return o -} diff --git a/model/websocket_request_test.go b/model/websocket_request_test.go deleted file mode 100644 index 962cf88b6e..0000000000 --- a/model/websocket_request_test.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestWebSocketRequest(t *testing.T) { - m := WebSocketRequest{Seq: 1, Action: "test"} - json := m.ToJson() - result := WebSocketRequestFromJson(strings.NewReader(json)) - - require.NotNil(t, result) - - badresult := WebSocketRequestFromJson(strings.NewReader("junk")) - - require.Nil(t, badresult) -} diff --git a/plugin/environment_test.go b/plugin/environment_test.go index 6b32b7721e..aa1789da50 100644 --- a/plugin/environment_test.go +++ b/plugin/environment_test.go @@ -4,6 +4,7 @@ package plugin import ( + "encoding/json" "io/ioutil" "os" "path/filepath" @@ -38,7 +39,9 @@ func TestAvaliablePlugins(t *testing.T) { defer os.RemoveAll(filepath.Join(dir, "plugin1")) path := filepath.Join(dir, "plugin1", "plugin.json") - err = ioutil.WriteFile(path, []byte(bundle1.Manifest.ToJson()), 0644) + manifestJSON, jsonErr := json.Marshal(bundle1.Manifest) + require.NoError(t, jsonErr) + err = ioutil.WriteFile(path, manifestJSON, 0644) require.NoError(t, err) bundles, err := env.Available() diff --git a/services/remotecluster/ping_test.go b/services/remotecluster/ping_test.go index 7254f60f98..b786c785e8 100644 --- a/services/remotecluster/ping_test.go +++ b/services/remotecluster/ping_test.go @@ -4,6 +4,7 @@ package remotecluster import ( + "encoding/json" "fmt" "net/http" "net/http/httptest" @@ -37,7 +38,8 @@ func TestPing(t *testing.T) { defer w.WriteHeader(200) atomic.AddInt32(&countWebReq, 1) - frame, err := model.RemoteClusterFrameFromJSON(r.Body) + var frame model.RemoteClusterFrame + err := json.NewDecoder(r.Body).Decode(&frame) if err != nil { merr.Append(err) return @@ -47,7 +49,8 @@ func TestPing(t *testing.T) { return } - ping, err := model.RemoteClusterPingFromRawJSON(frame.Msg.Payload) + var ping model.RemoteClusterPing + err = json.Unmarshal(frame.Msg.Payload, &ping) if err != nil { merr.Append(err) return @@ -93,11 +96,13 @@ func TestPing(t *testing.T) { defer wg.Done() atomic.AddInt32(&countWebReq, 1) - frame, err := model.RemoteClusterFrameFromJSON(r.Body) + var frame model.RemoteClusterFrame + err := json.NewDecoder(r.Body).Decode(&frame) if err != nil { merr.Append(err) } - ping, err := model.RemoteClusterPingFromRawJSON(frame.Msg.Payload) + var ping model.RemoteClusterPing + err = json.Unmarshal(frame.Msg.Payload, &ping) if err != nil { merr.Append(err) } diff --git a/services/remotecluster/send_test.go b/services/remotecluster/send_test.go index 1df582cb29..e5b0ef746b 100644 --- a/services/remotecluster/send_test.go +++ b/services/remotecluster/send_test.go @@ -55,9 +55,10 @@ func TestBroadcastMsg(t *testing.T) { atomic.AddInt32(&countWebReq, 1) - frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) - if appErr != nil { - merr.Append(appErr) + var frame model.RemoteClusterFrame + jsonErr := json.NewDecoder(r.Body).Decode(&frame) + if jsonErr != nil { + merr.Append(jsonErr) return } if len(frame.Msg.Payload) == 0 { diff --git a/services/remotecluster/sendprofileImage_test.go b/services/remotecluster/sendprofileImage_test.go index dc32748ffb..a2249fd58a 100644 --- a/services/remotecluster/sendprofileImage_test.go +++ b/services/remotecluster/sendprofileImage_test.go @@ -41,7 +41,7 @@ func TestService_sendProfileImageToRemote(t *testing.T) { w.WriteHeader(http.StatusInternalServerError) resp := make(map[string]string) resp[model.STATUS] = model.StatusFail - w.Write([]byte(model.MapToJson(resp))) + w.Write([]byte(model.MapToJSON(resp))) return } @@ -52,7 +52,7 @@ func TestService_sendProfileImageToRemote(t *testing.T) { } resp := make(map[string]string) resp[model.STATUS] = *s - w.Write([]byte(model.MapToJson(resp))) + w.Write([]byte(model.MapToJSON(resp))) }(&status) if err := r.ParseMultipartForm(1024 * 1024); err != nil { diff --git a/store/sqlstore/adapters.go b/store/sqlstore/adapters.go index 35aa1aedcf..2e264834f4 100644 --- a/store/sqlstore/adapters.go +++ b/store/sqlstore/adapters.go @@ -66,7 +66,7 @@ func (t *TraceOnAdapter) Printf(format string, v ...interface{}) { } type JSONSerializable interface { - ToJson() string + ToJSON() string } type mattermConverter struct{} @@ -74,19 +74,21 @@ type mattermConverter struct{} func (me mattermConverter) ToDb(val interface{}) (interface{}, error) { switch t := val.(type) { case model.StringMap: - return model.MapToJson(t), nil + return model.MapToJSON(t), nil case map[string]string: - return model.MapToJson(model.StringMap(t)), nil + return model.MapToJSON(model.StringMap(t)), nil case model.StringArray: - return model.ArrayToJson(t), nil + return model.ArrayToJSON(t), nil case model.StringInterface: - return model.StringInterfaceToJson(t), nil + return model.StringInterfaceToJSON(t), nil case map[string]interface{}: - return model.StringInterfaceToJson(model.StringInterface(t)), nil + return model.StringInterfaceToJSON(model.StringInterface(t)), nil case JSONSerializable: - return t.ToJson(), nil + return t.ToJSON(), nil case *opengraph.OpenGraph: return json.Marshal(t) + case *model.PostImage: + return json.Marshal(t) } return val, nil diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go index 2a72633e5f..58e8259738 100644 --- a/store/sqlstore/channel_store.go +++ b/store/sqlstore/channel_store.go @@ -108,7 +108,7 @@ func channelMemberToSlice(member *model.ChannelMember) []interface{} { resultSlice = append(resultSlice, member.MsgCountRoot) resultSlice = append(resultSlice, member.MentionCount) resultSlice = append(resultSlice, member.MentionCountRoot) - resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps)) + resultSlice = append(resultSlice, model.MapToJSON(member.NotifyProps)) resultSlice = append(resultSlice, member.LastUpdateAt) resultSlice = append(resultSlice, member.SchemeUser) resultSlice = append(resultSlice, member.SchemeAdmin) @@ -1642,7 +1642,7 @@ func (s SqlChannelStore) UpdateMemberNotifyProps(channelID, userID string, props if s.DriverName() == model.DatabaseDriverPostgres { _, err = tx.Exec(`UPDATE channelmembers SET notifyprops = notifyprops || $1::jsonb - WHERE userid=$2 AND channelid=$3`, model.MapToJson(props), userID, channelID) + WHERE userid=$2 AND channelid=$3`, model.MapToJSON(props), userID, channelID) } else { // It's difficult to construct a SQL query for MySQL // to handle a case of empty map. So we just ignore it. diff --git a/store/sqlstore/job_store.go b/store/sqlstore/job_store.go index bc26560b37..1aebd0153d 100644 --- a/store/sqlstore/job_store.go +++ b/store/sqlstore/job_store.go @@ -5,6 +5,7 @@ package sqlstore import ( "database/sql" + "encoding/json" "fmt" "strings" @@ -46,11 +47,15 @@ func (jss SqlJobStore) Save(job *model.Job) (*model.Job, error) { } func (jss SqlJobStore) UpdateOptimistically(job *model.Job, currentStatus string) (bool, error) { + dataJSON, jsonErr := json.Marshal(job.Data) + if jsonErr != nil { + return false, errors.Wrap(jsonErr, "failed to encode job's data to JSON") + } query, args, err := jss.getQueryBuilder(). Update("Jobs"). Set("LastActivityAt", model.GetMillis()). Set("Status", job.Status). - Set("Data", job.DataToJson()). + Set("Data", string(dataJSON)). Set("Progress", job.Progress). Where(sq.Eq{"Id": job.Id, "Status": currentStatus}).ToSql() if err != nil { diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index 7762f7d4fa..f2fb29056d 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -85,10 +85,10 @@ func postToSlice(post *model.Post) []interface{} { post.OriginalId, post.Message, post.Type, - model.StringInterfaceToJson(post.Props), + model.StringInterfaceToJSON(post.Props), post.Hashtags, - model.ArrayToJson(post.Filenames), - model.ArrayToJson(post.FileIds), + model.ArrayToJSON(post.Filenames), + model.ArrayToJSON(post.FileIds), post.HasReactions, post.RemoteId, } diff --git a/store/sqlstore/session_store.go b/store/sqlstore/session_store.go index 3d7fce9195..0773d6adce 100644 --- a/store/sqlstore/session_store.go +++ b/store/sqlstore/session_store.go @@ -251,7 +251,7 @@ func (me SqlSessionStore) UpdateProps(session *model.Session) error { _, err := me.GetMaster().Exec(`UPDATE Sessions SET Props=:Props WHERE Id=:Id`, map[string]interface{}{ - "Props": model.MapToJson(session.Props), + "Props": model.MapToJSON(session.Props), "Id": session.Id, }) if err != nil { diff --git a/store/sqlstore/thread_store.go b/store/sqlstore/thread_store.go index 5585addddd..8a1cce8f20 100644 --- a/store/sqlstore/thread_store.go +++ b/store/sqlstore/thread_store.go @@ -53,7 +53,7 @@ func threadToSlice(thread *model.Thread) []interface{} { thread.ChannelId, thread.LastReplyAt, thread.ReplyCount, - model.ArrayToJson(thread.Participants), + model.ArrayToJSON(thread.Participants), } } diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index 15381ef145..59729921c1 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -230,7 +230,7 @@ func (us SqlUserStore) UpdateNotifyProps(userID string, props map[string]string) if _, err := us.GetMaster().Exec(`UPDATE Users SET NotifyProps = :NotifyProps WHERE Id = :UserId`, map[string]interface{}{ - "NotifyProps": model.MapToJson(props), + "NotifyProps": model.MapToJSON(props), "UserId": userID}); err != nil { return errors.Wrapf(err, "failed to update User with userId=%s", userID) } diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index c7ea2a6b97..d82398cd56 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -5,6 +5,7 @@ package storetest import ( "context" + "encoding/json" "errors" "sort" "strconv" @@ -36,6 +37,20 @@ func cleanupChannels(t *testing.T, ss store.Store) { } } +func channelToJSON(t *testing.T, channel *model.Channel) string { + t.Helper() + js, err := json.Marshal(channel) + require.NoError(t, err) + return string(js) +} + +func channelMemberToJSON(t *testing.T, cm *model.ChannelMember) string { + t.Helper() + js, err := json.Marshal(cm) + require.NoError(t, err) + return string(js) +} + func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) { createDefaultRoles(ss) @@ -379,7 +394,7 @@ func testChannelStoreGet(t *testing.T, ss store.Store, s SqlStore) { c1, err := ss.Channel().Get(o1.Id, false) require.NoError(t, err, err) - require.Equal(t, o1.ToJson(), c1.ToJson(), "invalid returned channel") + require.Equal(t, channelToJSON(t, &o1), channelToJSON(t, c1), "invalid returned channel") _, err = ss.Channel().Get("", false) require.Error(t, err, "missing id should have failed") @@ -421,11 +436,11 @@ func testChannelStoreGet(t *testing.T, ss store.Store, s SqlStore) { c2, err := ss.Channel().Get(o2.Id, false) require.NoError(t, err, err) - require.Equal(t, o2.ToJson(), c2.ToJson(), "invalid returned channel") + require.Equal(t, channelToJSON(t, &o2), channelToJSON(t, c2), "invalid returned channel") c4, err := ss.Channel().Get(o2.Id, true) require.NoError(t, err, err) - require.Equal(t, o2.ToJson(), c4.ToJson(), "invalid returned channel") + require.Equal(t, channelToJSON(t, &o2), channelToJSON(t, c4), "invalid returned channel") channels, chanErr := ss.Channel().GetAll(o1.TeamId) require.NoError(t, chanErr, chanErr) @@ -499,8 +514,8 @@ func testChannelStoreGetChannelsByIds(t *testing.T, ss store.Store) { r1, err := ss.Channel().GetChannelsByIds([]string{o1.Id, o2.Id}, false) require.NoError(t, err, err) require.Len(t, r1, 2, "invalid returned channels, exepected 2 and got "+strconv.Itoa(len(r1))) - require.Equal(t, o1.ToJson(), r1[0].ToJson()) - require.Equal(t, o2.ToJson(), r1[1].ToJson()) + require.Equal(t, channelToJSON(t, &o1), channelToJSON(t, r1[0])) + require.Equal(t, channelToJSON(t, &o2), channelToJSON(t, r1[1])) }) t.Run("Get 1 existing and 1 not existing channel", func(t *testing.T) { @@ -508,16 +523,16 @@ func testChannelStoreGetChannelsByIds(t *testing.T, ss store.Store) { r2, err := ss.Channel().GetChannelsByIds([]string{o1.Id, nonexistentId}, false) require.NoError(t, err, err) require.Len(t, r2, 1, "invalid returned channels, expected 1 and got "+strconv.Itoa(len(r2))) - require.Equal(t, o1.ToJson(), r2[0].ToJson(), "invalid returned channel") + require.Equal(t, channelToJSON(t, &o1), channelToJSON(t, r2[0]), "invalid returned channel") }) t.Run("Get 2 existing and 1 deleted channel", func(t *testing.T) { r1, err := ss.Channel().GetChannelsByIds([]string{o1.Id, o2.Id, o3.Id}, true) require.NoError(t, err, err) require.Len(t, r1, 3, "invalid returned channels, exepected 3 and got "+strconv.Itoa(len(r1))) - require.Equal(t, o1.ToJson(), r1[0].ToJson()) - require.Equal(t, o2.ToJson(), r1[1].ToJson()) - require.Equal(t, o3.ToJson(), r1[2].ToJson()) + require.Equal(t, channelToJSON(t, &o1), channelToJSON(t, r1[0])) + require.Equal(t, channelToJSON(t, &o2), channelToJSON(t, r1[1])) + require.Equal(t, channelToJSON(t, &o3), channelToJSON(t, r1[2])) }) } @@ -656,7 +671,7 @@ func testChannelStoreGetByName(t *testing.T, ss store.Store) { result, err := ss.Channel().GetByName(o1.TeamId, o1.Name, true) require.NoError(t, err) - require.Equal(t, o1.ToJson(), result.ToJson(), "invalid returned channel") + require.Equal(t, channelToJSON(t, &o1), channelToJSON(t, result), "invalid returned channel") channelID := result.Id @@ -665,7 +680,7 @@ func testChannelStoreGetByName(t *testing.T, ss store.Store) { result, err = ss.Channel().GetByName(o1.TeamId, o1.Name, false) require.NoError(t, err) - require.Equal(t, o1.ToJson(), result.ToJson(), "invalid returned channel") + require.Equal(t, channelToJSON(t, &o1), channelToJSON(t, result), "invalid returned channel") _, err = ss.Channel().GetByName(o1.TeamId, "", false) require.Error(t, err, "Missing id should have failed") @@ -4405,7 +4420,7 @@ func testChannelStoreGetMemberForPost(t *testing.T, ss store.Store) { r1, err := ss.Channel().GetMemberForPost(p1.Id, m1.UserId) require.NoError(t, err, err) - require.Equal(t, m1.ToJson(), r1.ToJson(), "invalid returned channel member") + require.Equal(t, channelMemberToJSON(t, m1), channelMemberToJSON(t, r1), "invalid returned channel member") _, err = ss.Channel().GetMemberForPost(p1.Id, model.NewId()) require.Error(t, err, "shouldn't have returned a member") diff --git a/store/storetest/link_metadata_store.go b/store/storetest/link_metadata_store.go index feb56787c7..c4a7986af6 100644 --- a/store/storetest/link_metadata_store.go +++ b/store/storetest/link_metadata_store.go @@ -40,7 +40,6 @@ func testLinkMetadataStoreSave(t *testing.T, ss store.Store) { } linkMetadata, err := ss.LinkMetadata().Save(metadata) - require.NoError(t, err) assert.Equal(t, *metadata, *linkMetadata) }) diff --git a/store/storetest/mocks/JSONSerializable.go b/store/storetest/mocks/JSONSerializable.go index 05a7d65348..4ef82ee79a 100644 --- a/store/storetest/mocks/JSONSerializable.go +++ b/store/storetest/mocks/JSONSerializable.go @@ -11,8 +11,8 @@ type JSONSerializable struct { mock.Mock } -// ToJson provides a mock function with given fields: -func (_m *JSONSerializable) ToJson() string { +// ToJSON provides a mock function with given fields: +func (_m *JSONSerializable) ToJSON() string { ret := _m.Called() var r0 string diff --git a/store/storetest/preference_store.go b/store/storetest/preference_store.go index ebd66dde8d..5d645f345a 100644 --- a/store/storetest/preference_store.go +++ b/store/storetest/preference_store.go @@ -47,7 +47,7 @@ func testPreferenceSave(t *testing.T, ss store.Store) { for _, preference := range preferences { data, _ := ss.Preference().Get(preference.UserId, preference.Category, preference.Name) - require.Equal(t, data.ToJson(), preference.ToJson(), "got incorrect preference after first Save") + require.Equal(t, data, &preference, "got incorrect preference after first Save") } preferences[0].Value = "value2a" @@ -57,7 +57,7 @@ func testPreferenceSave(t *testing.T, ss store.Store) { for _, preference := range preferences { data, _ := ss.Preference().Get(preference.UserId, preference.Category, preference.Name) - require.Equal(t, data.ToJson(), preference.ToJson(), "got incorrect preference after second Save") + require.Equal(t, data, &preference, "got incorrect preference after second Save") } } @@ -94,7 +94,7 @@ func testPreferenceGet(t *testing.T, ss store.Store) { data, err := ss.Preference().Get(userId, category, name) require.NoError(t, err) - require.Equal(t, preferences[0].ToJson(), data.ToJson(), "got incorrect preference") + require.Equal(t, &preferences[0], data, "got incorrect preference") // make sure getting a missing preference fails _, err = ss.Preference().Get(model.NewId(), model.NewId(), model.NewId()) diff --git a/store/storetest/team_store.go b/store/storetest/team_store.go index 808a69d2ae..5edaf4b229 100644 --- a/store/storetest/team_store.go +++ b/store/storetest/team_store.go @@ -126,7 +126,7 @@ func testTeamStoreGet(t *testing.T, ss store.Store) { r1, err := ss.Team().Get(o1.Id) require.NoError(t, err) - require.Equal(t, r1.ToJson(), o1.ToJson()) + require.Equal(t, r1, &o1) _, err = ss.Team().Get("") require.Error(t, err, "Missing id should have failed") diff --git a/utils/license.go b/utils/license.go index 4067b5f461..cd449cd8fc 100644 --- a/utils/license.go +++ b/utils/license.go @@ -9,13 +9,13 @@ import ( "crypto/sha512" "crypto/x509" "encoding/base64" + "encoding/json" "encoding/pem" "io/ioutil" "net/http" "os" "path/filepath" "strconv" - "strings" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -54,8 +54,12 @@ func (l *LicenseValidatorImpl) LicenseFromBytes(licenseBytes []byte) (*model.Lic return nil, model.NewAppError("LicenseFromBytes", model.InvalidLicenseError, nil, "", http.StatusBadRequest) } - license := model.LicenseFromJson(strings.NewReader(licenseStr)) - return license, nil + var license model.License + if jsonErr := json.Unmarshal([]byte(licenseStr), &license); jsonErr != nil { + return nil, model.NewAppError("LicenseFromBytes", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + } + + return &license, nil } func (l *LicenseValidatorImpl) ValidateLicense(signed []byte) (bool, string) { @@ -119,7 +123,14 @@ func GetAndValidateLicenseFileFromDisk(location string) (*model.License, []byte) mlog.Error("Found license key at %v but it appears to be invalid.", mlog.String("filename", fileName)) return nil, nil } - return model.LicenseFromJson(strings.NewReader(licenseStr)), licenseBytes + + var license model.License + if jsonErr := json.Unmarshal([]byte(licenseStr), &license); jsonErr != nil { + mlog.Error("Failed to decode license from JSON", mlog.Err(jsonErr)) + return nil, nil + } + + return &license, licenseBytes } func GetLicenseFileFromDisk(fileName string) []byte { diff --git a/web/handlers.go b/web/handlers.go index b6b64cdee8..3a21df8099 100644 --- a/web/handlers.go +++ b/web/handlers.go @@ -322,7 +322,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if IsAPICall(c.App, r) || IsWebhookCall(c.App, r) || IsOAuthAPICall(c.App, r) || r.Header.Get("X-Mobile-App") != "" { w.WriteHeader(c.Err.StatusCode) - w.Write([]byte(c.Err.ToJson())) + w.Write([]byte(c.Err.ToJSON())) } else { utils.RenderWebAppError(c.App.Config(), w, r, c.Err, c.App.AsymmetricSigningKey()) } diff --git a/web/oauth.go b/web/oauth.go index c369b3746f..524f0751de 100644 --- a/web/oauth.go +++ b/web/oauth.go @@ -76,11 +76,11 @@ func authorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() c.LogAudit("") - w.Write([]byte(model.MapToJson(map[string]string{"redirect": redirectURL}))) + w.Write([]byte(model.MapToJSON(map[string]string{"redirect": redirectURL}))) } func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { - requestData := model.MapFromJson(r.Body) + requestData := model.MapFromJSON(r.Body) clientId := requestData["client_id"] if !model.IsValidId(clientId) { diff --git a/web/oauth_test.go b/web/oauth_test.go index e69a516e7e..eb39ab6634 100644 --- a/web/oauth_test.go +++ b/web/oauth_test.go @@ -6,6 +6,7 @@ package web import ( "context" "encoding/base64" + "encoding/json" "io" "io/ioutil" "net/http" @@ -450,13 +451,13 @@ func TestOAuthComplete(t *testing.T) { stateProps["team_id"] = th.BasicTeam.Id stateProps["redirect_to"] = *th.App.Config().GitLabSettings.AuthEndpoint - state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state := base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) r, err = HTTPGet(apiClient.URL+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), apiClient.HTTPClient, "", true) assert.Error(t, err) closeBody(r) stateProps["hash"] = utils.HashSha256(*th.App.Config().GitLabSettings.Id) - state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state = base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) r, err = HTTPGet(apiClient.URL+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), apiClient.HTTPClient, "", true) assert.Error(t, err) closeBody(r) @@ -511,7 +512,7 @@ func TestOAuthComplete(t *testing.T) { stateProps["redirect_to"] = *th.App.Config().GitLabSettings.AuthEndpoint stateProps["hash"] = utils.HashSha256(*th.App.Config().GitLabSettings.Id) stateProps["redirect_to"] = "/oauth/authorize" - state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state = base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) r, err = HTTPGet(apiClient.URL+"/login/"+model.ServiceGitlab+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), apiClient.HTTPClient, "", false) if err == nil { closeBody(r) @@ -539,7 +540,7 @@ func TestOAuthComplete(t *testing.T) { code = rurl.Query().Get("code") stateProps["action"] = model.OAuthActionLogin - state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state = base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) if r, err = HTTPGet(apiClient.URL+"/login/"+model.ServiceGitlab+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), apiClient.HTTPClient, "", false); err == nil { closeBody(r) } @@ -550,7 +551,7 @@ func TestOAuthComplete(t *testing.T) { code = rurl.Query().Get("code") delete(stateProps, "action") - state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state = base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) if r, err = HTTPGet(apiClient.URL+"/login/"+model.ServiceGitlab+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), apiClient.HTTPClient, "", false); err == nil { closeBody(r) } @@ -561,7 +562,7 @@ func TestOAuthComplete(t *testing.T) { code = rurl.Query().Get("code") stateProps["action"] = model.OAuthActionSignup - state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state = base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) if r, err := HTTPGet(apiClient.URL+"/login/"+model.ServiceGitlab+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), apiClient.HTTPClient, "", false); err == nil { closeBody(r) } @@ -599,7 +600,7 @@ func TestOAuthComplete_ErrorMessages(t *testing.T) { stateProps := map[string]string{} stateProps["action"] = model.OAuthActionMobile stateProps["redirect_to"] = th.App.Config().NativeAppSettings.AppCustomURLSchemes[0] - state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) + state := base64.StdEncoding.EncodeToString([]byte(model.MapToJSON(stateProps))) request2, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/gitlab/complete?code=1234&state="+url.QueryEscape(state), nil) completeOAuth(c, responseWriter, request2) @@ -628,7 +629,7 @@ func HTTPGet(url string, httpClient *http.Client, authToken string, followRedire return rp, nil } else if rp.StatusCode >= 300 { defer closeBody(rp) - return rp, model.AppErrorFromJson(rp.Body) + return rp, model.AppErrorFromJSON(rp.Body) } else { return rp, nil } @@ -644,10 +645,13 @@ func closeBody(r *http.Response) { type MattermostTestProvider struct { } -func (m *MattermostTestProvider) GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) { - user := model.UserFromJson(data) +func (m *MattermostTestProvider) GetUserFromJSON(data io.Reader, tokenUser *model.User) (*model.User, error) { + var user model.User + if err := json.NewDecoder(data).Decode(&user); err != nil { + return nil, err + } user.AuthData = &user.Email - return user, nil + return &user, nil } func (m *MattermostTestProvider) GetSSOSettings(config *model.Config, service string) (*model.SSOSettings, error) { diff --git a/web/saml.go b/web/saml.go index 005874b7f5..9968ef8ab1 100644 --- a/web/saml.go +++ b/web/saml.go @@ -60,7 +60,7 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) { relayProps[model.UserAuthServiceIsMobile] = strconv.FormatBool(isMobile) if len(relayProps) > 0 { - relayState = b64.StdEncoding.EncodeToString([]byte(model.MapToJson(relayProps))) + relayState = b64.StdEncoding.EncodeToString([]byte(model.MapToJSON(relayProps))) } data, err := samlInterface.BuildRequest(relayState) @@ -93,7 +93,7 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) { return } stateStr = string(b) - relayProps = model.MapFromJson(strings.NewReader(stateStr)) + relayProps = model.MapFromJSON(strings.NewReader(stateStr)) } auditRec := c.MakeAuditRecord("completeSaml", audit.Fail) diff --git a/web/web.go b/web/web.go index 33ff506d5d..3dd8aa58fa 100644 --- a/web/web.go +++ b/web/web.go @@ -65,7 +65,7 @@ func Handle404(a app.AppIface, w http.ResponseWriter, r *http.Request) { if IsAPICall(a, r) { w.WriteHeader(err.StatusCode) err.DetailedError = "There doesn't appear to be an api call for the url='" + r.URL.Path + "'. Typo? are you missing a team_id or user_id as part of the url?" - w.Write([]byte(err.ToJson())) + w.Write([]byte(err.ToJSON())) } else if *a.Config().ServiceSettings.WebserverMode == "disabled" { http.NotFound(w, r) } else { @@ -103,5 +103,5 @@ func IsOAuthAPICall(a app.AppIface, r *http.Request) bool { func ReturnStatusOK(w http.ResponseWriter) { m := make(map[string]string) m[model.STATUS] = model.StatusOk - w.Write([]byte(model.MapToJson(m))) + w.Write([]byte(model.MapToJSON(m))) } diff --git a/web/webhook.go b/web/webhook.go index d47f3d434b..be3822e7f4 100644 --- a/web/webhook.go +++ b/web/webhook.go @@ -4,6 +4,7 @@ package web import ( + "encoding/json" "io" "mime" "net/http" @@ -49,7 +50,8 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { defer func() { if *c.App.Config().LogSettings.EnableWebhookDebugging { if c.Err != nil { - mlog.Debug("Incoming webhook received", mlog.String("webhook_id", id), mlog.String("request_id", c.AppContext.RequestId()), mlog.String("payload", incomingWebhookPayload.ToJson())) + payload, _ := json.Marshal(incomingWebhookPayload) + mlog.Debug("Incoming webhook received", mlog.String("webhook_id", id), mlog.String("request_id", c.AppContext.RequestId()), mlog.String("payload", string(payload))) } } }() @@ -116,7 +118,7 @@ func commandWebhook(c *Context, w http.ResponseWriter, r *http.Request) { } func decodePayload(payload io.Reader) (*model.IncomingWebhookRequest, *model.AppError) { - incomingWebhookPayload, decodeError := model.IncomingWebhookRequestFromJson(payload) + incomingWebhookPayload, decodeError := model.IncomingWebhookRequestFromJSON(payload) if decodeError != nil { return nil, decodeError diff --git a/wsapi/status.go b/wsapi/status.go index 7e10ff12cd..49c9fa887e 100644 --- a/wsapi/status.go +++ b/wsapi/status.go @@ -21,7 +21,7 @@ func (api *API) getStatuses(req *model.WebSocketRequest) (map[string]interface{} func (api *API) getStatusesByIds(req *model.WebSocketRequest) (map[string]interface{}, *model.AppError) { var userIds []string if userIds = model.ArrayFromInterface(req.Data["user_ids"]); len(userIds) == 0 { - mlog.Debug("Error while parsing user_ids", mlog.String("data", model.StringInterfaceToJson(req.Data))) + mlog.Debug("Error while parsing user_ids", mlog.String("data", model.StringInterfaceToJSON(req.Data))) return nil, NewInvalidWebSocketParamError(req.Action, "user_ids") }