github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+incompatible/app/import.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"bufio"
     8  	"bytes"
     9  	"encoding/json"
    10  	"io"
    11  	"net/http"
    12  	"os"
    13  	"regexp"
    14  	"strings"
    15  	"sync"
    16  	"time"
    17  	"unicode/utf8"
    18  
    19  	l4g "github.com/alecthomas/log4go"
    20  
    21  	"github.com/mattermost/mattermost-server/model"
    22  	"github.com/mattermost/mattermost-server/store"
    23  	"github.com/mattermost/mattermost-server/utils"
    24  )
    25  
    26  // Import Data Models
    27  
    28  type LineImportData struct {
    29  	Type          string                   `json:"type"`
    30  	Team          *TeamImportData          `json:"team"`
    31  	Channel       *ChannelImportData       `json:"channel"`
    32  	User          *UserImportData          `json:"user"`
    33  	Post          *PostImportData          `json:"post"`
    34  	DirectChannel *DirectChannelImportData `json:"direct_channel"`
    35  	DirectPost    *DirectPostImportData    `json:"direct_post"`
    36  	Version       *int                     `json:"version"`
    37  }
    38  
    39  type TeamImportData struct {
    40  	Name            *string `json:"name"`
    41  	DisplayName     *string `json:"display_name"`
    42  	Type            *string `json:"type"`
    43  	Description     *string `json:"description"`
    44  	AllowOpenInvite *bool   `json:"allow_open_invite"`
    45  }
    46  
    47  type ChannelImportData struct {
    48  	Team        *string `json:"team"`
    49  	Name        *string `json:"name"`
    50  	DisplayName *string `json:"display_name"`
    51  	Type        *string `json:"type"`
    52  	Header      *string `json:"header"`
    53  	Purpose     *string `json:"purpose"`
    54  }
    55  
    56  type UserImportData struct {
    57  	ProfileImage *string `json:"profile_image"`
    58  	Username     *string `json:"username"`
    59  	Email        *string `json:"email"`
    60  	AuthService  *string `json:"auth_service"`
    61  	AuthData     *string `json:"auth_data"`
    62  	Password     *string `json:"password"`
    63  	Nickname     *string `json:"nickname"`
    64  	FirstName    *string `json:"first_name"`
    65  	LastName     *string `json:"last_name"`
    66  	Position     *string `json:"position"`
    67  	Roles        *string `json:"roles"`
    68  	Locale       *string `json:"locale"`
    69  
    70  	Teams *[]UserTeamImportData `json:"teams"`
    71  
    72  	Theme              *string `json:"theme"`
    73  	UseMilitaryTime    *string `json:"military_time"`
    74  	CollapsePreviews   *string `json:"link_previews"`
    75  	MessageDisplay     *string `json:"message_display"`
    76  	ChannelDisplayMode *string `json:"channel_display_mode"`
    77  	TutorialStep       *string `json:"tutorial_step"`
    78  
    79  	NotifyProps *UserNotifyPropsImportData `json:"notify_props"`
    80  }
    81  
    82  type UserNotifyPropsImportData struct {
    83  	Desktop         *string `json:"desktop"`
    84  	DesktopDuration *string `json:"desktop_duration"`
    85  	DesktopSound    *string `json:"desktop_sound"`
    86  
    87  	Email *string `json:"email"`
    88  
    89  	Mobile           *string `json:"mobile"`
    90  	MobilePushStatus *string `json:"mobile_push_status"`
    91  
    92  	ChannelTrigger  *string `json:"channel"`
    93  	CommentsTrigger *string `json:"comments"`
    94  	MentionKeys     *string `json:"mention_keys"`
    95  }
    96  
    97  type UserTeamImportData struct {
    98  	Name     *string                  `json:"name"`
    99  	Roles    *string                  `json:"roles"`
   100  	Channels *[]UserChannelImportData `json:"channels"`
   101  }
   102  
   103  type UserChannelImportData struct {
   104  	Name        *string                           `json:"name"`
   105  	Roles       *string                           `json:"roles"`
   106  	NotifyProps *UserChannelNotifyPropsImportData `json:"notify_props"`
   107  	Favorite    *bool                             `json:"favorite"`
   108  }
   109  
   110  type UserChannelNotifyPropsImportData struct {
   111  	Desktop    *string `json:"desktop"`
   112  	Mobile     *string `json:"mobile"`
   113  	MarkUnread *string `json:"mark_unread"`
   114  }
   115  
   116  type ReactionImportData struct {
   117  	User      *string `json:"user"`
   118  	CreateAt  *int64  `json:"create_at"`
   119  	EmojiName *string `json:"emoji_name"`
   120  }
   121  
   122  type ReplyImportData struct {
   123  	User *string `json:"user"`
   124  
   125  	Message  *string `json:"message"`
   126  	CreateAt *int64  `json:"create_at"`
   127  
   128  	FlaggedBy *[]string             `json:"flagged_by"`
   129  	Reactions *[]ReactionImportData `json:"reactions"`
   130  }
   131  
   132  type PostImportData struct {
   133  	Team    *string `json:"team"`
   134  	Channel *string `json:"channel"`
   135  	User    *string `json:"user"`
   136  
   137  	Message  *string `json:"message"`
   138  	CreateAt *int64  `json:"create_at"`
   139  
   140  	FlaggedBy *[]string             `json:"flagged_by"`
   141  	Reactions *[]ReactionImportData `json:"reactions"`
   142  	Replies   *[]ReplyImportData    `json:"replies"`
   143  }
   144  
   145  type DirectChannelImportData struct {
   146  	Members     *[]string `json:"members"`
   147  	FavoritedBy *[]string `json:"favorited_by"`
   148  
   149  	Header *string `json:"header"`
   150  }
   151  
   152  type DirectPostImportData struct {
   153  	ChannelMembers *[]string `json:"channel_members"`
   154  	User           *string   `json:"user"`
   155  
   156  	Message  *string `json:"message"`
   157  	CreateAt *int64  `json:"create_at"`
   158  
   159  	FlaggedBy *[]string             `json:"flagged_by"`
   160  	Reactions *[]ReactionImportData `json:"reactions"`
   161  	Replies   *[]ReplyImportData    `json:"replies"`
   162  }
   163  
   164  type LineImportWorkerData struct {
   165  	LineImportData
   166  	LineNumber int
   167  }
   168  
   169  type LineImportWorkerError struct {
   170  	Error      *model.AppError
   171  	LineNumber int
   172  }
   173  
   174  //
   175  // -- Bulk Import Functions --
   176  // These functions import data directly into the database. Security and permission checks are bypassed but validity is
   177  // still enforced.
   178  //
   179  
   180  func (a *App) bulkImportWorker(dryRun bool, wg *sync.WaitGroup, lines <-chan LineImportWorkerData, errors chan<- LineImportWorkerError) {
   181  	for line := range lines {
   182  		if err := a.ImportLine(line.LineImportData, dryRun); err != nil {
   183  			errors <- LineImportWorkerError{err, line.LineNumber}
   184  		}
   185  	}
   186  	wg.Done()
   187  }
   188  
   189  func (a *App) BulkImport(fileReader io.Reader, dryRun bool, workers int) (*model.AppError, int) {
   190  	scanner := bufio.NewScanner(fileReader)
   191  	lineNumber := 0
   192  
   193  	errorsChan := make(chan LineImportWorkerError, (2*workers)+1) // size chosen to ensure it never gets filled up completely.
   194  	var wg sync.WaitGroup
   195  	var linesChan chan LineImportWorkerData
   196  	lastLineType := ""
   197  
   198  	for scanner.Scan() {
   199  		decoder := json.NewDecoder(strings.NewReader(scanner.Text()))
   200  		lineNumber++
   201  
   202  		var line LineImportData
   203  		if err := decoder.Decode(&line); err != nil {
   204  			return model.NewAppError("BulkImport", "app.import.bulk_import.json_decode.error", nil, err.Error(), http.StatusBadRequest), lineNumber
   205  		} else {
   206  			if lineNumber == 1 {
   207  				importDataFileVersion, apperr := processImportDataFileVersionLine(line)
   208  				if apperr != nil {
   209  					return apperr, lineNumber
   210  				}
   211  
   212  				if importDataFileVersion != 1 {
   213  					return model.NewAppError("BulkImport", "app.import.bulk_import.unsupported_version.error", nil, "", http.StatusBadRequest), lineNumber
   214  				}
   215  			} else {
   216  				if line.Type != lastLineType {
   217  					if lastLineType != "" {
   218  						// Changing type. Clear out the worker queue before continuing.
   219  						close(linesChan)
   220  						wg.Wait()
   221  
   222  						// Check no errors occurred while waiting for the queue to empty.
   223  						if len(errorsChan) != 0 {
   224  							err := <-errorsChan
   225  							return err.Error, err.LineNumber
   226  						}
   227  					}
   228  
   229  					// Set up the workers and channel for this type.
   230  					lastLineType = line.Type
   231  					linesChan = make(chan LineImportWorkerData, workers)
   232  					for i := 0; i < workers; i++ {
   233  						wg.Add(1)
   234  						go a.bulkImportWorker(dryRun, &wg, linesChan, errorsChan)
   235  					}
   236  				}
   237  
   238  				select {
   239  				case linesChan <- LineImportWorkerData{line, lineNumber}:
   240  				case err := <-errorsChan:
   241  					close(linesChan)
   242  					wg.Wait()
   243  					return err.Error, err.LineNumber
   244  				}
   245  			}
   246  		}
   247  	}
   248  
   249  	// No more lines. Clear out the worker queue before continuing.
   250  	close(linesChan)
   251  	wg.Wait()
   252  
   253  	// Check no errors occurred while waiting for the queue to empty.
   254  	if len(errorsChan) != 0 {
   255  		err := <-errorsChan
   256  		return err.Error, err.LineNumber
   257  	}
   258  
   259  	if err := scanner.Err(); err != nil {
   260  		return model.NewAppError("BulkImport", "app.import.bulk_import.file_scan.error", nil, err.Error(), http.StatusInternalServerError), 0
   261  	}
   262  
   263  	return nil, 0
   264  }
   265  
   266  func processImportDataFileVersionLine(line LineImportData) (int, *model.AppError) {
   267  	if line.Type != "version" || line.Version == nil {
   268  		return -1, model.NewAppError("BulkImport", "app.import.process_import_data_file_version_line.invalid_version.error", nil, "", http.StatusBadRequest)
   269  	}
   270  
   271  	return *line.Version, nil
   272  }
   273  
   274  func (a *App) ImportLine(line LineImportData, dryRun bool) *model.AppError {
   275  	switch {
   276  	case line.Type == "team":
   277  		if line.Team == nil {
   278  			return model.NewAppError("BulkImport", "app.import.import_line.null_team.error", nil, "", http.StatusBadRequest)
   279  		} else {
   280  			return a.ImportTeam(line.Team, dryRun)
   281  		}
   282  	case line.Type == "channel":
   283  		if line.Channel == nil {
   284  			return model.NewAppError("BulkImport", "app.import.import_line.null_channel.error", nil, "", http.StatusBadRequest)
   285  		} else {
   286  			return a.ImportChannel(line.Channel, dryRun)
   287  		}
   288  	case line.Type == "user":
   289  		if line.User == nil {
   290  			return model.NewAppError("BulkImport", "app.import.import_line.null_user.error", nil, "", http.StatusBadRequest)
   291  		} else {
   292  			return a.ImportUser(line.User, dryRun)
   293  		}
   294  	case line.Type == "post":
   295  		if line.Post == nil {
   296  			return model.NewAppError("BulkImport", "app.import.import_line.null_post.error", nil, "", http.StatusBadRequest)
   297  		} else {
   298  			return a.ImportPost(line.Post, dryRun)
   299  		}
   300  	case line.Type == "direct_channel":
   301  		if line.DirectChannel == nil {
   302  			return model.NewAppError("BulkImport", "app.import.import_line.null_direct_channel.error", nil, "", http.StatusBadRequest)
   303  		} else {
   304  			return a.ImportDirectChannel(line.DirectChannel, dryRun)
   305  		}
   306  	case line.Type == "direct_post":
   307  		if line.DirectPost == nil {
   308  			return model.NewAppError("BulkImport", "app.import.import_line.null_direct_post.error", nil, "", http.StatusBadRequest)
   309  		} else {
   310  			return a.ImportDirectPost(line.DirectPost, dryRun)
   311  		}
   312  	default:
   313  		return model.NewAppError("BulkImport", "app.import.import_line.unknown_line_type.error", map[string]interface{}{"Type": line.Type}, "", http.StatusBadRequest)
   314  	}
   315  }
   316  
   317  func (a *App) ImportTeam(data *TeamImportData, dryRun bool) *model.AppError {
   318  	if err := validateTeamImportData(data); err != nil {
   319  		return err
   320  	}
   321  
   322  	// If this is a Dry Run, do not continue any further.
   323  	if dryRun {
   324  		return nil
   325  	}
   326  
   327  	var team *model.Team
   328  	if result := <-a.Srv.Store.Team().GetByName(*data.Name); result.Err == nil {
   329  		team = result.Data.(*model.Team)
   330  	} else {
   331  		team = &model.Team{}
   332  	}
   333  
   334  	team.Name = *data.Name
   335  	team.DisplayName = *data.DisplayName
   336  	team.Type = *data.Type
   337  
   338  	if data.Description != nil {
   339  		team.Description = *data.Description
   340  	}
   341  
   342  	if data.AllowOpenInvite != nil {
   343  		team.AllowOpenInvite = *data.AllowOpenInvite
   344  	}
   345  
   346  	if team.Id == "" {
   347  		if _, err := a.CreateTeam(team); err != nil {
   348  			return err
   349  		}
   350  	} else {
   351  		if _, err := a.UpdateTeam(team); err != nil {
   352  			return err
   353  		}
   354  	}
   355  
   356  	return nil
   357  }
   358  
   359  func validateTeamImportData(data *TeamImportData) *model.AppError {
   360  
   361  	if data.Name == nil {
   362  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_missing.error", nil, "", http.StatusBadRequest)
   363  	} else if len(*data.Name) > model.TEAM_NAME_MAX_LENGTH {
   364  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_length.error", nil, "", http.StatusBadRequest)
   365  	} else if model.IsReservedTeamName(*data.Name) {
   366  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_reserved.error", nil, "", http.StatusBadRequest)
   367  	} else if !model.IsValidTeamName(*data.Name) {
   368  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_characters.error", nil, "", http.StatusBadRequest)
   369  	}
   370  
   371  	if data.DisplayName == nil {
   372  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.display_name_missing.error", nil, "", http.StatusBadRequest)
   373  	} else if utf8.RuneCountInString(*data.DisplayName) == 0 || utf8.RuneCountInString(*data.DisplayName) > model.TEAM_DISPLAY_NAME_MAX_RUNES {
   374  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.display_name_length.error", nil, "", http.StatusBadRequest)
   375  	}
   376  
   377  	if data.Type == nil {
   378  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.type_missing.error", nil, "", http.StatusBadRequest)
   379  	} else if *data.Type != model.TEAM_OPEN && *data.Type != model.TEAM_INVITE {
   380  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.type_invalid.error", nil, "", http.StatusBadRequest)
   381  	}
   382  
   383  	if data.Description != nil && len(*data.Description) > model.TEAM_DESCRIPTION_MAX_LENGTH {
   384  		return model.NewAppError("BulkImport", "app.import.validate_team_import_data.description_length.error", nil, "", http.StatusBadRequest)
   385  	}
   386  
   387  	return nil
   388  }
   389  
   390  func (a *App) ImportChannel(data *ChannelImportData, dryRun bool) *model.AppError {
   391  	if err := validateChannelImportData(data); err != nil {
   392  		return err
   393  	}
   394  
   395  	// If this is a Dry Run, do not continue any further.
   396  	if dryRun {
   397  		return nil
   398  	}
   399  
   400  	var team *model.Team
   401  	if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
   402  		return model.NewAppError("BulkImport", "app.import.import_channel.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, "", http.StatusBadRequest)
   403  	} else {
   404  		team = result.Data.(*model.Team)
   405  	}
   406  
   407  	var channel *model.Channel
   408  	if result := <-a.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, *data.Name, true); result.Err == nil {
   409  		channel = result.Data.(*model.Channel)
   410  	} else {
   411  		channel = &model.Channel{}
   412  	}
   413  
   414  	channel.TeamId = team.Id
   415  	channel.Name = *data.Name
   416  	channel.DisplayName = *data.DisplayName
   417  	channel.Type = *data.Type
   418  
   419  	if data.Header != nil {
   420  		channel.Header = *data.Header
   421  	}
   422  
   423  	if data.Purpose != nil {
   424  		channel.Purpose = *data.Purpose
   425  	}
   426  
   427  	if channel.Id == "" {
   428  		if _, err := a.CreateChannel(channel, false); err != nil {
   429  			return err
   430  		}
   431  	} else {
   432  		if _, err := a.UpdateChannel(channel); err != nil {
   433  			return err
   434  		}
   435  	}
   436  
   437  	return nil
   438  }
   439  
   440  func validateChannelImportData(data *ChannelImportData) *model.AppError {
   441  
   442  	if data.Team == nil {
   443  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.team_missing.error", nil, "", http.StatusBadRequest)
   444  	}
   445  
   446  	if data.Name == nil {
   447  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.name_missing.error", nil, "", http.StatusBadRequest)
   448  	} else if len(*data.Name) > model.CHANNEL_NAME_MAX_LENGTH {
   449  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.name_length.error", nil, "", http.StatusBadRequest)
   450  	} else if !model.IsValidChannelIdentifier(*data.Name) {
   451  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.name_characters.error", nil, "", http.StatusBadRequest)
   452  	}
   453  
   454  	if data.DisplayName == nil {
   455  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.display_name_missing.error", nil, "", http.StatusBadRequest)
   456  	} else if utf8.RuneCountInString(*data.DisplayName) == 0 || utf8.RuneCountInString(*data.DisplayName) > model.CHANNEL_DISPLAY_NAME_MAX_RUNES {
   457  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.display_name_length.error", nil, "", http.StatusBadRequest)
   458  	}
   459  
   460  	if data.Type == nil {
   461  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.type_missing.error", nil, "", http.StatusBadRequest)
   462  	} else if *data.Type != model.CHANNEL_OPEN && *data.Type != model.CHANNEL_PRIVATE {
   463  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.type_invalid.error", nil, "", http.StatusBadRequest)
   464  	}
   465  
   466  	if data.Header != nil && utf8.RuneCountInString(*data.Header) > model.CHANNEL_HEADER_MAX_RUNES {
   467  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.header_length.error", nil, "", http.StatusBadRequest)
   468  	}
   469  
   470  	if data.Purpose != nil && utf8.RuneCountInString(*data.Purpose) > model.CHANNEL_PURPOSE_MAX_RUNES {
   471  		return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.purpose_length.error", nil, "", http.StatusBadRequest)
   472  	}
   473  
   474  	return nil
   475  }
   476  
   477  func (a *App) ImportUser(data *UserImportData, dryRun bool) *model.AppError {
   478  	if err := validateUserImportData(data); err != nil {
   479  		return err
   480  	}
   481  
   482  	// If this is a Dry Run, do not continue any further.
   483  	if dryRun {
   484  		return nil
   485  	}
   486  
   487  	// We want to avoid database writes if nothing has changed.
   488  	hasUserChanged := false
   489  	hasNotifyPropsChanged := false
   490  	hasUserRolesChanged := false
   491  	hasUserAuthDataChanged := false
   492  	hasUserEmailVerifiedChanged := false
   493  
   494  	var user *model.User
   495  	if result := <-a.Srv.Store.User().GetByUsername(*data.Username); result.Err == nil {
   496  		user = result.Data.(*model.User)
   497  	} else {
   498  		user = &model.User{}
   499  		user.MakeNonNil()
   500  		hasUserChanged = true
   501  	}
   502  
   503  	user.Username = *data.Username
   504  
   505  	if user.Email != *data.Email {
   506  		hasUserChanged = true
   507  		hasUserEmailVerifiedChanged = true // Changing the email resets email verified to false by default.
   508  		user.Email = *data.Email
   509  	}
   510  
   511  	var password string
   512  	var authService string
   513  	var authData *string
   514  
   515  	if data.AuthService != nil {
   516  		if user.AuthService != *data.AuthService {
   517  			hasUserAuthDataChanged = true
   518  		}
   519  		authService = *data.AuthService
   520  	}
   521  
   522  	// AuthData and Password are mutually exclusive.
   523  	if data.AuthData != nil {
   524  		if user.AuthData == nil || *user.AuthData != *data.AuthData {
   525  			hasUserAuthDataChanged = true
   526  		}
   527  		authData = data.AuthData
   528  		password = ""
   529  	} else if data.Password != nil {
   530  		password = *data.Password
   531  		authData = nil
   532  	} else {
   533  		// If no AuthData or Password is specified, we must generate a password.
   534  		password = model.NewId()
   535  		authData = nil
   536  	}
   537  
   538  	user.Password = password
   539  	user.AuthService = authService
   540  	user.AuthData = authData
   541  
   542  	// Automatically assume all emails are verified.
   543  	emailVerified := true
   544  	if user.EmailVerified != emailVerified {
   545  		user.EmailVerified = emailVerified
   546  		hasUserEmailVerifiedChanged = true
   547  	}
   548  
   549  	if data.Nickname != nil {
   550  		if user.Nickname != *data.Nickname {
   551  			user.Nickname = *data.Nickname
   552  			hasUserChanged = true
   553  		}
   554  	}
   555  
   556  	if data.FirstName != nil {
   557  		if user.FirstName != *data.FirstName {
   558  			user.FirstName = *data.FirstName
   559  			hasUserChanged = true
   560  		}
   561  	}
   562  
   563  	if data.LastName != nil {
   564  		if user.LastName != *data.LastName {
   565  			user.LastName = *data.LastName
   566  			hasUserChanged = true
   567  		}
   568  	}
   569  
   570  	if data.Position != nil {
   571  		if user.Position != *data.Position {
   572  			user.Position = *data.Position
   573  			hasUserChanged = true
   574  		}
   575  	}
   576  
   577  	if data.Locale != nil {
   578  		if user.Locale != *data.Locale {
   579  			user.Locale = *data.Locale
   580  			hasUserChanged = true
   581  		}
   582  	} else {
   583  		if user.Locale != *a.Config().LocalizationSettings.DefaultClientLocale {
   584  			user.Locale = *a.Config().LocalizationSettings.DefaultClientLocale
   585  			hasUserChanged = true
   586  		}
   587  	}
   588  
   589  	var roles string
   590  	if data.Roles != nil {
   591  		if user.Roles != *data.Roles {
   592  			roles = *data.Roles
   593  			hasUserRolesChanged = true
   594  		}
   595  	} else if len(user.Roles) == 0 {
   596  		// Set SYSTEM_USER roles on newly created users by default.
   597  		if user.Roles != model.SYSTEM_USER_ROLE_ID {
   598  			roles = model.SYSTEM_USER_ROLE_ID
   599  			hasUserRolesChanged = true
   600  		}
   601  	}
   602  	user.Roles = roles
   603  
   604  	if data.NotifyProps != nil {
   605  		if data.NotifyProps.Desktop != nil {
   606  			if value, ok := user.NotifyProps[model.DESKTOP_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Desktop {
   607  				user.AddNotifyProp(model.DESKTOP_NOTIFY_PROP, *data.NotifyProps.Desktop)
   608  				hasNotifyPropsChanged = true
   609  			}
   610  		}
   611  
   612  		if data.NotifyProps.DesktopDuration != nil {
   613  			if value, ok := user.NotifyProps[model.DESKTOP_DURATION_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopDuration {
   614  				user.AddNotifyProp(model.DESKTOP_DURATION_NOTIFY_PROP, *data.NotifyProps.DesktopDuration)
   615  				hasNotifyPropsChanged = true
   616  			}
   617  		}
   618  
   619  		if data.NotifyProps.DesktopSound != nil {
   620  			if value, ok := user.NotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopSound {
   621  				user.AddNotifyProp(model.DESKTOP_SOUND_NOTIFY_PROP, *data.NotifyProps.DesktopSound)
   622  				hasNotifyPropsChanged = true
   623  			}
   624  		}
   625  
   626  		if data.NotifyProps.Email != nil {
   627  			if value, ok := user.NotifyProps[model.EMAIL_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Email {
   628  				user.AddNotifyProp(model.EMAIL_NOTIFY_PROP, *data.NotifyProps.Email)
   629  				hasNotifyPropsChanged = true
   630  			}
   631  		}
   632  
   633  		if data.NotifyProps.Mobile != nil {
   634  			if value, ok := user.NotifyProps[model.PUSH_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Mobile {
   635  				user.AddNotifyProp(model.PUSH_NOTIFY_PROP, *data.NotifyProps.Mobile)
   636  				hasNotifyPropsChanged = true
   637  			}
   638  		}
   639  
   640  		if data.NotifyProps.MobilePushStatus != nil {
   641  			if value, ok := user.NotifyProps[model.PUSH_STATUS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MobilePushStatus {
   642  				user.AddNotifyProp(model.PUSH_STATUS_NOTIFY_PROP, *data.NotifyProps.MobilePushStatus)
   643  				hasNotifyPropsChanged = true
   644  			}
   645  		}
   646  
   647  		if data.NotifyProps.ChannelTrigger != nil {
   648  			if value, ok := user.NotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.ChannelTrigger {
   649  				user.AddNotifyProp(model.CHANNEL_MENTIONS_NOTIFY_PROP, *data.NotifyProps.ChannelTrigger)
   650  				hasNotifyPropsChanged = true
   651  			}
   652  		}
   653  
   654  		if data.NotifyProps.CommentsTrigger != nil {
   655  			if value, ok := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.CommentsTrigger {
   656  				user.AddNotifyProp(model.COMMENTS_NOTIFY_PROP, *data.NotifyProps.CommentsTrigger)
   657  				hasNotifyPropsChanged = true
   658  			}
   659  		}
   660  
   661  		if data.NotifyProps.MentionKeys != nil {
   662  			if value, ok := user.NotifyProps[model.MENTION_KEYS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MentionKeys {
   663  				user.AddNotifyProp(model.MENTION_KEYS_NOTIFY_PROP, *data.NotifyProps.MentionKeys)
   664  				hasNotifyPropsChanged = true
   665  			}
   666  		}
   667  	}
   668  
   669  	var err *model.AppError
   670  	var savedUser *model.User
   671  	if user.Id == "" {
   672  		if savedUser, err = a.createUser(user); err != nil {
   673  			return err
   674  		}
   675  	} else {
   676  		if hasUserChanged {
   677  			if savedUser, err = a.UpdateUser(user, false); err != nil {
   678  				return err
   679  			}
   680  		}
   681  		if hasUserRolesChanged {
   682  			if savedUser, err = a.UpdateUserRoles(user.Id, roles, false); err != nil {
   683  				return err
   684  			}
   685  		}
   686  		if hasNotifyPropsChanged {
   687  			if savedUser, err = a.UpdateUserNotifyProps(user.Id, user.NotifyProps); err != nil {
   688  				return err
   689  			}
   690  		}
   691  		if len(password) > 0 {
   692  			if err = a.UpdatePassword(user, password); err != nil {
   693  				return err
   694  			}
   695  		} else {
   696  			if hasUserAuthDataChanged {
   697  				if res := <-a.Srv.Store.User().UpdateAuthData(user.Id, authService, authData, user.Email, false); res.Err != nil {
   698  					return res.Err
   699  				}
   700  			}
   701  		}
   702  		if emailVerified {
   703  			if hasUserEmailVerifiedChanged {
   704  				if err := a.VerifyUserEmail(user.Id); err != nil {
   705  					return err
   706  				}
   707  			}
   708  		}
   709  	}
   710  
   711  	if savedUser == nil {
   712  		savedUser = user
   713  	}
   714  
   715  	if data.ProfileImage != nil {
   716  		file, err := os.Open(*data.ProfileImage)
   717  		if err != nil {
   718  			l4g.Error(utils.T("api.import.import_user.profile_image.error"), err)
   719  		}
   720  		if err := a.SetProfileImageFromFile(savedUser.Id, file); err != nil {
   721  			l4g.Error(utils.T("api.import.import_user.profile_image.error"), err)
   722  		}
   723  	}
   724  
   725  	// Preferences.
   726  	var preferences model.Preferences
   727  
   728  	if data.Theme != nil {
   729  		preferences = append(preferences, model.Preference{
   730  			UserId:   savedUser.Id,
   731  			Category: model.PREFERENCE_CATEGORY_THEME,
   732  			Name:     "",
   733  			Value:    *data.Theme,
   734  		})
   735  	}
   736  
   737  	if data.UseMilitaryTime != nil {
   738  		preferences = append(preferences, model.Preference{
   739  			UserId:   savedUser.Id,
   740  			Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
   741  			Name:     "use_military_time",
   742  			Value:    *data.UseMilitaryTime,
   743  		})
   744  	}
   745  
   746  	if data.CollapsePreviews != nil {
   747  		preferences = append(preferences, model.Preference{
   748  			UserId:   savedUser.Id,
   749  			Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
   750  			Name:     "collapse_previews",
   751  			Value:    *data.CollapsePreviews,
   752  		})
   753  	}
   754  
   755  	if data.MessageDisplay != nil {
   756  		preferences = append(preferences, model.Preference{
   757  			UserId:   savedUser.Id,
   758  			Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
   759  			Name:     "message_display",
   760  			Value:    *data.MessageDisplay,
   761  		})
   762  	}
   763  
   764  	if data.ChannelDisplayMode != nil {
   765  		preferences = append(preferences, model.Preference{
   766  			UserId:   savedUser.Id,
   767  			Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
   768  			Name:     "channel_display_mode",
   769  			Value:    *data.ChannelDisplayMode,
   770  		})
   771  	}
   772  
   773  	if data.TutorialStep != nil {
   774  		preferences = append(preferences, model.Preference{
   775  			UserId:   savedUser.Id,
   776  			Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS,
   777  			Name:     savedUser.Id,
   778  			Value:    *data.TutorialStep,
   779  		})
   780  	}
   781  
   782  	if len(preferences) > 0 {
   783  		if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
   784  			return model.NewAppError("BulkImport", "app.import.import_user.save_preferences.error", nil, "", http.StatusInternalServerError)
   785  		}
   786  	}
   787  
   788  	return a.ImportUserTeams(savedUser, data.Teams)
   789  }
   790  
   791  func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *model.AppError {
   792  	if data == nil {
   793  		return nil
   794  	}
   795  
   796  	for _, tdata := range *data {
   797  		team, err := a.GetTeamByName(*tdata.Name)
   798  		if err != nil {
   799  			return err
   800  		}
   801  
   802  		var roles string
   803  		if tdata.Roles == nil {
   804  			roles = model.TEAM_USER_ROLE_ID
   805  		} else {
   806  			roles = *tdata.Roles
   807  		}
   808  
   809  		var member *model.TeamMember
   810  		if member, _, err = a.joinUserToTeam(team, user); err != nil {
   811  			return err
   812  		}
   813  
   814  		if member.Roles != roles {
   815  			if _, err := a.UpdateTeamMemberRoles(team.Id, user.Id, roles); err != nil {
   816  				return err
   817  			}
   818  		}
   819  
   820  		if err := a.ImportUserChannels(user, team, member, tdata.Channels); err != nil {
   821  			return err
   822  		}
   823  	}
   824  
   825  	return nil
   826  }
   827  
   828  func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember *model.TeamMember, data *[]UserChannelImportData) *model.AppError {
   829  	if data == nil {
   830  		return nil
   831  	}
   832  
   833  	var preferences model.Preferences
   834  
   835  	// Loop through all channels.
   836  	for _, cdata := range *data {
   837  		channel, err := a.GetChannelByName(*cdata.Name, team.Id)
   838  		if err != nil {
   839  			return err
   840  		}
   841  
   842  		var roles string
   843  		if cdata.Roles == nil {
   844  			roles = model.CHANNEL_USER_ROLE_ID
   845  		} else {
   846  			roles = *cdata.Roles
   847  		}
   848  
   849  		var member *model.ChannelMember
   850  		member, err = a.GetChannelMember(channel.Id, user.Id)
   851  		if err != nil {
   852  			member, err = a.addUserToChannel(user, channel, teamMember)
   853  			if err != nil {
   854  				return err
   855  			}
   856  		}
   857  
   858  		if member.Roles != roles {
   859  			if _, err := a.UpdateChannelMemberRoles(channel.Id, user.Id, roles); err != nil {
   860  				return err
   861  			}
   862  		}
   863  
   864  		if cdata.NotifyProps != nil {
   865  			notifyProps := member.NotifyProps
   866  
   867  			if cdata.NotifyProps.Desktop != nil {
   868  				notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
   869  			}
   870  
   871  			if cdata.NotifyProps.Mobile != nil {
   872  				notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile
   873  			}
   874  
   875  			if cdata.NotifyProps.MarkUnread != nil {
   876  				notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
   877  			}
   878  
   879  			if _, err := a.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id); err != nil {
   880  				return err
   881  			}
   882  		}
   883  
   884  		if cdata.Favorite != nil && *cdata.Favorite {
   885  			preferences = append(preferences, model.Preference{
   886  				UserId:   user.Id,
   887  				Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
   888  				Name:     channel.Id,
   889  				Value:    "true",
   890  			})
   891  		}
   892  	}
   893  
   894  	if len(preferences) > 0 {
   895  		if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
   896  			return model.NewAppError("BulkImport", "app.import.import_user_channels.save_preferences.error", nil, "", http.StatusInternalServerError)
   897  		}
   898  	}
   899  
   900  	return nil
   901  }
   902  
   903  func validateUserImportData(data *UserImportData) *model.AppError {
   904  	if data.ProfileImage != nil {
   905  		if _, err := os.Stat(*data.ProfileImage); os.IsNotExist(err) {
   906  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.profile_image.error", nil, "", http.StatusBadRequest)
   907  		}
   908  	}
   909  
   910  	if data.Username == nil {
   911  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_missing.error", nil, "", http.StatusBadRequest)
   912  	} else if !model.IsValidUsername(*data.Username) {
   913  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_invalid.error", nil, "", http.StatusBadRequest)
   914  	}
   915  
   916  	if data.Email == nil {
   917  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_missing.error", nil, "", http.StatusBadRequest)
   918  	} else if len(*data.Email) == 0 || len(*data.Email) > model.USER_EMAIL_MAX_LENGTH {
   919  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_length.error", nil, "", http.StatusBadRequest)
   920  	}
   921  
   922  	if data.AuthService != nil && len(*data.AuthService) == 0 {
   923  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_service_length.error", nil, "", http.StatusBadRequest)
   924  	}
   925  
   926  	if data.AuthData != nil && data.Password != nil {
   927  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_and_password.error", nil, "", http.StatusBadRequest)
   928  	}
   929  
   930  	if data.AuthData != nil && len(*data.AuthData) > model.USER_AUTH_DATA_MAX_LENGTH {
   931  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_length.error", nil, "", http.StatusBadRequest)
   932  	}
   933  
   934  	if data.Password != nil && len(*data.Password) == 0 {
   935  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.pasword_length.error", nil, "", http.StatusBadRequest)
   936  	}
   937  
   938  	if data.Password != nil && len(*data.Password) > model.USER_PASSWORD_MAX_LENGTH {
   939  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.password_length.error", nil, "", http.StatusBadRequest)
   940  	}
   941  
   942  	if data.Nickname != nil && utf8.RuneCountInString(*data.Nickname) > model.USER_NICKNAME_MAX_RUNES {
   943  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.nickname_length.error", nil, "", http.StatusBadRequest)
   944  	}
   945  
   946  	if data.FirstName != nil && utf8.RuneCountInString(*data.FirstName) > model.USER_FIRST_NAME_MAX_RUNES {
   947  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.first_name_length.error", nil, "", http.StatusBadRequest)
   948  	}
   949  
   950  	if data.LastName != nil && utf8.RuneCountInString(*data.LastName) > model.USER_LAST_NAME_MAX_RUNES {
   951  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.last_name_length.error", nil, "", http.StatusBadRequest)
   952  	}
   953  
   954  	if data.Position != nil && utf8.RuneCountInString(*data.Position) > model.USER_POSITION_MAX_RUNES {
   955  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.position_length.error", nil, "", http.StatusBadRequest)
   956  	}
   957  
   958  	if data.Roles != nil && !model.IsValidUserRoles(*data.Roles) {
   959  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
   960  	}
   961  
   962  	if data.NotifyProps != nil {
   963  		if data.NotifyProps.Desktop != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Desktop) {
   964  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_invalid.error", nil, "", http.StatusBadRequest)
   965  		}
   966  
   967  		if data.NotifyProps.DesktopDuration != nil && !model.IsValidNumberString(*data.NotifyProps.DesktopDuration) {
   968  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", nil, "", http.StatusBadRequest)
   969  		}
   970  
   971  		if data.NotifyProps.DesktopSound != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.DesktopSound) {
   972  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_sound_invalid.error", nil, "", http.StatusBadRequest)
   973  		}
   974  
   975  		if data.NotifyProps.Email != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.Email) {
   976  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_email_invalid.error", nil, "", http.StatusBadRequest)
   977  		}
   978  
   979  		if data.NotifyProps.Mobile != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Mobile) {
   980  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_invalid.error", nil, "", http.StatusBadRequest)
   981  		}
   982  
   983  		if data.NotifyProps.MobilePushStatus != nil && !model.IsValidPushStatusNotifyLevel(*data.NotifyProps.MobilePushStatus) {
   984  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_push_status_invalid.error", nil, "", http.StatusBadRequest)
   985  		}
   986  
   987  		if data.NotifyProps.ChannelTrigger != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.ChannelTrigger) {
   988  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_channel_trigger_invalid.error", nil, "", http.StatusBadRequest)
   989  		}
   990  
   991  		if data.NotifyProps.CommentsTrigger != nil && !model.IsValidCommentsNotifyLevel(*data.NotifyProps.CommentsTrigger) {
   992  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_comments_trigger_invalid.error", nil, "", http.StatusBadRequest)
   993  		}
   994  	}
   995  
   996  	if data.Teams != nil {
   997  		return validateUserTeamsImportData(data.Teams)
   998  	} else {
   999  		return nil
  1000  	}
  1001  }
  1002  
  1003  func validateUserTeamsImportData(data *[]UserTeamImportData) *model.AppError {
  1004  	if data == nil {
  1005  		return nil
  1006  	}
  1007  
  1008  	for _, tdata := range *data {
  1009  		if tdata.Name == nil {
  1010  			return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.team_name_missing.error", nil, "", http.StatusBadRequest)
  1011  		}
  1012  
  1013  		if tdata.Roles != nil && !model.IsValidUserRoles(*tdata.Roles) {
  1014  			return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.invalid_roles.error", nil, "", http.StatusBadRequest)
  1015  		}
  1016  
  1017  		if tdata.Channels != nil {
  1018  			if err := validateUserChannelsImportData(tdata.Channels); err != nil {
  1019  				return err
  1020  			}
  1021  		}
  1022  	}
  1023  
  1024  	return nil
  1025  }
  1026  
  1027  func validateUserChannelsImportData(data *[]UserChannelImportData) *model.AppError {
  1028  	if data == nil {
  1029  		return nil
  1030  	}
  1031  
  1032  	for _, cdata := range *data {
  1033  		if cdata.Name == nil {
  1034  			return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.channel_name_missing.error", nil, "", http.StatusBadRequest)
  1035  		}
  1036  
  1037  		if cdata.Roles != nil && !model.IsValidUserRoles(*cdata.Roles) {
  1038  			return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_roles.error", nil, "", http.StatusBadRequest)
  1039  		}
  1040  
  1041  		if cdata.NotifyProps != nil {
  1042  			if cdata.NotifyProps.Desktop != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Desktop) {
  1043  				return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error", nil, "", http.StatusBadRequest)
  1044  			}
  1045  
  1046  			if cdata.NotifyProps.Mobile != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Mobile) {
  1047  				return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mobile.error", nil, "", http.StatusBadRequest)
  1048  			}
  1049  
  1050  			if cdata.NotifyProps.MarkUnread != nil && !model.IsChannelMarkUnreadLevelValid(*cdata.NotifyProps.MarkUnread) {
  1051  				return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error", nil, "", http.StatusBadRequest)
  1052  			}
  1053  		}
  1054  	}
  1055  
  1056  	return nil
  1057  }
  1058  
  1059  func (a *App) ImportReaction(data *ReactionImportData, post *model.Post, dryRun bool) *model.AppError {
  1060  	if err := validateReactionImportData(data, post.CreateAt); err != nil {
  1061  		return err
  1062  	}
  1063  
  1064  	var user *model.User
  1065  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1066  		return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, "", http.StatusBadRequest)
  1067  	} else {
  1068  		user = result.Data.(*model.User)
  1069  	}
  1070  	reaction := &model.Reaction{
  1071  		UserId:    user.Id,
  1072  		PostId:    post.Id,
  1073  		EmojiName: *data.EmojiName,
  1074  		CreateAt:  *data.CreateAt,
  1075  	}
  1076  	if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil {
  1077  		return result.Err
  1078  	}
  1079  	return nil
  1080  }
  1081  
  1082  func (a *App) ImportReply(data *ReplyImportData, post *model.Post, dryRun bool) *model.AppError {
  1083  	if err := validateReplyImportData(data, post.CreateAt); err != nil {
  1084  		return err
  1085  	}
  1086  
  1087  	var user *model.User
  1088  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1089  		return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, "", http.StatusBadRequest)
  1090  	} else {
  1091  		user = result.Data.(*model.User)
  1092  	}
  1093  
  1094  	// Check if this post already exists.
  1095  	var replies []*model.Post
  1096  	if result := <-a.Srv.Store.Post().GetPostsCreatedAt(post.ChannelId, *data.CreateAt); result.Err != nil {
  1097  		return result.Err
  1098  	} else {
  1099  		replies = result.Data.([]*model.Post)
  1100  	}
  1101  
  1102  	var reply *model.Post
  1103  	for _, r := range replies {
  1104  		if r.Message == *data.Message {
  1105  			reply = r
  1106  			break
  1107  		}
  1108  	}
  1109  
  1110  	if reply == nil {
  1111  		reply = &model.Post{}
  1112  	}
  1113  	reply.UserId = user.Id
  1114  	reply.ChannelId = post.ChannelId
  1115  	reply.ParentId = post.Id
  1116  	reply.RootId = post.Id
  1117  	reply.Message = *data.Message
  1118  	reply.CreateAt = *data.CreateAt
  1119  
  1120  	if reply.Id == "" {
  1121  		if result := <-a.Srv.Store.Post().Save(reply); result.Err != nil {
  1122  			return result.Err
  1123  		}
  1124  	} else {
  1125  		if result := <-a.Srv.Store.Post().Overwrite(reply); result.Err != nil {
  1126  			return result.Err
  1127  		}
  1128  	}
  1129  	return nil
  1130  }
  1131  
  1132  func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError {
  1133  	if err := validatePostImportData(data); err != nil {
  1134  		return err
  1135  	}
  1136  
  1137  	// If this is a Dry Run, do not continue any further.
  1138  	if dryRun {
  1139  		return nil
  1140  	}
  1141  
  1142  	var team *model.Team
  1143  	if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
  1144  		return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, "", http.StatusBadRequest)
  1145  	} else {
  1146  		team = result.Data.(*model.Team)
  1147  	}
  1148  
  1149  	var channel *model.Channel
  1150  	if result := <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false); result.Err != nil {
  1151  		return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, "", http.StatusBadRequest)
  1152  	} else {
  1153  		channel = result.Data.(*model.Channel)
  1154  	}
  1155  
  1156  	var user *model.User
  1157  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1158  		return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
  1159  	} else {
  1160  		user = result.Data.(*model.User)
  1161  	}
  1162  
  1163  	// Check if this post already exists.
  1164  	var posts []*model.Post
  1165  	if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
  1166  		return result.Err
  1167  	} else {
  1168  		posts = result.Data.([]*model.Post)
  1169  	}
  1170  
  1171  	var post *model.Post
  1172  	for _, p := range posts {
  1173  		if p.Message == *data.Message {
  1174  			post = p
  1175  			break
  1176  		}
  1177  	}
  1178  
  1179  	if post == nil {
  1180  		post = &model.Post{}
  1181  	}
  1182  
  1183  	post.ChannelId = channel.Id
  1184  	post.Message = *data.Message
  1185  	post.UserId = user.Id
  1186  	post.CreateAt = *data.CreateAt
  1187  
  1188  	post.Hashtags, _ = model.ParseHashtags(post.Message)
  1189  
  1190  	if post.Id == "" {
  1191  		if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
  1192  			return result.Err
  1193  		}
  1194  	} else {
  1195  		if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
  1196  			return result.Err
  1197  		}
  1198  	}
  1199  
  1200  	if data.FlaggedBy != nil {
  1201  		var preferences model.Preferences
  1202  
  1203  		for _, username := range *data.FlaggedBy {
  1204  			var user *model.User
  1205  
  1206  			if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
  1207  				return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
  1208  			} else {
  1209  				user = result.Data.(*model.User)
  1210  			}
  1211  
  1212  			preferences = append(preferences, model.Preference{
  1213  				UserId:   user.Id,
  1214  				Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
  1215  				Name:     post.Id,
  1216  				Value:    "true",
  1217  			})
  1218  		}
  1219  
  1220  		if len(preferences) > 0 {
  1221  			if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
  1222  				return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, "", http.StatusInternalServerError)
  1223  			}
  1224  		}
  1225  	}
  1226  
  1227  	if data.Reactions != nil {
  1228  		for _, reaction := range *data.Reactions {
  1229  			if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
  1230  				return err
  1231  			}
  1232  		}
  1233  	}
  1234  
  1235  	if data.Replies != nil {
  1236  		for _, reply := range *data.Replies {
  1237  			if err := a.ImportReply(&reply, post, dryRun); err != nil {
  1238  				return err
  1239  			}
  1240  		}
  1241  	}
  1242  
  1243  	return nil
  1244  }
  1245  
  1246  func validateReactionImportData(data *ReactionImportData, parentCreateAt int64) *model.AppError {
  1247  	if data.User == nil {
  1248  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1249  	}
  1250  
  1251  	if data.EmojiName == nil {
  1252  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_missing.error", nil, "", http.StatusBadRequest)
  1253  	} else if utf8.RuneCountInString(*data.EmojiName) > model.EMOJI_NAME_MAX_LENGTH {
  1254  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_length.error", nil, "", http.StatusBadRequest)
  1255  	}
  1256  
  1257  	if data.CreateAt == nil {
  1258  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1259  	} else if *data.CreateAt == 0 {
  1260  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1261  	} else if *data.CreateAt < parentCreateAt {
  1262  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
  1263  	}
  1264  
  1265  	return nil
  1266  }
  1267  
  1268  func validateReplyImportData(data *ReplyImportData, parentCreateAt int64) *model.AppError {
  1269  	if data.User == nil {
  1270  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1271  	}
  1272  
  1273  	if data.Message == nil {
  1274  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_missing.error", nil, "", http.StatusBadRequest)
  1275  	} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
  1276  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_length.error", nil, "", http.StatusBadRequest)
  1277  	}
  1278  
  1279  	if data.CreateAt == nil {
  1280  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1281  	} else if *data.CreateAt == 0 {
  1282  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1283  	} else if *data.CreateAt < parentCreateAt {
  1284  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
  1285  	}
  1286  
  1287  	return nil
  1288  }
  1289  
  1290  func validatePostImportData(data *PostImportData) *model.AppError {
  1291  	if data.Team == nil {
  1292  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.team_missing.error", nil, "", http.StatusBadRequest)
  1293  	}
  1294  
  1295  	if data.Channel == nil {
  1296  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.channel_missing.error", nil, "", http.StatusBadRequest)
  1297  	}
  1298  
  1299  	if data.User == nil {
  1300  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1301  	}
  1302  
  1303  	if data.Message == nil {
  1304  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.message_missing.error", nil, "", http.StatusBadRequest)
  1305  	} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
  1306  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.message_length.error", nil, "", http.StatusBadRequest)
  1307  	}
  1308  
  1309  	if data.CreateAt == nil {
  1310  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1311  	} else if *data.CreateAt == 0 {
  1312  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1313  	}
  1314  
  1315  	if data.Reactions != nil {
  1316  		for _, reaction := range *data.Reactions {
  1317  			validateReactionImportData(&reaction, *data.CreateAt)
  1318  		}
  1319  	}
  1320  
  1321  	if data.Replies != nil {
  1322  		for _, reply := range *data.Replies {
  1323  			validateReplyImportData(&reply, *data.CreateAt)
  1324  		}
  1325  	}
  1326  
  1327  	return nil
  1328  }
  1329  
  1330  func (a *App) ImportDirectChannel(data *DirectChannelImportData, dryRun bool) *model.AppError {
  1331  	if err := validateDirectChannelImportData(data); err != nil {
  1332  		return err
  1333  	}
  1334  
  1335  	// If this is a Dry Run, do not continue any further.
  1336  	if dryRun {
  1337  		return nil
  1338  	}
  1339  
  1340  	var userIds []string
  1341  	userMap := make(map[string]string)
  1342  	for _, username := range *data.Members {
  1343  		if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
  1344  			user := result.Data.(*model.User)
  1345  			userIds = append(userIds, user.Id)
  1346  			userMap[username] = user.Id
  1347  		} else {
  1348  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.member_not_found.error", nil, "", http.StatusBadRequest)
  1349  		}
  1350  	}
  1351  
  1352  	var channel *model.Channel
  1353  
  1354  	if len(userIds) == 2 {
  1355  		ch, err := a.createDirectChannel(userIds[0], userIds[1])
  1356  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1357  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_direct_channel.error", nil, "", http.StatusBadRequest)
  1358  		} else {
  1359  			channel = ch
  1360  		}
  1361  	} else {
  1362  		ch, err := a.createGroupChannel(userIds, userIds[0])
  1363  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1364  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_group_channel.error", nil, "", http.StatusBadRequest)
  1365  		} else {
  1366  			channel = ch
  1367  		}
  1368  	}
  1369  
  1370  	var preferences model.Preferences
  1371  
  1372  	for _, userId := range userIds {
  1373  		preferences = append(preferences, model.Preference{
  1374  			UserId:   userId,
  1375  			Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
  1376  			Name:     channel.Id,
  1377  			Value:    "true",
  1378  		})
  1379  	}
  1380  
  1381  	if data.FavoritedBy != nil {
  1382  		for _, favoriter := range *data.FavoritedBy {
  1383  			preferences = append(preferences, model.Preference{
  1384  				UserId:   userMap[favoriter],
  1385  				Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
  1386  				Name:     channel.Id,
  1387  				Value:    "true",
  1388  			})
  1389  		}
  1390  	}
  1391  
  1392  	if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
  1393  		result.Err.StatusCode = http.StatusBadRequest
  1394  		return result.Err
  1395  	}
  1396  
  1397  	if data.Header != nil {
  1398  		channel.Header = *data.Header
  1399  		if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil {
  1400  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.update_header_failed.error", nil, "", http.StatusBadRequest)
  1401  		}
  1402  	}
  1403  
  1404  	return nil
  1405  }
  1406  
  1407  func validateDirectChannelImportData(data *DirectChannelImportData) *model.AppError {
  1408  	if data.Members == nil {
  1409  		return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_required.error", nil, "", http.StatusBadRequest)
  1410  	}
  1411  
  1412  	if len(*data.Members) != 2 {
  1413  		if len(*data.Members) < model.CHANNEL_GROUP_MIN_USERS {
  1414  			return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_too_few.error", nil, "", http.StatusBadRequest)
  1415  		} else if len(*data.Members) > model.CHANNEL_GROUP_MAX_USERS {
  1416  			return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_too_many.error", nil, "", http.StatusBadRequest)
  1417  		}
  1418  	}
  1419  
  1420  	if data.Header != nil && utf8.RuneCountInString(*data.Header) > model.CHANNEL_HEADER_MAX_RUNES {
  1421  		return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.header_length.error", nil, "", http.StatusBadRequest)
  1422  	}
  1423  
  1424  	if data.FavoritedBy != nil {
  1425  		for _, favoriter := range *data.FavoritedBy {
  1426  			found := false
  1427  			for _, member := range *data.Members {
  1428  				if favoriter == member {
  1429  					found = true
  1430  					break
  1431  				}
  1432  			}
  1433  			if !found {
  1434  				return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.unknown_favoriter.error", map[string]interface{}{"Username": favoriter}, "", http.StatusBadRequest)
  1435  			}
  1436  		}
  1437  	}
  1438  
  1439  	return nil
  1440  }
  1441  
  1442  func (a *App) ImportDirectPost(data *DirectPostImportData, dryRun bool) *model.AppError {
  1443  	if err := validateDirectPostImportData(data); err != nil {
  1444  		return err
  1445  	}
  1446  
  1447  	// If this is a Dry Run, do not continue any further.
  1448  	if dryRun {
  1449  		return nil
  1450  	}
  1451  
  1452  	var userIds []string
  1453  	for _, username := range *data.ChannelMembers {
  1454  		if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
  1455  			user := result.Data.(*model.User)
  1456  			userIds = append(userIds, user.Id)
  1457  		} else {
  1458  			return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, "", http.StatusBadRequest)
  1459  		}
  1460  	}
  1461  
  1462  	var channel *model.Channel
  1463  	if len(userIds) == 2 {
  1464  		ch, err := a.createDirectChannel(userIds[0], userIds[1])
  1465  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1466  			return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, "", http.StatusBadRequest)
  1467  		} else {
  1468  			channel = ch
  1469  		}
  1470  	} else {
  1471  		ch, err := a.createGroupChannel(userIds, userIds[0])
  1472  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1473  			return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, "", http.StatusBadRequest)
  1474  		} else {
  1475  			channel = ch
  1476  		}
  1477  	}
  1478  
  1479  	var user *model.User
  1480  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1481  		return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
  1482  	} else {
  1483  		user = result.Data.(*model.User)
  1484  	}
  1485  
  1486  	// Check if this post already exists.
  1487  	var posts []*model.Post
  1488  	if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
  1489  		return result.Err
  1490  	} else {
  1491  		posts = result.Data.([]*model.Post)
  1492  	}
  1493  
  1494  	var post *model.Post
  1495  	for _, p := range posts {
  1496  		if p.Message == *data.Message {
  1497  			post = p
  1498  			break
  1499  		}
  1500  	}
  1501  
  1502  	if post == nil {
  1503  		post = &model.Post{}
  1504  	}
  1505  
  1506  	post.ChannelId = channel.Id
  1507  	post.Message = *data.Message
  1508  	post.UserId = user.Id
  1509  	post.CreateAt = *data.CreateAt
  1510  
  1511  	post.Hashtags, _ = model.ParseHashtags(post.Message)
  1512  
  1513  	if post.Id == "" {
  1514  		if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
  1515  			return result.Err
  1516  		}
  1517  	} else {
  1518  		if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
  1519  			return result.Err
  1520  		}
  1521  	}
  1522  
  1523  	if data.FlaggedBy != nil {
  1524  		var preferences model.Preferences
  1525  
  1526  		for _, username := range *data.FlaggedBy {
  1527  			var user *model.User
  1528  
  1529  			if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
  1530  				return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
  1531  			} else {
  1532  				user = result.Data.(*model.User)
  1533  			}
  1534  
  1535  			preferences = append(preferences, model.Preference{
  1536  				UserId:   user.Id,
  1537  				Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
  1538  				Name:     post.Id,
  1539  				Value:    "true",
  1540  			})
  1541  		}
  1542  
  1543  		if len(preferences) > 0 {
  1544  			if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
  1545  				return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, "", http.StatusInternalServerError)
  1546  			}
  1547  		}
  1548  	}
  1549  
  1550  	if data.Reactions != nil {
  1551  		for _, reaction := range *data.Reactions {
  1552  			if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
  1553  				return err
  1554  			}
  1555  		}
  1556  	}
  1557  
  1558  	if data.Replies != nil {
  1559  		for _, reply := range *data.Replies {
  1560  			if err := a.ImportReply(&reply, post, dryRun); err != nil {
  1561  				return err
  1562  			}
  1563  		}
  1564  	}
  1565  
  1566  	return nil
  1567  }
  1568  
  1569  func validateDirectPostImportData(data *DirectPostImportData) *model.AppError {
  1570  	if data.ChannelMembers == nil {
  1571  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_required.error", nil, "", http.StatusBadRequest)
  1572  	}
  1573  
  1574  	if len(*data.ChannelMembers) != 2 {
  1575  		if len(*data.ChannelMembers) < model.CHANNEL_GROUP_MIN_USERS {
  1576  			return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_too_few.error", nil, "", http.StatusBadRequest)
  1577  		} else if len(*data.ChannelMembers) > model.CHANNEL_GROUP_MAX_USERS {
  1578  			return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_too_many.error", nil, "", http.StatusBadRequest)
  1579  		}
  1580  	}
  1581  
  1582  	if data.User == nil {
  1583  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1584  	}
  1585  
  1586  	if data.Message == nil {
  1587  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.message_missing.error", nil, "", http.StatusBadRequest)
  1588  	} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
  1589  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.message_length.error", nil, "", http.StatusBadRequest)
  1590  	}
  1591  
  1592  	if data.CreateAt == nil {
  1593  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1594  	} else if *data.CreateAt == 0 {
  1595  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1596  	}
  1597  
  1598  	if data.FlaggedBy != nil {
  1599  		for _, flagger := range *data.FlaggedBy {
  1600  			found := false
  1601  			for _, member := range *data.ChannelMembers {
  1602  				if flagger == member {
  1603  					found = true
  1604  					break
  1605  				}
  1606  			}
  1607  			if !found {
  1608  				return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.unknown_flagger.error", map[string]interface{}{"Username": flagger}, "", http.StatusBadRequest)
  1609  			}
  1610  		}
  1611  	}
  1612  
  1613  	if data.Reactions != nil {
  1614  		for _, reaction := range *data.Reactions {
  1615  			validateReactionImportData(&reaction, *data.CreateAt)
  1616  		}
  1617  	}
  1618  
  1619  	if data.Replies != nil {
  1620  		for _, reply := range *data.Replies {
  1621  			validateReplyImportData(&reply, *data.CreateAt)
  1622  		}
  1623  	}
  1624  
  1625  	return nil
  1626  }
  1627  
  1628  //
  1629  // -- Old SlackImport Functions --
  1630  // Import functions are sutible for entering posts and users into the database without
  1631  // some of the usual checks. (IsValid is still run)
  1632  //
  1633  
  1634  func (a *App) OldImportPost(post *model.Post) {
  1635  	// Workaround for empty messages, which may be the case if they are webhook posts.
  1636  	firstIteration := true
  1637  	for messageRuneCount := utf8.RuneCountInString(post.Message); messageRuneCount > 0 || firstIteration; messageRuneCount = utf8.RuneCountInString(post.Message) {
  1638  		firstIteration = false
  1639  		var remainder string
  1640  		if messageRuneCount > model.POST_MESSAGE_MAX_RUNES {
  1641  			remainder = string(([]rune(post.Message))[model.POST_MESSAGE_MAX_RUNES:])
  1642  			post.Message = truncateRunes(post.Message, model.POST_MESSAGE_MAX_RUNES)
  1643  		} else {
  1644  			remainder = ""
  1645  		}
  1646  
  1647  		post.Hashtags, _ = model.ParseHashtags(post.Message)
  1648  
  1649  		if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
  1650  			l4g.Debug(utils.T("api.import.import_post.saving.debug"), post.UserId, post.Message)
  1651  		}
  1652  
  1653  		for _, fileId := range post.FileIds {
  1654  			if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
  1655  				l4g.Error(utils.T("api.import.import_post.attach_files.error"), post.Id, post.FileIds, result.Err)
  1656  			}
  1657  		}
  1658  
  1659  		post.Id = ""
  1660  		post.CreateAt++
  1661  		post.Message = remainder
  1662  	}
  1663  }
  1664  
  1665  func (a *App) OldImportUser(team *model.Team, user *model.User) *model.User {
  1666  	user.MakeNonNil()
  1667  
  1668  	user.Roles = model.SYSTEM_USER_ROLE_ID
  1669  
  1670  	if result := <-a.Srv.Store.User().Save(user); result.Err != nil {
  1671  		l4g.Error(utils.T("api.import.import_user.saving.error"), result.Err)
  1672  		return nil
  1673  	} else {
  1674  		ruser := result.Data.(*model.User)
  1675  
  1676  		if cresult := <-a.Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
  1677  			l4g.Error(utils.T("api.import.import_user.set_email.error"), cresult.Err)
  1678  		}
  1679  
  1680  		if err := a.JoinUserToTeam(team, user, ""); err != nil {
  1681  			l4g.Error(utils.T("api.import.import_user.join_team.error"), err)
  1682  		}
  1683  
  1684  		return ruser
  1685  	}
  1686  }
  1687  
  1688  func (a *App) OldImportChannel(channel *model.Channel) *model.Channel {
  1689  	if result := <-a.Srv.Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam); result.Err != nil {
  1690  		return nil
  1691  	} else {
  1692  		sc := result.Data.(*model.Channel)
  1693  
  1694  		return sc
  1695  	}
  1696  }
  1697  
  1698  func (a *App) OldImportFile(timestamp time.Time, file io.Reader, teamId string, channelId string, userId string, fileName string) (*model.FileInfo, error) {
  1699  	buf := bytes.NewBuffer(nil)
  1700  	io.Copy(buf, file)
  1701  	data := buf.Bytes()
  1702  
  1703  	fileInfo, err := a.DoUploadFile(timestamp, teamId, channelId, userId, fileName, data)
  1704  	if err != nil {
  1705  		return nil, err
  1706  	}
  1707  
  1708  	img, width, height := prepareImage(data)
  1709  	if img != nil {
  1710  		a.generateThumbnailImage(*img, fileInfo.ThumbnailPath, width, height)
  1711  		a.generatePreviewImage(*img, fileInfo.PreviewPath, width)
  1712  	}
  1713  
  1714  	return fileInfo, nil
  1715  }
  1716  
  1717  func (a *App) OldImportIncomingWebhookPost(post *model.Post, props model.StringInterface) {
  1718  	linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
  1719  	post.Message = linkWithTextRegex.ReplaceAllString(post.Message, "[${2}](${1})")
  1720  
  1721  	post.AddProp("from_webhook", "true")
  1722  
  1723  	if _, ok := props["override_username"]; !ok {
  1724  		post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
  1725  	}
  1726  
  1727  	if len(props) > 0 {
  1728  		for key, val := range props {
  1729  			if key == "attachments" {
  1730  				if attachments, success := val.([]*model.SlackAttachment); success {
  1731  					parseSlackAttachment(post, attachments)
  1732  				}
  1733  			} else if key != "from_webhook" {
  1734  				post.AddProp(key, val)
  1735  			}
  1736  		}
  1737  	}
  1738  
  1739  	a.OldImportPost(post)
  1740  }