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