summaryrefslogtreecommitdiffstats
path: root/app/import_functions.go
diff options
context:
space:
mode:
authorJesús Espino <jespinog@gmail.com>2018-08-01 15:45:26 +0200
committerGitHub <noreply@github.com>2018-08-01 15:45:26 +0200
commit1f168263a2ff73ddee1193cccdeea533f6d501fe (patch)
tree61a59be015b121cee5df9b4c6cf809980814ff63 /app/import_functions.go
parentf4fdd7835b8eeb04106a9ff6a4f85b8593d9074b (diff)
downloadchat-1f168263a2ff73ddee1193cccdeea533f6d501fe.tar.gz
chat-1f168263a2ff73ddee1193cccdeea533f6d501fe.tar.bz2
chat-1f168263a2ff73ddee1193cccdeea533f6d501fe.zip
Split app/import.go in multiple files (#9179)
Diffstat (limited to 'app/import_functions.go')
-rw-r--r--app/import_functions.go1218
1 files changed, 1218 insertions, 0 deletions
diff --git a/app/import_functions.go b/app/import_functions.go
new file mode 100644
index 000000000..f4ff5607f
--- /dev/null
+++ b/app/import_functions.go
@@ -0,0 +1,1218 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "strings"
+
+ "github.com/mattermost/mattermost-server/mlog"
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/store"
+ "github.com/mattermost/mattermost-server/utils"
+)
+
+//
+// -- Bulk Import Functions --
+// These functions import data directly into the database. Security and permission checks are bypassed but validity is
+// still enforced.
+//
+
+func (a *App) ImportScheme(data *SchemeImportData, dryRun bool) *model.AppError {
+ if err := validateSchemeImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ scheme, err := a.GetSchemeByName(*data.Name)
+ if err != nil {
+ scheme = new(model.Scheme)
+ } else if scheme.Scope != *data.Scope {
+ return model.NewAppError("BulkImport", "app.import.import_scheme.scope_change.error", map[string]interface{}{"SchemeName": scheme.Name}, "", http.StatusBadRequest)
+ }
+
+ scheme.Name = *data.Name
+ scheme.DisplayName = *data.DisplayName
+ scheme.Scope = *data.Scope
+
+ if data.Description != nil {
+ scheme.Description = *data.Description
+ }
+
+ if len(scheme.Id) == 0 {
+ scheme, err = a.CreateScheme(scheme)
+ } else {
+ scheme, err = a.UpdateScheme(scheme)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ if scheme.Scope == model.SCHEME_SCOPE_TEAM {
+ data.DefaultTeamAdminRole.Name = &scheme.DefaultTeamAdminRole
+ if err := a.ImportRole(data.DefaultTeamAdminRole, dryRun, true); err != nil {
+ return err
+ }
+
+ data.DefaultTeamUserRole.Name = &scheme.DefaultTeamUserRole
+ if err := a.ImportRole(data.DefaultTeamUserRole, dryRun, true); err != nil {
+ return err
+ }
+ }
+
+ if scheme.Scope == model.SCHEME_SCOPE_TEAM || scheme.Scope == model.SCHEME_SCOPE_CHANNEL {
+ data.DefaultChannelAdminRole.Name = &scheme.DefaultChannelAdminRole
+ if err := a.ImportRole(data.DefaultChannelAdminRole, dryRun, true); err != nil {
+ return err
+ }
+
+ data.DefaultChannelUserRole.Name = &scheme.DefaultChannelUserRole
+ if err := a.ImportRole(data.DefaultChannelUserRole, dryRun, true); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportRole(data *RoleImportData, dryRun bool, isSchemeRole bool) *model.AppError {
+ if !isSchemeRole {
+ if err := validateRoleImportData(data); err != nil {
+ return err
+ }
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ role, err := a.GetRoleByName(*data.Name)
+ if err != nil {
+ role = new(model.Role)
+ }
+
+ role.Name = *data.Name
+
+ if data.DisplayName != nil {
+ role.DisplayName = *data.DisplayName
+ }
+
+ if data.Description != nil {
+ role.Description = *data.Description
+ }
+
+ if data.Permissions != nil {
+ role.Permissions = *data.Permissions
+ }
+
+ if isSchemeRole {
+ role.SchemeManaged = true
+ } else {
+ role.SchemeManaged = false
+ }
+
+ if len(role.Id) == 0 {
+ role, err = a.CreateRole(role)
+ } else {
+ role, err = a.UpdateRole(role)
+ }
+
+ return err
+}
+
+func (a *App) ImportTeam(data *TeamImportData, dryRun bool) *model.AppError {
+ if err := validateTeamImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var team *model.Team
+ if result := <-a.Srv.Store.Team().GetByName(*data.Name); result.Err == nil {
+ team = result.Data.(*model.Team)
+ } else {
+ team = &model.Team{}
+ }
+
+ team.Name = *data.Name
+ team.DisplayName = *data.DisplayName
+ team.Type = *data.Type
+
+ if data.Description != nil {
+ team.Description = *data.Description
+ }
+
+ if data.AllowOpenInvite != nil {
+ team.AllowOpenInvite = *data.AllowOpenInvite
+ }
+
+ if data.Scheme != nil {
+ scheme, err := a.GetSchemeByName(*data.Scheme)
+ if err != nil {
+ return err
+ }
+
+ if scheme.DeleteAt != 0 {
+ return model.NewAppError("BulkImport", "app.import.import_team.scheme_deleted.error", nil, "", http.StatusBadRequest)
+ }
+
+ if scheme.Scope != model.SCHEME_SCOPE_TEAM {
+ return model.NewAppError("BulkImport", "app.import.import_team.scheme_wrong_scope.error", nil, "", http.StatusBadRequest)
+ }
+
+ team.SchemeId = &scheme.Id
+ }
+
+ if team.Id == "" {
+ if _, err := a.CreateTeam(team); err != nil {
+ return err
+ }
+ } else {
+ if _, err := a.updateTeamUnsanitized(team); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportChannel(data *ChannelImportData, dryRun bool) *model.AppError {
+ if err := validateChannelImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var team *model.Team
+ if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_channel.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ var channel *model.Channel
+ if result := <-a.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, *data.Name, true); result.Err == nil {
+ channel = result.Data.(*model.Channel)
+ } else {
+ channel = &model.Channel{}
+ }
+
+ channel.TeamId = team.Id
+ channel.Name = *data.Name
+ channel.DisplayName = *data.DisplayName
+ channel.Type = *data.Type
+
+ if data.Header != nil {
+ channel.Header = *data.Header
+ }
+
+ if data.Purpose != nil {
+ channel.Purpose = *data.Purpose
+ }
+
+ if data.Scheme != nil {
+ scheme, err := a.GetSchemeByName(*data.Scheme)
+ if err != nil {
+ return err
+ }
+
+ if scheme.DeleteAt != 0 {
+ return model.NewAppError("BulkImport", "app.import.import_channel.scheme_deleted.error", nil, "", http.StatusBadRequest)
+ }
+
+ if scheme.Scope != model.SCHEME_SCOPE_CHANNEL {
+ return model.NewAppError("BulkImport", "app.import.import_channel.scheme_wrong_scope.error", nil, "", http.StatusBadRequest)
+ }
+
+ channel.SchemeId = &scheme.Id
+ }
+
+ if channel.Id == "" {
+ if _, err := a.CreateChannel(channel, false); err != nil {
+ return err
+ }
+ } else {
+ if _, err := a.UpdateChannel(channel); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportUser(data *UserImportData, dryRun bool) *model.AppError {
+ if err := validateUserImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ // We want to avoid database writes if nothing has changed.
+ hasUserChanged := false
+ hasNotifyPropsChanged := false
+ hasUserRolesChanged := false
+ hasUserAuthDataChanged := false
+ hasUserEmailVerifiedChanged := false
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.Username); result.Err == nil {
+ user = result.Data.(*model.User)
+ } else {
+ user = &model.User{}
+ user.MakeNonNil()
+ hasUserChanged = true
+ }
+
+ user.Username = *data.Username
+
+ if user.Email != *data.Email {
+ hasUserChanged = true
+ hasUserEmailVerifiedChanged = true // Changing the email resets email verified to false by default.
+ user.Email = *data.Email
+ }
+
+ var password string
+ var authService string
+ var authData *string
+
+ if data.AuthService != nil {
+ if user.AuthService != *data.AuthService {
+ hasUserAuthDataChanged = true
+ }
+ authService = *data.AuthService
+ }
+
+ // AuthData and Password are mutually exclusive.
+ if data.AuthData != nil {
+ if user.AuthData == nil || *user.AuthData != *data.AuthData {
+ hasUserAuthDataChanged = true
+ }
+ authData = data.AuthData
+ password = ""
+ } else if data.Password != nil {
+ password = *data.Password
+ authData = nil
+ } else {
+ // If no AuthData or Password is specified, we must generate a password.
+ password = model.NewId()
+ authData = nil
+ }
+
+ user.Password = password
+ user.AuthService = authService
+ user.AuthData = authData
+
+ // Automatically assume all emails are verified.
+ emailVerified := true
+ if user.EmailVerified != emailVerified {
+ user.EmailVerified = emailVerified
+ hasUserEmailVerifiedChanged = true
+ }
+
+ if data.Nickname != nil {
+ if user.Nickname != *data.Nickname {
+ user.Nickname = *data.Nickname
+ hasUserChanged = true
+ }
+ }
+
+ if data.FirstName != nil {
+ if user.FirstName != *data.FirstName {
+ user.FirstName = *data.FirstName
+ hasUserChanged = true
+ }
+ }
+
+ if data.LastName != nil {
+ if user.LastName != *data.LastName {
+ user.LastName = *data.LastName
+ hasUserChanged = true
+ }
+ }
+
+ if data.Position != nil {
+ if user.Position != *data.Position {
+ user.Position = *data.Position
+ hasUserChanged = true
+ }
+ }
+
+ if data.Locale != nil {
+ if user.Locale != *data.Locale {
+ user.Locale = *data.Locale
+ hasUserChanged = true
+ }
+ } else {
+ if user.Locale != *a.Config().LocalizationSettings.DefaultClientLocale {
+ user.Locale = *a.Config().LocalizationSettings.DefaultClientLocale
+ hasUserChanged = true
+ }
+ }
+
+ var roles string
+ if data.Roles != nil {
+ if user.Roles != *data.Roles {
+ roles = *data.Roles
+ hasUserRolesChanged = true
+ }
+ } else if len(user.Roles) == 0 {
+ // Set SYSTEM_USER roles on newly created users by default.
+ if user.Roles != model.SYSTEM_USER_ROLE_ID {
+ roles = model.SYSTEM_USER_ROLE_ID
+ hasUserRolesChanged = true
+ }
+ }
+ user.Roles = roles
+
+ if data.NotifyProps != nil {
+ if data.NotifyProps.Desktop != nil {
+ if value, ok := user.NotifyProps[model.DESKTOP_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Desktop {
+ user.AddNotifyProp(model.DESKTOP_NOTIFY_PROP, *data.NotifyProps.Desktop)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.DesktopSound != nil {
+ if value, ok := user.NotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopSound {
+ user.AddNotifyProp(model.DESKTOP_SOUND_NOTIFY_PROP, *data.NotifyProps.DesktopSound)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.Email != nil {
+ if value, ok := user.NotifyProps[model.EMAIL_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Email {
+ user.AddNotifyProp(model.EMAIL_NOTIFY_PROP, *data.NotifyProps.Email)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.Mobile != nil {
+ if value, ok := user.NotifyProps[model.PUSH_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Mobile {
+ user.AddNotifyProp(model.PUSH_NOTIFY_PROP, *data.NotifyProps.Mobile)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.MobilePushStatus != nil {
+ if value, ok := user.NotifyProps[model.PUSH_STATUS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MobilePushStatus {
+ user.AddNotifyProp(model.PUSH_STATUS_NOTIFY_PROP, *data.NotifyProps.MobilePushStatus)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.ChannelTrigger != nil {
+ if value, ok := user.NotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.ChannelTrigger {
+ user.AddNotifyProp(model.CHANNEL_MENTIONS_NOTIFY_PROP, *data.NotifyProps.ChannelTrigger)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.CommentsTrigger != nil {
+ if value, ok := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.CommentsTrigger {
+ user.AddNotifyProp(model.COMMENTS_NOTIFY_PROP, *data.NotifyProps.CommentsTrigger)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.MentionKeys != nil {
+ if value, ok := user.NotifyProps[model.MENTION_KEYS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MentionKeys {
+ user.AddNotifyProp(model.MENTION_KEYS_NOTIFY_PROP, *data.NotifyProps.MentionKeys)
+ hasNotifyPropsChanged = true
+ }
+ }
+ }
+
+ var err *model.AppError
+ var savedUser *model.User
+ if user.Id == "" {
+ if savedUser, err = a.createUser(user); err != nil {
+ return err
+ }
+ } else {
+ if hasUserChanged {
+ if savedUser, err = a.UpdateUser(user, false); err != nil {
+ return err
+ }
+ }
+ if hasUserRolesChanged {
+ if savedUser, err = a.UpdateUserRoles(user.Id, roles, false); err != nil {
+ return err
+ }
+ }
+ if hasNotifyPropsChanged {
+ if savedUser, err = a.UpdateUserNotifyProps(user.Id, user.NotifyProps); err != nil {
+ return err
+ }
+ }
+ if len(password) > 0 {
+ if err = a.UpdatePassword(user, password); err != nil {
+ return err
+ }
+ } else {
+ if hasUserAuthDataChanged {
+ if res := <-a.Srv.Store.User().UpdateAuthData(user.Id, authService, authData, user.Email, false); res.Err != nil {
+ return res.Err
+ }
+ }
+ }
+ if emailVerified {
+ if hasUserEmailVerifiedChanged {
+ if err := a.VerifyUserEmail(user.Id); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ if savedUser == nil {
+ savedUser = user
+ }
+
+ if data.ProfileImage != nil {
+ file, err := os.Open(*data.ProfileImage)
+ if err != nil {
+ mlog.Error(fmt.Sprint("api.import.import_user.profile_image.error FIXME: NOT FOUND IN TRANSLATIONS FILE", err))
+ }
+ if err := a.SetProfileImageFromFile(savedUser.Id, file); err != nil {
+ mlog.Error(fmt.Sprint("api.import.import_user.profile_image.error FIXME: NOT FOUND IN TRANSLATIONS FILE", err))
+ }
+ }
+
+ // Preferences.
+ var preferences model.Preferences
+
+ if data.Theme != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_THEME,
+ Name: "",
+ Value: *data.Theme,
+ })
+ }
+
+ if data.UseMilitaryTime != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "use_military_time",
+ Value: *data.UseMilitaryTime,
+ })
+ }
+
+ if data.CollapsePreviews != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "collapse_previews",
+ Value: *data.CollapsePreviews,
+ })
+ }
+
+ if data.MessageDisplay != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "message_display",
+ Value: *data.MessageDisplay,
+ })
+ }
+
+ if data.ChannelDisplayMode != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "channel_display_mode",
+ Value: *data.ChannelDisplayMode,
+ })
+ }
+
+ if data.TutorialStep != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS,
+ Name: savedUser.Id,
+ Value: *data.TutorialStep,
+ })
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_user.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ return a.ImportUserTeams(savedUser, data.Teams)
+}
+
+func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *model.AppError {
+ if data == nil {
+ return nil
+ }
+
+ for _, tdata := range *data {
+ team, err := a.GetTeamByName(*tdata.Name)
+ if err != nil {
+ return err
+ }
+
+ var roles string
+ isSchemeUser := true
+ isSchemeAdmin := false
+
+ if tdata.Roles == nil {
+ isSchemeUser = true
+ } else {
+ rawRoles := *tdata.Roles
+ explicitRoles := []string{}
+ for _, role := range strings.Fields(rawRoles) {
+ if role == model.TEAM_USER_ROLE_ID {
+ isSchemeUser = true
+ } else if role == model.TEAM_ADMIN_ROLE_ID {
+ isSchemeAdmin = true
+ } else {
+ explicitRoles = append(explicitRoles, role)
+ }
+ }
+ roles = strings.Join(explicitRoles, " ")
+ }
+
+ var member *model.TeamMember
+ if member, _, err = a.joinUserToTeam(team, user); err != nil {
+ return err
+ }
+
+ if member.ExplicitRoles != roles {
+ if _, err := a.UpdateTeamMemberRoles(team.Id, user.Id, roles); err != nil {
+ return err
+ }
+ }
+
+ if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser {
+ a.UpdateTeamMemberSchemeRoles(team.Id, user.Id, isSchemeUser, isSchemeAdmin)
+ }
+
+ if defaultChannel, err := a.GetChannelByName(model.DEFAULT_CHANNEL, team.Id, true); err != nil {
+ return err
+ } else if _, err = a.addUserToChannel(user, defaultChannel, member); err != nil {
+ return err
+ }
+
+ if err := a.ImportUserChannels(user, team, member, tdata.Channels); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember *model.TeamMember, data *[]UserChannelImportData) *model.AppError {
+ if data == nil {
+ return nil
+ }
+
+ var preferences model.Preferences
+
+ // Loop through all channels.
+ for _, cdata := range *data {
+ channel, err := a.GetChannelByName(*cdata.Name, team.Id, true)
+ if err != nil {
+ return err
+ }
+
+ var roles string
+ isSchemeUser := true
+ isSchemeAdmin := false
+
+ if cdata.Roles == nil {
+ isSchemeUser = true
+ } else {
+ rawRoles := *cdata.Roles
+ explicitRoles := []string{}
+ for _, role := range strings.Fields(rawRoles) {
+ if role == model.CHANNEL_USER_ROLE_ID {
+ isSchemeUser = true
+ } else if role == model.CHANNEL_ADMIN_ROLE_ID {
+ isSchemeAdmin = true
+ } else {
+ explicitRoles = append(explicitRoles, role)
+ }
+ }
+ roles = strings.Join(explicitRoles, " ")
+ }
+
+ var member *model.ChannelMember
+ member, err = a.GetChannelMember(channel.Id, user.Id)
+ if err != nil {
+ member, err = a.addUserToChannel(user, channel, teamMember)
+ if err != nil {
+ return err
+ }
+ }
+
+ if member.ExplicitRoles != roles {
+ if _, err := a.UpdateChannelMemberRoles(channel.Id, user.Id, roles); err != nil {
+ return err
+ }
+ }
+
+ if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser {
+ a.UpdateChannelMemberSchemeRoles(channel.Id, user.Id, isSchemeUser, isSchemeAdmin)
+ }
+
+ if cdata.NotifyProps != nil {
+ notifyProps := member.NotifyProps
+
+ if cdata.NotifyProps.Desktop != nil {
+ notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
+ }
+
+ if cdata.NotifyProps.Mobile != nil {
+ notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile
+ }
+
+ if cdata.NotifyProps.MarkUnread != nil {
+ notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
+ }
+
+ if _, err := a.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id); err != nil {
+ return err
+ }
+ }
+
+ if cdata.Favorite != nil && *cdata.Favorite {
+ preferences = append(preferences, model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
+ Name: channel.Id,
+ Value: "true",
+ })
+ }
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_user_channels.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportReaction(data *ReactionImportData, post *model.Post, dryRun bool) *model.AppError {
+ if err := validateReactionImportData(data, post.CreateAt); err != nil {
+ return err
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+ reaction := &model.Reaction{
+ UserId: user.Id,
+ PostId: post.Id,
+ EmojiName: *data.EmojiName,
+ CreateAt: *data.CreateAt,
+ }
+ if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil {
+ return result.Err
+ }
+ return nil
+}
+
+func (a *App) ImportReply(data *ReplyImportData, post *model.Post, teamId string, dryRun bool) *model.AppError {
+ if err := validateReplyImportData(data, post.CreateAt, a.MaxPostSize()); err != nil {
+ return err
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ // Check if this post already exists.
+ var replies []*model.Post
+ if result := <-a.Srv.Store.Post().GetPostsCreatedAt(post.ChannelId, *data.CreateAt); result.Err != nil {
+ return result.Err
+ } else {
+ replies = result.Data.([]*model.Post)
+ }
+
+ var reply *model.Post
+ for _, r := range replies {
+ if r.Message == *data.Message {
+ reply = r
+ break
+ }
+ }
+
+ if reply == nil {
+ reply = &model.Post{}
+ }
+ reply.UserId = user.Id
+ reply.ChannelId = post.ChannelId
+ reply.ParentId = post.Id
+ reply.RootId = post.Id
+ reply.Message = *data.Message
+ reply.CreateAt = *data.CreateAt
+
+ if data.Attachments != nil {
+ fileIds, err := a.uploadAttachments(data.Attachments, reply, teamId, dryRun)
+ if err != nil {
+ return err
+ }
+ reply.FileIds = fileIds
+ }
+
+ if reply.Id == "" {
+ if result := <-a.Srv.Store.Post().Save(reply); result.Err != nil {
+ return result.Err
+ }
+ } else {
+ if result := <-a.Srv.Store.Post().Overwrite(reply); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ a.UpdateFileInfoWithPostId(reply)
+
+ return nil
+}
+
+func (a *App) ImportAttachment(data *AttachmentImportData, post *model.Post, teamId string, dryRun bool) (*model.FileInfo, *model.AppError) {
+ fileUploadError := model.NewAppError("BulkImport", "app.import.attachment.file_upload.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest)
+ file, err := os.Open(*data.Path)
+ if err != nil {
+ return nil, model.NewAppError("BulkImport", "app.import.attachment.bad_file.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest)
+ }
+ if file != nil {
+ timestamp := utils.TimeFromMillis(post.CreateAt)
+ buf := bytes.NewBuffer(nil)
+ io.Copy(buf, file)
+
+ fileInfo, err := a.DoUploadFile(timestamp, teamId, post.ChannelId, post.UserId, file.Name(), buf.Bytes())
+
+ if err != nil {
+ fmt.Print(err)
+ return nil, fileUploadError
+ }
+
+ mlog.Info(fmt.Sprintf("uploading file with name %s", file.Name()))
+ return fileInfo, nil
+ }
+ return nil, fileUploadError
+}
+
+func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError {
+ if err := validatePostImportData(data, a.MaxPostSize()); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var team *model.Team
+ if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ var channel *model.Channel
+ if result := <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ channel = result.Data.(*model.Channel)
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ // Check if this post already exists.
+ var posts []*model.Post
+ if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
+ return result.Err
+ } else {
+ posts = result.Data.([]*model.Post)
+ }
+
+ var post *model.Post
+ for _, p := range posts {
+ if p.Message == *data.Message {
+ post = p
+ break
+ }
+ }
+
+ if post == nil {
+ post = &model.Post{}
+ }
+
+ post.ChannelId = channel.Id
+ post.Message = *data.Message
+ post.UserId = user.Id
+ post.CreateAt = *data.CreateAt
+
+ post.Hashtags, _ = model.ParseHashtags(post.Message)
+
+ if data.Attachments != nil {
+ fileIds, err := a.uploadAttachments(data.Attachments, post, team.Id, dryRun)
+ if err != nil {
+ return err
+ }
+ post.FileIds = fileIds
+ }
+
+ if post.Id == "" {
+ if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
+ return result.Err
+ }
+ } else {
+ if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ if data.FlaggedBy != nil {
+ var preferences model.Preferences
+
+ for _, username := range *data.FlaggedBy {
+ var user *model.User
+
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ preferences = append(preferences, model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
+ Name: post.Id,
+ Value: "true",
+ })
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+ }
+
+ if data.Reactions != nil {
+ for _, reaction := range *data.Reactions {
+ if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ if data.Replies != nil {
+ for _, reply := range *data.Replies {
+ if err := a.ImportReply(&reply, post, team.Id, dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ a.UpdateFileInfoWithPostId(post)
+ return nil
+}
+
+func (a *App) uploadAttachments(attachments *[]AttachmentImportData, post *model.Post, teamId string, dryRun bool) ([]string, *model.AppError) {
+ fileIds := []string{}
+ for _, attachment := range *attachments {
+ fileInfo, err := a.ImportAttachment(&attachment, post, teamId, dryRun)
+ if err != nil {
+ return nil, err
+ }
+ fileIds = append(fileIds, fileInfo.Id)
+ }
+ return fileIds, nil
+}
+
+func (a *App) UpdateFileInfoWithPostId(post *model.Post) {
+ for _, fileId := range post.FileIds {
+ if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
+ mlog.Error(fmt.Sprintf("Error attaching files to post. postId=%v, fileIds=%v, message=%v", post.Id, post.FileIds, result.Err), mlog.String("post_id", post.Id))
+ }
+ }
+}
+func (a *App) ImportDirectChannel(data *DirectChannelImportData, dryRun bool) *model.AppError {
+ if err := validateDirectChannelImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var userIds []string
+ userMap := make(map[string]string)
+ for _, username := range *data.Members {
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
+ user := result.Data.(*model.User)
+ userIds = append(userIds, user.Id)
+ userMap[username] = user.Id
+ } else {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest)
+ }
+ }
+
+ var channel *model.Channel
+
+ if len(userIds) == 2 {
+ ch, err := a.createDirectChannel(userIds[0], userIds[1])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ } else {
+ ch, err := a.createGroupChannel(userIds, userIds[0])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_group_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ }
+
+ var preferences model.Preferences
+
+ for _, userId := range userIds {
+ preferences = append(preferences, model.Preference{
+ UserId: userId,
+ Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
+ Name: channel.Id,
+ Value: "true",
+ })
+ }
+
+ if data.FavoritedBy != nil {
+ for _, favoriter := range *data.FavoritedBy {
+ preferences = append(preferences, model.Preference{
+ UserId: userMap[favoriter],
+ Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
+ Name: channel.Id,
+ Value: "true",
+ })
+ }
+ }
+
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ result.Err.StatusCode = http.StatusBadRequest
+ return result.Err
+ }
+
+ if data.Header != nil {
+ channel.Header = *data.Header
+ if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.update_header_failed.error", nil, result.Err.Error(), http.StatusBadRequest)
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportDirectPost(data *DirectPostImportData, dryRun bool) *model.AppError {
+ if err := validateDirectPostImportData(data, a.MaxPostSize()); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var userIds []string
+ for _, username := range *data.ChannelMembers {
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
+ user := result.Data.(*model.User)
+ userIds = append(userIds, user.Id)
+ } else {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest)
+ }
+ }
+
+ var channel *model.Channel
+ if len(userIds) == 2 {
+ ch, err := a.createDirectChannel(userIds[0], userIds[1])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ } else {
+ ch, err := a.createGroupChannel(userIds, userIds[0])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ // Check if this post already exists.
+ var posts []*model.Post
+ if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
+ return result.Err
+ } else {
+ posts = result.Data.([]*model.Post)
+ }
+
+ var post *model.Post
+ for _, p := range posts {
+ if p.Message == *data.Message {
+ post = p
+ break
+ }
+ }
+
+ if post == nil {
+ post = &model.Post{}
+ }
+
+ post.ChannelId = channel.Id
+ post.Message = *data.Message
+ post.UserId = user.Id
+ post.CreateAt = *data.CreateAt
+
+ post.Hashtags, _ = model.ParseHashtags(post.Message)
+
+ if post.Id == "" {
+ if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
+ return result.Err
+ }
+ } else {
+ if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ if data.FlaggedBy != nil {
+ var preferences model.Preferences
+
+ for _, username := range *data.FlaggedBy {
+ var user *model.User
+
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ preferences = append(preferences, model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
+ Name: post.Id,
+ Value: "true",
+ })
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+ }
+
+ if data.Reactions != nil {
+ for _, reaction := range *data.Reactions {
+ if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ if data.Replies != nil {
+ for _, reply := range *data.Replies {
+ if err := a.ImportReply(&reply, post, "noteam", dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportEmoji(data *EmojiImportData, dryRun bool) *model.AppError {
+ if err := validateEmojiImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var emoji *model.Emoji
+
+ if result := <-a.Srv.Store.Emoji().GetByName(*data.Name); result.Err != nil && result.Err.StatusCode != http.StatusNotFound {
+ return result.Err
+ } else if result.Data != nil {
+ emoji = result.Data.(*model.Emoji)
+ }
+
+ alreadyExists := emoji != nil
+
+ if !alreadyExists {
+ emoji = &model.Emoji{
+ Name: *data.Name,
+ }
+ emoji.PreSave()
+ }
+
+ file, err := os.Open(*data.Image)
+ if err != nil {
+ return model.NewAppError("BulkImport", "app.import.emoji.bad_file.error", map[string]interface{}{"EmojiName": *data.Name}, "", http.StatusBadRequest)
+ }
+
+ if _, err := a.WriteFile(file, getEmojiImagePath(emoji.Id)); err != nil {
+ return err
+ }
+
+ if !alreadyExists {
+ if result := <-a.Srv.Store.Emoji().Save(emoji); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ return nil
+}