github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+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 defaultChannel, err := a.GetChannelByName(model.DEFAULT_CHANNEL, team.Id); err != nil {
   821  			return err
   822  		} else if _, err = a.addUserToChannel(user, defaultChannel, member); err != nil {
   823  			return err
   824  		}
   825  
   826  		if err := a.ImportUserChannels(user, team, member, tdata.Channels); err != nil {
   827  			return err
   828  		}
   829  	}
   830  
   831  	return nil
   832  }
   833  
   834  func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember *model.TeamMember, data *[]UserChannelImportData) *model.AppError {
   835  	if data == nil {
   836  		return nil
   837  	}
   838  
   839  	var preferences model.Preferences
   840  
   841  	// Loop through all channels.
   842  	for _, cdata := range *data {
   843  		channel, err := a.GetChannelByName(*cdata.Name, team.Id)
   844  		if err != nil {
   845  			return err
   846  		}
   847  
   848  		var roles string
   849  		if cdata.Roles == nil {
   850  			roles = model.CHANNEL_USER_ROLE_ID
   851  		} else {
   852  			roles = *cdata.Roles
   853  		}
   854  
   855  		var member *model.ChannelMember
   856  		member, err = a.GetChannelMember(channel.Id, user.Id)
   857  		if err != nil {
   858  			member, err = a.addUserToChannel(user, channel, teamMember)
   859  			if err != nil {
   860  				return err
   861  			}
   862  		}
   863  
   864  		if member.Roles != roles {
   865  			if _, err := a.UpdateChannelMemberRoles(channel.Id, user.Id, roles); err != nil {
   866  				return err
   867  			}
   868  		}
   869  
   870  		if cdata.NotifyProps != nil {
   871  			notifyProps := member.NotifyProps
   872  
   873  			if cdata.NotifyProps.Desktop != nil {
   874  				notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
   875  			}
   876  
   877  			if cdata.NotifyProps.Mobile != nil {
   878  				notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile
   879  			}
   880  
   881  			if cdata.NotifyProps.MarkUnread != nil {
   882  				notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
   883  			}
   884  
   885  			if _, err := a.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id); err != nil {
   886  				return err
   887  			}
   888  		}
   889  
   890  		if cdata.Favorite != nil && *cdata.Favorite {
   891  			preferences = append(preferences, model.Preference{
   892  				UserId:   user.Id,
   893  				Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
   894  				Name:     channel.Id,
   895  				Value:    "true",
   896  			})
   897  		}
   898  	}
   899  
   900  	if len(preferences) > 0 {
   901  		if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
   902  			return model.NewAppError("BulkImport", "app.import.import_user_channels.save_preferences.error", nil, "", http.StatusInternalServerError)
   903  		}
   904  	}
   905  
   906  	return nil
   907  }
   908  
   909  func validateUserImportData(data *UserImportData) *model.AppError {
   910  	if data.ProfileImage != nil {
   911  		if _, err := os.Stat(*data.ProfileImage); os.IsNotExist(err) {
   912  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.profile_image.error", nil, "", http.StatusBadRequest)
   913  		}
   914  	}
   915  
   916  	if data.Username == nil {
   917  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_missing.error", nil, "", http.StatusBadRequest)
   918  	} else if !model.IsValidUsername(*data.Username) {
   919  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_invalid.error", nil, "", http.StatusBadRequest)
   920  	}
   921  
   922  	if data.Email == nil {
   923  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_missing.error", nil, "", http.StatusBadRequest)
   924  	} else if len(*data.Email) == 0 || len(*data.Email) > model.USER_EMAIL_MAX_LENGTH {
   925  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_length.error", nil, "", http.StatusBadRequest)
   926  	}
   927  
   928  	if data.AuthService != nil && len(*data.AuthService) == 0 {
   929  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_service_length.error", nil, "", http.StatusBadRequest)
   930  	}
   931  
   932  	if data.AuthData != nil && data.Password != nil {
   933  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_and_password.error", nil, "", http.StatusBadRequest)
   934  	}
   935  
   936  	if data.AuthData != nil && len(*data.AuthData) > model.USER_AUTH_DATA_MAX_LENGTH {
   937  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_length.error", nil, "", http.StatusBadRequest)
   938  	}
   939  
   940  	if data.Password != nil && len(*data.Password) == 0 {
   941  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.pasword_length.error", nil, "", http.StatusBadRequest)
   942  	}
   943  
   944  	if data.Password != nil && len(*data.Password) > model.USER_PASSWORD_MAX_LENGTH {
   945  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.password_length.error", nil, "", http.StatusBadRequest)
   946  	}
   947  
   948  	if data.Nickname != nil && utf8.RuneCountInString(*data.Nickname) > model.USER_NICKNAME_MAX_RUNES {
   949  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.nickname_length.error", nil, "", http.StatusBadRequest)
   950  	}
   951  
   952  	if data.FirstName != nil && utf8.RuneCountInString(*data.FirstName) > model.USER_FIRST_NAME_MAX_RUNES {
   953  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.first_name_length.error", nil, "", http.StatusBadRequest)
   954  	}
   955  
   956  	if data.LastName != nil && utf8.RuneCountInString(*data.LastName) > model.USER_LAST_NAME_MAX_RUNES {
   957  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.last_name_length.error", nil, "", http.StatusBadRequest)
   958  	}
   959  
   960  	if data.Position != nil && utf8.RuneCountInString(*data.Position) > model.USER_POSITION_MAX_RUNES {
   961  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.position_length.error", nil, "", http.StatusBadRequest)
   962  	}
   963  
   964  	if data.Roles != nil && !model.IsValidUserRoles(*data.Roles) {
   965  		return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
   966  	}
   967  
   968  	if data.NotifyProps != nil {
   969  		if data.NotifyProps.Desktop != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Desktop) {
   970  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_invalid.error", nil, "", http.StatusBadRequest)
   971  		}
   972  
   973  		if data.NotifyProps.DesktopDuration != nil && !model.IsValidNumberString(*data.NotifyProps.DesktopDuration) {
   974  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", nil, "", http.StatusBadRequest)
   975  		}
   976  
   977  		if data.NotifyProps.DesktopSound != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.DesktopSound) {
   978  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_sound_invalid.error", nil, "", http.StatusBadRequest)
   979  		}
   980  
   981  		if data.NotifyProps.Email != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.Email) {
   982  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_email_invalid.error", nil, "", http.StatusBadRequest)
   983  		}
   984  
   985  		if data.NotifyProps.Mobile != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Mobile) {
   986  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_invalid.error", nil, "", http.StatusBadRequest)
   987  		}
   988  
   989  		if data.NotifyProps.MobilePushStatus != nil && !model.IsValidPushStatusNotifyLevel(*data.NotifyProps.MobilePushStatus) {
   990  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_push_status_invalid.error", nil, "", http.StatusBadRequest)
   991  		}
   992  
   993  		if data.NotifyProps.ChannelTrigger != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.ChannelTrigger) {
   994  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_channel_trigger_invalid.error", nil, "", http.StatusBadRequest)
   995  		}
   996  
   997  		if data.NotifyProps.CommentsTrigger != nil && !model.IsValidCommentsNotifyLevel(*data.NotifyProps.CommentsTrigger) {
   998  			return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_comments_trigger_invalid.error", nil, "", http.StatusBadRequest)
   999  		}
  1000  	}
  1001  
  1002  	if data.Teams != nil {
  1003  		return validateUserTeamsImportData(data.Teams)
  1004  	} else {
  1005  		return nil
  1006  	}
  1007  }
  1008  
  1009  func validateUserTeamsImportData(data *[]UserTeamImportData) *model.AppError {
  1010  	if data == nil {
  1011  		return nil
  1012  	}
  1013  
  1014  	for _, tdata := range *data {
  1015  		if tdata.Name == nil {
  1016  			return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.team_name_missing.error", nil, "", http.StatusBadRequest)
  1017  		}
  1018  
  1019  		if tdata.Roles != nil && !model.IsValidUserRoles(*tdata.Roles) {
  1020  			return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.invalid_roles.error", nil, "", http.StatusBadRequest)
  1021  		}
  1022  
  1023  		if tdata.Channels != nil {
  1024  			if err := validateUserChannelsImportData(tdata.Channels); err != nil {
  1025  				return err
  1026  			}
  1027  		}
  1028  	}
  1029  
  1030  	return nil
  1031  }
  1032  
  1033  func validateUserChannelsImportData(data *[]UserChannelImportData) *model.AppError {
  1034  	if data == nil {
  1035  		return nil
  1036  	}
  1037  
  1038  	for _, cdata := range *data {
  1039  		if cdata.Name == nil {
  1040  			return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.channel_name_missing.error", nil, "", http.StatusBadRequest)
  1041  		}
  1042  
  1043  		if cdata.Roles != nil && !model.IsValidUserRoles(*cdata.Roles) {
  1044  			return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_roles.error", nil, "", http.StatusBadRequest)
  1045  		}
  1046  
  1047  		if cdata.NotifyProps != nil {
  1048  			if cdata.NotifyProps.Desktop != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Desktop) {
  1049  				return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error", nil, "", http.StatusBadRequest)
  1050  			}
  1051  
  1052  			if cdata.NotifyProps.Mobile != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Mobile) {
  1053  				return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mobile.error", nil, "", http.StatusBadRequest)
  1054  			}
  1055  
  1056  			if cdata.NotifyProps.MarkUnread != nil && !model.IsChannelMarkUnreadLevelValid(*cdata.NotifyProps.MarkUnread) {
  1057  				return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error", nil, "", http.StatusBadRequest)
  1058  			}
  1059  		}
  1060  	}
  1061  
  1062  	return nil
  1063  }
  1064  
  1065  func (a *App) ImportReaction(data *ReactionImportData, post *model.Post, dryRun bool) *model.AppError {
  1066  	if err := validateReactionImportData(data, post.CreateAt); err != nil {
  1067  		return err
  1068  	}
  1069  
  1070  	var user *model.User
  1071  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1072  		return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, "", http.StatusBadRequest)
  1073  	} else {
  1074  		user = result.Data.(*model.User)
  1075  	}
  1076  	reaction := &model.Reaction{
  1077  		UserId:    user.Id,
  1078  		PostId:    post.Id,
  1079  		EmojiName: *data.EmojiName,
  1080  		CreateAt:  *data.CreateAt,
  1081  	}
  1082  	if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil {
  1083  		return result.Err
  1084  	}
  1085  	return nil
  1086  }
  1087  
  1088  func (a *App) ImportReply(data *ReplyImportData, post *model.Post, dryRun bool) *model.AppError {
  1089  	if err := validateReplyImportData(data, post.CreateAt); err != nil {
  1090  		return err
  1091  	}
  1092  
  1093  	var user *model.User
  1094  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1095  		return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, "", http.StatusBadRequest)
  1096  	} else {
  1097  		user = result.Data.(*model.User)
  1098  	}
  1099  
  1100  	// Check if this post already exists.
  1101  	var replies []*model.Post
  1102  	if result := <-a.Srv.Store.Post().GetPostsCreatedAt(post.ChannelId, *data.CreateAt); result.Err != nil {
  1103  		return result.Err
  1104  	} else {
  1105  		replies = result.Data.([]*model.Post)
  1106  	}
  1107  
  1108  	var reply *model.Post
  1109  	for _, r := range replies {
  1110  		if r.Message == *data.Message {
  1111  			reply = r
  1112  			break
  1113  		}
  1114  	}
  1115  
  1116  	if reply == nil {
  1117  		reply = &model.Post{}
  1118  	}
  1119  	reply.UserId = user.Id
  1120  	reply.ChannelId = post.ChannelId
  1121  	reply.ParentId = post.Id
  1122  	reply.RootId = post.Id
  1123  	reply.Message = *data.Message
  1124  	reply.CreateAt = *data.CreateAt
  1125  
  1126  	if reply.Id == "" {
  1127  		if result := <-a.Srv.Store.Post().Save(reply); result.Err != nil {
  1128  			return result.Err
  1129  		}
  1130  	} else {
  1131  		if result := <-a.Srv.Store.Post().Overwrite(reply); result.Err != nil {
  1132  			return result.Err
  1133  		}
  1134  	}
  1135  	return nil
  1136  }
  1137  
  1138  func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError {
  1139  	if err := validatePostImportData(data); err != nil {
  1140  		return err
  1141  	}
  1142  
  1143  	// If this is a Dry Run, do not continue any further.
  1144  	if dryRun {
  1145  		return nil
  1146  	}
  1147  
  1148  	var team *model.Team
  1149  	if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
  1150  		return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, "", http.StatusBadRequest)
  1151  	} else {
  1152  		team = result.Data.(*model.Team)
  1153  	}
  1154  
  1155  	var channel *model.Channel
  1156  	if result := <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false); result.Err != nil {
  1157  		return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, "", http.StatusBadRequest)
  1158  	} else {
  1159  		channel = result.Data.(*model.Channel)
  1160  	}
  1161  
  1162  	var user *model.User
  1163  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1164  		return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
  1165  	} else {
  1166  		user = result.Data.(*model.User)
  1167  	}
  1168  
  1169  	// Check if this post already exists.
  1170  	var posts []*model.Post
  1171  	if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
  1172  		return result.Err
  1173  	} else {
  1174  		posts = result.Data.([]*model.Post)
  1175  	}
  1176  
  1177  	var post *model.Post
  1178  	for _, p := range posts {
  1179  		if p.Message == *data.Message {
  1180  			post = p
  1181  			break
  1182  		}
  1183  	}
  1184  
  1185  	if post == nil {
  1186  		post = &model.Post{}
  1187  	}
  1188  
  1189  	post.ChannelId = channel.Id
  1190  	post.Message = *data.Message
  1191  	post.UserId = user.Id
  1192  	post.CreateAt = *data.CreateAt
  1193  
  1194  	post.Hashtags, _ = model.ParseHashtags(post.Message)
  1195  
  1196  	if post.Id == "" {
  1197  		if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
  1198  			return result.Err
  1199  		}
  1200  	} else {
  1201  		if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
  1202  			return result.Err
  1203  		}
  1204  	}
  1205  
  1206  	if data.FlaggedBy != nil {
  1207  		var preferences model.Preferences
  1208  
  1209  		for _, username := range *data.FlaggedBy {
  1210  			var user *model.User
  1211  
  1212  			if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
  1213  				return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
  1214  			} else {
  1215  				user = result.Data.(*model.User)
  1216  			}
  1217  
  1218  			preferences = append(preferences, model.Preference{
  1219  				UserId:   user.Id,
  1220  				Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
  1221  				Name:     post.Id,
  1222  				Value:    "true",
  1223  			})
  1224  		}
  1225  
  1226  		if len(preferences) > 0 {
  1227  			if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
  1228  				return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, "", http.StatusInternalServerError)
  1229  			}
  1230  		}
  1231  	}
  1232  
  1233  	if data.Reactions != nil {
  1234  		for _, reaction := range *data.Reactions {
  1235  			if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
  1236  				return err
  1237  			}
  1238  		}
  1239  	}
  1240  
  1241  	if data.Replies != nil {
  1242  		for _, reply := range *data.Replies {
  1243  			if err := a.ImportReply(&reply, post, dryRun); err != nil {
  1244  				return err
  1245  			}
  1246  		}
  1247  	}
  1248  
  1249  	return nil
  1250  }
  1251  
  1252  func validateReactionImportData(data *ReactionImportData, parentCreateAt int64) *model.AppError {
  1253  	if data.User == nil {
  1254  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1255  	}
  1256  
  1257  	if data.EmojiName == nil {
  1258  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_missing.error", nil, "", http.StatusBadRequest)
  1259  	} else if utf8.RuneCountInString(*data.EmojiName) > model.EMOJI_NAME_MAX_LENGTH {
  1260  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_length.error", nil, "", http.StatusBadRequest)
  1261  	}
  1262  
  1263  	if data.CreateAt == nil {
  1264  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1265  	} else if *data.CreateAt == 0 {
  1266  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1267  	} else if *data.CreateAt < parentCreateAt {
  1268  		return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
  1269  	}
  1270  
  1271  	return nil
  1272  }
  1273  
  1274  func validateReplyImportData(data *ReplyImportData, parentCreateAt int64) *model.AppError {
  1275  	if data.User == nil {
  1276  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1277  	}
  1278  
  1279  	if data.Message == nil {
  1280  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_missing.error", nil, "", http.StatusBadRequest)
  1281  	} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
  1282  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_length.error", nil, "", http.StatusBadRequest)
  1283  	}
  1284  
  1285  	if data.CreateAt == nil {
  1286  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1287  	} else if *data.CreateAt == 0 {
  1288  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1289  	} else if *data.CreateAt < parentCreateAt {
  1290  		return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
  1291  	}
  1292  
  1293  	return nil
  1294  }
  1295  
  1296  func validatePostImportData(data *PostImportData) *model.AppError {
  1297  	if data.Team == nil {
  1298  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.team_missing.error", nil, "", http.StatusBadRequest)
  1299  	}
  1300  
  1301  	if data.Channel == nil {
  1302  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.channel_missing.error", nil, "", http.StatusBadRequest)
  1303  	}
  1304  
  1305  	if data.User == nil {
  1306  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1307  	}
  1308  
  1309  	if data.Message == nil {
  1310  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.message_missing.error", nil, "", http.StatusBadRequest)
  1311  	} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
  1312  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.message_length.error", nil, "", http.StatusBadRequest)
  1313  	}
  1314  
  1315  	if data.CreateAt == nil {
  1316  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1317  	} else if *data.CreateAt == 0 {
  1318  		return model.NewAppError("BulkImport", "app.import.validate_post_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1319  	}
  1320  
  1321  	if data.Reactions != nil {
  1322  		for _, reaction := range *data.Reactions {
  1323  			validateReactionImportData(&reaction, *data.CreateAt)
  1324  		}
  1325  	}
  1326  
  1327  	if data.Replies != nil {
  1328  		for _, reply := range *data.Replies {
  1329  			validateReplyImportData(&reply, *data.CreateAt)
  1330  		}
  1331  	}
  1332  
  1333  	return nil
  1334  }
  1335  
  1336  func (a *App) ImportDirectChannel(data *DirectChannelImportData, dryRun bool) *model.AppError {
  1337  	if err := validateDirectChannelImportData(data); err != nil {
  1338  		return err
  1339  	}
  1340  
  1341  	// If this is a Dry Run, do not continue any further.
  1342  	if dryRun {
  1343  		return nil
  1344  	}
  1345  
  1346  	var userIds []string
  1347  	userMap := make(map[string]string)
  1348  	for _, username := range *data.Members {
  1349  		if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
  1350  			user := result.Data.(*model.User)
  1351  			userIds = append(userIds, user.Id)
  1352  			userMap[username] = user.Id
  1353  		} else {
  1354  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.member_not_found.error", nil, "", http.StatusBadRequest)
  1355  		}
  1356  	}
  1357  
  1358  	var channel *model.Channel
  1359  
  1360  	if len(userIds) == 2 {
  1361  		ch, err := a.createDirectChannel(userIds[0], userIds[1])
  1362  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1363  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_direct_channel.error", nil, "", http.StatusBadRequest)
  1364  		} else {
  1365  			channel = ch
  1366  		}
  1367  	} else {
  1368  		ch, err := a.createGroupChannel(userIds, userIds[0])
  1369  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1370  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_group_channel.error", nil, "", http.StatusBadRequest)
  1371  		} else {
  1372  			channel = ch
  1373  		}
  1374  	}
  1375  
  1376  	var preferences model.Preferences
  1377  
  1378  	for _, userId := range userIds {
  1379  		preferences = append(preferences, model.Preference{
  1380  			UserId:   userId,
  1381  			Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
  1382  			Name:     channel.Id,
  1383  			Value:    "true",
  1384  		})
  1385  	}
  1386  
  1387  	if data.FavoritedBy != nil {
  1388  		for _, favoriter := range *data.FavoritedBy {
  1389  			preferences = append(preferences, model.Preference{
  1390  				UserId:   userMap[favoriter],
  1391  				Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
  1392  				Name:     channel.Id,
  1393  				Value:    "true",
  1394  			})
  1395  		}
  1396  	}
  1397  
  1398  	if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
  1399  		result.Err.StatusCode = http.StatusBadRequest
  1400  		return result.Err
  1401  	}
  1402  
  1403  	if data.Header != nil {
  1404  		channel.Header = *data.Header
  1405  		if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil {
  1406  			return model.NewAppError("BulkImport", "app.import.import_direct_channel.update_header_failed.error", nil, "", http.StatusBadRequest)
  1407  		}
  1408  	}
  1409  
  1410  	return nil
  1411  }
  1412  
  1413  func validateDirectChannelImportData(data *DirectChannelImportData) *model.AppError {
  1414  	if data.Members == nil {
  1415  		return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_required.error", nil, "", http.StatusBadRequest)
  1416  	}
  1417  
  1418  	if len(*data.Members) != 2 {
  1419  		if len(*data.Members) < model.CHANNEL_GROUP_MIN_USERS {
  1420  			return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_too_few.error", nil, "", http.StatusBadRequest)
  1421  		} else if len(*data.Members) > model.CHANNEL_GROUP_MAX_USERS {
  1422  			return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_too_many.error", nil, "", http.StatusBadRequest)
  1423  		}
  1424  	}
  1425  
  1426  	if data.Header != nil && utf8.RuneCountInString(*data.Header) > model.CHANNEL_HEADER_MAX_RUNES {
  1427  		return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.header_length.error", nil, "", http.StatusBadRequest)
  1428  	}
  1429  
  1430  	if data.FavoritedBy != nil {
  1431  		for _, favoriter := range *data.FavoritedBy {
  1432  			found := false
  1433  			for _, member := range *data.Members {
  1434  				if favoriter == member {
  1435  					found = true
  1436  					break
  1437  				}
  1438  			}
  1439  			if !found {
  1440  				return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.unknown_favoriter.error", map[string]interface{}{"Username": favoriter}, "", http.StatusBadRequest)
  1441  			}
  1442  		}
  1443  	}
  1444  
  1445  	return nil
  1446  }
  1447  
  1448  func (a *App) ImportDirectPost(data *DirectPostImportData, dryRun bool) *model.AppError {
  1449  	if err := validateDirectPostImportData(data); err != nil {
  1450  		return err
  1451  	}
  1452  
  1453  	// If this is a Dry Run, do not continue any further.
  1454  	if dryRun {
  1455  		return nil
  1456  	}
  1457  
  1458  	var userIds []string
  1459  	for _, username := range *data.ChannelMembers {
  1460  		if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
  1461  			user := result.Data.(*model.User)
  1462  			userIds = append(userIds, user.Id)
  1463  		} else {
  1464  			return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, "", http.StatusBadRequest)
  1465  		}
  1466  	}
  1467  
  1468  	var channel *model.Channel
  1469  	if len(userIds) == 2 {
  1470  		ch, err := a.createDirectChannel(userIds[0], userIds[1])
  1471  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1472  			return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, "", http.StatusBadRequest)
  1473  		} else {
  1474  			channel = ch
  1475  		}
  1476  	} else {
  1477  		ch, err := a.createGroupChannel(userIds, userIds[0])
  1478  		if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
  1479  			return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, "", http.StatusBadRequest)
  1480  		} else {
  1481  			channel = ch
  1482  		}
  1483  	}
  1484  
  1485  	var user *model.User
  1486  	if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
  1487  		return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
  1488  	} else {
  1489  		user = result.Data.(*model.User)
  1490  	}
  1491  
  1492  	// Check if this post already exists.
  1493  	var posts []*model.Post
  1494  	if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
  1495  		return result.Err
  1496  	} else {
  1497  		posts = result.Data.([]*model.Post)
  1498  	}
  1499  
  1500  	var post *model.Post
  1501  	for _, p := range posts {
  1502  		if p.Message == *data.Message {
  1503  			post = p
  1504  			break
  1505  		}
  1506  	}
  1507  
  1508  	if post == nil {
  1509  		post = &model.Post{}
  1510  	}
  1511  
  1512  	post.ChannelId = channel.Id
  1513  	post.Message = *data.Message
  1514  	post.UserId = user.Id
  1515  	post.CreateAt = *data.CreateAt
  1516  
  1517  	post.Hashtags, _ = model.ParseHashtags(post.Message)
  1518  
  1519  	if post.Id == "" {
  1520  		if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
  1521  			return result.Err
  1522  		}
  1523  	} else {
  1524  		if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
  1525  			return result.Err
  1526  		}
  1527  	}
  1528  
  1529  	if data.FlaggedBy != nil {
  1530  		var preferences model.Preferences
  1531  
  1532  		for _, username := range *data.FlaggedBy {
  1533  			var user *model.User
  1534  
  1535  			if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
  1536  				return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
  1537  			} else {
  1538  				user = result.Data.(*model.User)
  1539  			}
  1540  
  1541  			preferences = append(preferences, model.Preference{
  1542  				UserId:   user.Id,
  1543  				Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
  1544  				Name:     post.Id,
  1545  				Value:    "true",
  1546  			})
  1547  		}
  1548  
  1549  		if len(preferences) > 0 {
  1550  			if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
  1551  				return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, "", http.StatusInternalServerError)
  1552  			}
  1553  		}
  1554  	}
  1555  
  1556  	if data.Reactions != nil {
  1557  		for _, reaction := range *data.Reactions {
  1558  			if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
  1559  				return err
  1560  			}
  1561  		}
  1562  	}
  1563  
  1564  	if data.Replies != nil {
  1565  		for _, reply := range *data.Replies {
  1566  			if err := a.ImportReply(&reply, post, dryRun); err != nil {
  1567  				return err
  1568  			}
  1569  		}
  1570  	}
  1571  
  1572  	return nil
  1573  }
  1574  
  1575  func validateDirectPostImportData(data *DirectPostImportData) *model.AppError {
  1576  	if data.ChannelMembers == nil {
  1577  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_required.error", nil, "", http.StatusBadRequest)
  1578  	}
  1579  
  1580  	if len(*data.ChannelMembers) != 2 {
  1581  		if len(*data.ChannelMembers) < model.CHANNEL_GROUP_MIN_USERS {
  1582  			return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_too_few.error", nil, "", http.StatusBadRequest)
  1583  		} else if len(*data.ChannelMembers) > model.CHANNEL_GROUP_MAX_USERS {
  1584  			return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_too_many.error", nil, "", http.StatusBadRequest)
  1585  		}
  1586  	}
  1587  
  1588  	if data.User == nil {
  1589  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.user_missing.error", nil, "", http.StatusBadRequest)
  1590  	}
  1591  
  1592  	if data.Message == nil {
  1593  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.message_missing.error", nil, "", http.StatusBadRequest)
  1594  	} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
  1595  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.message_length.error", nil, "", http.StatusBadRequest)
  1596  	}
  1597  
  1598  	if data.CreateAt == nil {
  1599  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
  1600  	} else if *data.CreateAt == 0 {
  1601  		return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
  1602  	}
  1603  
  1604  	if data.FlaggedBy != nil {
  1605  		for _, flagger := range *data.FlaggedBy {
  1606  			found := false
  1607  			for _, member := range *data.ChannelMembers {
  1608  				if flagger == member {
  1609  					found = true
  1610  					break
  1611  				}
  1612  			}
  1613  			if !found {
  1614  				return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.unknown_flagger.error", map[string]interface{}{"Username": flagger}, "", http.StatusBadRequest)
  1615  			}
  1616  		}
  1617  	}
  1618  
  1619  	if data.Reactions != nil {
  1620  		for _, reaction := range *data.Reactions {
  1621  			validateReactionImportData(&reaction, *data.CreateAt)
  1622  		}
  1623  	}
  1624  
  1625  	if data.Replies != nil {
  1626  		for _, reply := range *data.Replies {
  1627  			validateReplyImportData(&reply, *data.CreateAt)
  1628  		}
  1629  	}
  1630  
  1631  	return nil
  1632  }
  1633  
  1634  //
  1635  // -- Old SlackImport Functions --
  1636  // Import functions are sutible for entering posts and users into the database without
  1637  // some of the usual checks. (IsValid is still run)
  1638  //
  1639  
  1640  func (a *App) OldImportPost(post *model.Post) {
  1641  	// Workaround for empty messages, which may be the case if they are webhook posts.
  1642  	firstIteration := true
  1643  	for messageRuneCount := utf8.RuneCountInString(post.Message); messageRuneCount > 0 || firstIteration; messageRuneCount = utf8.RuneCountInString(post.Message) {
  1644  		firstIteration = false
  1645  		var remainder string
  1646  		if messageRuneCount > model.POST_MESSAGE_MAX_RUNES {
  1647  			remainder = string(([]rune(post.Message))[model.POST_MESSAGE_MAX_RUNES:])
  1648  			post.Message = truncateRunes(post.Message, model.POST_MESSAGE_MAX_RUNES)
  1649  		} else {
  1650  			remainder = ""
  1651  		}
  1652  
  1653  		post.Hashtags, _ = model.ParseHashtags(post.Message)
  1654  
  1655  		if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
  1656  			l4g.Debug(utils.T("api.import.import_post.saving.debug"), post.UserId, post.Message)
  1657  		}
  1658  
  1659  		for _, fileId := range post.FileIds {
  1660  			if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
  1661  				l4g.Error(utils.T("api.import.import_post.attach_files.error"), post.Id, post.FileIds, result.Err)
  1662  			}
  1663  		}
  1664  
  1665  		post.Id = ""
  1666  		post.CreateAt++
  1667  		post.Message = remainder
  1668  	}
  1669  }
  1670  
  1671  func (a *App) OldImportUser(team *model.Team, user *model.User) *model.User {
  1672  	user.MakeNonNil()
  1673  
  1674  	user.Roles = model.SYSTEM_USER_ROLE_ID
  1675  
  1676  	if result := <-a.Srv.Store.User().Save(user); result.Err != nil {
  1677  		l4g.Error(utils.T("api.import.import_user.saving.error"), result.Err)
  1678  		return nil
  1679  	} else {
  1680  		ruser := result.Data.(*model.User)
  1681  
  1682  		if cresult := <-a.Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
  1683  			l4g.Error(utils.T("api.import.import_user.set_email.error"), cresult.Err)
  1684  		}
  1685  
  1686  		if err := a.JoinUserToTeam(team, user, ""); err != nil {
  1687  			l4g.Error(utils.T("api.import.import_user.join_team.error"), err)
  1688  		}
  1689  
  1690  		return ruser
  1691  	}
  1692  }
  1693  
  1694  func (a *App) OldImportChannel(channel *model.Channel) *model.Channel {
  1695  	if result := <-a.Srv.Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam); result.Err != nil {
  1696  		return nil
  1697  	} else {
  1698  		sc := result.Data.(*model.Channel)
  1699  
  1700  		return sc
  1701  	}
  1702  }
  1703  
  1704  func (a *App) OldImportFile(timestamp time.Time, file io.Reader, teamId string, channelId string, userId string, fileName string) (*model.FileInfo, error) {
  1705  	buf := bytes.NewBuffer(nil)
  1706  	io.Copy(buf, file)
  1707  	data := buf.Bytes()
  1708  
  1709  	fileInfo, err := a.DoUploadFile(timestamp, teamId, channelId, userId, fileName, data)
  1710  	if err != nil {
  1711  		return nil, err
  1712  	}
  1713  
  1714  	img, width, height := prepareImage(data)
  1715  	if img != nil {
  1716  		a.generateThumbnailImage(*img, fileInfo.ThumbnailPath, width, height)
  1717  		a.generatePreviewImage(*img, fileInfo.PreviewPath, width)
  1718  	}
  1719  
  1720  	return fileInfo, nil
  1721  }
  1722  
  1723  func (a *App) OldImportIncomingWebhookPost(post *model.Post, props model.StringInterface) {
  1724  	linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
  1725  	post.Message = linkWithTextRegex.ReplaceAllString(post.Message, "[${2}](${1})")
  1726  
  1727  	post.AddProp("from_webhook", "true")
  1728  
  1729  	if _, ok := props["override_username"]; !ok {
  1730  		post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
  1731  	}
  1732  
  1733  	if len(props) > 0 {
  1734  		for key, val := range props {
  1735  			if key == "attachments" {
  1736  				if attachments, success := val.([]*model.SlackAttachment); success {
  1737  					parseSlackAttachment(post, attachments)
  1738  				}
  1739  			} else if key != "from_webhook" {
  1740  				post.AddProp(key, val)
  1741  			}
  1742  		}
  1743  	}
  1744  
  1745  	a.OldImportPost(post)
  1746  }