Files
mattermost/app/import.go

1531 lines
49 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
"bufio"
"bytes"
"encoding/json"
"io"
"net/http"
"regexp"
"strings"
"sync"
"time"
"unicode/utf8"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
"github.com/mattermost/mattermost-server/utils"
)
// Import Data Models
type LineImportData struct {
Type string `json:"type"`
Team *TeamImportData `json:"team"`
Channel *ChannelImportData `json:"channel"`
User *UserImportData `json:"user"`
Post *PostImportData `json:"post"`
DirectChannel *DirectChannelImportData `json:"direct_channel"`
DirectPost *DirectPostImportData `json:"direct_post"`
Version *int `json:"version"`
}
type TeamImportData struct {
Name *string `json:"name"`
DisplayName *string `json:"display_name"`
Type *string `json:"type"`
Description *string `json:"description"`
AllowOpenInvite *bool `json:"allow_open_invite"`
}
type ChannelImportData struct {
Team *string `json:"team"`
Name *string `json:"name"`
DisplayName *string `json:"display_name"`
Type *string `json:"type"`
Header *string `json:"header"`
Purpose *string `json:"purpose"`
}
type UserImportData struct {
Username *string `json:"username"`
Email *string `json:"email"`
AuthService *string `json:"auth_service"`
AuthData *string `json:"auth_data"`
Password *string `json:"password"`
Nickname *string `json:"nickname"`
FirstName *string `json:"first_name"`
LastName *string `json:"last_name"`
Position *string `json:"position"`
Roles *string `json:"roles"`
Locale *string `json:"locale"`
Teams *[]UserTeamImportData `json:"teams"`
Theme *string `json:"theme"`
UseMilitaryTime *string `json:"military_time"`
CollapsePreviews *string `json:"link_previews"`
MessageDisplay *string `json:"message_display"`
ChannelDisplayMode *string `json:"channel_display_mode"`
TutorialStep *string `json:"tutorial_step"`
NotifyProps *UserNotifyPropsImportData `json:"notify_props"`
}
type UserNotifyPropsImportData struct {
Desktop *string `json:"desktop"`
DesktopDuration *string `json:"desktop_duration"`
DesktopSound *string `json:"desktop_sound"`
Email *string `json:"email"`
Mobile *string `json:"mobile"`
MobilePushStatus *string `json:"mobile_push_status"`
ChannelTrigger *string `json:"channel"`
CommentsTrigger *string `json:"comments"`
MentionKeys *string `json:"mention_keys"`
}
type UserTeamImportData struct {
Name *string `json:"name"`
Roles *string `json:"roles"`
Channels *[]UserChannelImportData `json:"channels"`
}
type UserChannelImportData struct {
Name *string `json:"name"`
Roles *string `json:"roles"`
NotifyProps *UserChannelNotifyPropsImportData `json:"notify_props"`
Favorite *bool `json:"favorite"`
}
type UserChannelNotifyPropsImportData struct {
Desktop *string `json:"desktop"`
Mobile *string `json:"mobile"`
MarkUnread *string `json:"mark_unread"`
}
type PostImportData struct {
Team *string `json:"team"`
Channel *string `json:"channel"`
User *string `json:"user"`
Message *string `json:"message"`
CreateAt *int64 `json:"create_at"`
FlaggedBy *[]string `json:"flagged_by"`
}
type DirectChannelImportData struct {
Members *[]string `json:"members"`
FavoritedBy *[]string `json:"favorited_by"`
Header *string `json:"header"`
}
type DirectPostImportData struct {
ChannelMembers *[]string `json:"channel_members"`
User *string `json:"user"`
Message *string `json:"message"`
CreateAt *int64 `json:"create_at"`
FlaggedBy *[]string `json:"flagged_by"`
}
type LineImportWorkerData struct {
LineImportData
LineNumber int
}
type LineImportWorkerError struct {
Error *model.AppError
LineNumber int
}
//
// -- Bulk Import Functions --
// These functions import data directly into the database. Security and permission checks are bypassed but validity is
// still enforced.
//
func (a *App) bulkImportWorker(dryRun bool, wg *sync.WaitGroup, lines <-chan LineImportWorkerData, errors chan<- LineImportWorkerError) {
for line := range lines {
if err := a.ImportLine(line.LineImportData, dryRun); err != nil {
errors <- LineImportWorkerError{err, line.LineNumber}
}
}
wg.Done()
}
func (a *App) BulkImport(fileReader io.Reader, dryRun bool, workers int) (*model.AppError, int) {
scanner := bufio.NewScanner(fileReader)
lineNumber := 0
errorsChan := make(chan LineImportWorkerError, (2*workers)+1) // size chosen to ensure it never gets filled up completely.
var wg sync.WaitGroup
var linesChan chan LineImportWorkerData
lastLineType := ""
for scanner.Scan() {
decoder := json.NewDecoder(strings.NewReader(scanner.Text()))
lineNumber++
var line LineImportData
if err := decoder.Decode(&line); err != nil {
return model.NewAppError("BulkImport", "app.import.bulk_import.json_decode.error", nil, err.Error(), http.StatusBadRequest), lineNumber
} else {
if lineNumber == 1 {
importDataFileVersion, apperr := processImportDataFileVersionLine(line)
if apperr != nil {
return apperr, lineNumber
}
if importDataFileVersion != 1 {
return model.NewAppError("BulkImport", "app.import.bulk_import.unsupported_version.error", nil, "", http.StatusBadRequest), lineNumber
}
} else {
if line.Type != lastLineType {
if lastLineType != "" {
// Changing type. Clear out the worker queue before continuing.
close(linesChan)
wg.Wait()
// Check no errors occurred while waiting for the queue to empty.
if len(errorsChan) != 0 {
err := <-errorsChan
return err.Error, err.LineNumber
}
}
// Set up the workers and channel for this type.
lastLineType = line.Type
linesChan = make(chan LineImportWorkerData, workers)
for i := 0; i < workers; i++ {
wg.Add(1)
go a.bulkImportWorker(dryRun, &wg, linesChan, errorsChan)
}
}
select {
case linesChan <- LineImportWorkerData{line, lineNumber}:
case err := <-errorsChan:
close(linesChan)
wg.Wait()
return err.Error, err.LineNumber
}
}
}
}
// No more lines. Clear out the worker queue before continuing.
close(linesChan)
wg.Wait()
// Check no errors occurred while waiting for the queue to empty.
if len(errorsChan) != 0 {
err := <-errorsChan
return err.Error, err.LineNumber
}
if err := scanner.Err(); err != nil {
return model.NewAppError("BulkImport", "app.import.bulk_import.file_scan.error", nil, err.Error(), http.StatusInternalServerError), 0
}
return nil, 0
}
func processImportDataFileVersionLine(line LineImportData) (int, *model.AppError) {
if line.Type != "version" || line.Version == nil {
return -1, model.NewAppError("BulkImport", "app.import.process_import_data_file_version_line.invalid_version.error", nil, "", http.StatusBadRequest)
}
return *line.Version, nil
}
func (a *App) ImportLine(line LineImportData, dryRun bool) *model.AppError {
switch {
case line.Type == "team":
if line.Team == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_team.error", nil, "", http.StatusBadRequest)
} else {
return a.ImportTeam(line.Team, dryRun)
}
case line.Type == "channel":
if line.Channel == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_channel.error", nil, "", http.StatusBadRequest)
} else {
return a.ImportChannel(line.Channel, dryRun)
}
case line.Type == "user":
if line.User == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_user.error", nil, "", http.StatusBadRequest)
} else {
return a.ImportUser(line.User, dryRun)
}
case line.Type == "post":
if line.Post == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_post.error", nil, "", http.StatusBadRequest)
} else {
return a.ImportPost(line.Post, dryRun)
}
case line.Type == "direct_channel":
if line.DirectChannel == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_direct_channel.error", nil, "", http.StatusBadRequest)
} else {
return a.ImportDirectChannel(line.DirectChannel, dryRun)
}
case line.Type == "direct_post":
if line.DirectPost == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_direct_post.error", nil, "", http.StatusBadRequest)
} else {
return a.ImportDirectPost(line.DirectPost, dryRun)
}
default:
return model.NewAppError("BulkImport", "app.import.import_line.unknown_line_type.error", map[string]interface{}{"Type": line.Type}, "", http.StatusBadRequest)
}
}
func (a *App) ImportTeam(data *TeamImportData, dryRun bool) *model.AppError {
if err := validateTeamImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
if dryRun {
return nil
}
var team *model.Team
if result := <-a.Srv.Store.Team().GetByName(*data.Name); result.Err == nil {
team = result.Data.(*model.Team)
} else {
team = &model.Team{}
}
team.Name = *data.Name
team.DisplayName = *data.DisplayName
team.Type = *data.Type
if data.Description != nil {
team.Description = *data.Description
}
if data.AllowOpenInvite != nil {
team.AllowOpenInvite = *data.AllowOpenInvite
}
if team.Id == "" {
if _, err := a.CreateTeam(team); err != nil {
return err
}
} else {
if _, err := a.UpdateTeam(team); err != nil {
return err
}
}
return nil
}
func validateTeamImportData(data *TeamImportData) *model.AppError {
if data.Name == nil {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_missing.error", nil, "", http.StatusBadRequest)
} else if len(*data.Name) > model.TEAM_NAME_MAX_LENGTH {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_length.error", nil, "", http.StatusBadRequest)
} else if model.IsReservedTeamName(*data.Name) {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_reserved.error", nil, "", http.StatusBadRequest)
} else if !model.IsValidTeamName(*data.Name) {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.name_characters.error", nil, "", http.StatusBadRequest)
}
if data.DisplayName == nil {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.display_name_missing.error", nil, "", http.StatusBadRequest)
} else if utf8.RuneCountInString(*data.DisplayName) == 0 || utf8.RuneCountInString(*data.DisplayName) > model.TEAM_DISPLAY_NAME_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.display_name_length.error", nil, "", http.StatusBadRequest)
}
if data.Type == nil {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.type_missing.error", nil, "", http.StatusBadRequest)
} else if *data.Type != model.TEAM_OPEN && *data.Type != model.TEAM_INVITE {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.type_invalid.error", nil, "", http.StatusBadRequest)
}
if data.Description != nil && len(*data.Description) > model.TEAM_DESCRIPTION_MAX_LENGTH {
return model.NewAppError("BulkImport", "app.import.validate_team_import_data.description_length.error", nil, "", http.StatusBadRequest)
}
return nil
}
func (a *App) ImportChannel(data *ChannelImportData, dryRun bool) *model.AppError {
if err := validateChannelImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
if dryRun {
return nil
}
var team *model.Team
if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_channel.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, "", http.StatusBadRequest)
} else {
team = result.Data.(*model.Team)
}
var channel *model.Channel
if result := <-a.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, *data.Name, true); result.Err == nil {
channel = result.Data.(*model.Channel)
} else {
channel = &model.Channel{}
}
channel.TeamId = team.Id
channel.Name = *data.Name
channel.DisplayName = *data.DisplayName
channel.Type = *data.Type
if data.Header != nil {
channel.Header = *data.Header
}
if data.Purpose != nil {
channel.Purpose = *data.Purpose
}
if channel.Id == "" {
if _, err := a.CreateChannel(channel, false); err != nil {
return err
}
} else {
if _, err := a.UpdateChannel(channel); err != nil {
return err
}
}
return nil
}
func validateChannelImportData(data *ChannelImportData) *model.AppError {
if data.Team == nil {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.team_missing.error", nil, "", http.StatusBadRequest)
}
if data.Name == nil {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.name_missing.error", nil, "", http.StatusBadRequest)
} else if len(*data.Name) > model.CHANNEL_NAME_MAX_LENGTH {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.name_length.error", nil, "", http.StatusBadRequest)
} else if !model.IsValidChannelIdentifier(*data.Name) {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.name_characters.error", nil, "", http.StatusBadRequest)
}
if data.DisplayName == nil {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.display_name_missing.error", nil, "", http.StatusBadRequest)
} else if utf8.RuneCountInString(*data.DisplayName) == 0 || utf8.RuneCountInString(*data.DisplayName) > model.CHANNEL_DISPLAY_NAME_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.display_name_length.error", nil, "", http.StatusBadRequest)
}
if data.Type == nil {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.type_missing.error", nil, "", http.StatusBadRequest)
} else if *data.Type != model.CHANNEL_OPEN && *data.Type != model.CHANNEL_PRIVATE {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.type_invalid.error", nil, "", http.StatusBadRequest)
}
if data.Header != nil && utf8.RuneCountInString(*data.Header) > model.CHANNEL_HEADER_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.header_length.error", nil, "", http.StatusBadRequest)
}
if data.Purpose != nil && utf8.RuneCountInString(*data.Purpose) > model.CHANNEL_PURPOSE_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.purpose_length.error", nil, "", http.StatusBadRequest)
}
return nil
}
func (a *App) ImportUser(data *UserImportData, dryRun bool) *model.AppError {
if err := validateUserImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
if dryRun {
return nil
}
// We want to avoid database writes if nothing has changed.
hasUserChanged := false
hasNotifyPropsChanged := false
hasUserRolesChanged := false
hasUserAuthDataChanged := false
hasUserEmailVerifiedChanged := false
var user *model.User
if result := <-a.Srv.Store.User().GetByUsername(*data.Username); result.Err == nil {
user = result.Data.(*model.User)
} else {
user = &model.User{}
user.MakeNonNil()
hasUserChanged = true
}
user.Username = *data.Username
if user.Email != *data.Email {
hasUserChanged = true
hasUserEmailVerifiedChanged = true // Changing the email resets email verified to false by default.
user.Email = *data.Email
}
var password string
var authService string
var authData *string
if data.AuthService != nil {
if user.AuthService != *data.AuthService {
hasUserAuthDataChanged = true
}
authService = *data.AuthService
}
// AuthData and Password are mutually exclusive.
if data.AuthData != nil {
if user.AuthData == nil || *user.AuthData != *data.AuthData {
hasUserAuthDataChanged = true
}
authData = data.AuthData
password = ""
} else if data.Password != nil {
password = *data.Password
authData = nil
} else {
// If no AuthData or Password is specified, we must generate a password.
password = model.NewId()
authData = nil
}
user.Password = password
user.AuthService = authService
user.AuthData = authData
// Automatically assume all emails are verified.
emailVerified := true
if user.EmailVerified != emailVerified {
user.EmailVerified = emailVerified
hasUserEmailVerifiedChanged = true
}
if data.Nickname != nil {
if user.Nickname != *data.Nickname {
user.Nickname = *data.Nickname
hasUserChanged = true
}
}
if data.FirstName != nil {
if user.FirstName != *data.FirstName {
user.FirstName = *data.FirstName
hasUserChanged = true
}
}
if data.LastName != nil {
if user.LastName != *data.LastName {
user.LastName = *data.LastName
hasUserChanged = true
}
}
if data.Position != nil {
if user.Position != *data.Position {
user.Position = *data.Position
hasUserChanged = true
}
}
if data.Locale != nil {
if user.Locale != *data.Locale {
user.Locale = *data.Locale
hasUserChanged = true
}
} else {
if user.Locale != *utils.Cfg.LocalizationSettings.DefaultClientLocale {
user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
hasUserChanged = true
}
}
var roles string
if data.Roles != nil {
if user.Roles != *data.Roles {
roles = *data.Roles
hasUserRolesChanged = true
}
} else if len(user.Roles) == 0 {
// Set SYSTEM_USER roles on newly created users by default.
if user.Roles != model.ROLE_SYSTEM_USER.Id {
roles = model.ROLE_SYSTEM_USER.Id
hasUserRolesChanged = true
}
}
user.Roles = roles
if data.NotifyProps != nil {
if data.NotifyProps.Desktop != nil {
if value, ok := user.NotifyProps[model.DESKTOP_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Desktop {
user.AddNotifyProp(model.DESKTOP_NOTIFY_PROP, *data.NotifyProps.Desktop)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.DesktopDuration != nil {
if value, ok := user.NotifyProps[model.DESKTOP_DURATION_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopDuration {
user.AddNotifyProp(model.DESKTOP_DURATION_NOTIFY_PROP, *data.NotifyProps.DesktopDuration)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.DesktopSound != nil {
if value, ok := user.NotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopSound {
user.AddNotifyProp(model.DESKTOP_SOUND_NOTIFY_PROP, *data.NotifyProps.DesktopSound)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.Email != nil {
if value, ok := user.NotifyProps[model.EMAIL_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Email {
user.AddNotifyProp(model.EMAIL_NOTIFY_PROP, *data.NotifyProps.Email)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.Mobile != nil {
if value, ok := user.NotifyProps[model.PUSH_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Mobile {
user.AddNotifyProp(model.PUSH_NOTIFY_PROP, *data.NotifyProps.Mobile)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.MobilePushStatus != nil {
if value, ok := user.NotifyProps[model.PUSH_STATUS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MobilePushStatus {
user.AddNotifyProp(model.PUSH_STATUS_NOTIFY_PROP, *data.NotifyProps.MobilePushStatus)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.ChannelTrigger != nil {
if value, ok := user.NotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.ChannelTrigger {
user.AddNotifyProp(model.CHANNEL_MENTIONS_NOTIFY_PROP, *data.NotifyProps.ChannelTrigger)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.CommentsTrigger != nil {
if value, ok := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.CommentsTrigger {
user.AddNotifyProp(model.COMMENTS_NOTIFY_PROP, *data.NotifyProps.CommentsTrigger)
hasNotifyPropsChanged = true
}
}
if data.NotifyProps.MentionKeys != nil {
if value, ok := user.NotifyProps[model.MENTION_KEYS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MentionKeys {
user.AddNotifyProp(model.MENTION_KEYS_NOTIFY_PROP, *data.NotifyProps.MentionKeys)
hasNotifyPropsChanged = true
}
}
}
var err *model.AppError
var savedUser *model.User
if user.Id == "" {
if savedUser, err = a.createUser(user); err != nil {
return err
}
} else {
if hasUserChanged {
if savedUser, err = a.UpdateUser(user, false); err != nil {
return err
}
}
if hasUserRolesChanged {
if savedUser, err = a.UpdateUserRoles(user.Id, roles); err != nil {
return err
}
}
if hasNotifyPropsChanged {
if savedUser, err = a.UpdateUserNotifyProps(user.Id, user.NotifyProps); err != nil {
return err
}
}
if len(password) > 0 {
if err = a.UpdatePassword(user, password); err != nil {
return err
}
} else {
if hasUserAuthDataChanged {
if res := <-a.Srv.Store.User().UpdateAuthData(user.Id, authService, authData, user.Email, false); res.Err != nil {
return res.Err
}
}
}
if emailVerified {
if hasUserEmailVerifiedChanged {
if err := a.VerifyUserEmail(user.Id); err != nil {
return err
}
}
}
}
if savedUser == nil {
savedUser = user
}
// Preferences.
var preferences model.Preferences
if data.Theme != nil {
preferences = append(preferences, model.Preference{
UserId: savedUser.Id,
Category: model.PREFERENCE_CATEGORY_THEME,
Name: "",
Value: *data.Theme,
})
}
if data.UseMilitaryTime != nil {
preferences = append(preferences, model.Preference{
UserId: savedUser.Id,
Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
Name: "use_military_time",
Value: *data.UseMilitaryTime,
})
}
if data.CollapsePreviews != nil {
preferences = append(preferences, model.Preference{
UserId: savedUser.Id,
Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
Name: "collapse_previews",
Value: *data.CollapsePreviews,
})
}
if data.MessageDisplay != nil {
preferences = append(preferences, model.Preference{
UserId: savedUser.Id,
Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
Name: "message_display",
Value: *data.MessageDisplay,
})
}
if data.ChannelDisplayMode != nil {
preferences = append(preferences, model.Preference{
UserId: savedUser.Id,
Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
Name: "channel_display_mode",
Value: *data.ChannelDisplayMode,
})
}
if data.TutorialStep != nil {
preferences = append(preferences, model.Preference{
UserId: savedUser.Id,
Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS,
Name: savedUser.Id,
Value: *data.TutorialStep,
})
}
if len(preferences) > 0 {
if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_user.save_preferences.error", nil, "", http.StatusInternalServerError)
}
}
return a.ImportUserTeams(savedUser, data.Teams)
}
func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *model.AppError {
if data == nil {
return nil
}
for _, tdata := range *data {
team, err := a.GetTeamByName(*tdata.Name)
if err != nil {
return err
}
var roles string
if tdata.Roles == nil {
roles = model.ROLE_TEAM_USER.Id
} else {
roles = *tdata.Roles
}
var member *model.TeamMember
if member, _, err = a.joinUserToTeam(team, user); err != nil {
return err
}
if member.Roles != roles {
if _, err := a.UpdateTeamMemberRoles(team.Id, user.Id, roles); err != nil {
return err
}
}
if err := a.ImportUserChannels(user, team, member, tdata.Channels); err != nil {
return err
}
}
return nil
}
func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember *model.TeamMember, data *[]UserChannelImportData) *model.AppError {
if data == nil {
return nil
}
var preferences model.Preferences
// Loop through all channels.
for _, cdata := range *data {
channel, err := a.GetChannelByName(*cdata.Name, team.Id)
if err != nil {
return err
}
var roles string
if cdata.Roles == nil {
roles = model.ROLE_CHANNEL_USER.Id
} else {
roles = *cdata.Roles
}
var member *model.ChannelMember
member, err = a.GetChannelMember(channel.Id, user.Id)
if err != nil {
member, err = a.addUserToChannel(user, channel, teamMember)
if err != nil {
return err
}
}
if member.Roles != roles {
if _, err := a.UpdateChannelMemberRoles(channel.Id, user.Id, roles); err != nil {
return err
}
}
if cdata.NotifyProps != nil {
notifyProps := member.NotifyProps
if cdata.NotifyProps.Desktop != nil {
notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
}
if cdata.NotifyProps.Mobile != nil {
notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile
}
if cdata.NotifyProps.MarkUnread != nil {
notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
}
if _, err := a.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id); err != nil {
return err
}
}
if cdata.Favorite != nil && *cdata.Favorite == true {
preferences = append(preferences, model.Preference{
UserId: user.Id,
Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
Name: channel.Id,
Value: "true",
})
}
}
if len(preferences) > 0 {
if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_user_channels.save_preferences.error", nil, "", http.StatusInternalServerError)
}
}
return nil
}
func validateUserImportData(data *UserImportData) *model.AppError {
if data.Username == nil {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_missing.error", nil, "", http.StatusBadRequest)
} else if !model.IsValidUsername(*data.Username) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.username_invalid.error", nil, "", http.StatusBadRequest)
}
if data.Email == nil {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_missing.error", nil, "", http.StatusBadRequest)
} else if len(*data.Email) == 0 || len(*data.Email) > model.USER_EMAIL_MAX_LENGTH {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.email_length.error", nil, "", http.StatusBadRequest)
}
if data.AuthService != nil && len(*data.AuthService) == 0 {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_service_length.error", nil, "", http.StatusBadRequest)
}
if data.AuthData != nil && data.Password != nil {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_and_password.error", nil, "", http.StatusBadRequest)
}
if data.AuthData != nil && len(*data.AuthData) > model.USER_AUTH_DATA_MAX_LENGTH {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.auth_data_length.error", nil, "", http.StatusBadRequest)
}
if data.Password != nil && len(*data.Password) == 0 {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.pasword_length.error", nil, "", http.StatusBadRequest)
}
if data.Password != nil && len(*data.Password) > model.USER_PASSWORD_MAX_LENGTH {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.password_length.error", nil, "", http.StatusBadRequest)
}
if data.Nickname != nil && utf8.RuneCountInString(*data.Nickname) > model.USER_NICKNAME_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.nickname_length.error", nil, "", http.StatusBadRequest)
}
if data.FirstName != nil && utf8.RuneCountInString(*data.FirstName) > model.USER_FIRST_NAME_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.first_name_length.error", nil, "", http.StatusBadRequest)
}
if data.LastName != nil && utf8.RuneCountInString(*data.LastName) > model.USER_LAST_NAME_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.last_name_length.error", nil, "", http.StatusBadRequest)
}
if data.Position != nil && utf8.RuneCountInString(*data.Position) > model.USER_POSITION_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.position_length.error", nil, "", http.StatusBadRequest)
}
if data.Roles != nil && !model.IsValidUserRoles(*data.Roles) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps != nil {
if data.NotifyProps.Desktop != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Desktop) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.DesktopDuration != nil && !model.IsValidNumberString(*data.NotifyProps.DesktopDuration) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.DesktopSound != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.DesktopSound) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_sound_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.Email != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.Email) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_email_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.Mobile != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Mobile) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.MobilePushStatus != nil && !model.IsValidPushStatusNotifyLevel(*data.NotifyProps.MobilePushStatus) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_push_status_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.ChannelTrigger != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.ChannelTrigger) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_channel_trigger_invalid.error", nil, "", http.StatusBadRequest)
}
if data.NotifyProps.CommentsTrigger != nil && !model.IsValidCommentsNotifyLevel(*data.NotifyProps.CommentsTrigger) {
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_comments_trigger_invalid.error", nil, "", http.StatusBadRequest)
}
}
if data.Teams != nil {
return validateUserTeamsImportData(data.Teams)
} else {
return nil
}
}
func validateUserTeamsImportData(data *[]UserTeamImportData) *model.AppError {
if data == nil {
return nil
}
for _, tdata := range *data {
if tdata.Name == nil {
return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.team_name_missing.error", nil, "", http.StatusBadRequest)
}
if tdata.Roles != nil && !model.IsValidUserRoles(*tdata.Roles) {
return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.invalid_roles.error", nil, "", http.StatusBadRequest)
}
if tdata.Channels != nil {
if err := validateUserChannelsImportData(tdata.Channels); err != nil {
return err
}
}
}
return nil
}
func validateUserChannelsImportData(data *[]UserChannelImportData) *model.AppError {
if data == nil {
return nil
}
for _, cdata := range *data {
if cdata.Name == nil {
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.channel_name_missing.error", nil, "", http.StatusBadRequest)
}
if cdata.Roles != nil && !model.IsValidUserRoles(*cdata.Roles) {
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_roles.error", nil, "", http.StatusBadRequest)
}
if cdata.NotifyProps != nil {
if cdata.NotifyProps.Desktop != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Desktop) {
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error", nil, "", http.StatusBadRequest)
}
if cdata.NotifyProps.Mobile != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Mobile) {
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mobile.error", nil, "", http.StatusBadRequest)
}
if cdata.NotifyProps.MarkUnread != nil && !model.IsChannelMarkUnreadLevelValid(*cdata.NotifyProps.MarkUnread) {
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error", nil, "", http.StatusBadRequest)
}
}
}
return nil
}
func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError {
if err := validatePostImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
if dryRun {
return nil
}
var team *model.Team
if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, "", http.StatusBadRequest)
} else {
team = result.Data.(*model.Team)
}
var channel *model.Channel
if result := <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, "", http.StatusBadRequest)
} else {
channel = result.Data.(*model.Channel)
}
var user *model.User
if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
} else {
user = result.Data.(*model.User)
}
// Check if this post already exists.
var posts []*model.Post
if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
return result.Err
} else {
posts = result.Data.([]*model.Post)
}
var post *model.Post
for _, p := range posts {
if p.Message == *data.Message {
post = p
break
}
}
if post == nil {
post = &model.Post{}
}
post.ChannelId = channel.Id
post.Message = *data.Message
post.UserId = user.Id
post.CreateAt = *data.CreateAt
post.Hashtags, _ = model.ParseHashtags(post.Message)
if post.Id == "" {
if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
return result.Err
}
} else {
if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
return result.Err
}
}
if data.FlaggedBy != nil {
var preferences model.Preferences
for _, username := range *data.FlaggedBy {
var user *model.User
if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
} else {
user = result.Data.(*model.User)
}
preferences = append(preferences, model.Preference{
UserId: user.Id,
Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
Name: post.Id,
Value: "true",
})
}
if len(preferences) > 0 {
if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, "", http.StatusInternalServerError)
}
}
}
return nil
}
func validatePostImportData(data *PostImportData) *model.AppError {
if data.Team == nil {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.team_missing.error", nil, "", http.StatusBadRequest)
}
if data.Channel == nil {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.channel_missing.error", nil, "", http.StatusBadRequest)
}
if data.User == nil {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.user_missing.error", nil, "", http.StatusBadRequest)
}
if data.Message == nil {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.message_missing.error", nil, "", http.StatusBadRequest)
} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.message_length.error", nil, "", http.StatusBadRequest)
}
if data.CreateAt == nil {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
} else if *data.CreateAt == 0 {
return model.NewAppError("BulkImport", "app.import.validate_post_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
}
return nil
}
func (a *App) ImportDirectChannel(data *DirectChannelImportData, dryRun bool) *model.AppError {
if err := validateDirectChannelImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
if dryRun {
return nil
}
var userIds []string
userMap := make(map[string]string)
for _, username := range *data.Members {
if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
user := result.Data.(*model.User)
userIds = append(userIds, user.Id)
userMap[username] = user.Id
} else {
return model.NewAppError("BulkImport", "app.import.import_direct_channel.member_not_found.error", nil, "", http.StatusBadRequest)
}
}
var channel *model.Channel
if len(userIds) == 2 {
ch, err := a.createDirectChannel(userIds[0], userIds[1])
if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_direct_channel.error", nil, "", http.StatusBadRequest)
} else {
channel = ch
}
} else {
ch, err := a.createGroupChannel(userIds, userIds[0])
if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_group_channel.error", nil, "", http.StatusBadRequest)
} else {
channel = ch
}
}
var preferences model.Preferences
for _, userId := range userIds {
preferences = append(preferences, model.Preference{
UserId: userId,
Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
Name: channel.Id,
Value: "true",
})
}
if data.FavoritedBy != nil {
for _, favoriter := range *data.FavoritedBy {
preferences = append(preferences, model.Preference{
UserId: userMap[favoriter],
Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
Name: channel.Id,
Value: "true",
})
}
}
if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
result.Err.StatusCode = http.StatusBadRequest
return result.Err
}
if data.Header != nil {
channel.Header = *data.Header
if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_direct_channel.update_header_failed.error", nil, "", http.StatusBadRequest)
}
}
return nil
}
func validateDirectChannelImportData(data *DirectChannelImportData) *model.AppError {
if data.Members == nil {
return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_required.error", nil, "", http.StatusBadRequest)
}
if len(*data.Members) != 2 {
if len(*data.Members) < model.CHANNEL_GROUP_MIN_USERS {
return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_too_few.error", nil, "", http.StatusBadRequest)
} else if len(*data.Members) > model.CHANNEL_GROUP_MAX_USERS {
return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.members_too_many.error", nil, "", http.StatusBadRequest)
}
}
if data.Header != nil && utf8.RuneCountInString(*data.Header) > model.CHANNEL_HEADER_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.header_length.error", nil, "", http.StatusBadRequest)
}
if data.FavoritedBy != nil {
for _, favoriter := range *data.FavoritedBy {
found := false
for _, member := range *data.Members {
if favoriter == member {
found = true
break
}
}
if !found {
return model.NewAppError("BulkImport", "app.import.validate_direct_channel_import_data.unknown_favoriter.error", map[string]interface{}{"Username": favoriter}, "", http.StatusBadRequest)
}
}
}
return nil
}
func (a *App) ImportDirectPost(data *DirectPostImportData, dryRun bool) *model.AppError {
if err := validateDirectPostImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
if dryRun {
return nil
}
var userIds []string
for _, username := range *data.ChannelMembers {
if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
user := result.Data.(*model.User)
userIds = append(userIds, user.Id)
} else {
return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, "", http.StatusBadRequest)
}
}
var channel *model.Channel
if len(userIds) == 2 {
ch, err := a.createDirectChannel(userIds[0], userIds[1])
if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, "", http.StatusBadRequest)
} else {
channel = ch
}
} else {
ch, err := a.createGroupChannel(userIds, userIds[0])
if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, "", http.StatusBadRequest)
} else {
channel = ch
}
}
var user *model.User
if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
} else {
user = result.Data.(*model.User)
}
// Check if this post already exists.
var posts []*model.Post
if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
return result.Err
} else {
posts = result.Data.([]*model.Post)
}
var post *model.Post
for _, p := range posts {
if p.Message == *data.Message {
post = p
break
}
}
if post == nil {
post = &model.Post{}
}
post.ChannelId = channel.Id
post.Message = *data.Message
post.UserId = user.Id
post.CreateAt = *data.CreateAt
post.Hashtags, _ = model.ParseHashtags(post.Message)
if post.Id == "" {
if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
return result.Err
}
} else {
if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
return result.Err
}
}
if data.FlaggedBy != nil {
var preferences model.Preferences
for _, username := range *data.FlaggedBy {
var user *model.User
if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
} else {
user = result.Data.(*model.User)
}
preferences = append(preferences, model.Preference{
UserId: user.Id,
Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
Name: post.Id,
Value: "true",
})
}
if len(preferences) > 0 {
if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, "", http.StatusInternalServerError)
}
}
}
return nil
}
func validateDirectPostImportData(data *DirectPostImportData) *model.AppError {
if data.ChannelMembers == nil {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_required.error", nil, "", http.StatusBadRequest)
}
if len(*data.ChannelMembers) != 2 {
if len(*data.ChannelMembers) < model.CHANNEL_GROUP_MIN_USERS {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_too_few.error", nil, "", http.StatusBadRequest)
} else if len(*data.ChannelMembers) > model.CHANNEL_GROUP_MAX_USERS {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.channel_members_too_many.error", nil, "", http.StatusBadRequest)
}
}
if data.User == nil {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.user_missing.error", nil, "", http.StatusBadRequest)
}
if data.Message == nil {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.message_missing.error", nil, "", http.StatusBadRequest)
} else if utf8.RuneCountInString(*data.Message) > model.POST_MESSAGE_MAX_RUNES {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.message_length.error", nil, "", http.StatusBadRequest)
}
if data.CreateAt == nil {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
} else if *data.CreateAt == 0 {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
}
if data.FlaggedBy != nil {
for _, flagger := range *data.FlaggedBy {
found := false
for _, member := range *data.ChannelMembers {
if flagger == member {
found = true
break
}
}
if !found {
return model.NewAppError("BulkImport", "app.import.validate_direct_post_import_data.unknown_flagger.error", map[string]interface{}{"Username": flagger}, "", http.StatusBadRequest)
}
}
}
return nil
}
//
// -- Old SlackImport Functions --
// Import functions are sutible for entering posts and users into the database without
// some of the usual checks. (IsValid is still run)
//
func (a *App) OldImportPost(post *model.Post) {
// Workaround for empty messages, which may be the case if they are webhook posts.
firstIteration := true
for messageRuneCount := utf8.RuneCountInString(post.Message); messageRuneCount > 0 || firstIteration; messageRuneCount = utf8.RuneCountInString(post.Message) {
firstIteration = false
var remainder string
if messageRuneCount > model.POST_MESSAGE_MAX_RUNES {
remainder = string(([]rune(post.Message))[model.POST_MESSAGE_MAX_RUNES:])
post.Message = truncateRunes(post.Message, model.POST_MESSAGE_MAX_RUNES)
} else {
remainder = ""
}
post.Hashtags, _ = model.ParseHashtags(post.Message)
if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
l4g.Debug(utils.T("api.import.import_post.saving.debug"), post.UserId, post.Message)
}
for _, fileId := range post.FileIds {
if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
l4g.Error(utils.T("api.import.import_post.attach_files.error"), post.Id, post.FileIds, result.Err)
}
}
post.Id = ""
post.CreateAt++
post.Message = remainder
}
}
func (a *App) OldImportUser(team *model.Team, user *model.User) *model.User {
user.MakeNonNil()
user.Roles = model.ROLE_SYSTEM_USER.Id
if result := <-a.Srv.Store.User().Save(user); result.Err != nil {
l4g.Error(utils.T("api.import.import_user.saving.error"), result.Err)
return nil
} else {
ruser := result.Data.(*model.User)
if cresult := <-a.Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
l4g.Error(utils.T("api.import.import_user.set_email.error"), cresult.Err)
}
if err := a.JoinUserToTeam(team, user, ""); err != nil {
l4g.Error(utils.T("api.import.import_user.join_team.error"), err)
}
return ruser
}
}
func (a *App) OldImportChannel(channel *model.Channel) *model.Channel {
if result := <-a.Srv.Store.Channel().Save(channel); result.Err != nil {
return nil
} else {
sc := result.Data.(*model.Channel)
return sc
}
}
func (a *App) OldImportFile(timestamp time.Time, file io.Reader, teamId string, channelId string, userId string, fileName string) (*model.FileInfo, error) {
buf := bytes.NewBuffer(nil)
io.Copy(buf, file)
data := buf.Bytes()
fileInfo, err := a.DoUploadFile(timestamp, teamId, channelId, userId, fileName, data)
if err != nil {
return nil, err
}
img, width, height := prepareImage(data)
if img != nil {
generateThumbnailImage(*img, fileInfo.ThumbnailPath, width, height)
generatePreviewImage(*img, fileInfo.PreviewPath, width)
}
return fileInfo, nil
}
func (a *App) OldImportIncomingWebhookPost(post *model.Post, props model.StringInterface) {
linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
post.Message = linkWithTextRegex.ReplaceAllString(post.Message, "[${2}](${1})")
post.AddProp("from_webhook", "true")
if _, ok := props["override_username"]; !ok {
post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
}
if len(props) > 0 {
for key, val := range props {
if key == "attachments" {
if attachments, success := val.([]*model.SlackAttachment); success {
parseSlackAttachment(post, attachments)
}
} else if key != "from_webhook" {
post.AddProp(key, val)
}
}
}
a.OldImportPost(post)
}