summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/import.go2023
-rw-r--r--app/import_functions.go1218
-rw-r--r--app/import_functions_test.go2501
-rw-r--r--app/import_test.go3845
-rw-r--r--app/import_types.go186
-rw-r--r--app/import_validators.go529
-rw-r--r--app/import_validators_test.go1372
-rw-r--r--app/slackimport.go118
8 files changed, 5924 insertions, 5868 deletions
diff --git a/app/import.go b/app/import.go
index 50973d504..078198dd4 100644
--- a/app/import.go
+++ b/app/import.go
@@ -5,210 +5,15 @@ package app
import (
"bufio"
- "bytes"
"encoding/json"
- "fmt"
"io"
"net/http"
- "os"
- "regexp"
"strings"
"sync"
- "time"
- "unicode/utf8"
- "github.com/mattermost/mattermost-server/mlog"
"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"`
- Scheme *SchemeImportData `json:"scheme"`
- 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"`
- Emoji *EmojiImportData `json:"emoji"`
- 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"`
- Scheme *string `json:"scheme"`
-}
-
-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"`
- Scheme *string `json:"scheme"`
-}
-
-type UserImportData struct {
- ProfileImage *string `json:"profile_image"`
- 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"`
- 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 EmojiImportData struct {
- Name *string `json:"name"`
- Image *string `json:"image"`
-}
-
-type ReactionImportData struct {
- User *string `json:"user"`
- CreateAt *int64 `json:"create_at"`
- EmojiName *string `json:"emoji_name"`
-}
-
-type ReplyImportData struct {
- User *string `json:"user"`
-
- Message *string `json:"message"`
- CreateAt *int64 `json:"create_at"`
-
- FlaggedBy *[]string `json:"flagged_by"`
- Reactions *[]ReactionImportData `json:"reactions"`
- Attachments *[]AttachmentImportData `json:"attachments"`
-}
-
-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"`
- Reactions *[]ReactionImportData `json:"reactions"`
- Replies *[]ReplyImportData `json:"replies"`
- Attachments *[]AttachmentImportData `json:"attachments"`
-}
-
-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"`
- Reactions *[]ReactionImportData `json:"reactions"`
- Replies *[]ReplyImportData `json:"replies"`
-}
-
-type SchemeImportData struct {
- Name *string `json:"name"`
- DisplayName *string `json:"display_name"`
- Description *string `json:"description"`
- Scope *string `json:"scope"`
- DefaultTeamAdminRole *RoleImportData `json:"default_team_admin_role"`
- DefaultTeamUserRole *RoleImportData `json:"default_team_user_role"`
- DefaultChannelAdminRole *RoleImportData `json:"default_channel_admin_role"`
- DefaultChannelUserRole *RoleImportData `json:"default_channel_user_role"`
-}
-
-type RoleImportData struct {
- Name *string `json:"name"`
- DisplayName *string `json:"display_name"`
- Description *string `json:"description"`
- Permissions *[]string `json:"permissions"`
-}
-
-type LineImportWorkerData struct {
- LineImportData
- LineNumber int
-}
-
-type LineImportWorkerError struct {
- Error *model.AppError
- LineNumber int
-}
-
-type AttachmentImportData struct {
- Path *string `json:"path"`
-}
-
-//
-// -- 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 {
@@ -360,1831 +165,3 @@ func (a *App) ImportLine(line LineImportData, dryRun bool) *model.AppError {
return model.NewAppError("BulkImport", "app.import.import_line.unknown_line_type.error", map[string]interface{}{"Type": line.Type}, "", http.StatusBadRequest)
}
}
-
-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 validateSchemeImportData(data *SchemeImportData) *model.AppError {
-
- if data.Scope == nil {
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.null_scope.error", nil, "", http.StatusBadRequest)
- }
-
- switch *data.Scope {
- case model.SCHEME_SCOPE_TEAM:
- if data.DefaultTeamAdminRole == nil || data.DefaultTeamUserRole == nil || data.DefaultChannelAdminRole == nil || data.DefaultChannelUserRole == nil {
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.wrong_roles_for_scope.error", nil, "", http.StatusBadRequest)
- }
- case model.SCHEME_SCOPE_CHANNEL:
- if data.DefaultTeamAdminRole != nil || data.DefaultTeamUserRole != nil || data.DefaultChannelAdminRole == nil || data.DefaultChannelUserRole == nil {
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.wrong_roles_for_scope.error", nil, "", http.StatusBadRequest)
- }
- default:
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.unknown_scheme.error", nil, "", http.StatusBadRequest)
- }
-
- if data.Name == nil || !model.IsValidSchemeName(*data.Name) {
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.name_invalid.error", nil, "", http.StatusBadRequest)
- }
-
- if data.DisplayName == nil || len(*data.DisplayName) == 0 || len(*data.DisplayName) > model.SCHEME_DISPLAY_NAME_MAX_LENGTH {
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.display_name_invalid.error", nil, "", http.StatusBadRequest)
- }
-
- if data.Description != nil && len(*data.Description) > model.SCHEME_DESCRIPTION_MAX_LENGTH {
- return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.description_invalid.error", nil, "", http.StatusBadRequest)
- }
-
- if data.DefaultTeamAdminRole != nil {
- if err := validateRoleImportData(data.DefaultTeamAdminRole); err != nil {
- return err
- }
- }
-
- if data.DefaultTeamUserRole != nil {
- if err := validateRoleImportData(data.DefaultTeamUserRole); err != nil {
- return err
- }
- }
-
- if data.DefaultChannelAdminRole != nil {
- if err := validateRoleImportData(data.DefaultChannelAdminRole); err != nil {
- return err
- }
- }
-
- if data.DefaultChannelUserRole != nil {
- if err := validateRoleImportData(data.DefaultChannelUserRole); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func validateRoleImportData(data *RoleImportData) *model.AppError {
-
- if data.Name == nil || !model.IsValidRoleName(*data.Name) {
- return model.NewAppError("BulkImport", "app.import.validate_role_import_data.name_invalid.error", nil, "", http.StatusBadRequest)
- }
-
- if data.DisplayName == nil || len(*data.DisplayName) == 0 || len(*data.DisplayName) > model.ROLE_DISPLAY_NAME_MAX_LENGTH {
- return model.NewAppError("BulkImport", "app.import.validate_role_import_data.display_name_invalid.error", nil, "", http.StatusBadRequest)
- }
-
- if data.Description != nil && len(*data.Description) > model.ROLE_DESCRIPTION_MAX_LENGTH {
- return model.NewAppError("BulkImport", "app.import.validate_role_import_data.description_invalid.error", nil, "", http.StatusBadRequest)
- }
-
- if data.Permissions != nil {
- for _, permission := range *data.Permissions {
- permissionValidated := false
- for _, p := range model.ALL_PERMISSIONS {
- if permission == p.Id {
- permissionValidated = true
- break
- }
- }
-
- if !permissionValidated {
- return model.NewAppError("BulkImport", "app.import.validate_role_import_data.invalid_permission.error", nil, "permission"+permission, http.StatusBadRequest)
- }
- }
- }
-
- return nil
-}
-
-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 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)
- }
-
- if data.Scheme != nil && !model.IsValidSchemeName(*data.Scheme) {
- return model.NewAppError("BulkImport", "app.import.validate_team_import_data.scheme_invalid.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}, 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 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)
- }
-
- if data.Scheme != nil && !model.IsValidSchemeName(*data.Scheme) {
- return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.scheme_invalid.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 != *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 validateUserImportData(data *UserImportData) *model.AppError {
- if data.ProfileImage != nil {
- if _, err := os.Stat(*data.ProfileImage); os.IsNotExist(err) {
- return model.NewAppError("BulkImport", "app.import.validate_user_import_data.profile_image.error", nil, "", http.StatusBadRequest)
- }
- }
-
- 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.password_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.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) ImportReaction(data *ReactionImportData, post *model.Post, dryRun bool) *model.AppError {
- if err := validateReactionImportData(data, post.CreateAt); err != nil {
- return err
- }
-
- var user *model.User
- if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest)
- } else {
- user = result.Data.(*model.User)
- }
- reaction := &model.Reaction{
- UserId: user.Id,
- PostId: post.Id,
- EmojiName: *data.EmojiName,
- CreateAt: *data.CreateAt,
- }
- if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil {
- return result.Err
- }
- return nil
-}
-
-func (a *App) ImportReply(data *ReplyImportData, post *model.Post, teamId string, dryRun bool) *model.AppError {
- if err := validateReplyImportData(data, post.CreateAt, a.MaxPostSize()); err != nil {
- return err
- }
-
- var user *model.User
- if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest)
- } else {
- user = result.Data.(*model.User)
- }
-
- // Check if this post already exists.
- var replies []*model.Post
- if result := <-a.Srv.Store.Post().GetPostsCreatedAt(post.ChannelId, *data.CreateAt); result.Err != nil {
- return result.Err
- } else {
- replies = result.Data.([]*model.Post)
- }
-
- var reply *model.Post
- for _, r := range replies {
- if r.Message == *data.Message {
- reply = r
- break
- }
- }
-
- if reply == nil {
- reply = &model.Post{}
- }
- reply.UserId = user.Id
- reply.ChannelId = post.ChannelId
- reply.ParentId = post.Id
- reply.RootId = post.Id
- reply.Message = *data.Message
- reply.CreateAt = *data.CreateAt
-
- if data.Attachments != nil {
- fileIds, err := a.uploadAttachments(data.Attachments, reply, teamId, dryRun)
- if err != nil {
- return err
- }
- reply.FileIds = fileIds
- }
-
- if reply.Id == "" {
- if result := <-a.Srv.Store.Post().Save(reply); result.Err != nil {
- return result.Err
- }
- } else {
- if result := <-a.Srv.Store.Post().Overwrite(reply); result.Err != nil {
- return result.Err
- }
- }
-
- a.UpdateFileInfoWithPostId(reply)
-
- return nil
-}
-
-func (a *App) ImportAttachment(data *AttachmentImportData, post *model.Post, teamId string, dryRun bool) (*model.FileInfo, *model.AppError) {
- fileUploadError := model.NewAppError("BulkImport", "app.import.attachment.file_upload.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest)
- file, err := os.Open(*data.Path)
- if err != nil {
- return nil, model.NewAppError("BulkImport", "app.import.attachment.bad_file.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest)
- }
- if file != nil {
- timestamp := utils.TimeFromMillis(post.CreateAt)
- buf := bytes.NewBuffer(nil)
- io.Copy(buf, file)
-
- fileInfo, err := a.DoUploadFile(timestamp, teamId, post.ChannelId, post.UserId, file.Name(), buf.Bytes())
-
- if err != nil {
- fmt.Print(err)
- return nil, fileUploadError
- }
-
- mlog.Info(fmt.Sprintf("uploading file with name %s", file.Name()))
- return fileInfo, nil
- }
- return nil, fileUploadError
-}
-
-func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError {
- if err := validatePostImportData(data, a.MaxPostSize()); err != nil {
- return err
- }
-
- // If this is a Dry Run, do not continue any further.
- if dryRun {
- return nil
- }
-
- var team *model.Team
- if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest)
- } else {
- team = result.Data.(*model.Team)
- }
-
- var channel *model.Channel
- if result := <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, result.Err.Error(), http.StatusBadRequest)
- } else {
- channel = result.Data.(*model.Channel)
- }
-
- var user *model.User
- if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, result.Err.Error(), http.StatusBadRequest)
- } else {
- user = result.Data.(*model.User)
- }
-
- // Check if this post already exists.
- var posts []*model.Post
- if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
- return result.Err
- } else {
- posts = result.Data.([]*model.Post)
- }
-
- var post *model.Post
- for _, p := range posts {
- if p.Message == *data.Message {
- post = p
- break
- }
- }
-
- if post == nil {
- post = &model.Post{}
- }
-
- post.ChannelId = channel.Id
- post.Message = *data.Message
- post.UserId = user.Id
- post.CreateAt = *data.CreateAt
-
- post.Hashtags, _ = model.ParseHashtags(post.Message)
-
- if data.Attachments != nil {
- fileIds, err := a.uploadAttachments(data.Attachments, post, team.Id, dryRun)
- if err != nil {
- return err
- }
- post.FileIds = fileIds
- }
-
- if post.Id == "" {
- if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
- return result.Err
- }
- } else {
- if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
- return result.Err
- }
- }
-
- if data.FlaggedBy != nil {
- var preferences model.Preferences
-
- for _, username := range *data.FlaggedBy {
- var user *model.User
-
- if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, result.Err.Error(), http.StatusBadRequest)
- } else {
- user = result.Data.(*model.User)
- }
-
- preferences = append(preferences, model.Preference{
- UserId: user.Id,
- Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
- Name: post.Id,
- Value: "true",
- })
- }
-
- if len(preferences) > 0 {
- if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
- }
- }
- }
-
- if data.Reactions != nil {
- for _, reaction := range *data.Reactions {
- if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
- return err
- }
- }
- }
-
- if data.Replies != nil {
- for _, reply := range *data.Replies {
- if err := a.ImportReply(&reply, post, team.Id, dryRun); err != nil {
- return err
- }
- }
- }
-
- a.UpdateFileInfoWithPostId(post)
- return nil
-}
-
-func (a *App) uploadAttachments(attachments *[]AttachmentImportData, post *model.Post, teamId string, dryRun bool) ([]string, *model.AppError) {
- fileIds := []string{}
- for _, attachment := range *attachments {
- fileInfo, err := a.ImportAttachment(&attachment, post, teamId, dryRun)
- if err != nil {
- return nil, err
- }
- fileIds = append(fileIds, fileInfo.Id)
- }
- return fileIds, nil
-}
-
-func (a *App) UpdateFileInfoWithPostId(post *model.Post) {
- for _, fileId := range post.FileIds {
- if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
- mlog.Error(fmt.Sprintf("Error attaching files to post. postId=%v, fileIds=%v, message=%v", post.Id, post.FileIds, result.Err), mlog.String("post_id", post.Id))
- }
- }
-}
-func validateReactionImportData(data *ReactionImportData, parentCreateAt int64) *model.AppError {
- if data.User == nil {
- return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.user_missing.error", nil, "", http.StatusBadRequest)
- }
-
- if data.EmojiName == nil {
- return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_missing.error", nil, "", http.StatusBadRequest)
- } else if utf8.RuneCountInString(*data.EmojiName) > model.EMOJI_NAME_MAX_LENGTH {
- return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_length.error", nil, "", http.StatusBadRequest)
- }
-
- if data.CreateAt == nil {
- return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
- } else if *data.CreateAt == 0 {
- return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
- } else if *data.CreateAt < parentCreateAt {
- return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
- }
-
- return nil
-}
-
-func validateReplyImportData(data *ReplyImportData, parentCreateAt int64, maxPostSize int) *model.AppError {
- if data.User == nil {
- return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.user_missing.error", nil, "", http.StatusBadRequest)
- }
-
- if data.Message == nil {
- return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_missing.error", nil, "", http.StatusBadRequest)
- } else if utf8.RuneCountInString(*data.Message) > maxPostSize {
- return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_length.error", nil, "", http.StatusBadRequest)
- }
-
- if data.CreateAt == nil {
- return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
- } else if *data.CreateAt == 0 {
- return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
- } else if *data.CreateAt < parentCreateAt {
- return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
- }
-
- return nil
-}
-
-func validatePostImportData(data *PostImportData, maxPostSize int) *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) > maxPostSize {
- 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)
- }
-
- if data.Reactions != nil {
- for _, reaction := range *data.Reactions {
- validateReactionImportData(&reaction, *data.CreateAt)
- }
- }
-
- if data.Replies != nil {
- for _, reply := range *data.Replies {
- validateReplyImportData(&reply, *data.CreateAt, maxPostSize)
- }
- }
-
- 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, 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 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, a.MaxPostSize()); err != nil {
- return err
- }
-
- // If this is a Dry Run, do not continue any further.
- if dryRun {
- return nil
- }
-
- var userIds []string
- for _, username := range *data.ChannelMembers {
- if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
- user := result.Data.(*model.User)
- userIds = append(userIds, user.Id)
- } else {
- return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest)
- }
- }
-
- var channel *model.Channel
- if len(userIds) == 2 {
- ch, err := a.createDirectChannel(userIds[0], userIds[1])
- if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
- return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest)
- } else {
- channel = ch
- }
- } else {
- ch, err := a.createGroupChannel(userIds, userIds[0])
- if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
- return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, err.Error(), http.StatusBadRequest)
- } else {
- channel = ch
- }
- }
-
- var user *model.User
- if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
- } else {
- user = result.Data.(*model.User)
- }
-
- // Check if this post already exists.
- var posts []*model.Post
- if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
- return result.Err
- } else {
- posts = result.Data.([]*model.Post)
- }
-
- var post *model.Post
- for _, p := range posts {
- if p.Message == *data.Message {
- post = p
- break
- }
- }
-
- if post == nil {
- post = &model.Post{}
- }
-
- post.ChannelId = channel.Id
- post.Message = *data.Message
- post.UserId = user.Id
- post.CreateAt = *data.CreateAt
-
- post.Hashtags, _ = model.ParseHashtags(post.Message)
-
- if post.Id == "" {
- if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
- return result.Err
- }
- } else {
- if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
- return result.Err
- }
- }
-
- if data.FlaggedBy != nil {
- var preferences model.Preferences
-
- for _, username := range *data.FlaggedBy {
- var user *model.User
-
- if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
- } else {
- user = result.Data.(*model.User)
- }
-
- preferences = append(preferences, model.Preference{
- UserId: user.Id,
- Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
- Name: post.Id,
- Value: "true",
- })
- }
-
- if len(preferences) > 0 {
- if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
- return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
- }
- }
- }
-
- if data.Reactions != nil {
- for _, reaction := range *data.Reactions {
- if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
- return err
- }
- }
- }
-
- if data.Replies != nil {
- for _, reply := range *data.Replies {
- if err := a.ImportReply(&reply, post, "noteam", dryRun); err != nil {
- return err
- }
- }
- }
-
- return nil
-}
-
-func validateDirectPostImportData(data *DirectPostImportData, maxPostSize int) *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) > maxPostSize {
- 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)
- }
- }
- }
-
- if data.Reactions != nil {
- for _, reaction := range *data.Reactions {
- validateReactionImportData(&reaction, *data.CreateAt)
- }
- }
-
- if data.Replies != nil {
- for _, reply := range *data.Replies {
- validateReplyImportData(&reply, *data.CreateAt, maxPostSize)
- }
- }
-
- 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
-}
-
-func validateEmojiImportData(data *EmojiImportData) *model.AppError {
- if data == nil {
- return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.empty.error", nil, "", http.StatusBadRequest)
- }
-
- if data.Name == nil || len(*data.Name) == 0 {
- return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.name_missing.error", nil, "", http.StatusBadRequest)
- }
-
- if err := model.IsValidEmojiName(*data.Name); err != nil {
- return err
- }
-
- if data.Image == nil || len(*data.Image) == 0 {
- return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.image_missing.error", nil, "", 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
- maxPostSize := a.MaxPostSize()
- for messageRuneCount := utf8.RuneCountInString(post.Message); messageRuneCount > 0 || firstIteration; messageRuneCount = utf8.RuneCountInString(post.Message) {
- firstIteration = false
- var remainder string
- if messageRuneCount > maxPostSize {
- remainder = string(([]rune(post.Message))[maxPostSize:])
- post.Message = truncateRunes(post.Message, maxPostSize)
- } else {
- remainder = ""
- }
-
- post.Hashtags, _ = model.ParseHashtags(post.Message)
-
- if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
- mlog.Debug(fmt.Sprintf("Error saving post. user=%v, message=%v", post.UserId, post.Message))
- }
-
- 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))
- }
- }
-
- post.Id = ""
- post.CreateAt++
- post.Message = remainder
- }
-}
-
-func (a *App) OldImportUser(team *model.Team, user *model.User) *model.User {
- user.MakeNonNil()
-
- user.Roles = model.SYSTEM_USER_ROLE_ID
-
- if result := <-a.Srv.Store.User().Save(user); result.Err != nil {
- mlog.Error(fmt.Sprintf("Error saving user. err=%v", result.Err))
- return nil
- } else {
- ruser := result.Data.(*model.User)
-
- if cresult := <-a.Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- mlog.Error(fmt.Sprintf("Failed to set email verified err=%v", cresult.Err))
- }
-
- if err := a.JoinUserToTeam(team, user, ""); err != nil {
- mlog.Error(fmt.Sprintf("Failed to join team when importing err=%v", err))
- }
-
- return ruser
- }
-}
-
-func (a *App) OldImportChannel(channel *model.Channel) *model.Channel {
- if result := <-a.Srv.Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam); 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
- }
-
- if fileInfo.IsImage() && fileInfo.MimeType != "image/svg+xml" {
- img, width, height := prepareImage(data)
- if img != nil {
- a.generateThumbnailImage(*img, fileInfo.ThumbnailPath, width, height)
- a.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)
-}
diff --git a/app/import_functions.go b/app/import_functions.go
new file mode 100644
index 000000000..f4ff5607f
--- /dev/null
+++ b/app/import_functions.go
@@ -0,0 +1,1218 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "strings"
+
+ "github.com/mattermost/mattermost-server/mlog"
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/store"
+ "github.com/mattermost/mattermost-server/utils"
+)
+
+//
+// -- Bulk Import Functions --
+// These functions import data directly into the database. Security and permission checks are bypassed but validity is
+// still enforced.
+//
+
+func (a *App) ImportScheme(data *SchemeImportData, dryRun bool) *model.AppError {
+ if err := validateSchemeImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ scheme, err := a.GetSchemeByName(*data.Name)
+ if err != nil {
+ scheme = new(model.Scheme)
+ } else if scheme.Scope != *data.Scope {
+ return model.NewAppError("BulkImport", "app.import.import_scheme.scope_change.error", map[string]interface{}{"SchemeName": scheme.Name}, "", http.StatusBadRequest)
+ }
+
+ scheme.Name = *data.Name
+ scheme.DisplayName = *data.DisplayName
+ scheme.Scope = *data.Scope
+
+ if data.Description != nil {
+ scheme.Description = *data.Description
+ }
+
+ if len(scheme.Id) == 0 {
+ scheme, err = a.CreateScheme(scheme)
+ } else {
+ scheme, err = a.UpdateScheme(scheme)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ if scheme.Scope == model.SCHEME_SCOPE_TEAM {
+ data.DefaultTeamAdminRole.Name = &scheme.DefaultTeamAdminRole
+ if err := a.ImportRole(data.DefaultTeamAdminRole, dryRun, true); err != nil {
+ return err
+ }
+
+ data.DefaultTeamUserRole.Name = &scheme.DefaultTeamUserRole
+ if err := a.ImportRole(data.DefaultTeamUserRole, dryRun, true); err != nil {
+ return err
+ }
+ }
+
+ if scheme.Scope == model.SCHEME_SCOPE_TEAM || scheme.Scope == model.SCHEME_SCOPE_CHANNEL {
+ data.DefaultChannelAdminRole.Name = &scheme.DefaultChannelAdminRole
+ if err := a.ImportRole(data.DefaultChannelAdminRole, dryRun, true); err != nil {
+ return err
+ }
+
+ data.DefaultChannelUserRole.Name = &scheme.DefaultChannelUserRole
+ if err := a.ImportRole(data.DefaultChannelUserRole, dryRun, true); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportRole(data *RoleImportData, dryRun bool, isSchemeRole bool) *model.AppError {
+ if !isSchemeRole {
+ if err := validateRoleImportData(data); err != nil {
+ return err
+ }
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ role, err := a.GetRoleByName(*data.Name)
+ if err != nil {
+ role = new(model.Role)
+ }
+
+ role.Name = *data.Name
+
+ if data.DisplayName != nil {
+ role.DisplayName = *data.DisplayName
+ }
+
+ if data.Description != nil {
+ role.Description = *data.Description
+ }
+
+ if data.Permissions != nil {
+ role.Permissions = *data.Permissions
+ }
+
+ if isSchemeRole {
+ role.SchemeManaged = true
+ } else {
+ role.SchemeManaged = false
+ }
+
+ if len(role.Id) == 0 {
+ role, err = a.CreateRole(role)
+ } else {
+ role, err = a.UpdateRole(role)
+ }
+
+ return err
+}
+
+func (a *App) ImportTeam(data *TeamImportData, dryRun bool) *model.AppError {
+ if err := validateTeamImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var team *model.Team
+ if result := <-a.Srv.Store.Team().GetByName(*data.Name); result.Err == nil {
+ team = result.Data.(*model.Team)
+ } else {
+ team = &model.Team{}
+ }
+
+ team.Name = *data.Name
+ team.DisplayName = *data.DisplayName
+ team.Type = *data.Type
+
+ if data.Description != nil {
+ team.Description = *data.Description
+ }
+
+ if data.AllowOpenInvite != nil {
+ team.AllowOpenInvite = *data.AllowOpenInvite
+ }
+
+ if data.Scheme != nil {
+ scheme, err := a.GetSchemeByName(*data.Scheme)
+ if err != nil {
+ return err
+ }
+
+ if scheme.DeleteAt != 0 {
+ return model.NewAppError("BulkImport", "app.import.import_team.scheme_deleted.error", nil, "", http.StatusBadRequest)
+ }
+
+ if scheme.Scope != model.SCHEME_SCOPE_TEAM {
+ return model.NewAppError("BulkImport", "app.import.import_team.scheme_wrong_scope.error", nil, "", http.StatusBadRequest)
+ }
+
+ team.SchemeId = &scheme.Id
+ }
+
+ if team.Id == "" {
+ if _, err := a.CreateTeam(team); err != nil {
+ return err
+ }
+ } else {
+ if _, err := a.updateTeamUnsanitized(team); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportChannel(data *ChannelImportData, dryRun bool) *model.AppError {
+ if err := validateChannelImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var team *model.Team
+ if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_channel.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ var channel *model.Channel
+ if result := <-a.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, *data.Name, true); result.Err == nil {
+ channel = result.Data.(*model.Channel)
+ } else {
+ channel = &model.Channel{}
+ }
+
+ channel.TeamId = team.Id
+ channel.Name = *data.Name
+ channel.DisplayName = *data.DisplayName
+ channel.Type = *data.Type
+
+ if data.Header != nil {
+ channel.Header = *data.Header
+ }
+
+ if data.Purpose != nil {
+ channel.Purpose = *data.Purpose
+ }
+
+ if data.Scheme != nil {
+ scheme, err := a.GetSchemeByName(*data.Scheme)
+ if err != nil {
+ return err
+ }
+
+ if scheme.DeleteAt != 0 {
+ return model.NewAppError("BulkImport", "app.import.import_channel.scheme_deleted.error", nil, "", http.StatusBadRequest)
+ }
+
+ if scheme.Scope != model.SCHEME_SCOPE_CHANNEL {
+ return model.NewAppError("BulkImport", "app.import.import_channel.scheme_wrong_scope.error", nil, "", http.StatusBadRequest)
+ }
+
+ channel.SchemeId = &scheme.Id
+ }
+
+ if channel.Id == "" {
+ if _, err := a.CreateChannel(channel, false); err != nil {
+ return err
+ }
+ } else {
+ if _, err := a.UpdateChannel(channel); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportUser(data *UserImportData, dryRun bool) *model.AppError {
+ if err := validateUserImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ // We want to avoid database writes if nothing has changed.
+ hasUserChanged := false
+ hasNotifyPropsChanged := false
+ hasUserRolesChanged := false
+ hasUserAuthDataChanged := false
+ hasUserEmailVerifiedChanged := false
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.Username); result.Err == nil {
+ user = result.Data.(*model.User)
+ } else {
+ user = &model.User{}
+ user.MakeNonNil()
+ hasUserChanged = true
+ }
+
+ user.Username = *data.Username
+
+ if user.Email != *data.Email {
+ hasUserChanged = true
+ hasUserEmailVerifiedChanged = true // Changing the email resets email verified to false by default.
+ user.Email = *data.Email
+ }
+
+ var password string
+ var authService string
+ var authData *string
+
+ if data.AuthService != nil {
+ if user.AuthService != *data.AuthService {
+ hasUserAuthDataChanged = true
+ }
+ authService = *data.AuthService
+ }
+
+ // AuthData and Password are mutually exclusive.
+ if data.AuthData != nil {
+ if user.AuthData == nil || *user.AuthData != *data.AuthData {
+ hasUserAuthDataChanged = true
+ }
+ authData = data.AuthData
+ password = ""
+ } else if data.Password != nil {
+ password = *data.Password
+ authData = nil
+ } else {
+ // If no AuthData or Password is specified, we must generate a password.
+ password = model.NewId()
+ authData = nil
+ }
+
+ user.Password = password
+ user.AuthService = authService
+ user.AuthData = authData
+
+ // Automatically assume all emails are verified.
+ emailVerified := true
+ if user.EmailVerified != emailVerified {
+ user.EmailVerified = emailVerified
+ hasUserEmailVerifiedChanged = true
+ }
+
+ if data.Nickname != nil {
+ if user.Nickname != *data.Nickname {
+ user.Nickname = *data.Nickname
+ hasUserChanged = true
+ }
+ }
+
+ if data.FirstName != nil {
+ if user.FirstName != *data.FirstName {
+ user.FirstName = *data.FirstName
+ hasUserChanged = true
+ }
+ }
+
+ if data.LastName != nil {
+ if user.LastName != *data.LastName {
+ user.LastName = *data.LastName
+ hasUserChanged = true
+ }
+ }
+
+ if data.Position != nil {
+ if user.Position != *data.Position {
+ user.Position = *data.Position
+ hasUserChanged = true
+ }
+ }
+
+ if data.Locale != nil {
+ if user.Locale != *data.Locale {
+ user.Locale = *data.Locale
+ hasUserChanged = true
+ }
+ } else {
+ if user.Locale != *a.Config().LocalizationSettings.DefaultClientLocale {
+ user.Locale = *a.Config().LocalizationSettings.DefaultClientLocale
+ hasUserChanged = true
+ }
+ }
+
+ var roles string
+ if data.Roles != nil {
+ if user.Roles != *data.Roles {
+ roles = *data.Roles
+ hasUserRolesChanged = true
+ }
+ } else if len(user.Roles) == 0 {
+ // Set SYSTEM_USER roles on newly created users by default.
+ if user.Roles != model.SYSTEM_USER_ROLE_ID {
+ roles = model.SYSTEM_USER_ROLE_ID
+ hasUserRolesChanged = true
+ }
+ }
+ user.Roles = roles
+
+ if data.NotifyProps != nil {
+ if data.NotifyProps.Desktop != nil {
+ if value, ok := user.NotifyProps[model.DESKTOP_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Desktop {
+ user.AddNotifyProp(model.DESKTOP_NOTIFY_PROP, *data.NotifyProps.Desktop)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.DesktopSound != nil {
+ if value, ok := user.NotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopSound {
+ user.AddNotifyProp(model.DESKTOP_SOUND_NOTIFY_PROP, *data.NotifyProps.DesktopSound)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.Email != nil {
+ if value, ok := user.NotifyProps[model.EMAIL_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Email {
+ user.AddNotifyProp(model.EMAIL_NOTIFY_PROP, *data.NotifyProps.Email)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.Mobile != nil {
+ if value, ok := user.NotifyProps[model.PUSH_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Mobile {
+ user.AddNotifyProp(model.PUSH_NOTIFY_PROP, *data.NotifyProps.Mobile)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.MobilePushStatus != nil {
+ if value, ok := user.NotifyProps[model.PUSH_STATUS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MobilePushStatus {
+ user.AddNotifyProp(model.PUSH_STATUS_NOTIFY_PROP, *data.NotifyProps.MobilePushStatus)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.ChannelTrigger != nil {
+ if value, ok := user.NotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.ChannelTrigger {
+ user.AddNotifyProp(model.CHANNEL_MENTIONS_NOTIFY_PROP, *data.NotifyProps.ChannelTrigger)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.CommentsTrigger != nil {
+ if value, ok := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.CommentsTrigger {
+ user.AddNotifyProp(model.COMMENTS_NOTIFY_PROP, *data.NotifyProps.CommentsTrigger)
+ hasNotifyPropsChanged = true
+ }
+ }
+
+ if data.NotifyProps.MentionKeys != nil {
+ if value, ok := user.NotifyProps[model.MENTION_KEYS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MentionKeys {
+ user.AddNotifyProp(model.MENTION_KEYS_NOTIFY_PROP, *data.NotifyProps.MentionKeys)
+ hasNotifyPropsChanged = true
+ }
+ }
+ }
+
+ var err *model.AppError
+ var savedUser *model.User
+ if user.Id == "" {
+ if savedUser, err = a.createUser(user); err != nil {
+ return err
+ }
+ } else {
+ if hasUserChanged {
+ if savedUser, err = a.UpdateUser(user, false); err != nil {
+ return err
+ }
+ }
+ if hasUserRolesChanged {
+ if savedUser, err = a.UpdateUserRoles(user.Id, roles, false); err != nil {
+ return err
+ }
+ }
+ if hasNotifyPropsChanged {
+ if savedUser, err = a.UpdateUserNotifyProps(user.Id, user.NotifyProps); err != nil {
+ return err
+ }
+ }
+ if len(password) > 0 {
+ if err = a.UpdatePassword(user, password); err != nil {
+ return err
+ }
+ } else {
+ if hasUserAuthDataChanged {
+ if res := <-a.Srv.Store.User().UpdateAuthData(user.Id, authService, authData, user.Email, false); res.Err != nil {
+ return res.Err
+ }
+ }
+ }
+ if emailVerified {
+ if hasUserEmailVerifiedChanged {
+ if err := a.VerifyUserEmail(user.Id); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ if savedUser == nil {
+ savedUser = user
+ }
+
+ if data.ProfileImage != nil {
+ file, err := os.Open(*data.ProfileImage)
+ if err != nil {
+ mlog.Error(fmt.Sprint("api.import.import_user.profile_image.error FIXME: NOT FOUND IN TRANSLATIONS FILE", err))
+ }
+ if err := a.SetProfileImageFromFile(savedUser.Id, file); err != nil {
+ mlog.Error(fmt.Sprint("api.import.import_user.profile_image.error FIXME: NOT FOUND IN TRANSLATIONS FILE", err))
+ }
+ }
+
+ // Preferences.
+ var preferences model.Preferences
+
+ if data.Theme != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_THEME,
+ Name: "",
+ Value: *data.Theme,
+ })
+ }
+
+ if data.UseMilitaryTime != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "use_military_time",
+ Value: *data.UseMilitaryTime,
+ })
+ }
+
+ if data.CollapsePreviews != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "collapse_previews",
+ Value: *data.CollapsePreviews,
+ })
+ }
+
+ if data.MessageDisplay != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "message_display",
+ Value: *data.MessageDisplay,
+ })
+ }
+
+ if data.ChannelDisplayMode != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS,
+ Name: "channel_display_mode",
+ Value: *data.ChannelDisplayMode,
+ })
+ }
+
+ if data.TutorialStep != nil {
+ preferences = append(preferences, model.Preference{
+ UserId: savedUser.Id,
+ Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS,
+ Name: savedUser.Id,
+ Value: *data.TutorialStep,
+ })
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_user.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ return a.ImportUserTeams(savedUser, data.Teams)
+}
+
+func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *model.AppError {
+ if data == nil {
+ return nil
+ }
+
+ for _, tdata := range *data {
+ team, err := a.GetTeamByName(*tdata.Name)
+ if err != nil {
+ return err
+ }
+
+ var roles string
+ isSchemeUser := true
+ isSchemeAdmin := false
+
+ if tdata.Roles == nil {
+ isSchemeUser = true
+ } else {
+ rawRoles := *tdata.Roles
+ explicitRoles := []string{}
+ for _, role := range strings.Fields(rawRoles) {
+ if role == model.TEAM_USER_ROLE_ID {
+ isSchemeUser = true
+ } else if role == model.TEAM_ADMIN_ROLE_ID {
+ isSchemeAdmin = true
+ } else {
+ explicitRoles = append(explicitRoles, role)
+ }
+ }
+ roles = strings.Join(explicitRoles, " ")
+ }
+
+ var member *model.TeamMember
+ if member, _, err = a.joinUserToTeam(team, user); err != nil {
+ return err
+ }
+
+ if member.ExplicitRoles != roles {
+ if _, err := a.UpdateTeamMemberRoles(team.Id, user.Id, roles); err != nil {
+ return err
+ }
+ }
+
+ if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser {
+ a.UpdateTeamMemberSchemeRoles(team.Id, user.Id, isSchemeUser, isSchemeAdmin)
+ }
+
+ if defaultChannel, err := a.GetChannelByName(model.DEFAULT_CHANNEL, team.Id, true); err != nil {
+ return err
+ } else if _, err = a.addUserToChannel(user, defaultChannel, member); err != nil {
+ return err
+ }
+
+ if err := a.ImportUserChannels(user, team, member, tdata.Channels); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember *model.TeamMember, data *[]UserChannelImportData) *model.AppError {
+ if data == nil {
+ return nil
+ }
+
+ var preferences model.Preferences
+
+ // Loop through all channels.
+ for _, cdata := range *data {
+ channel, err := a.GetChannelByName(*cdata.Name, team.Id, true)
+ if err != nil {
+ return err
+ }
+
+ var roles string
+ isSchemeUser := true
+ isSchemeAdmin := false
+
+ if cdata.Roles == nil {
+ isSchemeUser = true
+ } else {
+ rawRoles := *cdata.Roles
+ explicitRoles := []string{}
+ for _, role := range strings.Fields(rawRoles) {
+ if role == model.CHANNEL_USER_ROLE_ID {
+ isSchemeUser = true
+ } else if role == model.CHANNEL_ADMIN_ROLE_ID {
+ isSchemeAdmin = true
+ } else {
+ explicitRoles = append(explicitRoles, role)
+ }
+ }
+ roles = strings.Join(explicitRoles, " ")
+ }
+
+ var member *model.ChannelMember
+ member, err = a.GetChannelMember(channel.Id, user.Id)
+ if err != nil {
+ member, err = a.addUserToChannel(user, channel, teamMember)
+ if err != nil {
+ return err
+ }
+ }
+
+ if member.ExplicitRoles != roles {
+ if _, err := a.UpdateChannelMemberRoles(channel.Id, user.Id, roles); err != nil {
+ return err
+ }
+ }
+
+ if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser {
+ a.UpdateChannelMemberSchemeRoles(channel.Id, user.Id, isSchemeUser, isSchemeAdmin)
+ }
+
+ if cdata.NotifyProps != nil {
+ notifyProps := member.NotifyProps
+
+ if cdata.NotifyProps.Desktop != nil {
+ notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
+ }
+
+ if cdata.NotifyProps.Mobile != nil {
+ notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile
+ }
+
+ if cdata.NotifyProps.MarkUnread != nil {
+ notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
+ }
+
+ if _, err := a.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id); err != nil {
+ return err
+ }
+ }
+
+ if cdata.Favorite != nil && *cdata.Favorite {
+ preferences = append(preferences, model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
+ Name: channel.Id,
+ Value: "true",
+ })
+ }
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_user_channels.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportReaction(data *ReactionImportData, post *model.Post, dryRun bool) *model.AppError {
+ if err := validateReactionImportData(data, post.CreateAt); err != nil {
+ return err
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+ reaction := &model.Reaction{
+ UserId: user.Id,
+ PostId: post.Id,
+ EmojiName: *data.EmojiName,
+ CreateAt: *data.CreateAt,
+ }
+ if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil {
+ return result.Err
+ }
+ return nil
+}
+
+func (a *App) ImportReply(data *ReplyImportData, post *model.Post, teamId string, dryRun bool) *model.AppError {
+ if err := validateReplyImportData(data, post.CreateAt, a.MaxPostSize()); err != nil {
+ return err
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ // Check if this post already exists.
+ var replies []*model.Post
+ if result := <-a.Srv.Store.Post().GetPostsCreatedAt(post.ChannelId, *data.CreateAt); result.Err != nil {
+ return result.Err
+ } else {
+ replies = result.Data.([]*model.Post)
+ }
+
+ var reply *model.Post
+ for _, r := range replies {
+ if r.Message == *data.Message {
+ reply = r
+ break
+ }
+ }
+
+ if reply == nil {
+ reply = &model.Post{}
+ }
+ reply.UserId = user.Id
+ reply.ChannelId = post.ChannelId
+ reply.ParentId = post.Id
+ reply.RootId = post.Id
+ reply.Message = *data.Message
+ reply.CreateAt = *data.CreateAt
+
+ if data.Attachments != nil {
+ fileIds, err := a.uploadAttachments(data.Attachments, reply, teamId, dryRun)
+ if err != nil {
+ return err
+ }
+ reply.FileIds = fileIds
+ }
+
+ if reply.Id == "" {
+ if result := <-a.Srv.Store.Post().Save(reply); result.Err != nil {
+ return result.Err
+ }
+ } else {
+ if result := <-a.Srv.Store.Post().Overwrite(reply); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ a.UpdateFileInfoWithPostId(reply)
+
+ return nil
+}
+
+func (a *App) ImportAttachment(data *AttachmentImportData, post *model.Post, teamId string, dryRun bool) (*model.FileInfo, *model.AppError) {
+ fileUploadError := model.NewAppError("BulkImport", "app.import.attachment.file_upload.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest)
+ file, err := os.Open(*data.Path)
+ if err != nil {
+ return nil, model.NewAppError("BulkImport", "app.import.attachment.bad_file.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest)
+ }
+ if file != nil {
+ timestamp := utils.TimeFromMillis(post.CreateAt)
+ buf := bytes.NewBuffer(nil)
+ io.Copy(buf, file)
+
+ fileInfo, err := a.DoUploadFile(timestamp, teamId, post.ChannelId, post.UserId, file.Name(), buf.Bytes())
+
+ if err != nil {
+ fmt.Print(err)
+ return nil, fileUploadError
+ }
+
+ mlog.Info(fmt.Sprintf("uploading file with name %s", file.Name()))
+ return fileInfo, nil
+ }
+ return nil, fileUploadError
+}
+
+func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError {
+ if err := validatePostImportData(data, a.MaxPostSize()); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var team *model.Team
+ if result := <-a.Srv.Store.Team().GetByName(*data.Team); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ var channel *model.Channel
+ if result := <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ channel = result.Data.(*model.Channel)
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ // Check if this post already exists.
+ var posts []*model.Post
+ if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
+ return result.Err
+ } else {
+ posts = result.Data.([]*model.Post)
+ }
+
+ var post *model.Post
+ for _, p := range posts {
+ if p.Message == *data.Message {
+ post = p
+ break
+ }
+ }
+
+ if post == nil {
+ post = &model.Post{}
+ }
+
+ post.ChannelId = channel.Id
+ post.Message = *data.Message
+ post.UserId = user.Id
+ post.CreateAt = *data.CreateAt
+
+ post.Hashtags, _ = model.ParseHashtags(post.Message)
+
+ if data.Attachments != nil {
+ fileIds, err := a.uploadAttachments(data.Attachments, post, team.Id, dryRun)
+ if err != nil {
+ return err
+ }
+ post.FileIds = fileIds
+ }
+
+ if post.Id == "" {
+ if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
+ return result.Err
+ }
+ } else {
+ if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ if data.FlaggedBy != nil {
+ var preferences model.Preferences
+
+ for _, username := range *data.FlaggedBy {
+ var user *model.User
+
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, result.Err.Error(), http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ preferences = append(preferences, model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
+ Name: post.Id,
+ Value: "true",
+ })
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+ }
+
+ if data.Reactions != nil {
+ for _, reaction := range *data.Reactions {
+ if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ if data.Replies != nil {
+ for _, reply := range *data.Replies {
+ if err := a.ImportReply(&reply, post, team.Id, dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ a.UpdateFileInfoWithPostId(post)
+ return nil
+}
+
+func (a *App) uploadAttachments(attachments *[]AttachmentImportData, post *model.Post, teamId string, dryRun bool) ([]string, *model.AppError) {
+ fileIds := []string{}
+ for _, attachment := range *attachments {
+ fileInfo, err := a.ImportAttachment(&attachment, post, teamId, dryRun)
+ if err != nil {
+ return nil, err
+ }
+ fileIds = append(fileIds, fileInfo.Id)
+ }
+ return fileIds, nil
+}
+
+func (a *App) UpdateFileInfoWithPostId(post *model.Post) {
+ for _, fileId := range post.FileIds {
+ if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
+ mlog.Error(fmt.Sprintf("Error attaching files to post. postId=%v, fileIds=%v, message=%v", post.Id, post.FileIds, result.Err), mlog.String("post_id", post.Id))
+ }
+ }
+}
+func (a *App) ImportDirectChannel(data *DirectChannelImportData, dryRun bool) *model.AppError {
+ if err := validateDirectChannelImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var userIds []string
+ userMap := make(map[string]string)
+ for _, username := range *data.Members {
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
+ user := result.Data.(*model.User)
+ userIds = append(userIds, user.Id)
+ userMap[username] = user.Id
+ } else {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest)
+ }
+ }
+
+ var channel *model.Channel
+
+ if len(userIds) == 2 {
+ ch, err := a.createDirectChannel(userIds[0], userIds[1])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ } else {
+ ch, err := a.createGroupChannel(userIds, userIds[0])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_group_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ }
+
+ var preferences model.Preferences
+
+ for _, userId := range userIds {
+ preferences = append(preferences, model.Preference{
+ UserId: userId,
+ Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
+ Name: channel.Id,
+ Value: "true",
+ })
+ }
+
+ if data.FavoritedBy != nil {
+ for _, favoriter := range *data.FavoritedBy {
+ preferences = append(preferences, model.Preference{
+ UserId: userMap[favoriter],
+ Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL,
+ Name: channel.Id,
+ Value: "true",
+ })
+ }
+ }
+
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ result.Err.StatusCode = http.StatusBadRequest
+ return result.Err
+ }
+
+ if data.Header != nil {
+ channel.Header = *data.Header
+ if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_channel.update_header_failed.error", nil, result.Err.Error(), http.StatusBadRequest)
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportDirectPost(data *DirectPostImportData, dryRun bool) *model.AppError {
+ if err := validateDirectPostImportData(data, a.MaxPostSize()); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var userIds []string
+ for _, username := range *data.ChannelMembers {
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err == nil {
+ user := result.Data.(*model.User)
+ userIds = append(userIds, user.Id)
+ } else {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest)
+ }
+ }
+
+ var channel *model.Channel
+ if len(userIds) == 2 {
+ ch, err := a.createDirectChannel(userIds[0], userIds[1])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ } else {
+ ch, err := a.createGroupChannel(userIds, userIds[0])
+ if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ channel = ch
+ }
+ }
+
+ var user *model.User
+ if result := <-a.Srv.Store.User().GetByUsername(*data.User); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ // Check if this post already exists.
+ var posts []*model.Post
+ if result := <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt); result.Err != nil {
+ return result.Err
+ } else {
+ posts = result.Data.([]*model.Post)
+ }
+
+ var post *model.Post
+ for _, p := range posts {
+ if p.Message == *data.Message {
+ post = p
+ break
+ }
+ }
+
+ if post == nil {
+ post = &model.Post{}
+ }
+
+ post.ChannelId = channel.Id
+ post.Message = *data.Message
+ post.UserId = user.Id
+ post.CreateAt = *data.CreateAt
+
+ post.Hashtags, _ = model.ParseHashtags(post.Message)
+
+ if post.Id == "" {
+ if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
+ return result.Err
+ }
+ } else {
+ if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ if data.FlaggedBy != nil {
+ var preferences model.Preferences
+
+ for _, username := range *data.FlaggedBy {
+ var user *model.User
+
+ if result := <-a.Srv.Store.User().GetByUsername(username); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ preferences = append(preferences, model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
+ Name: post.Id,
+ Value: "true",
+ })
+ }
+
+ if len(preferences) > 0 {
+ if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError)
+ }
+ }
+ }
+
+ if data.Reactions != nil {
+ for _, reaction := range *data.Reactions {
+ if err := a.ImportReaction(&reaction, post, dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ if data.Replies != nil {
+ for _, reply := range *data.Replies {
+ if err := a.ImportReply(&reply, post, "noteam", dryRun); err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+func (a *App) ImportEmoji(data *EmojiImportData, dryRun bool) *model.AppError {
+ if err := validateEmojiImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var emoji *model.Emoji
+
+ if result := <-a.Srv.Store.Emoji().GetByName(*data.Name); result.Err != nil && result.Err.StatusCode != http.StatusNotFound {
+ return result.Err
+ } else if result.Data != nil {
+ emoji = result.Data.(*model.Emoji)
+ }
+
+ alreadyExists := emoji != nil
+
+ if !alreadyExists {
+ emoji = &model.Emoji{
+ Name: *data.Name,
+ }
+ emoji.PreSave()
+ }
+
+ file, err := os.Open(*data.Image)
+ if err != nil {
+ return model.NewAppError("BulkImport", "app.import.emoji.bad_file.error", map[string]interface{}{"EmojiName": *data.Name}, "", http.StatusBadRequest)
+ }
+
+ if _, err := a.WriteFile(file, getEmojiImagePath(emoji.Id)); err != nil {
+ return err
+ }
+
+ if !alreadyExists {
+ if result := <-a.Srv.Store.Emoji().Save(emoji); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ return nil
+}
diff --git a/app/import_functions_test.go b/app/import_functions_test.go
new file mode 100644
index 000000000..e0859af45
--- /dev/null
+++ b/app/import_functions_test.go
@@ -0,0 +1,2501 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/store"
+ "github.com/mattermost/mattermost-server/utils"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestImportImportScheme(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ // Mark the phase 2 permissions migration as completed.
+ <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
+
+ defer func() {
+ <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
+ }()
+
+ // Try importing an invalid scheme in dryRun mode.
+ data := SchemeImportData{
+ Name: ptrStr(model.NewId()),
+ Scope: ptrStr("team"),
+ DefaultTeamUserRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ DefaultTeamAdminRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ DefaultChannelUserRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ DefaultChannelAdminRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ Description: ptrStr("description"),
+ }
+
+ if err := th.App.ImportScheme(&data, true); err == nil {
+ t.Fatalf("Should have failed to import.")
+ }
+
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil {
+ t.Fatalf("Scheme should not have imported.")
+ }
+
+ // Try importing a valid scheme in dryRun mode.
+ data.DisplayName = ptrStr("display name")
+
+ if err := th.App.ImportScheme(&data, true); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil {
+ t.Fatalf("Scheme should not have imported.")
+ }
+
+ // Try importing an invalid scheme.
+ data.DisplayName = nil
+
+ if err := th.App.ImportScheme(&data, false); err == nil {
+ t.Fatalf("Should have failed to import.")
+ }
+
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil {
+ t.Fatalf("Scheme should not have imported.")
+ }
+
+ // Try importing a valid scheme with all params set.
+ data.DisplayName = ptrStr("display name")
+
+ if err := th.App.ImportScheme(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil {
+ t.Fatalf("Failed to import scheme: %v", res.Err)
+ } else {
+ scheme := res.Data.(*model.Scheme)
+ assert.Equal(t, *data.Name, scheme.Name)
+ assert.Equal(t, *data.DisplayName, scheme.DisplayName)
+ assert.Equal(t, *data.Description, scheme.Description)
+ assert.Equal(t, *data.Scope, scheme.Scope)
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamAdminRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamUserRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelUserRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+ }
+
+ // Try modifying all the fields and re-importing.
+ data.DisplayName = ptrStr("new display name")
+ data.Description = ptrStr("new description")
+
+ if err := th.App.ImportScheme(&data, false); err != nil {
+ t.Fatalf("Should have succeeded: %v", err)
+ }
+
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil {
+ t.Fatalf("Failed to import scheme: %v", res.Err)
+ } else {
+ scheme := res.Data.(*model.Scheme)
+ assert.Equal(t, *data.Name, scheme.Name)
+ assert.Equal(t, *data.DisplayName, scheme.DisplayName)
+ assert.Equal(t, *data.Description, scheme.Description)
+ assert.Equal(t, *data.Scope, scheme.Scope)
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamAdminRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamUserRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelUserRole); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+ }
+
+ // Try changing the scope of the scheme and reimporting.
+ data.Scope = ptrStr("channel")
+
+ if err := th.App.ImportScheme(&data, false); err == nil {
+ t.Fatalf("Should have failed to import.")
+ }
+
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil {
+ t.Fatalf("Failed to import scheme: %v", res.Err)
+ } else {
+ scheme := res.Data.(*model.Scheme)
+ assert.Equal(t, *data.Name, scheme.Name)
+ assert.Equal(t, *data.DisplayName, scheme.DisplayName)
+ assert.Equal(t, *data.Description, scheme.Description)
+ assert.Equal(t, "team", scheme.Scope)
+ }
+}
+
+func TestImportImportRole(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ // Try importing an invalid role in dryRun mode.
+ rid1 := model.NewId()
+ data := RoleImportData{
+ Name: &rid1,
+ }
+
+ if err := th.App.ImportRole(&data, true, false); err == nil {
+ t.Fatalf("Should have failed to import.")
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err == nil {
+ t.Fatalf("Role should not have imported.")
+ }
+
+ // Try importing the valid role in dryRun mode.
+ data.DisplayName = ptrStr("display name")
+
+ if err := th.App.ImportRole(&data, true, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err == nil {
+ t.Fatalf("Role should not have imported as we are in dry run mode.")
+ }
+
+ // Try importing an invalid role.
+ data.DisplayName = nil
+
+ if err := th.App.ImportRole(&data, false, false); err == nil {
+ t.Fatalf("Should have failed to import.")
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err == nil {
+ t.Fatalf("Role should not have imported.")
+ }
+
+ // Try importing a valid role with all params set.
+ data.DisplayName = ptrStr("display name")
+ data.Description = ptrStr("description")
+ data.Permissions = &[]string{"invite_user", "add_user_to_team"}
+
+ if err := th.App.ImportRole(&data, false, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.Name, role.Name)
+ assert.Equal(t, *data.DisplayName, role.DisplayName)
+ assert.Equal(t, *data.Description, role.Description)
+ assert.Equal(t, *data.Permissions, role.Permissions)
+ assert.False(t, role.BuiltIn)
+ assert.False(t, role.SchemeManaged)
+ }
+
+ // Try changing all the params and reimporting.
+ data.DisplayName = ptrStr("new display name")
+ data.Description = ptrStr("description")
+ data.Permissions = &[]string{"use_slash_commands"}
+
+ if err := th.App.ImportRole(&data, false, true); err != nil {
+ t.Fatalf("Should have succeeded. %v", err)
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data.Name, role.Name)
+ assert.Equal(t, *data.DisplayName, role.DisplayName)
+ assert.Equal(t, *data.Description, role.Description)
+ assert.Equal(t, *data.Permissions, role.Permissions)
+ assert.False(t, role.BuiltIn)
+ assert.True(t, role.SchemeManaged)
+ }
+
+ // Check that re-importing with only required fields doesn't update the others.
+ data2 := RoleImportData{
+ Name: &rid1,
+ DisplayName: ptrStr("new display name again"),
+ }
+
+ if err := th.App.ImportRole(&data2, false, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err != nil {
+ t.Fatalf("Should have found the imported role.")
+ } else {
+ role := res.Data.(*model.Role)
+ assert.Equal(t, *data2.Name, role.Name)
+ assert.Equal(t, *data2.DisplayName, role.DisplayName)
+ assert.Equal(t, *data.Description, role.Description)
+ assert.Equal(t, *data.Permissions, role.Permissions)
+ assert.False(t, role.BuiltIn)
+ assert.False(t, role.SchemeManaged)
+ }
+}
+
+func TestImportImportTeam(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ // Mark the phase 2 permissions migration as completed.
+ <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
+
+ defer func() {
+ <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
+ }()
+
+ scheme1 := th.SetupTeamScheme()
+ scheme2 := th.SetupTeamScheme()
+
+ // Check how many teams are in the database.
+ var teamsCount int64
+ if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
+ teamsCount = r.Data.(int64)
+ } else {
+ t.Fatalf("Failed to get team count.")
+ }
+
+ data := TeamImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("XYZ"),
+ Description: ptrStr("The team description."),
+ AllowOpenInvite: ptrBool(true),
+ Scheme: &scheme1.Name,
+ }
+
+ // Try importing an invalid team in dryRun mode.
+ if err := th.App.ImportTeam(&data, true); err == nil {
+ t.Fatalf("Should have received an error importing an invalid team.")
+ }
+
+ // Do a valid team in dry-run mode.
+ data.Type = ptrStr("O")
+ if err := th.App.ImportTeam(&data, true); err != nil {
+ t.Fatalf("Received an error validating valid team.")
+ }
+
+ // Check that no more teams are in the DB.
+ th.CheckTeamCount(t, teamsCount)
+
+ // Do an invalid team in apply mode, check db changes.
+ data.Type = ptrStr("XYZ")
+ if err := th.App.ImportTeam(&data, false); err == nil {
+ t.Fatalf("Import should have failed on invalid team.")
+ }
+
+ // Check that no more teams are in the DB.
+ th.CheckTeamCount(t, teamsCount)
+
+ // Do a valid team in apply mode, check db changes.
+ data.Type = ptrStr("O")
+ if err := th.App.ImportTeam(&data, false); err != nil {
+ t.Fatalf("Received an error importing valid team: %v", err)
+ }
+
+ // Check that one more team is in the DB.
+ th.CheckTeamCount(t, teamsCount+1)
+
+ // Get the team and check that all the fields are correct.
+ if team, err := th.App.GetTeamByName(*data.Name); err != nil {
+ t.Fatalf("Failed to get team from database.")
+ } else {
+ assert.Equal(t, *data.DisplayName, team.DisplayName)
+ assert.Equal(t, *data.Type, team.Type)
+ assert.Equal(t, *data.Description, team.Description)
+ assert.Equal(t, *data.AllowOpenInvite, team.AllowOpenInvite)
+ assert.Equal(t, scheme1.Id, *team.SchemeId)
+ }
+
+ // Alter all the fields of that team (apart from unique identifier) and import again.
+ data.DisplayName = ptrStr("Display Name 2")
+ data.Type = ptrStr("P")
+ data.Description = ptrStr("The new description")
+ data.AllowOpenInvite = ptrBool(false)
+ data.Scheme = &scheme2.Name
+
+ // Check that the original number of teams are again in the DB (because this query doesn't include deleted).
+ data.Type = ptrStr("O")
+ if err := th.App.ImportTeam(&data, false); err != nil {
+ t.Fatalf("Received an error importing updated valid team.")
+ }
+
+ th.CheckTeamCount(t, teamsCount+1)
+
+ // Get the team and check that all fields are correct.
+ if team, err := th.App.GetTeamByName(*data.Name); err != nil {
+ t.Fatalf("Failed to get team from database.")
+ } else {
+ assert.Equal(t, *data.DisplayName, team.DisplayName)
+ assert.Equal(t, *data.Type, team.Type)
+ assert.Equal(t, *data.Description, team.Description)
+ assert.Equal(t, *data.AllowOpenInvite, team.AllowOpenInvite)
+ assert.Equal(t, scheme2.Id, *team.SchemeId)
+ }
+}
+
+func TestImportImportChannel(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ // Mark the phase 2 permissions migration as completed.
+ <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
+
+ defer func() {
+ <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
+ }()
+
+ scheme1 := th.SetupChannelScheme()
+ scheme2 := th.SetupChannelScheme()
+
+ // Import a Team.
+ teamName := model.NewId()
+ th.App.ImportTeam(&TeamImportData{
+ Name: &teamName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ team, err := th.App.GetTeamByName(teamName)
+ if err != nil {
+ t.Fatalf("Failed to get team from database.")
+ }
+
+ // Check how many channels are in the database.
+ var channelCount int64
+ if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
+ channelCount = r.Data.(int64)
+ } else {
+ t.Fatalf("Failed to get team count.")
+ }
+
+ // Do an invalid channel in dry-run mode.
+ data := ChannelImportData{
+ Team: &teamName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ Header: ptrStr("Channe Header"),
+ Purpose: ptrStr("Channel Purpose"),
+ Scheme: &scheme1.Name,
+ }
+ if err := th.App.ImportChannel(&data, true); err == nil {
+ t.Fatalf("Expected error due to invalid name.")
+ }
+
+ // Check that no more channels are in the DB.
+ th.CheckChannelsCount(t, channelCount)
+
+ // Do a valid channel with a nonexistent team in dry-run mode.
+ data.Name = ptrStr("channelname")
+ data.Team = ptrStr(model.NewId())
+ if err := th.App.ImportChannel(&data, true); err != nil {
+ t.Fatalf("Expected success as cannot validate channel name in dry run mode.")
+ }
+
+ // Check that no more channels are in the DB.
+ th.CheckChannelsCount(t, channelCount)
+
+ // Do a valid channel in dry-run mode.
+ data.Team = &teamName
+ if err := th.App.ImportChannel(&data, true); err != nil {
+ t.Fatalf("Expected success as valid team.")
+ }
+
+ // Check that no more channels are in the DB.
+ th.CheckChannelsCount(t, channelCount)
+
+ // Do an invalid channel in apply mode.
+ data.Name = nil
+ if err := th.App.ImportChannel(&data, false); err == nil {
+ t.Fatalf("Expected error due to invalid name (apply mode).")
+ }
+
+ // Check that no more channels are in the DB.
+ th.CheckChannelsCount(t, channelCount)
+
+ // Do a valid channel in apply mode with a non-existent team.
+ data.Name = ptrStr("channelname")
+ data.Team = ptrStr(model.NewId())
+ if err := th.App.ImportChannel(&data, false); err == nil {
+ t.Fatalf("Expected error due to non-existent team (apply mode).")
+ }
+
+ // Check that no more channels are in the DB.
+ th.CheckChannelsCount(t, channelCount)
+
+ // Do a valid channel in apply mode.
+ data.Team = &teamName
+ if err := th.App.ImportChannel(&data, false); err != nil {
+ t.Fatalf("Expected success in apply mode: %v", err.Error())
+ }
+
+ // Check that 1 more channel is in the DB.
+ th.CheckChannelsCount(t, channelCount+1)
+
+ // Get the Channel and check all the fields are correct.
+ if channel, err := th.App.GetChannelByName(*data.Name, team.Id, false); err != nil {
+ t.Fatalf("Failed to get channel from database.")
+ } else {
+ assert.Equal(t, *data.Name, channel.Name)
+ assert.Equal(t, *data.DisplayName, channel.DisplayName)
+ assert.Equal(t, *data.Type, channel.Type)
+ assert.Equal(t, *data.Header, channel.Header)
+ assert.Equal(t, *data.Purpose, channel.Purpose)
+ assert.Equal(t, scheme1.Id, *channel.SchemeId)
+ }
+
+ // Alter all the fields of that channel.
+ data.DisplayName = ptrStr("Chaned Disp Name")
+ data.Type = ptrStr(model.CHANNEL_PRIVATE)
+ data.Header = ptrStr("New Header")
+ data.Purpose = ptrStr("New Purpose")
+ data.Scheme = &scheme2.Name
+ if err := th.App.ImportChannel(&data, false); err != nil {
+ t.Fatalf("Expected success in apply mode: %v", err.Error())
+ }
+
+ // Check channel count the same.
+ th.CheckChannelsCount(t, channelCount)
+
+ // Get the Channel and check all the fields are correct.
+ if channel, err := th.App.GetChannelByName(*data.Name, team.Id, false); err != nil {
+ t.Fatalf("Failed to get channel from database.")
+ } else {
+ assert.Equal(t, *data.Name, channel.Name)
+ assert.Equal(t, *data.DisplayName, channel.DisplayName)
+ assert.Equal(t, *data.Type, channel.Type)
+ assert.Equal(t, *data.Header, channel.Header)
+ assert.Equal(t, *data.Purpose, channel.Purpose)
+ assert.Equal(t, scheme2.Id, *channel.SchemeId)
+ }
+
+}
+
+func TestImportImportUser(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ // Check how many users are in the database.
+ var userCount int64
+ if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
+ userCount = r.Data.(int64)
+ } else {
+ t.Fatalf("Failed to get user count.")
+ }
+
+ // Do an invalid user in dry-run mode.
+ data := UserImportData{
+ Username: ptrStr(model.NewId()),
+ }
+ if err := th.App.ImportUser(&data, true); err == nil {
+ t.Fatalf("Should have failed to import invalid user.")
+ }
+
+ // Check that no more users are in the DB.
+ if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
+ if r.Data.(int64) != userCount {
+ t.Fatalf("Unexpected number of users")
+ }
+ } else {
+ t.Fatalf("Failed to get user count.")
+ }
+
+ // Do a valid user in dry-run mode.
+ data = UserImportData{
+ Username: ptrStr(model.NewId()),
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }
+ if err := th.App.ImportUser(&data, true); err != nil {
+ t.Fatalf("Should have succeeded to import valid user.")
+ }
+
+ // Check that no more users are in the DB.
+ if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
+ if r.Data.(int64) != userCount {
+ t.Fatalf("Unexpected number of users")
+ }
+ } else {
+ t.Fatalf("Failed to get user count.")
+ }
+
+ // Do an invalid user in apply mode.
+ data = UserImportData{
+ Username: ptrStr(model.NewId()),
+ }
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed to import invalid user.")
+ }
+
+ // Check that no more users are in the DB.
+ if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
+ if r.Data.(int64) != userCount {
+ t.Fatalf("Unexpected number of users")
+ }
+ } else {
+ t.Fatalf("Failed to get user count.")
+ }
+
+ // Do a valid user in apply mode.
+ username := model.NewId()
+ testsDir, _ := utils.FindDir("tests")
+ data = UserImportData{
+ ProfileImage: ptrStr(filepath.Join(testsDir, "test.png")),
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ Nickname: ptrStr(model.NewId()),
+ FirstName: ptrStr(model.NewId()),
+ LastName: ptrStr(model.NewId()),
+ Position: ptrStr(model.NewId()),
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded to import valid user.")
+ }
+
+ // Check that one more user is in the DB.
+ if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
+ if r.Data.(int64) != userCount+1 {
+ t.Fatalf("Unexpected number of users")
+ }
+ } else {
+ t.Fatalf("Failed to get user count.")
+ }
+
+ // Get the user and check all the fields are correct.
+ if user, err := th.App.GetUserByUsername(username); err != nil {
+ t.Fatalf("Failed to get user from database.")
+ } else {
+ if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
+ t.Fatalf("User properties do not match Import Data.")
+ }
+ // Check calculated properties.
+ if user.AuthService != "" {
+ t.Fatalf("Expected Auth Service to be empty.")
+ }
+
+ if !(user.AuthData == nil || *user.AuthData == "") {
+ t.Fatalf("Expected AuthData to be empty.")
+ }
+
+ if len(user.Password) == 0 {
+ t.Fatalf("Expected password to be set.")
+ }
+
+ if !user.EmailVerified {
+ t.Fatalf("Expected EmailVerified to be true.")
+ }
+
+ if user.Locale != *th.App.Config().LocalizationSettings.DefaultClientLocale {
+ t.Fatalf("Expected Locale to be the default.")
+ }
+
+ if user.Roles != "system_user" {
+ t.Fatalf("Expected roles to be system_user")
+ }
+ }
+
+ // Alter all the fields of that user.
+ data.Email = ptrStr(model.NewId() + "@example.com")
+ data.ProfileImage = ptrStr(filepath.Join(testsDir, "testgif.gif"))
+ data.AuthService = ptrStr("ldap")
+ data.AuthData = &username
+ data.Nickname = ptrStr(model.NewId())
+ data.FirstName = ptrStr(model.NewId())
+ data.LastName = ptrStr(model.NewId())
+ data.Position = ptrStr(model.NewId())
+ data.Roles = ptrStr("system_admin system_user")
+ data.Locale = ptrStr("zh_CN")
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded to update valid user %v", err)
+ }
+
+ // Check user count the same.
+ if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
+ if r.Data.(int64) != userCount+1 {
+ t.Fatalf("Unexpected number of users")
+ }
+ } else {
+ t.Fatalf("Failed to get user count.")
+ }
+
+ // Get the user and check all the fields are correct.
+ if user, err := th.App.GetUserByUsername(username); err != nil {
+ t.Fatalf("Failed to get user from database.")
+ } else {
+ if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
+ t.Fatalf("Updated User properties do not match Import Data.")
+ }
+ // Check calculated properties.
+ if user.AuthService != "ldap" {
+ t.Fatalf("Expected Auth Service to be ldap \"%v\"", user.AuthService)
+ }
+
+ if !(user.AuthData == data.AuthData || *user.AuthData == *data.AuthData) {
+ t.Fatalf("Expected AuthData to be set.")
+ }
+
+ if len(user.Password) != 0 {
+ t.Fatalf("Expected password to be empty.")
+ }
+
+ if !user.EmailVerified {
+ t.Fatalf("Expected EmailVerified to be true.")
+ }
+
+ if user.Locale != *data.Locale {
+ t.Fatalf("Expected Locale to be the set.")
+ }
+
+ if user.Roles != *data.Roles {
+ t.Fatalf("Expected roles to be set: %v", user.Roles)
+ }
+ }
+
+ // Check Password and AuthData together.
+ data.Password = ptrStr("PasswordTest")
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed to import invalid user.")
+ }
+
+ data.AuthData = nil
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded to update valid user %v", err)
+ }
+
+ data.Password = ptrStr("")
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed to import invalid user.")
+ }
+
+ data.Password = ptrStr(strings.Repeat("0123456789", 10))
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed to import invalid user.")
+ }
+
+ data.Password = ptrStr("TestPassword")
+
+ // Test team and channel memberships
+ teamName := model.NewId()
+ th.App.ImportTeam(&TeamImportData{
+ Name: &teamName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ team, err := th.App.GetTeamByName(teamName)
+ if err != nil {
+ t.Fatalf("Failed to get team from database.")
+ }
+
+ channelName := model.NewId()
+ th.App.ImportChannel(&ChannelImportData{
+ Team: &teamName,
+ Name: &channelName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ channel, err := th.App.GetChannelByName(channelName, team.Id, false)
+ if err != nil {
+ t.Fatalf("Failed to get channel from database.")
+ }
+
+ username = model.NewId()
+ data = UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ Nickname: ptrStr(model.NewId()),
+ FirstName: ptrStr(model.NewId()),
+ LastName: ptrStr(model.NewId()),
+ Position: ptrStr(model.NewId()),
+ }
+
+ teamMembers, err := th.App.GetTeamMembers(team.Id, 0, 1000)
+ if err != nil {
+ t.Fatalf("Failed to get team member count")
+ }
+ teamMemberCount := len(teamMembers)
+
+ channelMemberCount, err := th.App.GetChannelMemberCount(channel.Id)
+ if err != nil {
+ t.Fatalf("Failed to get channel member count")
+ }
+
+ // Test with an invalid team & channel membership in dry-run mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Roles: ptrStr("invalid"),
+ Channels: &[]UserChannelImportData{
+ {
+ Roles: ptrStr("invalid"),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, true); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Test with an unknown team name & invalid channel membership in dry-run mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: ptrStr(model.NewId()),
+ Channels: &[]UserChannelImportData{
+ {
+ Roles: ptrStr("invalid"),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, true); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Test with a valid team & invalid channel membership in dry-run mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Channels: &[]UserChannelImportData{
+ {
+ Roles: ptrStr("invalid"),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, true); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Test with a valid team & unknown channel name in dry-run mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Channels: &[]UserChannelImportData{
+ {
+ Name: ptrStr(model.NewId()),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, true); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ // Test with a valid team & valid channel name in dry-run mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Channels: &[]UserChannelImportData{
+ {
+ Name: &channelName,
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, true); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ // Check no new member objects were created because dry run mode.
+ if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
+ t.Fatalf("Failed to get Team Member Count")
+ } else if len(tmc) != teamMemberCount {
+ t.Fatalf("Number of team members not as expected")
+ }
+
+ if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
+ t.Fatalf("Failed to get Channel Member Count")
+ } else if cmc != channelMemberCount {
+ t.Fatalf("Number of channel members not as expected")
+ }
+
+ // Test with an invalid team & channel membership in apply mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Roles: ptrStr("invalid"),
+ Channels: &[]UserChannelImportData{
+ {
+ Roles: ptrStr("invalid"),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Test with an unknown team name & invalid channel membership in apply mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: ptrStr(model.NewId()),
+ Channels: &[]UserChannelImportData{
+ {
+ Roles: ptrStr("invalid"),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Test with a valid team & invalid channel membership in apply mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Channels: &[]UserChannelImportData{
+ {
+ Roles: ptrStr("invalid"),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Check no new member objects were created because all tests should have failed so far.
+ if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
+ t.Fatalf("Failed to get Team Member Count")
+ } else if len(tmc) != teamMemberCount {
+ t.Fatalf("Number of team members not as expected")
+ }
+
+ if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
+ t.Fatalf("Failed to get Channel Member Count")
+ } else if cmc != channelMemberCount {
+ t.Fatalf("Number of channel members not as expected")
+ }
+
+ // Test with a valid team & unknown channel name in apply mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Channels: &[]UserChannelImportData{
+ {
+ Name: ptrStr(model.NewId()),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, false); err == nil {
+ t.Fatalf("Should have failed.")
+ }
+
+ // Check only new team member object created because dry run mode.
+ if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
+ t.Fatalf("Failed to get Team Member Count")
+ } else if len(tmc) != teamMemberCount+1 {
+ t.Fatalf("Number of team members not as expected")
+ }
+
+ if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
+ t.Fatalf("Failed to get Channel Member Count")
+ } else if cmc != channelMemberCount {
+ t.Fatalf("Number of channel members not as expected")
+ }
+
+ // Check team member properties.
+ user, err := th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+ if teamMember, err := th.App.GetTeamMember(team.Id, user.Id); err != nil {
+ t.Fatalf("Failed to get team member from database.")
+ } else if teamMember.Roles != "team_user" {
+ t.Fatalf("Team member properties not as expected")
+ }
+
+ // Test with a valid team & valid channel name in apply mode.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Channels: &[]UserChannelImportData{
+ {
+ Name: &channelName,
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ // Check only new channel member object created because dry run mode.
+ if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
+ t.Fatalf("Failed to get Team Member Count")
+ } else if len(tmc) != teamMemberCount+1 {
+ t.Fatalf("Number of team members not as expected")
+ }
+
+ if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
+ t.Fatalf("Failed to get Channel Member Count")
+ } else if cmc != channelMemberCount+1 {
+ t.Fatalf("Number of channel members not as expected")
+ }
+
+ // Check channel member properties.
+ if channelMember, err := th.App.GetChannelMember(channel.Id, user.Id); err != nil {
+ t.Fatalf("Failed to get channel member from database.")
+ } else if channelMember.Roles != "channel_user" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != "all" {
+ t.Fatalf("Channel member properties not as expected")
+ }
+
+ // Test with the properties of the team and channel membership changed.
+ data.Teams = &[]UserTeamImportData{
+ {
+ Name: &teamName,
+ Roles: ptrStr("team_user team_admin"),
+ Channels: &[]UserChannelImportData{
+ {
+ Name: &channelName,
+ Roles: ptrStr("channel_user channel_admin"),
+ NotifyProps: &UserChannelNotifyPropsImportData{
+ Desktop: ptrStr(model.USER_NOTIFY_MENTION),
+ Mobile: ptrStr(model.USER_NOTIFY_MENTION),
+ MarkUnread: ptrStr(model.USER_NOTIFY_MENTION),
+ },
+ Favorite: ptrBool(true),
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ // Check both member properties.
+ if teamMember, err := th.App.GetTeamMember(team.Id, user.Id); err != nil {
+ t.Fatalf("Failed to get team member from database.")
+ } else if teamMember.Roles != "team_user team_admin" {
+ t.Fatalf("Team member properties not as expected: %v", teamMember.Roles)
+ }
+
+ if channelMember, err := th.App.GetChannelMember(channel.Id, user.Id); err != nil {
+ t.Fatalf("Failed to get channel member Desktop from database.")
+ } else if channelMember.Roles != "channel_user channel_admin" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.USER_NOTIFY_MENTION {
+ t.Fatalf("Channel member properties not as expected")
+ }
+
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
+
+ // No more new member objects.
+ if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
+ t.Fatalf("Failed to get Team Member Count")
+ } else if len(tmc) != teamMemberCount+1 {
+ t.Fatalf("Number of team members not as expected")
+ }
+
+ if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
+ t.Fatalf("Failed to get Channel Member Count")
+ } else if cmc != channelMemberCount+1 {
+ t.Fatalf("Number of channel members not as expected")
+ }
+
+ // Add a user with some preferences.
+ username = model.NewId()
+ data = UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ Theme: ptrStr(`{"awayIndicator":"#DCBD4E","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
+ UseMilitaryTime: ptrStr("true"),
+ CollapsePreviews: ptrStr("true"),
+ MessageDisplay: ptrStr("compact"),
+ ChannelDisplayMode: ptrStr("centered"),
+ TutorialStep: ptrStr("3"),
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ // Check their values.
+ user, err = th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, "", *data.Theme)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "use_military_time", *data.UseMilitaryTime)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "collapse_previews", *data.CollapsePreviews)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
+
+ // Change those preferences.
+ data = UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ Theme: ptrStr(`{"awayIndicator":"#123456","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
+ UseMilitaryTime: ptrStr("false"),
+ CollapsePreviews: ptrStr("false"),
+ MessageDisplay: ptrStr("clean"),
+ ChannelDisplayMode: ptrStr("full"),
+ TutorialStep: ptrStr("2"),
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ // Check their values again.
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, "", *data.Theme)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "use_military_time", *data.UseMilitaryTime)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "collapse_previews", *data.CollapsePreviews)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
+
+ // Set Notify Props
+ data.NotifyProps = &UserNotifyPropsImportData{
+ Desktop: ptrStr(model.USER_NOTIFY_ALL),
+ DesktopSound: ptrStr("true"),
+ Email: ptrStr("true"),
+ Mobile: ptrStr(model.USER_NOTIFY_ALL),
+ MobilePushStatus: ptrStr(model.STATUS_ONLINE),
+ ChannelTrigger: ptrStr("true"),
+ CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ROOT),
+ MentionKeys: ptrStr("valid,misc"),
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ user, err = th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_ALL)
+ checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "true")
+ checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "true")
+ checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_ALL)
+ checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_ONLINE)
+ checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "true")
+ checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ROOT)
+ checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "valid,misc")
+
+ // Change Notify Props
+ data.NotifyProps = &UserNotifyPropsImportData{
+ Desktop: ptrStr(model.USER_NOTIFY_MENTION),
+ DesktopSound: ptrStr("false"),
+ Email: ptrStr("false"),
+ Mobile: ptrStr(model.USER_NOTIFY_NONE),
+ MobilePushStatus: ptrStr(model.STATUS_AWAY),
+ ChannelTrigger: ptrStr("false"),
+ CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ANY),
+ MentionKeys: ptrStr("misc"),
+ }
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ user, err = th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
+ checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
+ checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
+ checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
+ checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
+ checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
+ checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
+ checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
+
+ // Check Notify Props get set on *create* user.
+ username = model.NewId()
+ data = UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }
+ data.NotifyProps = &UserNotifyPropsImportData{
+ Desktop: ptrStr(model.USER_NOTIFY_MENTION),
+ DesktopSound: ptrStr("false"),
+ Email: ptrStr("false"),
+ Mobile: ptrStr(model.USER_NOTIFY_NONE),
+ MobilePushStatus: ptrStr(model.STATUS_AWAY),
+ ChannelTrigger: ptrStr("false"),
+ CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ANY),
+ MentionKeys: ptrStr("misc"),
+ }
+
+ if err := th.App.ImportUser(&data, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ user, err = th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
+ checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
+ checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
+ checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
+ checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
+ checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
+ checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
+ checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
+
+ // Test importing a user with roles set to a team and a channel which are affected by an override scheme.
+ // The import subsystem should translate `channel_admin/channel_user/team_admin/team_user`
+ // to the appropriate scheme-managed-role booleans.
+
+ // Mark the phase 2 permissions migration as completed.
+ <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
+
+ defer func() {
+ <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
+ }()
+
+ teamSchemeData := &SchemeImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ Scope: ptrStr("team"),
+ DefaultTeamUserRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ DefaultTeamAdminRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ DefaultChannelUserRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ DefaultChannelAdminRole: &RoleImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr(model.NewId()),
+ },
+ Description: ptrStr("description"),
+ }
+
+ if err := th.App.ImportScheme(teamSchemeData, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ var teamScheme *model.Scheme
+ if res := <-th.App.Srv.Store.Scheme().GetByName(*teamSchemeData.Name); res.Err != nil {
+ t.Fatalf("Failed to import scheme: %v", res.Err)
+ } else {
+ teamScheme = res.Data.(*model.Scheme)
+ }
+
+ teamData := &TeamImportData{
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ Description: ptrStr("The team description."),
+ AllowOpenInvite: ptrBool(true),
+ Scheme: &teamScheme.Name,
+ }
+ if err := th.App.ImportTeam(teamData, false); err != nil {
+ t.Fatalf("Import should have succeeded: %v", err.Error())
+ }
+ team, err = th.App.GetTeamByName(teamName)
+ if err != nil {
+ t.Fatalf("Failed to get team from database.")
+ }
+
+ channelData := &ChannelImportData{
+ Team: &teamName,
+ Name: ptrStr(model.NewId()),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ Header: ptrStr("Channe Header"),
+ Purpose: ptrStr("Channel Purpose"),
+ }
+ if err := th.App.ImportChannel(channelData, false); err != nil {
+ t.Fatalf("Import should have succeeded.")
+ }
+ channel, err = th.App.GetChannelByName(*channelData.Name, team.Id, false)
+ if err != nil {
+ t.Fatalf("Failed to get channel from database: %v", err.Error())
+ }
+
+ // Test with a valid team & valid channel name in apply mode.
+ userData := &UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ Teams: &[]UserTeamImportData{
+ {
+ Name: &team.Name,
+ Roles: ptrStr("team_user team_admin"),
+ Channels: &[]UserChannelImportData{
+ {
+ Name: &channel.Name,
+ Roles: ptrStr("channel_admin channel_user"),
+ },
+ },
+ },
+ },
+ }
+ if err := th.App.ImportUser(userData, false); err != nil {
+ t.Fatalf("Should have succeeded.")
+ }
+
+ user, err = th.App.GetUserByUsername(*userData.Username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ teamMember, err := th.App.GetTeamMember(team.Id, user.Id)
+ if err != nil {
+ t.Fatalf("Failed to get the team member")
+ }
+ assert.True(t, teamMember.SchemeAdmin)
+ assert.True(t, teamMember.SchemeUser)
+ assert.Equal(t, "", teamMember.ExplicitRoles)
+
+ channelMember, err := th.App.GetChannelMember(channel.Id, user.Id)
+ if err != nil {
+ t.Fatalf("Failed to get the channel member")
+ }
+ assert.True(t, channelMember.SchemeAdmin)
+ assert.True(t, channelMember.SchemeUser)
+ assert.Equal(t, "", channelMember.ExplicitRoles)
+
+}
+
+func TestImportImportPost(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ // Create a Team.
+ teamName := model.NewId()
+ th.App.ImportTeam(&TeamImportData{
+ Name: &teamName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ team, err := th.App.GetTeamByName(teamName)
+ if err != nil {
+ t.Fatalf("Failed to get team from database.")
+ }
+
+ // Create a Channel.
+ channelName := model.NewId()
+ th.App.ImportChannel(&ChannelImportData{
+ Team: &teamName,
+ Name: &channelName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ channel, err := th.App.GetChannelByName(channelName, team.Id, false)
+ if err != nil {
+ t.Fatalf("Failed to get channel from database.")
+ }
+
+ // Create a user.
+ username := model.NewId()
+ th.App.ImportUser(&UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }, false)
+ user, err := th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ // Count the number of posts in the testing team.
+ var initialPostCount int64
+ if result := <-th.App.Srv.Store.Post().AnalyticsPostCount(team.Id, false, false); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ initialPostCount = result.Data.(int64)
+ }
+
+ // Try adding an invalid post in dry run mode.
+ data := &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ }
+ if err := th.App.ImportPost(data, true); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
+
+ // Try adding a valid post in dry run mode.
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Hello"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportPost(data, true); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
+
+ // Try adding an invalid post in apply mode.
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportPost(data, false); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
+
+ // Try adding a valid post with invalid team in apply mode.
+ data = &PostImportData{
+ Team: ptrStr(model.NewId()),
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportPost(data, false); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
+
+ // Try adding a valid post with invalid channel in apply mode.
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: ptrStr(model.NewId()),
+ User: &username,
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportPost(data, false); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
+
+ // Try adding a valid post with invalid user in apply mode.
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: ptrStr(model.NewId()),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportPost(data, false); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
+
+ // Try adding a valid post in apply mode.
+ time := model.GetMillis()
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message"),
+ CreateAt: &time,
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, time); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ }
+
+ // Update the post.
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message"),
+ CreateAt: &time,
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, time); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ }
+
+ // Save the post with a different time.
+ newTime := time + 1
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message"),
+ CreateAt: &newTime,
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 2, team.Id)
+
+ // Save the post with a different message.
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message 2"),
+ CreateAt: &time,
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 3, team.Id)
+
+ // Test with hashtags
+ hashtagTime := time + 2
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message 2 #hashtagmashupcity"),
+ CreateAt: &hashtagTime,
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 4, team.Id)
+
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, hashtagTime); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ if post.Hashtags != "#hashtagmashupcity" {
+ t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
+ }
+ }
+
+ // Post with flags.
+ username2 := model.NewId()
+ th.App.ImportUser(&UserImportData{
+ Username: &username2,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }, false)
+ user2, err := th.App.GetUserByUsername(username2)
+ if err != nil {
+ t.Fatalf("Failed to get user from database.")
+ }
+
+ flagsTime := hashtagTime + 1
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message with Favorites"),
+ CreateAt: &flagsTime,
+ FlaggedBy: &[]string{
+ username,
+ username2,
+ },
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 5, team.Id)
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, flagsTime); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
+ t.Fatal("Post properties not as expected")
+ }
+
+ checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
+ checkPreference(t, th.App, user2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
+ }
+
+ // Post with reaction.
+ reactionPostTime := hashtagTime + 2
+ reactionTime := hashtagTime + 3
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message with reaction"),
+ CreateAt: &reactionPostTime,
+ Reactions: &[]ReactionImportData{{
+ User: &user2.Username,
+ EmojiName: ptrStr("+1"),
+ CreateAt: &reactionTime,
+ }},
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 6, team.Id)
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, reactionPostTime); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id || !post.HasReactions {
+ t.Fatal("Post properties not as expected")
+ }
+
+ if result := <-th.App.Srv.Store.Reaction().GetForPost(post.Id, false); result.Err != nil {
+ t.Fatal("Can't get reaction")
+ } else if len(result.Data.([]*model.Reaction)) != 1 {
+ t.Fatal("Invalid number of reactions")
+ }
+ }
+
+ // Post with reply.
+ replyPostTime := hashtagTime + 4
+ replyTime := hashtagTime + 5
+ data = &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message with reply"),
+ CreateAt: &replyPostTime,
+ Replies: &[]ReplyImportData{{
+ User: &user2.Username,
+ Message: ptrStr("Message reply"),
+ CreateAt: &replyTime,
+ }},
+ }
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 8, team.Id)
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, replyPostTime); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
+ t.Fatal("Post properties not as expected")
+ }
+
+ // Check the reply values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, replyTime); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ replies := result.Data.([]*model.Post)
+ if len(replies) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ reply := replies[0]
+ if reply.Message != *(*data.Replies)[0].Message || reply.CreateAt != *(*data.Replies)[0].CreateAt || reply.UserId != user2.Id {
+ t.Fatal("Post properties not as expected")
+ }
+
+ if reply.RootId != post.Id {
+ t.Fatal("Unexpected reply RootId")
+ }
+ }
+ }
+}
+
+func TestImportImportDirectChannel(t *testing.T) {
+ th := Setup().InitBasic()
+ defer th.TearDown()
+
+ // Check how many channels are in the database.
+ var directChannelCount int64
+ if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_DIRECT); r.Err == nil {
+ directChannelCount = r.Data.(int64)
+ } else {
+ t.Fatalf("Failed to get direct channel count.")
+ }
+
+ var groupChannelCount int64
+ if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_GROUP); r.Err == nil {
+ groupChannelCount = r.Data.(int64)
+ } else {
+ t.Fatalf("Failed to get group channel count.")
+ }
+
+ // Do an invalid channel in dry-run mode.
+ data := DirectChannelImportData{
+ Members: &[]string{
+ model.NewId(),
+ },
+ Header: ptrStr("Channel Header"),
+ }
+ if err := th.App.ImportDirectChannel(&data, true); err == nil {
+ t.Fatalf("Expected error due to invalid name.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Do a valid DIRECT channel with a nonexistent member in dry-run mode.
+ data.Members = &[]string{
+ model.NewId(),
+ model.NewId(),
+ }
+ if err := th.App.ImportDirectChannel(&data, true); err != nil {
+ t.Fatalf("Expected success as cannot validate existence of channel members in dry run mode.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Do a valid GROUP channel with a nonexistent member in dry-run mode.
+ data.Members = &[]string{
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ }
+ if err := th.App.ImportDirectChannel(&data, true); err != nil {
+ t.Fatalf("Expected success as cannot validate existence of channel members in dry run mode.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Do an invalid channel in apply mode.
+ data.Members = &[]string{
+ model.NewId(),
+ }
+ if err := th.App.ImportDirectChannel(&data, false); err == nil {
+ t.Fatalf("Expected error due to invalid member (apply mode).")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Do a valid DIRECT channel.
+ data.Members = &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ }
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+
+ // Check that one more DIRECT channel is in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Do the same DIRECT channel again.
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Update the channel's HEADER
+ data.Header = ptrStr("New Channel Header 2")
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Get the channel to check that the header was updated.
+ if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err == nil || err.Id != store.CHANNEL_EXISTS_ERROR {
+ t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
+ } else {
+ if channel.Header != *data.Header {
+ t.Fatal("Channel header has not been updated successfully.")
+ }
+ }
+
+ // Do a GROUP channel with an extra invalid member.
+ user3 := th.CreateUser()
+ data.Members = &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ model.NewId(),
+ }
+ if err := th.App.ImportDirectChannel(&data, false); err == nil {
+ t.Fatalf("Should have failed due to invalid member in list.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
+
+ // Do a valid GROUP channel.
+ data.Members = &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ }
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ // Check that one more GROUP channel is in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
+
+ // Do the same DIRECT channel again.
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
+
+ // Update the channel's HEADER
+ data.Header = ptrStr("New Channel Header 3")
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ // Check that no more channels are in the DB.
+ AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
+ AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
+
+ // Get the channel to check that the header was updated.
+ userIds := []string{
+ th.BasicUser.Id,
+ th.BasicUser2.Id,
+ user3.Id,
+ }
+ if channel, err := th.App.createGroupChannel(userIds, th.BasicUser.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
+ t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
+ } else {
+ if channel.Header != *data.Header {
+ t.Fatal("Channel header has not been updated successfully.")
+ }
+ }
+
+ // Import a channel with some favorites.
+ data.Members = &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ }
+ data.FavoritedBy = &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ }
+ if err := th.App.ImportDirectChannel(&data, false); err != nil {
+ t.Fatal(err)
+ }
+
+ if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err == nil || err.Id != store.CHANNEL_EXISTS_ERROR {
+ t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
+ } else {
+ checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
+ checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
+ }
+}
+
+func TestImportImportDirectPost(t *testing.T) {
+ th := Setup().InitBasic()
+ defer th.TearDown()
+
+ // Create the DIRECT channel.
+ channelData := DirectChannelImportData{
+ Members: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ }
+ if err := th.App.ImportDirectChannel(&channelData, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+
+ // Get the channel.
+ var directChannel *model.Channel
+ if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
+ t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
+ } else {
+ directChannel = channel
+ }
+
+ // Get the number of posts in the system.
+ var initialPostCount int64
+ if result := <-th.App.Srv.Store.Post().AnalyticsPostCount("", false, false); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ initialPostCount = result.Data.(int64)
+ }
+
+ // Try adding an invalid post in dry run mode.
+ data := &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, true); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
+
+ // Try adding a valid post in dry run mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, true); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
+
+ // Try adding an invalid post in apply mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ model.NewId(),
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, false); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
+
+ // Try adding a valid post in apply mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ }
+
+ // Import the post again.
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ }
+
+ // Save the post with a different time.
+ data.CreateAt = ptrInt64(*data.CreateAt + 1)
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
+
+ // Save the post with a different message.
+ data.Message = ptrStr("Message 2")
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
+
+ // Test with hashtags
+ data.Message = ptrStr("Message 2 #hashtagmashupcity")
+ data.CreateAt = ptrInt64(*data.CreateAt + 1)
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
+
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ if post.Hashtags != "#hashtagmashupcity" {
+ t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
+ }
+ }
+
+ // Test with some flags.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ FlaggedBy: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
+ checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
+ }
+
+ // ------------------ Group Channel -------------------------
+
+ // Create the GROUP channel.
+ user3 := th.CreateUser()
+ channelData = DirectChannelImportData{
+ Members: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ },
+ }
+ if err := th.App.ImportDirectChannel(&channelData, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+
+ // Get the channel.
+ var groupChannel *model.Channel
+ userIds := []string{
+ th.BasicUser.Id,
+ th.BasicUser2.Id,
+ user3.Id,
+ }
+ if channel, err := th.App.createGroupChannel(userIds, th.BasicUser.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
+ t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
+ } else {
+ groupChannel = channel
+ }
+
+ // Get the number of posts in the system.
+ if result := <-th.App.Srv.Store.Post().AnalyticsPostCount("", false, false); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ initialPostCount = result.Data.(int64)
+ }
+
+ // Try adding an invalid post in dry run mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, true); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
+
+ // Try adding a valid post in dry run mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, true); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
+
+ // Try adding an invalid post in apply mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ model.NewId(),
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, false); err == nil {
+ t.Fatalf("Expected error.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
+
+ // Try adding a valid post in apply mode.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ }
+
+ // Import the post again.
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ }
+
+ // Save the post with a different time.
+ data.CreateAt = ptrInt64(*data.CreateAt + 1)
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
+
+ // Save the post with a different message.
+ data.Message = ptrStr("Message 2")
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
+
+ // Test with hashtags
+ data.Message = ptrStr("Message 2 #hashtagmashupcity")
+ data.CreateAt = ptrInt64(*data.CreateAt + 1)
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+ AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
+
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
+ t.Fatal("Post properties not as expected")
+ }
+ if post.Hashtags != "#hashtagmashupcity" {
+ t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
+ }
+ }
+
+ // Test with some flags.
+ data = &DirectPostImportData{
+ ChannelMembers: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ user3.Username,
+ },
+ FlaggedBy: &[]string{
+ th.BasicUser.Username,
+ th.BasicUser2.Username,
+ },
+ User: ptrStr(th.BasicUser.Username),
+ Message: ptrStr("Message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+
+ if err := th.App.ImportDirectPost(data, false); err != nil {
+ t.Fatalf("Expected success: %v", err.Error())
+ }
+
+ // Check the post values.
+ if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
+ t.Fatal(result.Err.Error())
+ } else {
+ posts := result.Data.([]*model.Post)
+ if len(posts) != 1 {
+ t.Fatal("Unexpected number of posts found.")
+ }
+ post := posts[0]
+ checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
+ checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
+ }
+}
+
+func TestImportImportEmoji(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
+
+ testsDir, _ := utils.FindDir("tests")
+ testImage := filepath.Join(testsDir, "test.png")
+
+ data := EmojiImportData{Name: ptrStr(model.NewId())}
+ err := th.App.ImportEmoji(&data, true)
+ assert.NotNil(t, err, "Invalid emoji should have failed dry run")
+
+ result := <-th.App.Srv.Store.Emoji().GetByName(*data.Name)
+ assert.Nil(t, result.Data, "Emoji should not have been imported")
+
+ data.Image = ptrStr(testImage)
+ err = th.App.ImportEmoji(&data, true)
+ assert.Nil(t, err, "Valid emoji should have passed dry run")
+
+ data = EmojiImportData{Name: ptrStr(model.NewId())}
+ err = th.App.ImportEmoji(&data, false)
+ assert.NotNil(t, err, "Invalid emoji should have failed apply mode")
+
+ data.Image = ptrStr("non-existent-file")
+ err = th.App.ImportEmoji(&data, false)
+ assert.NotNil(t, err, "Emoji with bad image file should have failed apply mode")
+
+ data.Image = ptrStr(testImage)
+ err = th.App.ImportEmoji(&data, false)
+ assert.Nil(t, err, "Valid emoji should have succeeded apply mode")
+
+ result = <-th.App.Srv.Store.Emoji().GetByName(*data.Name)
+ assert.NotNil(t, result.Data, "Emoji should have been imported")
+
+ err = th.App.ImportEmoji(&data, false)
+ assert.Nil(t, err, "Second run should have succeeded apply mode")
+}
+
+func TestImportAttachment(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ testsDir, _ := utils.FindDir("tests")
+ testImage := filepath.Join(testsDir, "test.png")
+ invalidPath := "some-invalid-path"
+
+ userId := model.NewId()
+ data := AttachmentImportData{Path: &testImage}
+ _, err := th.App.ImportAttachment(&data, &model.Post{UserId: userId, ChannelId: "some-channel"}, "some-team", true)
+ assert.Nil(t, err, "sample run without errors")
+
+ attachments := GetAttachments(userId, th, t)
+ assert.Equal(t, len(attachments), 1)
+
+ data = AttachmentImportData{Path: &invalidPath}
+ _, err = th.App.ImportAttachment(&data, &model.Post{UserId: model.NewId(), ChannelId: "some-channel"}, "some-team", true)
+ assert.NotNil(t, err, "should have failed when opening the file")
+ assert.Equal(t, err.Id, "app.import.attachment.bad_file.error")
+}
+
+func TestImportPostAndRepliesWithAttachments(t *testing.T) {
+
+ th := Setup()
+ defer th.TearDown()
+
+ // Create a Team.
+ teamName := model.NewId()
+ th.App.ImportTeam(&TeamImportData{
+ Name: &teamName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ team, err := th.App.GetTeamByName(teamName)
+ if err != nil {
+ t.Fatalf("Failed to get team from database.")
+ }
+
+ // Create a Channel.
+ channelName := model.NewId()
+ th.App.ImportChannel(&ChannelImportData{
+ Team: &teamName,
+ Name: &channelName,
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }, false)
+ _, err = th.App.GetChannelByName(channelName, team.Id, false)
+ if err != nil {
+ t.Fatalf("Failed to get channel from database.")
+ }
+
+ // Create a user3.
+ username := model.NewId()
+ th.App.ImportUser(&UserImportData{
+ Username: &username,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }, false)
+ user3, err := th.App.GetUserByUsername(username)
+ if err != nil {
+ t.Fatalf("Failed to get user3 from database.")
+ }
+
+ username2 := model.NewId()
+ th.App.ImportUser(&UserImportData{
+ Username: &username2,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }, false)
+ user4, err := th.App.GetUserByUsername(username2)
+ if err != nil {
+ t.Fatalf("Failed to get user3 from database.")
+ }
+
+ // Post with attachments.
+ time := model.GetMillis()
+ attachmentsPostTime := time
+ attachmentsReplyTime := time + 1
+ testsDir, _ := utils.FindDir("tests")
+ testImage := filepath.Join(testsDir, "test.png")
+ testMarkDown := filepath.Join(testsDir, "test-attachments.md")
+ data := &PostImportData{
+ Team: &teamName,
+ Channel: &channelName,
+ User: &username,
+ Message: ptrStr("Message with reply"),
+ CreateAt: &attachmentsPostTime,
+ Attachments: &[]AttachmentImportData{{Path: &testImage}, {Path: &testMarkDown}},
+ Replies: &[]ReplyImportData{{
+ User: &user4.Username,
+ Message: ptrStr("Message reply"),
+ CreateAt: &attachmentsReplyTime,
+ Attachments: &[]AttachmentImportData{{Path: &testImage}},
+ }},
+ }
+
+ if err := th.App.ImportPost(data, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ attachments := GetAttachments(user3.Id, th, t)
+ assert.Equal(t, len(attachments), 2)
+ assert.Contains(t, attachments[0].Path, team.Id)
+ assert.Contains(t, attachments[1].Path, team.Id)
+ AssertFileIdsInPost(attachments, th, t)
+
+ attachments = GetAttachments(user4.Id, th, t)
+ assert.Equal(t, len(attachments), 1)
+ assert.Contains(t, attachments[0].Path, team.Id)
+ AssertFileIdsInPost(attachments, th, t)
+
+ // Reply with Attachments in Direct Post
+
+ // Create direct post users.
+
+ username3 := model.NewId()
+ th.App.ImportUser(&UserImportData{
+ Username: &username3,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }, false)
+ user3, err = th.App.GetUserByUsername(username3)
+ if err != nil {
+ t.Fatalf("Failed to get user3 from database.")
+ }
+
+ username4 := model.NewId()
+ th.App.ImportUser(&UserImportData{
+ Username: &username4,
+ Email: ptrStr(model.NewId() + "@example.com"),
+ }, false)
+
+ user4, err = th.App.GetUserByUsername(username4)
+ if err != nil {
+ t.Fatalf("Failed to get user3 from database.")
+ }
+
+ directImportData := &DirectPostImportData{
+ ChannelMembers: &[]string{
+ user3.Username,
+ user4.Username,
+ },
+ User: &user3.Username,
+ Message: ptrStr("Message with Replies"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ Replies: &[]ReplyImportData{{
+ User: &user4.Username,
+ Message: ptrStr("Message reply with attachment"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ Attachments: &[]AttachmentImportData{{Path: &testImage}},
+ }},
+ }
+
+ if err := th.App.ImportDirectPost(directImportData, false); err != nil {
+ t.Fatalf("Expected success.")
+ }
+
+ attachments = GetAttachments(user4.Id, th, t)
+ assert.Equal(t, len(attachments), 1)
+ assert.Contains(t, attachments[0].Path, "noteam")
+ AssertFileIdsInPost(attachments, th, t)
+
+}
diff --git a/app/import_test.go b/app/import_test.go
index a8e5a65a8..839c46bb8 100644
--- a/app/import_test.go
+++ b/app/import_test.go
@@ -12,7 +12,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/store"
"github.com/mattermost/mattermost-server/utils"
)
@@ -80,2646 +79,6 @@ func checkNoError(t *testing.T, err *model.AppError) {
}
}
-func TestImportValidateSchemeImportData(t *testing.T) {
- // Test with minimum required valid properties and team scope.
- data := SchemeImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Scope: ptrStr("team"),
- DefaultTeamAdminRole: &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- },
- DefaultTeamUserRole: &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- },
- DefaultChannelAdminRole: &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- },
- DefaultChannelUserRole: &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- },
- }
- if err := validateSchemeImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.", err)
- }
-
- // Test with various invalid names.
- data.Name = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
-
- data.Name = ptrStr("")
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
-
- data.Name = ptrStr(strings.Repeat("1234567890", 100))
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
-
- data.Name = ptrStr("name")
- // Test with invalid display name.
- data.DisplayName = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid display name.")
- }
-
- data.DisplayName = ptrStr("")
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid display name.")
- }
-
- data.DisplayName = ptrStr(strings.Repeat("1234567890", 100))
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid display name.")
- }
-
- data.DisplayName = ptrStr("display name")
-
- // Test with various missing roles.
- data.DefaultTeamAdminRole = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing role.")
- }
-
- data.DefaultTeamAdminRole = &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- }
- data.DefaultTeamUserRole = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing role.")
- }
-
- data.DefaultTeamUserRole = &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- }
- data.DefaultChannelAdminRole = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing role.")
- }
-
- data.DefaultChannelAdminRole = &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- }
- data.DefaultChannelUserRole = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing role.")
- }
-
- data.DefaultChannelUserRole = &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- }
-
- // Test with various invalid roles.
- data.DefaultTeamAdminRole.Name = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid role.")
- }
-
- data.DefaultTeamAdminRole.Name = ptrStr("name")
- data.DefaultTeamUserRole.Name = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid role.")
- }
-
- data.DefaultTeamUserRole.Name = ptrStr("name")
- data.DefaultChannelAdminRole.Name = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid role.")
- }
-
- data.DefaultChannelAdminRole.Name = ptrStr("name")
- data.DefaultChannelUserRole.Name = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid role.")
- }
-
- data.DefaultChannelUserRole.Name = ptrStr("name")
-
- // Change to a Channel scope role, and check with missing or extra roles again.
- data.Scope = ptrStr("channel")
- data.DefaultTeamAdminRole = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to spurious role.")
- }
-
- data.DefaultTeamAdminRole = &RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- Permissions: &[]string{"invite_user"},
- }
- data.DefaultTeamUserRole = nil
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to spurious role.")
- }
-
- data.DefaultTeamAdminRole = nil
- if err := validateSchemeImportData(&data); err != nil {
- t.Fatal("Should have succeeded.")
- }
-
- // Test with all combinations of optional parameters.
- data.Description = ptrStr(strings.Repeat("1234567890", 1024))
- if err := validateSchemeImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid description.")
- }
-
- data.Description = ptrStr("description")
- if err := validateSchemeImportData(&data); err != nil {
- t.Fatal("Should have succeeded.")
- }
-}
-
-func TestImportValidateRoleImportData(t *testing.T) {
- // Test with minimum required valid properties.
- data := RoleImportData{
- Name: ptrStr("name"),
- DisplayName: ptrStr("display name"),
- }
- if err := validateRoleImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.", err)
- }
-
- // Test with various invalid names.
- data.Name = nil
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
-
- data.Name = ptrStr("")
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
-
- data.Name = ptrStr(strings.Repeat("1234567890", 100))
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
-
- data.Name = ptrStr("name")
- // Test with invalid display name.
- data.DisplayName = nil
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid display name.")
- }
-
- data.DisplayName = ptrStr("")
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid display name.")
- }
-
- data.DisplayName = ptrStr(strings.Repeat("1234567890", 100))
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid display name.")
- }
-
- data.DisplayName = ptrStr("display name")
-
- // Test with various valid/invalid permissions.
- data.Permissions = &[]string{}
- if err := validateRoleImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.", err)
- }
-
- data.Permissions = &[]string{"invite_user", "add_user_to_team"}
- if err := validateRoleImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.", err)
- }
-
- data.Permissions = &[]string{"invite_user", "add_user_to_team", "derp"}
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to invalid permission.", err)
- }
-
- data.Permissions = &[]string{"invite_user", "add_user_to_team"}
-
- // Test with various valid/invalid descriptions.
- data.Description = ptrStr(strings.Repeat("1234567890", 1024))
- if err := validateRoleImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to invalid description.", err)
- }
-
- data.Description = ptrStr("description")
- if err := validateRoleImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.", err)
- }
-}
-
-func TestImportValidateTeamImportData(t *testing.T) {
-
- // Test with minimum required valid properties.
- data := TeamImportData{
- Name: ptrStr("teamname"),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }
- if err := validateTeamImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with various invalid names.
- data = TeamImportData{
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing name.")
- }
-
- data.Name = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long name.")
- }
-
- data.Name = ptrStr("login")
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to reserved word in name.")
- }
-
- data.Name = ptrStr("Test::''ASD")
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to non alphanum characters in name.")
- }
-
- data.Name = ptrStr("A")
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to short name.")
- }
-
- // Test team various invalid display names.
- data = TeamImportData{
- Name: ptrStr("teamname"),
- Type: ptrStr("O"),
- }
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing display_name.")
- }
-
- data.DisplayName = ptrStr("")
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to empty display_name.")
- }
-
- data.DisplayName = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long display_name.")
- }
-
- // Test with various valid and invalid types.
- data = TeamImportData{
- Name: ptrStr("teamname"),
- DisplayName: ptrStr("Display Name"),
- }
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing type.")
- }
-
- data.Type = ptrStr("A")
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid type.")
- }
-
- data.Type = ptrStr("I")
- if err := validateTeamImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid type.")
- }
-
- // Test with all the combinations of optional parameters.
- data = TeamImportData{
- Name: ptrStr("teamname"),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- Description: ptrStr("The team description."),
- AllowOpenInvite: ptrBool(true),
- }
- if err := validateTeamImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid optional properties.")
- }
-
- data.AllowOpenInvite = ptrBool(false)
- if err := validateTeamImportData(&data); err != nil {
- t.Fatal("Should have succeeded with allow open invites false.")
- }
-
- data.Description = ptrStr(strings.Repeat("abcdefghij ", 26))
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long description.")
- }
-
- // Test with an empty scheme name.
- data.Description = ptrStr("abcdefg")
- data.Scheme = ptrStr("")
- if err := validateTeamImportData(&data); err == nil {
- t.Fatal("Should have failed due to empty scheme name.")
- }
-
- // Test with a valid scheme name.
- data.Scheme = ptrStr("abcdefg")
- if err := validateTeamImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid scheme name.")
- }
-}
-
-func TestImportValidateChannelImportData(t *testing.T) {
-
- // Test with minimum required valid properties.
- data := ChannelImportData{
- Team: ptrStr("teamname"),
- Name: ptrStr("channelname"),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }
- if err := validateChannelImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with missing team.
- data = ChannelImportData{
- Name: ptrStr("channelname"),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing team.")
- }
-
- // Test with various invalid names.
- data = ChannelImportData{
- Team: ptrStr("teamname"),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing name.")
- }
-
- data.Name = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long name.")
- }
-
- data.Name = ptrStr("Test::''ASD")
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to non alphanum characters in name.")
- }
-
- data.Name = ptrStr("A")
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to short name.")
- }
-
- // Test team various invalid display names.
- data = ChannelImportData{
- Team: ptrStr("teamname"),
- Name: ptrStr("channelname"),
- Type: ptrStr("O"),
- }
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing display_name.")
- }
-
- data.DisplayName = ptrStr("")
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to empty display_name.")
- }
-
- data.DisplayName = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long display_name.")
- }
-
- // Test with various valid and invalid types.
- data = ChannelImportData{
- Team: ptrStr("teamname"),
- Name: ptrStr("channelname"),
- DisplayName: ptrStr("Display Name"),
- }
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to missing type.")
- }
-
- data.Type = ptrStr("A")
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid type.")
- }
-
- data.Type = ptrStr("P")
- if err := validateChannelImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid type.")
- }
-
- // Test with all the combinations of optional parameters.
- data = ChannelImportData{
- Team: ptrStr("teamname"),
- Name: ptrStr("channelname"),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- Header: ptrStr("Channel Header Here"),
- Purpose: ptrStr("Channel Purpose Here"),
- }
- if err := validateChannelImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid optional properties.")
- }
-
- data.Header = ptrStr(strings.Repeat("abcdefghij ", 103))
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long header.")
- }
-
- data.Header = ptrStr("Channel Header Here")
- data.Purpose = ptrStr(strings.Repeat("abcdefghij ", 26))
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long purpose.")
- }
-
- // Test with an empty scheme name.
- data.Purpose = ptrStr("abcdefg")
- data.Scheme = ptrStr("")
- if err := validateChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to empty scheme name.")
- }
-
- // Test with a valid scheme name.
- data.Scheme = ptrStr("abcdefg")
- if err := validateChannelImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid scheme name.")
- }
-}
-
-func TestImportValidateUserImportData(t *testing.T) {
-
- // Test with minimum required valid properties.
- data := UserImportData{
- Username: ptrStr("bob"),
- Email: ptrStr("bob@example.com"),
- }
- if err := validateUserImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Invalid Usernames.
- data.Username = nil
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to nil Username.")
- }
-
- data.Username = ptrStr("")
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to 0 length Username.")
- }
-
- data.Username = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long Username.")
- }
-
- data.Username = ptrStr("i am a username with spaces and !!!")
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to invalid characters in Username.")
- }
-
- data.Username = ptrStr("bob")
-
- // Unexisting Picture Image
- data.ProfileImage = ptrStr("not-existing-file")
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to not existing profile image file.")
- }
- data.ProfileImage = nil
-
- // Invalid Emails
- data.Email = nil
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to nil Email.")
- }
-
- data.Email = ptrStr("")
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to 0 length Email.")
- }
-
- data.Email = ptrStr(strings.Repeat("abcdefghij", 13))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long Email.")
- }
-
- data.Email = ptrStr("bob@example.com")
-
- data.AuthService = ptrStr("")
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to 0-length auth service.")
- }
-
- data.AuthService = ptrStr("saml")
- data.AuthData = ptrStr(strings.Repeat("abcdefghij", 15))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long auth data.")
- }
-
- data.AuthData = ptrStr("bobbytables")
- if err := validateUserImportData(&data); err != nil {
- t.Fatal("Validation should have succeeded with valid auth service and auth data.")
- }
-
- // Test a valid User with all fields populated.
- testsDir, _ := utils.FindDir("tests")
- data = UserImportData{
- ProfileImage: ptrStr(filepath.Join(testsDir, "test.png")),
- Username: ptrStr("bob"),
- Email: ptrStr("bob@example.com"),
- AuthService: ptrStr("ldap"),
- AuthData: ptrStr("bob"),
- Nickname: ptrStr("BobNick"),
- FirstName: ptrStr("Bob"),
- LastName: ptrStr("Blob"),
- Position: ptrStr("The Boss"),
- Roles: ptrStr("system_user"),
- Locale: ptrStr("en"),
- }
- if err := validateUserImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test various invalid optional field values.
- data.Nickname = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long Nickname.")
- }
- data.Nickname = ptrStr("BobNick")
-
- data.FirstName = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long First Name.")
- }
- data.FirstName = ptrStr("Bob")
-
- data.LastName = ptrStr(strings.Repeat("abcdefghij", 7))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long Last name.")
- }
- data.LastName = ptrStr("Blob")
-
- data.Position = ptrStr(strings.Repeat("abcdefghij", 13))
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too long Position.")
- }
- data.Position = ptrStr("The Boss")
-
- data.Roles = nil
- if err := validateUserImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- data.Roles = ptrStr("")
- if err := validateUserImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
- data.Roles = ptrStr("system_user")
-
- // Try various valid/invalid notify props.
- data.NotifyProps = &UserNotifyPropsImportData{}
-
- data.NotifyProps.Desktop = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.Desktop = ptrStr(model.USER_NOTIFY_ALL)
- data.NotifyProps.DesktopSound = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.DesktopSound = ptrStr("true")
- data.NotifyProps.Email = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.Email = ptrStr("true")
- data.NotifyProps.Mobile = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.Mobile = ptrStr(model.USER_NOTIFY_ALL)
- data.NotifyProps.MobilePushStatus = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.MobilePushStatus = ptrStr(model.STATUS_ONLINE)
- data.NotifyProps.ChannelTrigger = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.ChannelTrigger = ptrStr("true")
- data.NotifyProps.CommentsTrigger = ptrStr("invalid")
- checkError(t, validateUserImportData(&data))
-
- data.NotifyProps.CommentsTrigger = ptrStr(model.COMMENTS_NOTIFY_ROOT)
- data.NotifyProps.MentionKeys = ptrStr("valid")
- checkNoError(t, validateUserImportData(&data))
-}
-
-func TestImportValidateUserTeamsImportData(t *testing.T) {
-
- // Invalid Name.
- data := []UserTeamImportData{
- {
- Roles: ptrStr("team_admin team_user"),
- },
- }
- if err := validateUserTeamsImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
- data[0].Name = ptrStr("teamname")
-
- // Valid (nil roles)
- data[0].Roles = nil
- if err := validateUserTeamsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with empty roles.")
- }
-
- // Valid (empty roles)
- data[0].Roles = ptrStr("")
- if err := validateUserTeamsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with empty roles.")
- }
-
- // Valid (with roles)
- data[0].Roles = ptrStr("team_admin team_user")
- if err := validateUserTeamsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid roles.")
- }
-}
-
-func TestImportValidateUserChannelsImportData(t *testing.T) {
-
- // Invalid Name.
- data := []UserChannelImportData{
- {
- Roles: ptrStr("channel_admin channel_user"),
- },
- }
- if err := validateUserChannelsImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid name.")
- }
- data[0].Name = ptrStr("channelname")
-
- // Valid (nil roles)
- data[0].Roles = nil
- if err := validateUserChannelsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with empty roles.")
- }
-
- // Valid (empty roles)
- data[0].Roles = ptrStr("")
- if err := validateUserChannelsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with empty roles.")
- }
-
- // Valid (with roles)
- data[0].Roles = ptrStr("channel_admin channel_user")
- if err := validateUserChannelsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid roles.")
- }
-
- // Empty notify props.
- data[0].NotifyProps = &UserChannelNotifyPropsImportData{}
- if err := validateUserChannelsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with empty notify props.")
- }
-
- // Invalid desktop notify props.
- data[0].NotifyProps.Desktop = ptrStr("invalid")
- if err := validateUserChannelsImportData(&data); err == nil {
- t.Fatal("Should have failed with invalid desktop notify props.")
- }
-
- // Invalid mobile notify props.
- data[0].NotifyProps.Desktop = ptrStr("mention")
- data[0].NotifyProps.Mobile = ptrStr("invalid")
- if err := validateUserChannelsImportData(&data); err == nil {
- t.Fatal("Should have failed with invalid mobile notify props.")
- }
-
- // Invalid mark_unread notify props.
- data[0].NotifyProps.Mobile = ptrStr("mention")
- data[0].NotifyProps.MarkUnread = ptrStr("invalid")
- if err := validateUserChannelsImportData(&data); err == nil {
- t.Fatal("Should have failed with invalid mark_unread notify props.")
- }
-
- // Valid notify props.
- data[0].NotifyProps.MarkUnread = ptrStr("mention")
- if err := validateUserChannelsImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid notify props.")
- }
-}
-
-func TestImportValidateReactionImportData(t *testing.T) {
- // Test with minimum required valid properties.
- parentCreateAt := model.GetMillis() - 100
- data := ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr("emoji"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with missing required properties.
- data = ReactionImportData{
- EmojiName: ptrStr("emoji"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = ReactionImportData{
- User: ptrStr("username"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr("emoji"),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- // Test with invalid emoji name.
- data = ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr(strings.Repeat("1234567890", 500)),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err == nil {
- t.Fatal("Should have failed due to too long emoji name.")
- }
-
- // Test with invalid CreateAt
- data = ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr("emoji"),
- CreateAt: ptrInt64(0),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err == nil {
- t.Fatal("Should have failed due to 0 create-at value.")
- }
-
- data = ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr("emoji"),
- CreateAt: ptrInt64(parentCreateAt - 100),
- }
- if err := validateReactionImportData(&data, parentCreateAt); err == nil {
- t.Fatal("Should have failed due parent with newer create-at value.")
- }
-}
-
-func TestImportValidateReplyImportData(t *testing.T) {
- // Test with minimum required valid properties.
- parentCreateAt := model.GetMillis() - 100
- maxPostSize := 10000
- data := ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with missing required properties.
- data = ReplyImportData{
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = ReplyImportData{
- User: ptrStr("username"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- // Test with invalid message.
- data = ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr(strings.Repeat("0", maxPostSize+1)),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
- t.Fatal("Should have failed due to too long message.")
- }
-
- // Test with invalid CreateAt
- data = ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(0),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
- t.Fatal("Should have failed due to 0 create-at value.")
- }
-
- data = ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(parentCreateAt - 100),
- }
- if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
- t.Fatal("Should have failed due parent with newer create-at value.")
- }
-}
-
-func TestImportValidatePostImportData(t *testing.T) {
- maxPostSize := 10000
-
- // Test with minimum required valid properties.
- data := PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validatePostImportData(&data, maxPostSize); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with missing required properties.
- data = PostImportData{
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = PostImportData{
- Team: ptrStr("teamname"),
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- Message: ptrStr("message"),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- // Test with invalid message.
- data = PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- Message: ptrStr(strings.Repeat("0", maxPostSize+1)),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to too long message.")
- }
-
- // Test with invalid CreateAt
- data = PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(0),
- }
- if err := validatePostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to 0 create-at value.")
- }
-
- // Test with valid all optional parameters.
- reactions := []ReactionImportData{ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr("emoji"),
- CreateAt: ptrInt64(model.GetMillis()),
- }}
- replies := []ReplyImportData{ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }}
- data = PostImportData{
- Team: ptrStr("teamname"),
- Channel: ptrStr("channelname"),
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- Reactions: &reactions,
- Replies: &replies,
- }
- if err := validatePostImportData(&data, maxPostSize); err != nil {
- t.Fatal("Should have succeeded.")
- }
-}
-
-func TestImportValidateDirectChannelImportData(t *testing.T) {
-
- // Test with valid number of members for direct message.
- data := DirectChannelImportData{
- Members: &[]string{
- model.NewId(),
- model.NewId(),
- },
- }
- if err := validateDirectChannelImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with valid number of members for group message.
- data = DirectChannelImportData{
- Members: &[]string{
- model.NewId(),
- model.NewId(),
- model.NewId(),
- },
- }
- if err := validateDirectChannelImportData(&data); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with all the combinations of optional parameters.
- data = DirectChannelImportData{
- Members: &[]string{
- model.NewId(),
- model.NewId(),
- },
- Header: ptrStr("Channel Header Here"),
- }
- if err := validateDirectChannelImportData(&data); err != nil {
- t.Fatal("Should have succeeded with valid optional properties.")
- }
-
- // Test with invalid Header.
- data.Header = ptrStr(strings.Repeat("abcdefghij ", 103))
- if err := validateDirectChannelImportData(&data); err == nil {
- t.Fatal("Should have failed due to too long header.")
- }
-
- // Test with different combinations of invalid member counts.
- data = DirectChannelImportData{
- Members: &[]string{},
- }
- if err := validateDirectChannelImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to invalid number of members.")
- }
-
- data = DirectChannelImportData{
- Members: &[]string{
- model.NewId(),
- },
- }
- if err := validateDirectChannelImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to invalid number of members.")
- }
-
- data = DirectChannelImportData{
- Members: &[]string{
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- },
- }
- if err := validateDirectChannelImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to invalid number of members.")
- }
-
- // Test with invalid FavoritedBy
- member1 := model.NewId()
- member2 := model.NewId()
- data = DirectChannelImportData{
- Members: &[]string{
- member1,
- member2,
- },
- FavoritedBy: &[]string{
- member1,
- model.NewId(),
- },
- }
- if err := validateDirectChannelImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to non-member favorited.")
- }
-
- // Test with valid FavoritedBy
- data = DirectChannelImportData{
- Members: &[]string{
- member1,
- member2,
- },
- FavoritedBy: &[]string{
- member1,
- member2,
- },
- }
- if err := validateDirectChannelImportData(&data); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestImportValidateDirectPostImportData(t *testing.T) {
- maxPostSize := 10000
-
- // Test with minimum required valid properties.
- data := DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with missing required properties.
- data = DirectPostImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- },
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to missing required property.")
- }
-
- // Test with invalid numbers of channel members.
- data = DirectPostImportData{
- ChannelMembers: &[]string{},
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to unsuitable number of members.")
- }
-
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to unsuitable number of members.")
- }
-
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to unsuitable number of members.")
- }
-
- // Test with group message number of members.
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
- t.Fatal("Validation failed but should have been valid.")
- }
-
- // Test with invalid message.
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr(strings.Repeat("0", maxPostSize+1)),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to too long message.")
- }
-
- // Test with invalid CreateAt
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- model.NewId(),
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(0),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Should have failed due to 0 create-at value.")
- }
-
- // Test with invalid FlaggedBy
- member1 := model.NewId()
- member2 := model.NewId()
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- member1,
- member2,
- },
- FlaggedBy: &[]string{
- member1,
- model.NewId(),
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
- t.Fatal("Validation should have failed due to non-member flagged.")
- }
-
- // Test with valid FlaggedBy
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- member1,
- member2,
- },
- FlaggedBy: &[]string{
- member1,
- member2,
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
- t.Fatal(err)
- }
-
- // Test with valid all optional parameters.
- reactions := []ReactionImportData{ReactionImportData{
- User: ptrStr("username"),
- EmojiName: ptrStr("emoji"),
- CreateAt: ptrInt64(model.GetMillis()),
- }}
- replies := []ReplyImportData{ReplyImportData{
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }}
- data = DirectPostImportData{
- ChannelMembers: &[]string{
- member1,
- member2,
- },
- FlaggedBy: &[]string{
- member1,
- member2,
- },
- User: ptrStr("username"),
- Message: ptrStr("message"),
- CreateAt: ptrInt64(model.GetMillis()),
- Reactions: &reactions,
- Replies: &replies,
- }
-
- if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestImportImportScheme(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- // Mark the phase 2 permissions migration as completed.
- <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
-
- defer func() {
- <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
- }()
-
- // Try importing an invalid scheme in dryRun mode.
- data := SchemeImportData{
- Name: ptrStr(model.NewId()),
- Scope: ptrStr("team"),
- DefaultTeamUserRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- DefaultTeamAdminRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- DefaultChannelUserRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- DefaultChannelAdminRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- Description: ptrStr("description"),
- }
-
- if err := th.App.ImportScheme(&data, true); err == nil {
- t.Fatalf("Should have failed to import.")
- }
-
- if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil {
- t.Fatalf("Scheme should not have imported.")
- }
-
- // Try importing a valid scheme in dryRun mode.
- data.DisplayName = ptrStr("display name")
-
- if err := th.App.ImportScheme(&data, true); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil {
- t.Fatalf("Scheme should not have imported.")
- }
-
- // Try importing an invalid scheme.
- data.DisplayName = nil
-
- if err := th.App.ImportScheme(&data, false); err == nil {
- t.Fatalf("Should have failed to import.")
- }
-
- if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil {
- t.Fatalf("Scheme should not have imported.")
- }
-
- // Try importing a valid scheme with all params set.
- data.DisplayName = ptrStr("display name")
-
- if err := th.App.ImportScheme(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil {
- t.Fatalf("Failed to import scheme: %v", res.Err)
- } else {
- scheme := res.Data.(*model.Scheme)
- assert.Equal(t, *data.Name, scheme.Name)
- assert.Equal(t, *data.DisplayName, scheme.DisplayName)
- assert.Equal(t, *data.Description, scheme.Description)
- assert.Equal(t, *data.Scope, scheme.Scope)
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamAdminRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamUserRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelUserRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
- }
-
- // Try modifying all the fields and re-importing.
- data.DisplayName = ptrStr("new display name")
- data.Description = ptrStr("new description")
-
- if err := th.App.ImportScheme(&data, false); err != nil {
- t.Fatalf("Should have succeeded: %v", err)
- }
-
- if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil {
- t.Fatalf("Failed to import scheme: %v", res.Err)
- } else {
- scheme := res.Data.(*model.Scheme)
- assert.Equal(t, *data.Name, scheme.Name)
- assert.Equal(t, *data.DisplayName, scheme.DisplayName)
- assert.Equal(t, *data.Description, scheme.Description)
- assert.Equal(t, *data.Scope, scheme.Scope)
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamAdminRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamUserRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelUserRole); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
- }
-
- // Try changing the scope of the scheme and reimporting.
- data.Scope = ptrStr("channel")
-
- if err := th.App.ImportScheme(&data, false); err == nil {
- t.Fatalf("Should have failed to import.")
- }
-
- if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil {
- t.Fatalf("Failed to import scheme: %v", res.Err)
- } else {
- scheme := res.Data.(*model.Scheme)
- assert.Equal(t, *data.Name, scheme.Name)
- assert.Equal(t, *data.DisplayName, scheme.DisplayName)
- assert.Equal(t, *data.Description, scheme.Description)
- assert.Equal(t, "team", scheme.Scope)
- }
-}
-
-func TestImportImportRole(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- // Try importing an invalid role in dryRun mode.
- rid1 := model.NewId()
- data := RoleImportData{
- Name: &rid1,
- }
-
- if err := th.App.ImportRole(&data, true, false); err == nil {
- t.Fatalf("Should have failed to import.")
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err == nil {
- t.Fatalf("Role should not have imported.")
- }
-
- // Try importing the valid role in dryRun mode.
- data.DisplayName = ptrStr("display name")
-
- if err := th.App.ImportRole(&data, true, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err == nil {
- t.Fatalf("Role should not have imported as we are in dry run mode.")
- }
-
- // Try importing an invalid role.
- data.DisplayName = nil
-
- if err := th.App.ImportRole(&data, false, false); err == nil {
- t.Fatalf("Should have failed to import.")
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err == nil {
- t.Fatalf("Role should not have imported.")
- }
-
- // Try importing a valid role with all params set.
- data.DisplayName = ptrStr("display name")
- data.Description = ptrStr("description")
- data.Permissions = &[]string{"invite_user", "add_user_to_team"}
-
- if err := th.App.ImportRole(&data, false, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.Name, role.Name)
- assert.Equal(t, *data.DisplayName, role.DisplayName)
- assert.Equal(t, *data.Description, role.Description)
- assert.Equal(t, *data.Permissions, role.Permissions)
- assert.False(t, role.BuiltIn)
- assert.False(t, role.SchemeManaged)
- }
-
- // Try changing all the params and reimporting.
- data.DisplayName = ptrStr("new display name")
- data.Description = ptrStr("description")
- data.Permissions = &[]string{"use_slash_commands"}
-
- if err := th.App.ImportRole(&data, false, true); err != nil {
- t.Fatalf("Should have succeeded. %v", err)
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data.Name, role.Name)
- assert.Equal(t, *data.DisplayName, role.DisplayName)
- assert.Equal(t, *data.Description, role.Description)
- assert.Equal(t, *data.Permissions, role.Permissions)
- assert.False(t, role.BuiltIn)
- assert.True(t, role.SchemeManaged)
- }
-
- // Check that re-importing with only required fields doesn't update the others.
- data2 := RoleImportData{
- Name: &rid1,
- DisplayName: ptrStr("new display name again"),
- }
-
- if err := th.App.ImportRole(&data2, false, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- if res := <-th.App.Srv.Store.Role().GetByName(rid1); res.Err != nil {
- t.Fatalf("Should have found the imported role.")
- } else {
- role := res.Data.(*model.Role)
- assert.Equal(t, *data2.Name, role.Name)
- assert.Equal(t, *data2.DisplayName, role.DisplayName)
- assert.Equal(t, *data.Description, role.Description)
- assert.Equal(t, *data.Permissions, role.Permissions)
- assert.False(t, role.BuiltIn)
- assert.False(t, role.SchemeManaged)
- }
-}
-
-func TestImportImportTeam(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- // Mark the phase 2 permissions migration as completed.
- <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
-
- defer func() {
- <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
- }()
-
- scheme1 := th.SetupTeamScheme()
- scheme2 := th.SetupTeamScheme()
-
- // Check how many teams are in the database.
- var teamsCount int64
- if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
- teamsCount = r.Data.(int64)
- } else {
- t.Fatalf("Failed to get team count.")
- }
-
- data := TeamImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("XYZ"),
- Description: ptrStr("The team description."),
- AllowOpenInvite: ptrBool(true),
- Scheme: &scheme1.Name,
- }
-
- // Try importing an invalid team in dryRun mode.
- if err := th.App.ImportTeam(&data, true); err == nil {
- t.Fatalf("Should have received an error importing an invalid team.")
- }
-
- // Do a valid team in dry-run mode.
- data.Type = ptrStr("O")
- if err := th.App.ImportTeam(&data, true); err != nil {
- t.Fatalf("Received an error validating valid team.")
- }
-
- // Check that no more teams are in the DB.
- th.CheckTeamCount(t, teamsCount)
-
- // Do an invalid team in apply mode, check db changes.
- data.Type = ptrStr("XYZ")
- if err := th.App.ImportTeam(&data, false); err == nil {
- t.Fatalf("Import should have failed on invalid team.")
- }
-
- // Check that no more teams are in the DB.
- th.CheckTeamCount(t, teamsCount)
-
- // Do a valid team in apply mode, check db changes.
- data.Type = ptrStr("O")
- if err := th.App.ImportTeam(&data, false); err != nil {
- t.Fatalf("Received an error importing valid team: %v", err)
- }
-
- // Check that one more team is in the DB.
- th.CheckTeamCount(t, teamsCount+1)
-
- // Get the team and check that all the fields are correct.
- if team, err := th.App.GetTeamByName(*data.Name); err != nil {
- t.Fatalf("Failed to get team from database.")
- } else {
- assert.Equal(t, *data.DisplayName, team.DisplayName)
- assert.Equal(t, *data.Type, team.Type)
- assert.Equal(t, *data.Description, team.Description)
- assert.Equal(t, *data.AllowOpenInvite, team.AllowOpenInvite)
- assert.Equal(t, scheme1.Id, *team.SchemeId)
- }
-
- // Alter all the fields of that team (apart from unique identifier) and import again.
- data.DisplayName = ptrStr("Display Name 2")
- data.Type = ptrStr("P")
- data.Description = ptrStr("The new description")
- data.AllowOpenInvite = ptrBool(false)
- data.Scheme = &scheme2.Name
-
- // Check that the original number of teams are again in the DB (because this query doesn't include deleted).
- data.Type = ptrStr("O")
- if err := th.App.ImportTeam(&data, false); err != nil {
- t.Fatalf("Received an error importing updated valid team.")
- }
-
- th.CheckTeamCount(t, teamsCount+1)
-
- // Get the team and check that all fields are correct.
- if team, err := th.App.GetTeamByName(*data.Name); err != nil {
- t.Fatalf("Failed to get team from database.")
- } else {
- assert.Equal(t, *data.DisplayName, team.DisplayName)
- assert.Equal(t, *data.Type, team.Type)
- assert.Equal(t, *data.Description, team.Description)
- assert.Equal(t, *data.AllowOpenInvite, team.AllowOpenInvite)
- assert.Equal(t, scheme2.Id, *team.SchemeId)
- }
-}
-
-func TestImportImportChannel(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- // Mark the phase 2 permissions migration as completed.
- <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
-
- defer func() {
- <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
- }()
-
- scheme1 := th.SetupChannelScheme()
- scheme2 := th.SetupChannelScheme()
-
- // Import a Team.
- teamName := model.NewId()
- th.App.ImportTeam(&TeamImportData{
- Name: &teamName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- team, err := th.App.GetTeamByName(teamName)
- if err != nil {
- t.Fatalf("Failed to get team from database.")
- }
-
- // Check how many channels are in the database.
- var channelCount int64
- if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
- channelCount = r.Data.(int64)
- } else {
- t.Fatalf("Failed to get team count.")
- }
-
- // Do an invalid channel in dry-run mode.
- data := ChannelImportData{
- Team: &teamName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- Header: ptrStr("Channe Header"),
- Purpose: ptrStr("Channel Purpose"),
- Scheme: &scheme1.Name,
- }
- if err := th.App.ImportChannel(&data, true); err == nil {
- t.Fatalf("Expected error due to invalid name.")
- }
-
- // Check that no more channels are in the DB.
- th.CheckChannelsCount(t, channelCount)
-
- // Do a valid channel with a nonexistent team in dry-run mode.
- data.Name = ptrStr("channelname")
- data.Team = ptrStr(model.NewId())
- if err := th.App.ImportChannel(&data, true); err != nil {
- t.Fatalf("Expected success as cannot validate channel name in dry run mode.")
- }
-
- // Check that no more channels are in the DB.
- th.CheckChannelsCount(t, channelCount)
-
- // Do a valid channel in dry-run mode.
- data.Team = &teamName
- if err := th.App.ImportChannel(&data, true); err != nil {
- t.Fatalf("Expected success as valid team.")
- }
-
- // Check that no more channels are in the DB.
- th.CheckChannelsCount(t, channelCount)
-
- // Do an invalid channel in apply mode.
- data.Name = nil
- if err := th.App.ImportChannel(&data, false); err == nil {
- t.Fatalf("Expected error due to invalid name (apply mode).")
- }
-
- // Check that no more channels are in the DB.
- th.CheckChannelsCount(t, channelCount)
-
- // Do a valid channel in apply mode with a non-existent team.
- data.Name = ptrStr("channelname")
- data.Team = ptrStr(model.NewId())
- if err := th.App.ImportChannel(&data, false); err == nil {
- t.Fatalf("Expected error due to non-existent team (apply mode).")
- }
-
- // Check that no more channels are in the DB.
- th.CheckChannelsCount(t, channelCount)
-
- // Do a valid channel in apply mode.
- data.Team = &teamName
- if err := th.App.ImportChannel(&data, false); err != nil {
- t.Fatalf("Expected success in apply mode: %v", err.Error())
- }
-
- // Check that 1 more channel is in the DB.
- th.CheckChannelsCount(t, channelCount+1)
-
- // Get the Channel and check all the fields are correct.
- if channel, err := th.App.GetChannelByName(*data.Name, team.Id, false); err != nil {
- t.Fatalf("Failed to get channel from database.")
- } else {
- assert.Equal(t, *data.Name, channel.Name)
- assert.Equal(t, *data.DisplayName, channel.DisplayName)
- assert.Equal(t, *data.Type, channel.Type)
- assert.Equal(t, *data.Header, channel.Header)
- assert.Equal(t, *data.Purpose, channel.Purpose)
- assert.Equal(t, scheme1.Id, *channel.SchemeId)
- }
-
- // Alter all the fields of that channel.
- data.DisplayName = ptrStr("Chaned Disp Name")
- data.Type = ptrStr(model.CHANNEL_PRIVATE)
- data.Header = ptrStr("New Header")
- data.Purpose = ptrStr("New Purpose")
- data.Scheme = &scheme2.Name
- if err := th.App.ImportChannel(&data, false); err != nil {
- t.Fatalf("Expected success in apply mode: %v", err.Error())
- }
-
- // Check channel count the same.
- th.CheckChannelsCount(t, channelCount)
-
- // Get the Channel and check all the fields are correct.
- if channel, err := th.App.GetChannelByName(*data.Name, team.Id, false); err != nil {
- t.Fatalf("Failed to get channel from database.")
- } else {
- assert.Equal(t, *data.Name, channel.Name)
- assert.Equal(t, *data.DisplayName, channel.DisplayName)
- assert.Equal(t, *data.Type, channel.Type)
- assert.Equal(t, *data.Header, channel.Header)
- assert.Equal(t, *data.Purpose, channel.Purpose)
- assert.Equal(t, scheme2.Id, *channel.SchemeId)
- }
-
-}
-
-func TestImportImportUser(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- // Check how many users are in the database.
- var userCount int64
- if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
- userCount = r.Data.(int64)
- } else {
- t.Fatalf("Failed to get user count.")
- }
-
- // Do an invalid user in dry-run mode.
- data := UserImportData{
- Username: ptrStr(model.NewId()),
- }
- if err := th.App.ImportUser(&data, true); err == nil {
- t.Fatalf("Should have failed to import invalid user.")
- }
-
- // Check that no more users are in the DB.
- if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
- if r.Data.(int64) != userCount {
- t.Fatalf("Unexpected number of users")
- }
- } else {
- t.Fatalf("Failed to get user count.")
- }
-
- // Do a valid user in dry-run mode.
- data = UserImportData{
- Username: ptrStr(model.NewId()),
- Email: ptrStr(model.NewId() + "@example.com"),
- }
- if err := th.App.ImportUser(&data, true); err != nil {
- t.Fatalf("Should have succeeded to import valid user.")
- }
-
- // Check that no more users are in the DB.
- if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
- if r.Data.(int64) != userCount {
- t.Fatalf("Unexpected number of users")
- }
- } else {
- t.Fatalf("Failed to get user count.")
- }
-
- // Do an invalid user in apply mode.
- data = UserImportData{
- Username: ptrStr(model.NewId()),
- }
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed to import invalid user.")
- }
-
- // Check that no more users are in the DB.
- if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
- if r.Data.(int64) != userCount {
- t.Fatalf("Unexpected number of users")
- }
- } else {
- t.Fatalf("Failed to get user count.")
- }
-
- // Do a valid user in apply mode.
- username := model.NewId()
- testsDir, _ := utils.FindDir("tests")
- data = UserImportData{
- ProfileImage: ptrStr(filepath.Join(testsDir, "test.png")),
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- Nickname: ptrStr(model.NewId()),
- FirstName: ptrStr(model.NewId()),
- LastName: ptrStr(model.NewId()),
- Position: ptrStr(model.NewId()),
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded to import valid user.")
- }
-
- // Check that one more user is in the DB.
- if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
- if r.Data.(int64) != userCount+1 {
- t.Fatalf("Unexpected number of users")
- }
- } else {
- t.Fatalf("Failed to get user count.")
- }
-
- // Get the user and check all the fields are correct.
- if user, err := th.App.GetUserByUsername(username); err != nil {
- t.Fatalf("Failed to get user from database.")
- } else {
- if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
- t.Fatalf("User properties do not match Import Data.")
- }
- // Check calculated properties.
- if user.AuthService != "" {
- t.Fatalf("Expected Auth Service to be empty.")
- }
-
- if !(user.AuthData == nil || *user.AuthData == "") {
- t.Fatalf("Expected AuthData to be empty.")
- }
-
- if len(user.Password) == 0 {
- t.Fatalf("Expected password to be set.")
- }
-
- if !user.EmailVerified {
- t.Fatalf("Expected EmailVerified to be true.")
- }
-
- if user.Locale != *th.App.Config().LocalizationSettings.DefaultClientLocale {
- t.Fatalf("Expected Locale to be the default.")
- }
-
- if user.Roles != "system_user" {
- t.Fatalf("Expected roles to be system_user")
- }
- }
-
- // Alter all the fields of that user.
- data.Email = ptrStr(model.NewId() + "@example.com")
- data.ProfileImage = ptrStr(filepath.Join(testsDir, "testgif.gif"))
- data.AuthService = ptrStr("ldap")
- data.AuthData = &username
- data.Nickname = ptrStr(model.NewId())
- data.FirstName = ptrStr(model.NewId())
- data.LastName = ptrStr(model.NewId())
- data.Position = ptrStr(model.NewId())
- data.Roles = ptrStr("system_admin system_user")
- data.Locale = ptrStr("zh_CN")
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded to update valid user %v", err)
- }
-
- // Check user count the same.
- if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
- if r.Data.(int64) != userCount+1 {
- t.Fatalf("Unexpected number of users")
- }
- } else {
- t.Fatalf("Failed to get user count.")
- }
-
- // Get the user and check all the fields are correct.
- if user, err := th.App.GetUserByUsername(username); err != nil {
- t.Fatalf("Failed to get user from database.")
- } else {
- if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
- t.Fatalf("Updated User properties do not match Import Data.")
- }
- // Check calculated properties.
- if user.AuthService != "ldap" {
- t.Fatalf("Expected Auth Service to be ldap \"%v\"", user.AuthService)
- }
-
- if !(user.AuthData == data.AuthData || *user.AuthData == *data.AuthData) {
- t.Fatalf("Expected AuthData to be set.")
- }
-
- if len(user.Password) != 0 {
- t.Fatalf("Expected password to be empty.")
- }
-
- if !user.EmailVerified {
- t.Fatalf("Expected EmailVerified to be true.")
- }
-
- if user.Locale != *data.Locale {
- t.Fatalf("Expected Locale to be the set.")
- }
-
- if user.Roles != *data.Roles {
- t.Fatalf("Expected roles to be set: %v", user.Roles)
- }
- }
-
- // Check Password and AuthData together.
- data.Password = ptrStr("PasswordTest")
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed to import invalid user.")
- }
-
- data.AuthData = nil
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded to update valid user %v", err)
- }
-
- data.Password = ptrStr("")
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed to import invalid user.")
- }
-
- data.Password = ptrStr(strings.Repeat("0123456789", 10))
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed to import invalid user.")
- }
-
- data.Password = ptrStr("TestPassword")
-
- // Test team and channel memberships
- teamName := model.NewId()
- th.App.ImportTeam(&TeamImportData{
- Name: &teamName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- team, err := th.App.GetTeamByName(teamName)
- if err != nil {
- t.Fatalf("Failed to get team from database.")
- }
-
- channelName := model.NewId()
- th.App.ImportChannel(&ChannelImportData{
- Team: &teamName,
- Name: &channelName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- channel, err := th.App.GetChannelByName(channelName, team.Id, false)
- if err != nil {
- t.Fatalf("Failed to get channel from database.")
- }
-
- username = model.NewId()
- data = UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- Nickname: ptrStr(model.NewId()),
- FirstName: ptrStr(model.NewId()),
- LastName: ptrStr(model.NewId()),
- Position: ptrStr(model.NewId()),
- }
-
- teamMembers, err := th.App.GetTeamMembers(team.Id, 0, 1000)
- if err != nil {
- t.Fatalf("Failed to get team member count")
- }
- teamMemberCount := len(teamMembers)
-
- channelMemberCount, err := th.App.GetChannelMemberCount(channel.Id)
- if err != nil {
- t.Fatalf("Failed to get channel member count")
- }
-
- // Test with an invalid team & channel membership in dry-run mode.
- data.Teams = &[]UserTeamImportData{
- {
- Roles: ptrStr("invalid"),
- Channels: &[]UserChannelImportData{
- {
- Roles: ptrStr("invalid"),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, true); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Test with an unknown team name & invalid channel membership in dry-run mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: ptrStr(model.NewId()),
- Channels: &[]UserChannelImportData{
- {
- Roles: ptrStr("invalid"),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, true); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Test with a valid team & invalid channel membership in dry-run mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Channels: &[]UserChannelImportData{
- {
- Roles: ptrStr("invalid"),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, true); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Test with a valid team & unknown channel name in dry-run mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Channels: &[]UserChannelImportData{
- {
- Name: ptrStr(model.NewId()),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, true); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- // Test with a valid team & valid channel name in dry-run mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Channels: &[]UserChannelImportData{
- {
- Name: &channelName,
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, true); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- // Check no new member objects were created because dry run mode.
- if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
- t.Fatalf("Failed to get Team Member Count")
- } else if len(tmc) != teamMemberCount {
- t.Fatalf("Number of team members not as expected")
- }
-
- if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
- t.Fatalf("Failed to get Channel Member Count")
- } else if cmc != channelMemberCount {
- t.Fatalf("Number of channel members not as expected")
- }
-
- // Test with an invalid team & channel membership in apply mode.
- data.Teams = &[]UserTeamImportData{
- {
- Roles: ptrStr("invalid"),
- Channels: &[]UserChannelImportData{
- {
- Roles: ptrStr("invalid"),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Test with an unknown team name & invalid channel membership in apply mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: ptrStr(model.NewId()),
- Channels: &[]UserChannelImportData{
- {
- Roles: ptrStr("invalid"),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Test with a valid team & invalid channel membership in apply mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Channels: &[]UserChannelImportData{
- {
- Roles: ptrStr("invalid"),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Check no new member objects were created because all tests should have failed so far.
- if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
- t.Fatalf("Failed to get Team Member Count")
- } else if len(tmc) != teamMemberCount {
- t.Fatalf("Number of team members not as expected")
- }
-
- if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
- t.Fatalf("Failed to get Channel Member Count")
- } else if cmc != channelMemberCount {
- t.Fatalf("Number of channel members not as expected")
- }
-
- // Test with a valid team & unknown channel name in apply mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Channels: &[]UserChannelImportData{
- {
- Name: ptrStr(model.NewId()),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, false); err == nil {
- t.Fatalf("Should have failed.")
- }
-
- // Check only new team member object created because dry run mode.
- if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
- t.Fatalf("Failed to get Team Member Count")
- } else if len(tmc) != teamMemberCount+1 {
- t.Fatalf("Number of team members not as expected")
- }
-
- if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
- t.Fatalf("Failed to get Channel Member Count")
- } else if cmc != channelMemberCount {
- t.Fatalf("Number of channel members not as expected")
- }
-
- // Check team member properties.
- user, err := th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
- if teamMember, err := th.App.GetTeamMember(team.Id, user.Id); err != nil {
- t.Fatalf("Failed to get team member from database.")
- } else if teamMember.Roles != "team_user" {
- t.Fatalf("Team member properties not as expected")
- }
-
- // Test with a valid team & valid channel name in apply mode.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Channels: &[]UserChannelImportData{
- {
- Name: &channelName,
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- // Check only new channel member object created because dry run mode.
- if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
- t.Fatalf("Failed to get Team Member Count")
- } else if len(tmc) != teamMemberCount+1 {
- t.Fatalf("Number of team members not as expected")
- }
-
- if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
- t.Fatalf("Failed to get Channel Member Count")
- } else if cmc != channelMemberCount+1 {
- t.Fatalf("Number of channel members not as expected")
- }
-
- // Check channel member properties.
- if channelMember, err := th.App.GetChannelMember(channel.Id, user.Id); err != nil {
- t.Fatalf("Failed to get channel member from database.")
- } else if channelMember.Roles != "channel_user" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != "all" {
- t.Fatalf("Channel member properties not as expected")
- }
-
- // Test with the properties of the team and channel membership changed.
- data.Teams = &[]UserTeamImportData{
- {
- Name: &teamName,
- Roles: ptrStr("team_user team_admin"),
- Channels: &[]UserChannelImportData{
- {
- Name: &channelName,
- Roles: ptrStr("channel_user channel_admin"),
- NotifyProps: &UserChannelNotifyPropsImportData{
- Desktop: ptrStr(model.USER_NOTIFY_MENTION),
- Mobile: ptrStr(model.USER_NOTIFY_MENTION),
- MarkUnread: ptrStr(model.USER_NOTIFY_MENTION),
- },
- Favorite: ptrBool(true),
- },
- },
- },
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- // Check both member properties.
- if teamMember, err := th.App.GetTeamMember(team.Id, user.Id); err != nil {
- t.Fatalf("Failed to get team member from database.")
- } else if teamMember.Roles != "team_user team_admin" {
- t.Fatalf("Team member properties not as expected: %v", teamMember.Roles)
- }
-
- if channelMember, err := th.App.GetChannelMember(channel.Id, user.Id); err != nil {
- t.Fatalf("Failed to get channel member Desktop from database.")
- } else if channelMember.Roles != "channel_user channel_admin" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.USER_NOTIFY_MENTION {
- t.Fatalf("Channel member properties not as expected")
- }
-
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
-
- // No more new member objects.
- if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
- t.Fatalf("Failed to get Team Member Count")
- } else if len(tmc) != teamMemberCount+1 {
- t.Fatalf("Number of team members not as expected")
- }
-
- if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
- t.Fatalf("Failed to get Channel Member Count")
- } else if cmc != channelMemberCount+1 {
- t.Fatalf("Number of channel members not as expected")
- }
-
- // Add a user with some preferences.
- username = model.NewId()
- data = UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- Theme: ptrStr(`{"awayIndicator":"#DCBD4E","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
- UseMilitaryTime: ptrStr("true"),
- CollapsePreviews: ptrStr("true"),
- MessageDisplay: ptrStr("compact"),
- ChannelDisplayMode: ptrStr("centered"),
- TutorialStep: ptrStr("3"),
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- // Check their values.
- user, err = th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, "", *data.Theme)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "use_military_time", *data.UseMilitaryTime)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "collapse_previews", *data.CollapsePreviews)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
-
- // Change those preferences.
- data = UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- Theme: ptrStr(`{"awayIndicator":"#123456","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
- UseMilitaryTime: ptrStr("false"),
- CollapsePreviews: ptrStr("false"),
- MessageDisplay: ptrStr("clean"),
- ChannelDisplayMode: ptrStr("full"),
- TutorialStep: ptrStr("2"),
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- // Check their values again.
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, "", *data.Theme)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "use_military_time", *data.UseMilitaryTime)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "collapse_previews", *data.CollapsePreviews)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
-
- // Set Notify Props
- data.NotifyProps = &UserNotifyPropsImportData{
- Desktop: ptrStr(model.USER_NOTIFY_ALL),
- DesktopSound: ptrStr("true"),
- Email: ptrStr("true"),
- Mobile: ptrStr(model.USER_NOTIFY_ALL),
- MobilePushStatus: ptrStr(model.STATUS_ONLINE),
- ChannelTrigger: ptrStr("true"),
- CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ROOT),
- MentionKeys: ptrStr("valid,misc"),
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- user, err = th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_ALL)
- checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "true")
- checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "true")
- checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_ALL)
- checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_ONLINE)
- checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "true")
- checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ROOT)
- checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "valid,misc")
-
- // Change Notify Props
- data.NotifyProps = &UserNotifyPropsImportData{
- Desktop: ptrStr(model.USER_NOTIFY_MENTION),
- DesktopSound: ptrStr("false"),
- Email: ptrStr("false"),
- Mobile: ptrStr(model.USER_NOTIFY_NONE),
- MobilePushStatus: ptrStr(model.STATUS_AWAY),
- ChannelTrigger: ptrStr("false"),
- CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ANY),
- MentionKeys: ptrStr("misc"),
- }
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- user, err = th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
- checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
- checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
- checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
- checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
- checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
- checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
- checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
-
- // Check Notify Props get set on *create* user.
- username = model.NewId()
- data = UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- }
- data.NotifyProps = &UserNotifyPropsImportData{
- Desktop: ptrStr(model.USER_NOTIFY_MENTION),
- DesktopSound: ptrStr("false"),
- Email: ptrStr("false"),
- Mobile: ptrStr(model.USER_NOTIFY_NONE),
- MobilePushStatus: ptrStr(model.STATUS_AWAY),
- ChannelTrigger: ptrStr("false"),
- CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ANY),
- MentionKeys: ptrStr("misc"),
- }
-
- if err := th.App.ImportUser(&data, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- user, err = th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
- checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
- checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
- checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
- checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
- checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
- checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
- checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
-
- // Test importing a user with roles set to a team and a channel which are affected by an override scheme.
- // The import subsystem should translate `channel_admin/channel_user/team_admin/team_user`
- // to the appropriate scheme-managed-role booleans.
-
- // Mark the phase 2 permissions migration as completed.
- <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"})
-
- defer func() {
- <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2)
- }()
-
- teamSchemeData := &SchemeImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- Scope: ptrStr("team"),
- DefaultTeamUserRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- DefaultTeamAdminRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- DefaultChannelUserRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- DefaultChannelAdminRole: &RoleImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr(model.NewId()),
- },
- Description: ptrStr("description"),
- }
-
- if err := th.App.ImportScheme(teamSchemeData, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- var teamScheme *model.Scheme
- if res := <-th.App.Srv.Store.Scheme().GetByName(*teamSchemeData.Name); res.Err != nil {
- t.Fatalf("Failed to import scheme: %v", res.Err)
- } else {
- teamScheme = res.Data.(*model.Scheme)
- }
-
- teamData := &TeamImportData{
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- Description: ptrStr("The team description."),
- AllowOpenInvite: ptrBool(true),
- Scheme: &teamScheme.Name,
- }
- if err := th.App.ImportTeam(teamData, false); err != nil {
- t.Fatalf("Import should have succeeded: %v", err.Error())
- }
- team, err = th.App.GetTeamByName(teamName)
- if err != nil {
- t.Fatalf("Failed to get team from database.")
- }
-
- channelData := &ChannelImportData{
- Team: &teamName,
- Name: ptrStr(model.NewId()),
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- Header: ptrStr("Channe Header"),
- Purpose: ptrStr("Channel Purpose"),
- }
- if err := th.App.ImportChannel(channelData, false); err != nil {
- t.Fatalf("Import should have succeeded.")
- }
- channel, err = th.App.GetChannelByName(*channelData.Name, team.Id, false)
- if err != nil {
- t.Fatalf("Failed to get channel from database: %v", err.Error())
- }
-
- // Test with a valid team & valid channel name in apply mode.
- userData := &UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- Teams: &[]UserTeamImportData{
- {
- Name: &team.Name,
- Roles: ptrStr("team_user team_admin"),
- Channels: &[]UserChannelImportData{
- {
- Name: &channel.Name,
- Roles: ptrStr("channel_admin channel_user"),
- },
- },
- },
- },
- }
- if err := th.App.ImportUser(userData, false); err != nil {
- t.Fatalf("Should have succeeded.")
- }
-
- user, err = th.App.GetUserByUsername(*userData.Username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- teamMember, err := th.App.GetTeamMember(team.Id, user.Id)
- if err != nil {
- t.Fatalf("Failed to get the team member")
- }
- assert.True(t, teamMember.SchemeAdmin)
- assert.True(t, teamMember.SchemeUser)
- assert.Equal(t, "", teamMember.ExplicitRoles)
-
- channelMember, err := th.App.GetChannelMember(channel.Id, user.Id)
- if err != nil {
- t.Fatalf("Failed to get the channel member")
- }
- assert.True(t, channelMember.SchemeAdmin)
- assert.True(t, channelMember.SchemeUser)
- assert.Equal(t, "", channelMember.ExplicitRoles)
-
-}
-
func AssertAllPostsCount(t *testing.T, a *App, initialCount int64, change int64, teamName string) {
if result := <-a.Srv.Store.Post().AnalyticsPostCount(teamName, false, false); result.Err != nil {
t.Fatal(result.Err)
@@ -2731,577 +90,6 @@ func AssertAllPostsCount(t *testing.T, a *App, initialCount int64, change int64,
}
}
-func TestImportImportPost(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- // Create a Team.
- teamName := model.NewId()
- th.App.ImportTeam(&TeamImportData{
- Name: &teamName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- team, err := th.App.GetTeamByName(teamName)
- if err != nil {
- t.Fatalf("Failed to get team from database.")
- }
-
- // Create a Channel.
- channelName := model.NewId()
- th.App.ImportChannel(&ChannelImportData{
- Team: &teamName,
- Name: &channelName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- channel, err := th.App.GetChannelByName(channelName, team.Id, false)
- if err != nil {
- t.Fatalf("Failed to get channel from database.")
- }
-
- // Create a user.
- username := model.NewId()
- th.App.ImportUser(&UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- }, false)
- user, err := th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- // Count the number of posts in the testing team.
- var initialPostCount int64
- if result := <-th.App.Srv.Store.Post().AnalyticsPostCount(team.Id, false, false); result.Err != nil {
- t.Fatal(result.Err)
- } else {
- initialPostCount = result.Data.(int64)
- }
-
- // Try adding an invalid post in dry run mode.
- data := &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- }
- if err := th.App.ImportPost(data, true); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
-
- // Try adding a valid post in dry run mode.
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Hello"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportPost(data, true); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
-
- // Try adding an invalid post in apply mode.
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportPost(data, false); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
-
- // Try adding a valid post with invalid team in apply mode.
- data = &PostImportData{
- Team: ptrStr(model.NewId()),
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportPost(data, false); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
-
- // Try adding a valid post with invalid channel in apply mode.
- data = &PostImportData{
- Team: &teamName,
- Channel: ptrStr(model.NewId()),
- User: &username,
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportPost(data, false); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
-
- // Try adding a valid post with invalid user in apply mode.
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: ptrStr(model.NewId()),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportPost(data, false); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
-
- // Try adding a valid post in apply mode.
- time := model.GetMillis()
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message"),
- CreateAt: &time,
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, time); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
- t.Fatal("Post properties not as expected")
- }
- }
-
- // Update the post.
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message"),
- CreateAt: &time,
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, time); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
- t.Fatal("Post properties not as expected")
- }
- }
-
- // Save the post with a different time.
- newTime := time + 1
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message"),
- CreateAt: &newTime,
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 2, team.Id)
-
- // Save the post with a different message.
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message 2"),
- CreateAt: &time,
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 3, team.Id)
-
- // Test with hashtags
- hashtagTime := time + 2
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message 2 #hashtagmashupcity"),
- CreateAt: &hashtagTime,
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 4, team.Id)
-
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, hashtagTime); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
- t.Fatal("Post properties not as expected")
- }
- if post.Hashtags != "#hashtagmashupcity" {
- t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
- }
- }
-
- // Post with flags.
- username2 := model.NewId()
- th.App.ImportUser(&UserImportData{
- Username: &username2,
- Email: ptrStr(model.NewId() + "@example.com"),
- }, false)
- user2, err := th.App.GetUserByUsername(username2)
- if err != nil {
- t.Fatalf("Failed to get user from database.")
- }
-
- flagsTime := hashtagTime + 1
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message with Favorites"),
- CreateAt: &flagsTime,
- FlaggedBy: &[]string{
- username,
- username2,
- },
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 5, team.Id)
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, flagsTime); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
- t.Fatal("Post properties not as expected")
- }
-
- checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
- checkPreference(t, th.App, user2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
- }
-
- // Post with reaction.
- reactionPostTime := hashtagTime + 2
- reactionTime := hashtagTime + 3
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message with reaction"),
- CreateAt: &reactionPostTime,
- Reactions: &[]ReactionImportData{{
- User: &user2.Username,
- EmojiName: ptrStr("+1"),
- CreateAt: &reactionTime,
- }},
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 6, team.Id)
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, reactionPostTime); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id || !post.HasReactions {
- t.Fatal("Post properties not as expected")
- }
-
- if result := <-th.App.Srv.Store.Reaction().GetForPost(post.Id, false); result.Err != nil {
- t.Fatal("Can't get reaction")
- } else if len(result.Data.([]*model.Reaction)) != 1 {
- t.Fatal("Invalid number of reactions")
- }
- }
-
- // Post with reply.
- replyPostTime := hashtagTime + 4
- replyTime := hashtagTime + 5
- data = &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message with reply"),
- CreateAt: &replyPostTime,
- Replies: &[]ReplyImportData{{
- User: &user2.Username,
- Message: ptrStr("Message reply"),
- CreateAt: &replyTime,
- }},
- }
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 8, team.Id)
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, replyPostTime); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
- t.Fatal("Post properties not as expected")
- }
-
- // Check the reply values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, replyTime); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- replies := result.Data.([]*model.Post)
- if len(replies) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- reply := replies[0]
- if reply.Message != *(*data.Replies)[0].Message || reply.CreateAt != *(*data.Replies)[0].CreateAt || reply.UserId != user2.Id {
- t.Fatal("Post properties not as expected")
- }
-
- if reply.RootId != post.Id {
- t.Fatal("Unexpected reply RootId")
- }
- }
- }
-}
-
-func TestImportImportDirectChannel(t *testing.T) {
- th := Setup().InitBasic()
- defer th.TearDown()
-
- // Check how many channels are in the database.
- var directChannelCount int64
- if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_DIRECT); r.Err == nil {
- directChannelCount = r.Data.(int64)
- } else {
- t.Fatalf("Failed to get direct channel count.")
- }
-
- var groupChannelCount int64
- if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_GROUP); r.Err == nil {
- groupChannelCount = r.Data.(int64)
- } else {
- t.Fatalf("Failed to get group channel count.")
- }
-
- // Do an invalid channel in dry-run mode.
- data := DirectChannelImportData{
- Members: &[]string{
- model.NewId(),
- },
- Header: ptrStr("Channel Header"),
- }
- if err := th.App.ImportDirectChannel(&data, true); err == nil {
- t.Fatalf("Expected error due to invalid name.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Do a valid DIRECT channel with a nonexistent member in dry-run mode.
- data.Members = &[]string{
- model.NewId(),
- model.NewId(),
- }
- if err := th.App.ImportDirectChannel(&data, true); err != nil {
- t.Fatalf("Expected success as cannot validate existence of channel members in dry run mode.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Do a valid GROUP channel with a nonexistent member in dry-run mode.
- data.Members = &[]string{
- model.NewId(),
- model.NewId(),
- model.NewId(),
- }
- if err := th.App.ImportDirectChannel(&data, true); err != nil {
- t.Fatalf("Expected success as cannot validate existence of channel members in dry run mode.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Do an invalid channel in apply mode.
- data.Members = &[]string{
- model.NewId(),
- }
- if err := th.App.ImportDirectChannel(&data, false); err == nil {
- t.Fatalf("Expected error due to invalid member (apply mode).")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Do a valid DIRECT channel.
- data.Members = &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- }
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
-
- // Check that one more DIRECT channel is in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Do the same DIRECT channel again.
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Update the channel's HEADER
- data.Header = ptrStr("New Channel Header 2")
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Get the channel to check that the header was updated.
- if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err == nil || err.Id != store.CHANNEL_EXISTS_ERROR {
- t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
- } else {
- if channel.Header != *data.Header {
- t.Fatal("Channel header has not been updated successfully.")
- }
- }
-
- // Do a GROUP channel with an extra invalid member.
- user3 := th.CreateUser()
- data.Members = &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- model.NewId(),
- }
- if err := th.App.ImportDirectChannel(&data, false); err == nil {
- t.Fatalf("Should have failed due to invalid member in list.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
-
- // Do a valid GROUP channel.
- data.Members = &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- }
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- // Check that one more GROUP channel is in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
-
- // Do the same DIRECT channel again.
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
-
- // Update the channel's HEADER
- data.Header = ptrStr("New Channel Header 3")
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- // Check that no more channels are in the DB.
- AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
- AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
-
- // Get the channel to check that the header was updated.
- userIds := []string{
- th.BasicUser.Id,
- th.BasicUser2.Id,
- user3.Id,
- }
- if channel, err := th.App.createGroupChannel(userIds, th.BasicUser.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
- t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
- } else {
- if channel.Header != *data.Header {
- t.Fatal("Channel header has not been updated successfully.")
- }
- }
-
- // Import a channel with some favorites.
- data.Members = &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- }
- data.FavoritedBy = &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- }
- if err := th.App.ImportDirectChannel(&data, false); err != nil {
- t.Fatal(err)
- }
-
- if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err == nil || err.Id != store.CHANNEL_EXISTS_ERROR {
- t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
- } else {
- checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
- checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
- }
-}
-
func AssertChannelCount(t *testing.T, a *App, channelType string, expectedCount int64) {
if r := <-a.Srv.Store.Channel().AnalyticsTypeCount("", channelType); r.Err == nil {
count := r.Data.(int64)
@@ -3315,405 +103,6 @@ func AssertChannelCount(t *testing.T, a *App, channelType string, expectedCount
}
}
-func TestImportImportDirectPost(t *testing.T) {
- th := Setup().InitBasic()
- defer th.TearDown()
-
- // Create the DIRECT channel.
- channelData := DirectChannelImportData{
- Members: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- }
- if err := th.App.ImportDirectChannel(&channelData, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
-
- // Get the channel.
- var directChannel *model.Channel
- if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
- t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
- } else {
- directChannel = channel
- }
-
- // Get the number of posts in the system.
- var initialPostCount int64
- if result := <-th.App.Srv.Store.Post().AnalyticsPostCount("", false, false); result.Err != nil {
- t.Fatal(result.Err)
- } else {
- initialPostCount = result.Data.(int64)
- }
-
- // Try adding an invalid post in dry run mode.
- data := &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, true); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
-
- // Try adding a valid post in dry run mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, true); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
-
- // Try adding an invalid post in apply mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- model.NewId(),
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, false); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
-
- // Try adding a valid post in apply mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
- t.Fatal("Post properties not as expected")
- }
- }
-
- // Import the post again.
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
- t.Fatal("Post properties not as expected")
- }
- }
-
- // Save the post with a different time.
- data.CreateAt = ptrInt64(*data.CreateAt + 1)
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
-
- // Save the post with a different message.
- data.Message = ptrStr("Message 2")
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
-
- // Test with hashtags
- data.Message = ptrStr("Message 2 #hashtagmashupcity")
- data.CreateAt = ptrInt64(*data.CreateAt + 1)
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
-
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
- t.Fatal("Post properties not as expected")
- }
- if post.Hashtags != "#hashtagmashupcity" {
- t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
- }
- }
-
- // Test with some flags.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- FlaggedBy: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
-
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
- checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
- }
-
- // ------------------ Group Channel -------------------------
-
- // Create the GROUP channel.
- user3 := th.CreateUser()
- channelData = DirectChannelImportData{
- Members: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- },
- }
- if err := th.App.ImportDirectChannel(&channelData, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
-
- // Get the channel.
- var groupChannel *model.Channel
- userIds := []string{
- th.BasicUser.Id,
- th.BasicUser2.Id,
- user3.Id,
- }
- if channel, err := th.App.createGroupChannel(userIds, th.BasicUser.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
- t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
- } else {
- groupChannel = channel
- }
-
- // Get the number of posts in the system.
- if result := <-th.App.Srv.Store.Post().AnalyticsPostCount("", false, false); result.Err != nil {
- t.Fatal(result.Err)
- } else {
- initialPostCount = result.Data.(int64)
- }
-
- // Try adding an invalid post in dry run mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, true); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
-
- // Try adding a valid post in dry run mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, true); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
-
- // Try adding an invalid post in apply mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- model.NewId(),
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, false); err == nil {
- t.Fatalf("Expected error.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
-
- // Try adding a valid post in apply mode.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
- t.Fatal("Post properties not as expected")
- }
- }
-
- // Import the post again.
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
- t.Fatal("Post properties not as expected")
- }
- }
-
- // Save the post with a different time.
- data.CreateAt = ptrInt64(*data.CreateAt + 1)
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
-
- // Save the post with a different message.
- data.Message = ptrStr("Message 2")
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
-
- // Test with hashtags
- data.Message = ptrStr("Message 2 #hashtagmashupcity")
- data.CreateAt = ptrInt64(*data.CreateAt + 1)
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
- AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
-
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
- t.Fatal("Post properties not as expected")
- }
- if post.Hashtags != "#hashtagmashupcity" {
- t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
- }
- }
-
- // Test with some flags.
- data = &DirectPostImportData{
- ChannelMembers: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- user3.Username,
- },
- FlaggedBy: &[]string{
- th.BasicUser.Username,
- th.BasicUser2.Username,
- },
- User: ptrStr(th.BasicUser.Username),
- Message: ptrStr("Message"),
- CreateAt: ptrInt64(model.GetMillis()),
- }
-
- if err := th.App.ImportDirectPost(data, false); err != nil {
- t.Fatalf("Expected success: %v", err.Error())
- }
-
- // Check the post values.
- if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
- t.Fatal(result.Err.Error())
- } else {
- posts := result.Data.([]*model.Post)
- if len(posts) != 1 {
- t.Fatal("Unexpected number of posts found.")
- }
- post := posts[0]
- checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
- checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
- }
-}
-
func TestImportImportLine(t *testing.T) {
th := Setup()
defer th.TearDown()
@@ -3840,240 +229,6 @@ func TestImportProcessImportDataFileVersionLine(t *testing.T) {
}
}
-func TestImportValidateEmojiImportData(t *testing.T) {
- data := EmojiImportData{
- Name: ptrStr("parrot"),
- Image: ptrStr("/path/to/image"),
- }
-
- err := validateEmojiImportData(&data)
- assert.Nil(t, err, "Validation should succeed")
-
- *data.Name = "smiley"
- err = validateEmojiImportData(&data)
- assert.NotNil(t, err)
-
- *data.Name = ""
- err = validateEmojiImportData(&data)
- assert.NotNil(t, err)
-
- *data.Name = ""
- *data.Image = ""
- err = validateEmojiImportData(&data)
- assert.NotNil(t, err)
-
- *data.Image = "/path/to/image"
- data.Name = nil
- err = validateEmojiImportData(&data)
- assert.NotNil(t, err)
-
- data.Name = ptrStr("parrot")
- data.Image = nil
- err = validateEmojiImportData(&data)
- assert.NotNil(t, err)
-}
-
-func TestImportImportEmoji(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
-
- testsDir, _ := utils.FindDir("tests")
- testImage := filepath.Join(testsDir, "test.png")
-
- data := EmojiImportData{Name: ptrStr(model.NewId())}
- err := th.App.ImportEmoji(&data, true)
- assert.NotNil(t, err, "Invalid emoji should have failed dry run")
-
- result := <-th.App.Srv.Store.Emoji().GetByName(*data.Name)
- assert.Nil(t, result.Data, "Emoji should not have been imported")
-
- data.Image = ptrStr(testImage)
- err = th.App.ImportEmoji(&data, true)
- assert.Nil(t, err, "Valid emoji should have passed dry run")
-
- data = EmojiImportData{Name: ptrStr(model.NewId())}
- err = th.App.ImportEmoji(&data, false)
- assert.NotNil(t, err, "Invalid emoji should have failed apply mode")
-
- data.Image = ptrStr("non-existent-file")
- err = th.App.ImportEmoji(&data, false)
- assert.NotNil(t, err, "Emoji with bad image file should have failed apply mode")
-
- data.Image = ptrStr(testImage)
- err = th.App.ImportEmoji(&data, false)
- assert.Nil(t, err, "Valid emoji should have succeeded apply mode")
-
- result = <-th.App.Srv.Store.Emoji().GetByName(*data.Name)
- assert.NotNil(t, result.Data, "Emoji should have been imported")
-
- err = th.App.ImportEmoji(&data, false)
- assert.Nil(t, err, "Second run should have succeeded apply mode")
-}
-
-func TestImportAttachment(t *testing.T) {
- th := Setup()
- defer th.TearDown()
-
- testsDir, _ := utils.FindDir("tests")
- testImage := filepath.Join(testsDir, "test.png")
- invalidPath := "some-invalid-path"
-
- userId := model.NewId()
- data := AttachmentImportData{Path: &testImage}
- _, err := th.App.ImportAttachment(&data, &model.Post{UserId: userId, ChannelId: "some-channel"}, "some-team", true)
- assert.Nil(t, err, "sample run without errors")
-
- attachments := GetAttachments(userId, th, t)
- assert.Equal(t, len(attachments), 1)
-
- data = AttachmentImportData{Path: &invalidPath}
- _, err = th.App.ImportAttachment(&data, &model.Post{UserId: model.NewId(), ChannelId: "some-channel"}, "some-team", true)
- assert.NotNil(t, err, "should have failed when opening the file")
- assert.Equal(t, err.Id, "app.import.attachment.bad_file.error")
-}
-
-func TestImportPostAndRepliesWithAttachments(t *testing.T) {
-
- th := Setup()
- defer th.TearDown()
-
- // Create a Team.
- teamName := model.NewId()
- th.App.ImportTeam(&TeamImportData{
- Name: &teamName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- team, err := th.App.GetTeamByName(teamName)
- if err != nil {
- t.Fatalf("Failed to get team from database.")
- }
-
- // Create a Channel.
- channelName := model.NewId()
- th.App.ImportChannel(&ChannelImportData{
- Team: &teamName,
- Name: &channelName,
- DisplayName: ptrStr("Display Name"),
- Type: ptrStr("O"),
- }, false)
- _, err = th.App.GetChannelByName(channelName, team.Id, false)
- if err != nil {
- t.Fatalf("Failed to get channel from database.")
- }
-
- // Create a user3.
- username := model.NewId()
- th.App.ImportUser(&UserImportData{
- Username: &username,
- Email: ptrStr(model.NewId() + "@example.com"),
- }, false)
- user3, err := th.App.GetUserByUsername(username)
- if err != nil {
- t.Fatalf("Failed to get user3 from database.")
- }
-
- username2 := model.NewId()
- th.App.ImportUser(&UserImportData{
- Username: &username2,
- Email: ptrStr(model.NewId() + "@example.com"),
- }, false)
- user4, err := th.App.GetUserByUsername(username2)
- if err != nil {
- t.Fatalf("Failed to get user3 from database.")
- }
-
- // Post with attachments.
- time := model.GetMillis()
- attachmentsPostTime := time
- attachmentsReplyTime := time + 1
- testsDir, _ := utils.FindDir("tests")
- testImage := filepath.Join(testsDir, "test.png")
- testMarkDown := filepath.Join(testsDir, "test-attachments.md")
- data := &PostImportData{
- Team: &teamName,
- Channel: &channelName,
- User: &username,
- Message: ptrStr("Message with reply"),
- CreateAt: &attachmentsPostTime,
- Attachments: &[]AttachmentImportData{{Path: &testImage}, {Path: &testMarkDown}},
- Replies: &[]ReplyImportData{{
- User: &user4.Username,
- Message: ptrStr("Message reply"),
- CreateAt: &attachmentsReplyTime,
- Attachments: &[]AttachmentImportData{{Path: &testImage}},
- }},
- }
-
- if err := th.App.ImportPost(data, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- attachments := GetAttachments(user3.Id, th, t)
- assert.Equal(t, len(attachments), 2)
- assert.Contains(t, attachments[0].Path, team.Id)
- assert.Contains(t, attachments[1].Path, team.Id)
- AssertFileIdsInPost(attachments, th, t)
-
- attachments = GetAttachments(user4.Id, th, t)
- assert.Equal(t, len(attachments), 1)
- assert.Contains(t, attachments[0].Path, team.Id)
- AssertFileIdsInPost(attachments, th, t)
-
- // Reply with Attachments in Direct Post
-
- // Create direct post users.
-
- username3 := model.NewId()
- th.App.ImportUser(&UserImportData{
- Username: &username3,
- Email: ptrStr(model.NewId() + "@example.com"),
- }, false)
- user3, err = th.App.GetUserByUsername(username3)
- if err != nil {
- t.Fatalf("Failed to get user3 from database.")
- }
-
- username4 := model.NewId()
- th.App.ImportUser(&UserImportData{
- Username: &username4,
- Email: ptrStr(model.NewId() + "@example.com"),
- }, false)
-
- user4, err = th.App.GetUserByUsername(username4)
- if err != nil {
- t.Fatalf("Failed to get user3 from database.")
- }
-
- directImportData := &DirectPostImportData{
- ChannelMembers: &[]string{
- user3.Username,
- user4.Username,
- },
- User: &user3.Username,
- Message: ptrStr("Message with Replies"),
- CreateAt: ptrInt64(model.GetMillis()),
- Replies: &[]ReplyImportData{{
- User: &user4.Username,
- Message: ptrStr("Message reply with attachment"),
- CreateAt: ptrInt64(model.GetMillis()),
- Attachments: &[]AttachmentImportData{{Path: &testImage}},
- }},
- }
-
- if err := th.App.ImportDirectPost(directImportData, false); err != nil {
- t.Fatalf("Expected success.")
- }
-
- attachments = GetAttachments(user4.Id, th, t)
- assert.Equal(t, len(attachments), 1)
- assert.Contains(t, attachments[0].Path, "noteam")
- AssertFileIdsInPost(attachments, th, t)
-
-}
-
func GetAttachments(userId string, th *TestHelper, t *testing.T) []*model.FileInfo {
if result := <-th.App.Srv.Store.FileInfo().GetForUser(userId); result.Err != nil {
t.Fatal(result.Err.Error())
diff --git a/app/import_types.go b/app/import_types.go
new file mode 100644
index 000000000..45119bffa
--- /dev/null
+++ b/app/import_types.go
@@ -0,0 +1,186 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import "github.com/mattermost/mattermost-server/model"
+
+// Import Data Models
+
+type LineImportData struct {
+ Type string `json:"type"`
+ Scheme *SchemeImportData `json:"scheme"`
+ 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"`
+ Emoji *EmojiImportData `json:"emoji"`
+ 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"`
+ Scheme *string `json:"scheme"`
+}
+
+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"`
+ Scheme *string `json:"scheme"`
+}
+
+type UserImportData struct {
+ ProfileImage *string `json:"profile_image"`
+ 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"`
+ 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 EmojiImportData struct {
+ Name *string `json:"name"`
+ Image *string `json:"image"`
+}
+
+type ReactionImportData struct {
+ User *string `json:"user"`
+ CreateAt *int64 `json:"create_at"`
+ EmojiName *string `json:"emoji_name"`
+}
+
+type ReplyImportData struct {
+ User *string `json:"user"`
+
+ Message *string `json:"message"`
+ CreateAt *int64 `json:"create_at"`
+
+ FlaggedBy *[]string `json:"flagged_by"`
+ Reactions *[]ReactionImportData `json:"reactions"`
+ Attachments *[]AttachmentImportData `json:"attachments"`
+}
+
+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"`
+ Reactions *[]ReactionImportData `json:"reactions"`
+ Replies *[]ReplyImportData `json:"replies"`
+ Attachments *[]AttachmentImportData `json:"attachments"`
+}
+
+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"`
+ Reactions *[]ReactionImportData `json:"reactions"`
+ Replies *[]ReplyImportData `json:"replies"`
+}
+
+type SchemeImportData struct {
+ Name *string `json:"name"`
+ DisplayName *string `json:"display_name"`
+ Description *string `json:"description"`
+ Scope *string `json:"scope"`
+ DefaultTeamAdminRole *RoleImportData `json:"default_team_admin_role"`
+ DefaultTeamUserRole *RoleImportData `json:"default_team_user_role"`
+ DefaultChannelAdminRole *RoleImportData `json:"default_channel_admin_role"`
+ DefaultChannelUserRole *RoleImportData `json:"default_channel_user_role"`
+}
+
+type RoleImportData struct {
+ Name *string `json:"name"`
+ DisplayName *string `json:"display_name"`
+ Description *string `json:"description"`
+ Permissions *[]string `json:"permissions"`
+}
+
+type LineImportWorkerData struct {
+ LineImportData
+ LineNumber int
+}
+
+type LineImportWorkerError struct {
+ Error *model.AppError
+ LineNumber int
+}
+
+type AttachmentImportData struct {
+ Path *string `json:"path"`
+}
diff --git a/app/import_validators.go b/app/import_validators.go
new file mode 100644
index 000000000..9b19ae45e
--- /dev/null
+++ b/app/import_validators.go
@@ -0,0 +1,529 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "net/http"
+ "os"
+ "unicode/utf8"
+
+ "github.com/mattermost/mattermost-server/model"
+)
+
+func validateSchemeImportData(data *SchemeImportData) *model.AppError {
+
+ if data.Scope == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.null_scope.error", nil, "", http.StatusBadRequest)
+ }
+
+ switch *data.Scope {
+ case model.SCHEME_SCOPE_TEAM:
+ if data.DefaultTeamAdminRole == nil || data.DefaultTeamUserRole == nil || data.DefaultChannelAdminRole == nil || data.DefaultChannelUserRole == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.wrong_roles_for_scope.error", nil, "", http.StatusBadRequest)
+ }
+ case model.SCHEME_SCOPE_CHANNEL:
+ if data.DefaultTeamAdminRole != nil || data.DefaultTeamUserRole != nil || data.DefaultChannelAdminRole == nil || data.DefaultChannelUserRole == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.wrong_roles_for_scope.error", nil, "", http.StatusBadRequest)
+ }
+ default:
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.unknown_scheme.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Name == nil || !model.IsValidSchemeName(*data.Name) {
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.name_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.DisplayName == nil || len(*data.DisplayName) == 0 || len(*data.DisplayName) > model.SCHEME_DISPLAY_NAME_MAX_LENGTH {
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.display_name_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Description != nil && len(*data.Description) > model.SCHEME_DESCRIPTION_MAX_LENGTH {
+ return model.NewAppError("BulkImport", "app.import.validate_scheme_import_data.description_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.DefaultTeamAdminRole != nil {
+ if err := validateRoleImportData(data.DefaultTeamAdminRole); err != nil {
+ return err
+ }
+ }
+
+ if data.DefaultTeamUserRole != nil {
+ if err := validateRoleImportData(data.DefaultTeamUserRole); err != nil {
+ return err
+ }
+ }
+
+ if data.DefaultChannelAdminRole != nil {
+ if err := validateRoleImportData(data.DefaultChannelAdminRole); err != nil {
+ return err
+ }
+ }
+
+ if data.DefaultChannelUserRole != nil {
+ if err := validateRoleImportData(data.DefaultChannelUserRole); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func validateRoleImportData(data *RoleImportData) *model.AppError {
+
+ if data.Name == nil || !model.IsValidRoleName(*data.Name) {
+ return model.NewAppError("BulkImport", "app.import.validate_role_import_data.name_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.DisplayName == nil || len(*data.DisplayName) == 0 || len(*data.DisplayName) > model.ROLE_DISPLAY_NAME_MAX_LENGTH {
+ return model.NewAppError("BulkImport", "app.import.validate_role_import_data.display_name_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Description != nil && len(*data.Description) > model.ROLE_DESCRIPTION_MAX_LENGTH {
+ return model.NewAppError("BulkImport", "app.import.validate_role_import_data.description_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Permissions != nil {
+ for _, permission := range *data.Permissions {
+ permissionValidated := false
+ for _, p := range model.ALL_PERMISSIONS {
+ if permission == p.Id {
+ permissionValidated = true
+ break
+ }
+ }
+
+ if !permissionValidated {
+ return model.NewAppError("BulkImport", "app.import.validate_role_import_data.invalid_permission.error", nil, "permission"+permission, http.StatusBadRequest)
+ }
+ }
+ }
+
+ 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)
+ }
+
+ if data.Scheme != nil && !model.IsValidSchemeName(*data.Scheme) {
+ return model.NewAppError("BulkImport", "app.import.validate_team_import_data.scheme_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ 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)
+ }
+
+ if data.Scheme != nil && !model.IsValidSchemeName(*data.Scheme) {
+ return model.NewAppError("BulkImport", "app.import.validate_channel_import_data.scheme_invalid.error", nil, "", http.StatusBadRequest)
+ }
+
+ return nil
+}
+
+func validateUserImportData(data *UserImportData) *model.AppError {
+ if data.ProfileImage != nil {
+ if _, err := os.Stat(*data.ProfileImage); os.IsNotExist(err) {
+ return model.NewAppError("BulkImport", "app.import.validate_user_import_data.profile_image.error", nil, "", http.StatusBadRequest)
+ }
+ }
+
+ 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.password_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.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 validateReactionImportData(data *ReactionImportData, parentCreateAt int64) *model.AppError {
+ if data.User == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.user_missing.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.EmojiName == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_missing.error", nil, "", http.StatusBadRequest)
+ } else if utf8.RuneCountInString(*data.EmojiName) > model.EMOJI_NAME_MAX_LENGTH {
+ return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.emoji_name_length.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.CreateAt == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
+ } else if *data.CreateAt == 0 {
+ return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
+ } else if *data.CreateAt < parentCreateAt {
+ return model.NewAppError("BulkImport", "app.import.validate_reaction_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
+ }
+
+ return nil
+}
+
+func validateReplyImportData(data *ReplyImportData, parentCreateAt int64, maxPostSize int) *model.AppError {
+ if data.User == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.user_missing.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Message == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_missing.error", nil, "", http.StatusBadRequest)
+ } else if utf8.RuneCountInString(*data.Message) > maxPostSize {
+ return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.message_length.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.CreateAt == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_missing.error", nil, "", http.StatusBadRequest)
+ } else if *data.CreateAt == 0 {
+ return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_zero.error", nil, "", http.StatusBadRequest)
+ } else if *data.CreateAt < parentCreateAt {
+ return model.NewAppError("BulkImport", "app.import.validate_reply_import_data.create_at_before_parent.error", nil, "", http.StatusBadRequest)
+ }
+
+ return nil
+}
+
+func validatePostImportData(data *PostImportData, maxPostSize int) *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) > maxPostSize {
+ 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)
+ }
+
+ if data.Reactions != nil {
+ for _, reaction := range *data.Reactions {
+ validateReactionImportData(&reaction, *data.CreateAt)
+ }
+ }
+
+ if data.Replies != nil {
+ for _, reply := range *data.Replies {
+ validateReplyImportData(&reply, *data.CreateAt, maxPostSize)
+ }
+ }
+
+ 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 validateDirectPostImportData(data *DirectPostImportData, maxPostSize int) *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) > maxPostSize {
+ 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)
+ }
+ }
+ }
+
+ if data.Reactions != nil {
+ for _, reaction := range *data.Reactions {
+ validateReactionImportData(&reaction, *data.CreateAt)
+ }
+ }
+
+ if data.Replies != nil {
+ for _, reply := range *data.Replies {
+ validateReplyImportData(&reply, *data.CreateAt, maxPostSize)
+ }
+ }
+
+ return nil
+}
+
+func validateEmojiImportData(data *EmojiImportData) *model.AppError {
+ if data == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.empty.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Name == nil || len(*data.Name) == 0 {
+ return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.name_missing.error", nil, "", http.StatusBadRequest)
+ }
+
+ if err := model.IsValidEmojiName(*data.Name); err != nil {
+ return err
+ }
+
+ if data.Image == nil || len(*data.Image) == 0 {
+ return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.image_missing.error", nil, "", http.StatusBadRequest)
+ }
+
+ return nil
+}
diff --git a/app/import_validators_test.go b/app/import_validators_test.go
new file mode 100644
index 000000000..5fb0518f7
--- /dev/null
+++ b/app/import_validators_test.go
@@ -0,0 +1,1372 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/utils"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestImportValidateSchemeImportData(t *testing.T) {
+ // Test with minimum required valid properties and team scope.
+ data := SchemeImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Scope: ptrStr("team"),
+ DefaultTeamAdminRole: &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ },
+ DefaultTeamUserRole: &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ },
+ DefaultChannelAdminRole: &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ },
+ DefaultChannelUserRole: &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ },
+ }
+ if err := validateSchemeImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.", err)
+ }
+
+ // Test with various invalid names.
+ data.Name = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+
+ data.Name = ptrStr("")
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+
+ data.Name = ptrStr(strings.Repeat("1234567890", 100))
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+
+ data.Name = ptrStr("name")
+ // Test with invalid display name.
+ data.DisplayName = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid display name.")
+ }
+
+ data.DisplayName = ptrStr("")
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid display name.")
+ }
+
+ data.DisplayName = ptrStr(strings.Repeat("1234567890", 100))
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid display name.")
+ }
+
+ data.DisplayName = ptrStr("display name")
+
+ // Test with various missing roles.
+ data.DefaultTeamAdminRole = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing role.")
+ }
+
+ data.DefaultTeamAdminRole = &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ }
+ data.DefaultTeamUserRole = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing role.")
+ }
+
+ data.DefaultTeamUserRole = &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ }
+ data.DefaultChannelAdminRole = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing role.")
+ }
+
+ data.DefaultChannelAdminRole = &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ }
+ data.DefaultChannelUserRole = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing role.")
+ }
+
+ data.DefaultChannelUserRole = &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ }
+
+ // Test with various invalid roles.
+ data.DefaultTeamAdminRole.Name = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid role.")
+ }
+
+ data.DefaultTeamAdminRole.Name = ptrStr("name")
+ data.DefaultTeamUserRole.Name = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid role.")
+ }
+
+ data.DefaultTeamUserRole.Name = ptrStr("name")
+ data.DefaultChannelAdminRole.Name = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid role.")
+ }
+
+ data.DefaultChannelAdminRole.Name = ptrStr("name")
+ data.DefaultChannelUserRole.Name = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid role.")
+ }
+
+ data.DefaultChannelUserRole.Name = ptrStr("name")
+
+ // Change to a Channel scope role, and check with missing or extra roles again.
+ data.Scope = ptrStr("channel")
+ data.DefaultTeamAdminRole = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to spurious role.")
+ }
+
+ data.DefaultTeamAdminRole = &RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ Permissions: &[]string{"invite_user"},
+ }
+ data.DefaultTeamUserRole = nil
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to spurious role.")
+ }
+
+ data.DefaultTeamAdminRole = nil
+ if err := validateSchemeImportData(&data); err != nil {
+ t.Fatal("Should have succeeded.")
+ }
+
+ // Test with all combinations of optional parameters.
+ data.Description = ptrStr(strings.Repeat("1234567890", 1024))
+ if err := validateSchemeImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid description.")
+ }
+
+ data.Description = ptrStr("description")
+ if err := validateSchemeImportData(&data); err != nil {
+ t.Fatal("Should have succeeded.")
+ }
+}
+
+func TestImportValidateRoleImportData(t *testing.T) {
+ // Test with minimum required valid properties.
+ data := RoleImportData{
+ Name: ptrStr("name"),
+ DisplayName: ptrStr("display name"),
+ }
+ if err := validateRoleImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.", err)
+ }
+
+ // Test with various invalid names.
+ data.Name = nil
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+
+ data.Name = ptrStr("")
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+
+ data.Name = ptrStr(strings.Repeat("1234567890", 100))
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+
+ data.Name = ptrStr("name")
+ // Test with invalid display name.
+ data.DisplayName = nil
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid display name.")
+ }
+
+ data.DisplayName = ptrStr("")
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid display name.")
+ }
+
+ data.DisplayName = ptrStr(strings.Repeat("1234567890", 100))
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid display name.")
+ }
+
+ data.DisplayName = ptrStr("display name")
+
+ // Test with various valid/invalid permissions.
+ data.Permissions = &[]string{}
+ if err := validateRoleImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.", err)
+ }
+
+ data.Permissions = &[]string{"invite_user", "add_user_to_team"}
+ if err := validateRoleImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.", err)
+ }
+
+ data.Permissions = &[]string{"invite_user", "add_user_to_team", "derp"}
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to invalid permission.", err)
+ }
+
+ data.Permissions = &[]string{"invite_user", "add_user_to_team"}
+
+ // Test with various valid/invalid descriptions.
+ data.Description = ptrStr(strings.Repeat("1234567890", 1024))
+ if err := validateRoleImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to invalid description.", err)
+ }
+
+ data.Description = ptrStr("description")
+ if err := validateRoleImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.", err)
+ }
+}
+
+func TestImportValidateTeamImportData(t *testing.T) {
+
+ // Test with minimum required valid properties.
+ data := TeamImportData{
+ Name: ptrStr("teamname"),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }
+ if err := validateTeamImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with various invalid names.
+ data = TeamImportData{
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing name.")
+ }
+
+ data.Name = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long name.")
+ }
+
+ data.Name = ptrStr("login")
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to reserved word in name.")
+ }
+
+ data.Name = ptrStr("Test::''ASD")
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to non alphanum characters in name.")
+ }
+
+ data.Name = ptrStr("A")
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to short name.")
+ }
+
+ // Test team various invalid display names.
+ data = TeamImportData{
+ Name: ptrStr("teamname"),
+ Type: ptrStr("O"),
+ }
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing display_name.")
+ }
+
+ data.DisplayName = ptrStr("")
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to empty display_name.")
+ }
+
+ data.DisplayName = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long display_name.")
+ }
+
+ // Test with various valid and invalid types.
+ data = TeamImportData{
+ Name: ptrStr("teamname"),
+ DisplayName: ptrStr("Display Name"),
+ }
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing type.")
+ }
+
+ data.Type = ptrStr("A")
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid type.")
+ }
+
+ data.Type = ptrStr("I")
+ if err := validateTeamImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid type.")
+ }
+
+ // Test with all the combinations of optional parameters.
+ data = TeamImportData{
+ Name: ptrStr("teamname"),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ Description: ptrStr("The team description."),
+ AllowOpenInvite: ptrBool(true),
+ }
+ if err := validateTeamImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid optional properties.")
+ }
+
+ data.AllowOpenInvite = ptrBool(false)
+ if err := validateTeamImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with allow open invites false.")
+ }
+
+ data.Description = ptrStr(strings.Repeat("abcdefghij ", 26))
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long description.")
+ }
+
+ // Test with an empty scheme name.
+ data.Description = ptrStr("abcdefg")
+ data.Scheme = ptrStr("")
+ if err := validateTeamImportData(&data); err == nil {
+ t.Fatal("Should have failed due to empty scheme name.")
+ }
+
+ // Test with a valid scheme name.
+ data.Scheme = ptrStr("abcdefg")
+ if err := validateTeamImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid scheme name.")
+ }
+}
+
+func TestImportValidateChannelImportData(t *testing.T) {
+
+ // Test with minimum required valid properties.
+ data := ChannelImportData{
+ Team: ptrStr("teamname"),
+ Name: ptrStr("channelname"),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }
+ if err := validateChannelImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with missing team.
+ data = ChannelImportData{
+ Name: ptrStr("channelname"),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing team.")
+ }
+
+ // Test with various invalid names.
+ data = ChannelImportData{
+ Team: ptrStr("teamname"),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ }
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing name.")
+ }
+
+ data.Name = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long name.")
+ }
+
+ data.Name = ptrStr("Test::''ASD")
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to non alphanum characters in name.")
+ }
+
+ data.Name = ptrStr("A")
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to short name.")
+ }
+
+ // Test team various invalid display names.
+ data = ChannelImportData{
+ Team: ptrStr("teamname"),
+ Name: ptrStr("channelname"),
+ Type: ptrStr("O"),
+ }
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing display_name.")
+ }
+
+ data.DisplayName = ptrStr("")
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to empty display_name.")
+ }
+
+ data.DisplayName = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long display_name.")
+ }
+
+ // Test with various valid and invalid types.
+ data = ChannelImportData{
+ Team: ptrStr("teamname"),
+ Name: ptrStr("channelname"),
+ DisplayName: ptrStr("Display Name"),
+ }
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to missing type.")
+ }
+
+ data.Type = ptrStr("A")
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid type.")
+ }
+
+ data.Type = ptrStr("P")
+ if err := validateChannelImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid type.")
+ }
+
+ // Test with all the combinations of optional parameters.
+ data = ChannelImportData{
+ Team: ptrStr("teamname"),
+ Name: ptrStr("channelname"),
+ DisplayName: ptrStr("Display Name"),
+ Type: ptrStr("O"),
+ Header: ptrStr("Channel Header Here"),
+ Purpose: ptrStr("Channel Purpose Here"),
+ }
+ if err := validateChannelImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid optional properties.")
+ }
+
+ data.Header = ptrStr(strings.Repeat("abcdefghij ", 103))
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long header.")
+ }
+
+ data.Header = ptrStr("Channel Header Here")
+ data.Purpose = ptrStr(strings.Repeat("abcdefghij ", 26))
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long purpose.")
+ }
+
+ // Test with an empty scheme name.
+ data.Purpose = ptrStr("abcdefg")
+ data.Scheme = ptrStr("")
+ if err := validateChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to empty scheme name.")
+ }
+
+ // Test with a valid scheme name.
+ data.Scheme = ptrStr("abcdefg")
+ if err := validateChannelImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid scheme name.")
+ }
+}
+
+func TestImportValidateUserImportData(t *testing.T) {
+
+ // Test with minimum required valid properties.
+ data := UserImportData{
+ Username: ptrStr("bob"),
+ Email: ptrStr("bob@example.com"),
+ }
+ if err := validateUserImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Invalid Usernames.
+ data.Username = nil
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to nil Username.")
+ }
+
+ data.Username = ptrStr("")
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to 0 length Username.")
+ }
+
+ data.Username = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long Username.")
+ }
+
+ data.Username = ptrStr("i am a username with spaces and !!!")
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to invalid characters in Username.")
+ }
+
+ data.Username = ptrStr("bob")
+
+ // Unexisting Picture Image
+ data.ProfileImage = ptrStr("not-existing-file")
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to not existing profile image file.")
+ }
+ data.ProfileImage = nil
+
+ // Invalid Emails
+ data.Email = nil
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to nil Email.")
+ }
+
+ data.Email = ptrStr("")
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to 0 length Email.")
+ }
+
+ data.Email = ptrStr(strings.Repeat("abcdefghij", 13))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long Email.")
+ }
+
+ data.Email = ptrStr("bob@example.com")
+
+ data.AuthService = ptrStr("")
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to 0-length auth service.")
+ }
+
+ data.AuthService = ptrStr("saml")
+ data.AuthData = ptrStr(strings.Repeat("abcdefghij", 15))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long auth data.")
+ }
+
+ data.AuthData = ptrStr("bobbytables")
+ if err := validateUserImportData(&data); err != nil {
+ t.Fatal("Validation should have succeeded with valid auth service and auth data.")
+ }
+
+ // Test a valid User with all fields populated.
+ testsDir, _ := utils.FindDir("tests")
+ data = UserImportData{
+ ProfileImage: ptrStr(filepath.Join(testsDir, "test.png")),
+ Username: ptrStr("bob"),
+ Email: ptrStr("bob@example.com"),
+ AuthService: ptrStr("ldap"),
+ AuthData: ptrStr("bob"),
+ Nickname: ptrStr("BobNick"),
+ FirstName: ptrStr("Bob"),
+ LastName: ptrStr("Blob"),
+ Position: ptrStr("The Boss"),
+ Roles: ptrStr("system_user"),
+ Locale: ptrStr("en"),
+ }
+ if err := validateUserImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test various invalid optional field values.
+ data.Nickname = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long Nickname.")
+ }
+ data.Nickname = ptrStr("BobNick")
+
+ data.FirstName = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long First Name.")
+ }
+ data.FirstName = ptrStr("Bob")
+
+ data.LastName = ptrStr(strings.Repeat("abcdefghij", 7))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long Last name.")
+ }
+ data.LastName = ptrStr("Blob")
+
+ data.Position = ptrStr(strings.Repeat("abcdefghij", 13))
+ if err := validateUserImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to too long Position.")
+ }
+ data.Position = ptrStr("The Boss")
+
+ data.Roles = nil
+ if err := validateUserImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ data.Roles = ptrStr("")
+ if err := validateUserImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+ data.Roles = ptrStr("system_user")
+
+ // Try various valid/invalid notify props.
+ data.NotifyProps = &UserNotifyPropsImportData{}
+
+ data.NotifyProps.Desktop = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.Desktop = ptrStr(model.USER_NOTIFY_ALL)
+ data.NotifyProps.DesktopSound = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.DesktopSound = ptrStr("true")
+ data.NotifyProps.Email = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.Email = ptrStr("true")
+ data.NotifyProps.Mobile = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.Mobile = ptrStr(model.USER_NOTIFY_ALL)
+ data.NotifyProps.MobilePushStatus = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.MobilePushStatus = ptrStr(model.STATUS_ONLINE)
+ data.NotifyProps.ChannelTrigger = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.ChannelTrigger = ptrStr("true")
+ data.NotifyProps.CommentsTrigger = ptrStr("invalid")
+ checkError(t, validateUserImportData(&data))
+
+ data.NotifyProps.CommentsTrigger = ptrStr(model.COMMENTS_NOTIFY_ROOT)
+ data.NotifyProps.MentionKeys = ptrStr("valid")
+ checkNoError(t, validateUserImportData(&data))
+}
+
+func TestImportValidateUserTeamsImportData(t *testing.T) {
+
+ // Invalid Name.
+ data := []UserTeamImportData{
+ {
+ Roles: ptrStr("team_admin team_user"),
+ },
+ }
+ if err := validateUserTeamsImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+ data[0].Name = ptrStr("teamname")
+
+ // Valid (nil roles)
+ data[0].Roles = nil
+ if err := validateUserTeamsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with empty roles.")
+ }
+
+ // Valid (empty roles)
+ data[0].Roles = ptrStr("")
+ if err := validateUserTeamsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with empty roles.")
+ }
+
+ // Valid (with roles)
+ data[0].Roles = ptrStr("team_admin team_user")
+ if err := validateUserTeamsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid roles.")
+ }
+}
+
+func TestImportValidateUserChannelsImportData(t *testing.T) {
+
+ // Invalid Name.
+ data := []UserChannelImportData{
+ {
+ Roles: ptrStr("channel_admin channel_user"),
+ },
+ }
+ if err := validateUserChannelsImportData(&data); err == nil {
+ t.Fatal("Should have failed due to invalid name.")
+ }
+ data[0].Name = ptrStr("channelname")
+
+ // Valid (nil roles)
+ data[0].Roles = nil
+ if err := validateUserChannelsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with empty roles.")
+ }
+
+ // Valid (empty roles)
+ data[0].Roles = ptrStr("")
+ if err := validateUserChannelsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with empty roles.")
+ }
+
+ // Valid (with roles)
+ data[0].Roles = ptrStr("channel_admin channel_user")
+ if err := validateUserChannelsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid roles.")
+ }
+
+ // Empty notify props.
+ data[0].NotifyProps = &UserChannelNotifyPropsImportData{}
+ if err := validateUserChannelsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with empty notify props.")
+ }
+
+ // Invalid desktop notify props.
+ data[0].NotifyProps.Desktop = ptrStr("invalid")
+ if err := validateUserChannelsImportData(&data); err == nil {
+ t.Fatal("Should have failed with invalid desktop notify props.")
+ }
+
+ // Invalid mobile notify props.
+ data[0].NotifyProps.Desktop = ptrStr("mention")
+ data[0].NotifyProps.Mobile = ptrStr("invalid")
+ if err := validateUserChannelsImportData(&data); err == nil {
+ t.Fatal("Should have failed with invalid mobile notify props.")
+ }
+
+ // Invalid mark_unread notify props.
+ data[0].NotifyProps.Mobile = ptrStr("mention")
+ data[0].NotifyProps.MarkUnread = ptrStr("invalid")
+ if err := validateUserChannelsImportData(&data); err == nil {
+ t.Fatal("Should have failed with invalid mark_unread notify props.")
+ }
+
+ // Valid notify props.
+ data[0].NotifyProps.MarkUnread = ptrStr("mention")
+ if err := validateUserChannelsImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid notify props.")
+ }
+}
+
+func TestImportValidateReactionImportData(t *testing.T) {
+ // Test with minimum required valid properties.
+ parentCreateAt := model.GetMillis() - 100
+ data := ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr("emoji"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with missing required properties.
+ data = ReactionImportData{
+ EmojiName: ptrStr("emoji"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = ReactionImportData{
+ User: ptrStr("username"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr("emoji"),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ // Test with invalid emoji name.
+ data = ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr(strings.Repeat("1234567890", 500)),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err == nil {
+ t.Fatal("Should have failed due to too long emoji name.")
+ }
+
+ // Test with invalid CreateAt
+ data = ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr("emoji"),
+ CreateAt: ptrInt64(0),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err == nil {
+ t.Fatal("Should have failed due to 0 create-at value.")
+ }
+
+ data = ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr("emoji"),
+ CreateAt: ptrInt64(parentCreateAt - 100),
+ }
+ if err := validateReactionImportData(&data, parentCreateAt); err == nil {
+ t.Fatal("Should have failed due parent with newer create-at value.")
+ }
+}
+
+func TestImportValidateReplyImportData(t *testing.T) {
+ // Test with minimum required valid properties.
+ parentCreateAt := model.GetMillis() - 100
+ maxPostSize := 10000
+ data := ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with missing required properties.
+ data = ReplyImportData{
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = ReplyImportData{
+ User: ptrStr("username"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ // Test with invalid message.
+ data = ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr(strings.Repeat("0", maxPostSize+1)),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to too long message.")
+ }
+
+ // Test with invalid CreateAt
+ data = ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(0),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to 0 create-at value.")
+ }
+
+ data = ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(parentCreateAt - 100),
+ }
+ if err := validateReplyImportData(&data, parentCreateAt, maxPostSize); err == nil {
+ t.Fatal("Should have failed due parent with newer create-at value.")
+ }
+}
+
+func TestImportValidatePostImportData(t *testing.T) {
+ maxPostSize := 10000
+
+ // Test with minimum required valid properties.
+ data := PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with missing required properties.
+ data = PostImportData{
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ // Test with invalid message.
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ Message: ptrStr(strings.Repeat("0", maxPostSize+1)),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to too long message.")
+ }
+
+ // Test with invalid CreateAt
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(0),
+ }
+ if err := validatePostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to 0 create-at value.")
+ }
+
+ // Test with valid all optional parameters.
+ reactions := []ReactionImportData{ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr("emoji"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }}
+ replies := []ReplyImportData{ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }}
+ data = PostImportData{
+ Team: ptrStr("teamname"),
+ Channel: ptrStr("channelname"),
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ Reactions: &reactions,
+ Replies: &replies,
+ }
+ if err := validatePostImportData(&data, maxPostSize); err != nil {
+ t.Fatal("Should have succeeded.")
+ }
+}
+
+func TestImportValidateDirectChannelImportData(t *testing.T) {
+
+ // Test with valid number of members for direct message.
+ data := DirectChannelImportData{
+ Members: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ }
+ if err := validateDirectChannelImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with valid number of members for group message.
+ data = DirectChannelImportData{
+ Members: &[]string{
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ },
+ }
+ if err := validateDirectChannelImportData(&data); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with all the combinations of optional parameters.
+ data = DirectChannelImportData{
+ Members: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ Header: ptrStr("Channel Header Here"),
+ }
+ if err := validateDirectChannelImportData(&data); err != nil {
+ t.Fatal("Should have succeeded with valid optional properties.")
+ }
+
+ // Test with invalid Header.
+ data.Header = ptrStr(strings.Repeat("abcdefghij ", 103))
+ if err := validateDirectChannelImportData(&data); err == nil {
+ t.Fatal("Should have failed due to too long header.")
+ }
+
+ // Test with different combinations of invalid member counts.
+ data = DirectChannelImportData{
+ Members: &[]string{},
+ }
+ if err := validateDirectChannelImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to invalid number of members.")
+ }
+
+ data = DirectChannelImportData{
+ Members: &[]string{
+ model.NewId(),
+ },
+ }
+ if err := validateDirectChannelImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to invalid number of members.")
+ }
+
+ data = DirectChannelImportData{
+ Members: &[]string{
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ },
+ }
+ if err := validateDirectChannelImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to invalid number of members.")
+ }
+
+ // Test with invalid FavoritedBy
+ member1 := model.NewId()
+ member2 := model.NewId()
+ data = DirectChannelImportData{
+ Members: &[]string{
+ member1,
+ member2,
+ },
+ FavoritedBy: &[]string{
+ member1,
+ model.NewId(),
+ },
+ }
+ if err := validateDirectChannelImportData(&data); err == nil {
+ t.Fatal("Validation should have failed due to non-member favorited.")
+ }
+
+ // Test with valid FavoritedBy
+ data = DirectChannelImportData{
+ Members: &[]string{
+ member1,
+ member2,
+ },
+ FavoritedBy: &[]string{
+ member1,
+ member2,
+ },
+ }
+ if err := validateDirectChannelImportData(&data); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestImportValidateDirectPostImportData(t *testing.T) {
+ maxPostSize := 10000
+
+ // Test with minimum required valid properties.
+ data := DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with missing required properties.
+ data = DirectPostImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to missing required property.")
+ }
+
+ // Test with invalid numbers of channel members.
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{},
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to unsuitable number of members.")
+ }
+
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to unsuitable number of members.")
+ }
+
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to unsuitable number of members.")
+ }
+
+ // Test with group message number of members.
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
+ t.Fatal("Validation failed but should have been valid.")
+ }
+
+ // Test with invalid message.
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr(strings.Repeat("0", maxPostSize+1)),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to too long message.")
+ }
+
+ // Test with invalid CreateAt
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ model.NewId(),
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(0),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Should have failed due to 0 create-at value.")
+ }
+
+ // Test with invalid FlaggedBy
+ member1 := model.NewId()
+ member2 := model.NewId()
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ member1,
+ member2,
+ },
+ FlaggedBy: &[]string{
+ member1,
+ model.NewId(),
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err == nil {
+ t.Fatal("Validation should have failed due to non-member flagged.")
+ }
+
+ // Test with valid FlaggedBy
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ member1,
+ member2,
+ },
+ FlaggedBy: &[]string{
+ member1,
+ member2,
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }
+ if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
+ t.Fatal(err)
+ }
+
+ // Test with valid all optional parameters.
+ reactions := []ReactionImportData{ReactionImportData{
+ User: ptrStr("username"),
+ EmojiName: ptrStr("emoji"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }}
+ replies := []ReplyImportData{ReplyImportData{
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ }}
+ data = DirectPostImportData{
+ ChannelMembers: &[]string{
+ member1,
+ member2,
+ },
+ FlaggedBy: &[]string{
+ member1,
+ member2,
+ },
+ User: ptrStr("username"),
+ Message: ptrStr("message"),
+ CreateAt: ptrInt64(model.GetMillis()),
+ Reactions: &reactions,
+ Replies: &replies,
+ }
+
+ if err := validateDirectPostImportData(&data, maxPostSize); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestImportValidateEmojiImportData(t *testing.T) {
+ data := EmojiImportData{
+ Name: ptrStr("parrot"),
+ Image: ptrStr("/path/to/image"),
+ }
+
+ err := validateEmojiImportData(&data)
+ assert.Nil(t, err, "Validation should succeed")
+
+ *data.Name = "smiley"
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ *data.Name = ""
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ *data.Name = ""
+ *data.Image = ""
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ *data.Image = "/path/to/image"
+ data.Name = nil
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ data.Name = ptrStr("parrot")
+ data.Image = nil
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+}
diff --git a/app/slackimport.go b/app/slackimport.go
index f9e2ac4ab..5f1f73632 100644
--- a/app/slackimport.go
+++ b/app/slackimport.go
@@ -14,6 +14,7 @@ import (
"regexp"
"strconv"
"strings"
+ "time"
"unicode/utf8"
"net/http"
@@ -688,3 +689,120 @@ func (a *App) SlackImport(fileData multipart.File, fileSize int64, teamID string
return nil, log
}
+
+//
+// -- 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
+ maxPostSize := a.MaxPostSize()
+ for messageRuneCount := utf8.RuneCountInString(post.Message); messageRuneCount > 0 || firstIteration; messageRuneCount = utf8.RuneCountInString(post.Message) {
+ firstIteration = false
+ var remainder string
+ if messageRuneCount > maxPostSize {
+ remainder = string(([]rune(post.Message))[maxPostSize:])
+ post.Message = truncateRunes(post.Message, maxPostSize)
+ } else {
+ remainder = ""
+ }
+
+ post.Hashtags, _ = model.ParseHashtags(post.Message)
+
+ if result := <-a.Srv.Store.Post().Save(post); result.Err != nil {
+ mlog.Debug(fmt.Sprintf("Error saving post. user=%v, message=%v", post.UserId, post.Message))
+ }
+
+ 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))
+ }
+ }
+
+ post.Id = ""
+ post.CreateAt++
+ post.Message = remainder
+ }
+}
+
+func (a *App) OldImportUser(team *model.Team, user *model.User) *model.User {
+ user.MakeNonNil()
+
+ user.Roles = model.SYSTEM_USER_ROLE_ID
+
+ if result := <-a.Srv.Store.User().Save(user); result.Err != nil {
+ mlog.Error(fmt.Sprintf("Error saving user. err=%v", result.Err))
+ return nil
+ } else {
+ ruser := result.Data.(*model.User)
+
+ if cresult := <-a.Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
+ mlog.Error(fmt.Sprintf("Failed to set email verified err=%v", cresult.Err))
+ }
+
+ if err := a.JoinUserToTeam(team, user, ""); err != nil {
+ mlog.Error(fmt.Sprintf("Failed to join team when importing err=%v", err))
+ }
+
+ return ruser
+ }
+}
+
+func (a *App) OldImportChannel(channel *model.Channel) *model.Channel {
+ if result := <-a.Srv.Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam); 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
+ }
+
+ if fileInfo.IsImage() && fileInfo.MimeType != "image/svg+xml" {
+ img, width, height := prepareImage(data)
+ if img != nil {
+ a.generateThumbnailImage(*img, fileInfo.ThumbnailPath, width, height)
+ a.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)
+}