github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+incompatible/app/import_functions.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "net/http" 11 "os" 12 "strings" 13 14 "github.com/mattermost/mattermost-server/mlog" 15 "github.com/mattermost/mattermost-server/model" 16 "github.com/mattermost/mattermost-server/store" 17 "github.com/mattermost/mattermost-server/utils" 18 ) 19 20 // 21 // -- Bulk Import Functions -- 22 // These functions import data directly into the database. Security and permission checks are bypassed but validity is 23 // still enforced. 24 // 25 26 func (a *App) ImportScheme(data *SchemeImportData, dryRun bool) *model.AppError { 27 if err := validateSchemeImportData(data); err != nil { 28 return err 29 } 30 31 // If this is a Dry Run, do not continue any further. 32 if dryRun { 33 return nil 34 } 35 36 scheme, err := a.GetSchemeByName(*data.Name) 37 if err != nil { 38 scheme = new(model.Scheme) 39 } else if scheme.Scope != *data.Scope { 40 return model.NewAppError("BulkImport", "app.import.import_scheme.scope_change.error", map[string]interface{}{"SchemeName": scheme.Name}, "", http.StatusBadRequest) 41 } 42 43 scheme.Name = *data.Name 44 scheme.DisplayName = *data.DisplayName 45 scheme.Scope = *data.Scope 46 47 if data.Description != nil { 48 scheme.Description = *data.Description 49 } 50 51 if len(scheme.Id) == 0 { 52 scheme, err = a.CreateScheme(scheme) 53 } else { 54 scheme, err = a.UpdateScheme(scheme) 55 } 56 57 if err != nil { 58 return err 59 } 60 61 if scheme.Scope == model.SCHEME_SCOPE_TEAM { 62 data.DefaultTeamAdminRole.Name = &scheme.DefaultTeamAdminRole 63 if err := a.ImportRole(data.DefaultTeamAdminRole, dryRun, true); err != nil { 64 return err 65 } 66 67 data.DefaultTeamUserRole.Name = &scheme.DefaultTeamUserRole 68 if err := a.ImportRole(data.DefaultTeamUserRole, dryRun, true); err != nil { 69 return err 70 } 71 } 72 73 if scheme.Scope == model.SCHEME_SCOPE_TEAM || scheme.Scope == model.SCHEME_SCOPE_CHANNEL { 74 data.DefaultChannelAdminRole.Name = &scheme.DefaultChannelAdminRole 75 if err := a.ImportRole(data.DefaultChannelAdminRole, dryRun, true); err != nil { 76 return err 77 } 78 79 data.DefaultChannelUserRole.Name = &scheme.DefaultChannelUserRole 80 if err := a.ImportRole(data.DefaultChannelUserRole, dryRun, true); err != nil { 81 return err 82 } 83 } 84 85 return nil 86 } 87 88 func (a *App) ImportRole(data *RoleImportData, dryRun bool, isSchemeRole bool) *model.AppError { 89 if !isSchemeRole { 90 if err := validateRoleImportData(data); err != nil { 91 return err 92 } 93 } 94 95 // If this is a Dry Run, do not continue any further. 96 if dryRun { 97 return nil 98 } 99 100 role, err := a.GetRoleByName(*data.Name) 101 if err != nil { 102 role = new(model.Role) 103 } 104 105 role.Name = *data.Name 106 107 if data.DisplayName != nil { 108 role.DisplayName = *data.DisplayName 109 } 110 111 if data.Description != nil { 112 role.Description = *data.Description 113 } 114 115 if data.Permissions != nil { 116 role.Permissions = *data.Permissions 117 } 118 119 if isSchemeRole { 120 role.SchemeManaged = true 121 } else { 122 role.SchemeManaged = false 123 } 124 125 if len(role.Id) == 0 { 126 _, err = a.CreateRole(role) 127 } else { 128 _, err = a.UpdateRole(role) 129 } 130 131 return err 132 } 133 134 func (a *App) ImportTeam(data *TeamImportData, dryRun bool) *model.AppError { 135 if err := validateTeamImportData(data); err != nil { 136 return err 137 } 138 139 // If this is a Dry Run, do not continue any further. 140 if dryRun { 141 return nil 142 } 143 144 var team *model.Team 145 if result := <-a.Srv.Store.Team().GetByName(*data.Name); result.Err == nil { 146 team = result.Data.(*model.Team) 147 } else { 148 team = &model.Team{} 149 } 150 151 team.Name = *data.Name 152 team.DisplayName = *data.DisplayName 153 team.Type = *data.Type 154 155 if data.Description != nil { 156 team.Description = *data.Description 157 } 158 159 if data.AllowOpenInvite != nil { 160 team.AllowOpenInvite = *data.AllowOpenInvite 161 } 162 163 if data.Scheme != nil { 164 scheme, err := a.GetSchemeByName(*data.Scheme) 165 if err != nil { 166 return err 167 } 168 169 if scheme.DeleteAt != 0 { 170 return model.NewAppError("BulkImport", "app.import.import_team.scheme_deleted.error", nil, "", http.StatusBadRequest) 171 } 172 173 if scheme.Scope != model.SCHEME_SCOPE_TEAM { 174 return model.NewAppError("BulkImport", "app.import.import_team.scheme_wrong_scope.error", nil, "", http.StatusBadRequest) 175 } 176 177 team.SchemeId = &scheme.Id 178 } 179 180 if team.Id == "" { 181 if _, err := a.CreateTeam(team); err != nil { 182 return err 183 } 184 } else { 185 if _, err := a.updateTeamUnsanitized(team); err != nil { 186 return err 187 } 188 } 189 190 return nil 191 } 192 193 func (a *App) ImportChannel(data *ChannelImportData, dryRun bool) *model.AppError { 194 if err := validateChannelImportData(data); err != nil { 195 return err 196 } 197 198 // If this is a Dry Run, do not continue any further. 199 if dryRun { 200 return nil 201 } 202 203 result := <-a.Srv.Store.Team().GetByName(*data.Team) 204 if result.Err != nil { 205 return model.NewAppError("BulkImport", "app.import.import_channel.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest) 206 } 207 team := result.Data.(*model.Team) 208 209 var channel *model.Channel 210 if result := <-a.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, *data.Name, true); result.Err == nil { 211 channel = result.Data.(*model.Channel) 212 } else { 213 channel = &model.Channel{} 214 } 215 216 channel.TeamId = team.Id 217 channel.Name = *data.Name 218 channel.DisplayName = *data.DisplayName 219 channel.Type = *data.Type 220 221 if data.Header != nil { 222 channel.Header = *data.Header 223 } 224 225 if data.Purpose != nil { 226 channel.Purpose = *data.Purpose 227 } 228 229 if data.Scheme != nil { 230 scheme, err := a.GetSchemeByName(*data.Scheme) 231 if err != nil { 232 return err 233 } 234 235 if scheme.DeleteAt != 0 { 236 return model.NewAppError("BulkImport", "app.import.import_channel.scheme_deleted.error", nil, "", http.StatusBadRequest) 237 } 238 239 if scheme.Scope != model.SCHEME_SCOPE_CHANNEL { 240 return model.NewAppError("BulkImport", "app.import.import_channel.scheme_wrong_scope.error", nil, "", http.StatusBadRequest) 241 } 242 243 channel.SchemeId = &scheme.Id 244 } 245 246 if channel.Id == "" { 247 if _, err := a.CreateChannel(channel, false); err != nil { 248 return err 249 } 250 } else { 251 if _, err := a.UpdateChannel(channel); err != nil { 252 return err 253 } 254 } 255 256 return nil 257 } 258 259 func (a *App) ImportUser(data *UserImportData, dryRun bool) *model.AppError { 260 if err := validateUserImportData(data); err != nil { 261 return err 262 } 263 264 // If this is a Dry Run, do not continue any further. 265 if dryRun { 266 return nil 267 } 268 269 // We want to avoid database writes if nothing has changed. 270 hasUserChanged := false 271 hasNotifyPropsChanged := false 272 hasUserRolesChanged := false 273 hasUserAuthDataChanged := false 274 hasUserEmailVerifiedChanged := false 275 276 var user *model.User 277 if result := <-a.Srv.Store.User().GetByUsername(*data.Username); result.Err == nil { 278 user = result.Data.(*model.User) 279 } else { 280 user = &model.User{} 281 user.MakeNonNil() 282 hasUserChanged = true 283 } 284 285 user.Username = *data.Username 286 287 if user.Email != *data.Email { 288 hasUserChanged = true 289 hasUserEmailVerifiedChanged = true // Changing the email resets email verified to false by default. 290 user.Email = *data.Email 291 } 292 293 var password string 294 var authService string 295 var authData *string 296 297 if data.AuthService != nil { 298 if user.AuthService != *data.AuthService { 299 hasUserAuthDataChanged = true 300 } 301 authService = *data.AuthService 302 } 303 304 // AuthData and Password are mutually exclusive. 305 if data.AuthData != nil { 306 if user.AuthData == nil || *user.AuthData != *data.AuthData { 307 hasUserAuthDataChanged = true 308 } 309 authData = data.AuthData 310 password = "" 311 } else if data.Password != nil { 312 password = *data.Password 313 authData = nil 314 } else { 315 // If no AuthData or Password is specified, we must generate a password. 316 password = model.NewId() 317 authData = nil 318 } 319 320 user.Password = password 321 user.AuthService = authService 322 user.AuthData = authData 323 324 // Automatically assume all emails are verified. 325 emailVerified := true 326 if user.EmailVerified != emailVerified { 327 user.EmailVerified = emailVerified 328 hasUserEmailVerifiedChanged = true 329 } 330 331 if data.Nickname != nil { 332 if user.Nickname != *data.Nickname { 333 user.Nickname = *data.Nickname 334 hasUserChanged = true 335 } 336 } 337 338 if data.FirstName != nil { 339 if user.FirstName != *data.FirstName { 340 user.FirstName = *data.FirstName 341 hasUserChanged = true 342 } 343 } 344 345 if data.LastName != nil { 346 if user.LastName != *data.LastName { 347 user.LastName = *data.LastName 348 hasUserChanged = true 349 } 350 } 351 352 if data.Position != nil { 353 if user.Position != *data.Position { 354 user.Position = *data.Position 355 hasUserChanged = true 356 } 357 } 358 359 if data.Locale != nil { 360 if user.Locale != *data.Locale { 361 user.Locale = *data.Locale 362 hasUserChanged = true 363 } 364 } else { 365 if user.Locale != *a.Config().LocalizationSettings.DefaultClientLocale { 366 user.Locale = *a.Config().LocalizationSettings.DefaultClientLocale 367 hasUserChanged = true 368 } 369 } 370 371 var roles string 372 if data.Roles != nil { 373 if user.Roles != *data.Roles { 374 roles = *data.Roles 375 hasUserRolesChanged = true 376 } 377 } else if len(user.Roles) == 0 { 378 // Set SYSTEM_USER roles on newly created users by default. 379 if user.Roles != model.SYSTEM_USER_ROLE_ID { 380 roles = model.SYSTEM_USER_ROLE_ID 381 hasUserRolesChanged = true 382 } 383 } 384 user.Roles = roles 385 386 if data.NotifyProps != nil { 387 if data.NotifyProps.Desktop != nil { 388 if value, ok := user.NotifyProps[model.DESKTOP_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Desktop { 389 user.AddNotifyProp(model.DESKTOP_NOTIFY_PROP, *data.NotifyProps.Desktop) 390 hasNotifyPropsChanged = true 391 } 392 } 393 394 if data.NotifyProps.DesktopSound != nil { 395 if value, ok := user.NotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopSound { 396 user.AddNotifyProp(model.DESKTOP_SOUND_NOTIFY_PROP, *data.NotifyProps.DesktopSound) 397 hasNotifyPropsChanged = true 398 } 399 } 400 401 if data.NotifyProps.Email != nil { 402 if value, ok := user.NotifyProps[model.EMAIL_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Email { 403 user.AddNotifyProp(model.EMAIL_NOTIFY_PROP, *data.NotifyProps.Email) 404 hasNotifyPropsChanged = true 405 } 406 } 407 408 if data.NotifyProps.Mobile != nil { 409 if value, ok := user.NotifyProps[model.PUSH_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Mobile { 410 user.AddNotifyProp(model.PUSH_NOTIFY_PROP, *data.NotifyProps.Mobile) 411 hasNotifyPropsChanged = true 412 } 413 } 414 415 if data.NotifyProps.MobilePushStatus != nil { 416 if value, ok := user.NotifyProps[model.PUSH_STATUS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MobilePushStatus { 417 user.AddNotifyProp(model.PUSH_STATUS_NOTIFY_PROP, *data.NotifyProps.MobilePushStatus) 418 hasNotifyPropsChanged = true 419 } 420 } 421 422 if data.NotifyProps.ChannelTrigger != nil { 423 if value, ok := user.NotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.ChannelTrigger { 424 user.AddNotifyProp(model.CHANNEL_MENTIONS_NOTIFY_PROP, *data.NotifyProps.ChannelTrigger) 425 hasNotifyPropsChanged = true 426 } 427 } 428 429 if data.NotifyProps.CommentsTrigger != nil { 430 if value, ok := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.CommentsTrigger { 431 user.AddNotifyProp(model.COMMENTS_NOTIFY_PROP, *data.NotifyProps.CommentsTrigger) 432 hasNotifyPropsChanged = true 433 } 434 } 435 436 if data.NotifyProps.MentionKeys != nil { 437 if value, ok := user.NotifyProps[model.MENTION_KEYS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MentionKeys { 438 user.AddNotifyProp(model.MENTION_KEYS_NOTIFY_PROP, *data.NotifyProps.MentionKeys) 439 hasNotifyPropsChanged = true 440 } 441 } 442 } 443 444 var err *model.AppError 445 var savedUser *model.User 446 if user.Id == "" { 447 if savedUser, err = a.createUser(user); err != nil { 448 return err 449 } 450 } else { 451 if hasUserChanged { 452 if savedUser, err = a.UpdateUser(user, false); err != nil { 453 return err 454 } 455 } 456 if hasUserRolesChanged { 457 if savedUser, err = a.UpdateUserRoles(user.Id, roles, false); err != nil { 458 return err 459 } 460 } 461 if hasNotifyPropsChanged { 462 if savedUser, err = a.UpdateUserNotifyProps(user.Id, user.NotifyProps); err != nil { 463 return err 464 } 465 } 466 if len(password) > 0 { 467 if err = a.UpdatePassword(user, password); err != nil { 468 return err 469 } 470 } else { 471 if hasUserAuthDataChanged { 472 if res := <-a.Srv.Store.User().UpdateAuthData(user.Id, authService, authData, user.Email, false); res.Err != nil { 473 return res.Err 474 } 475 } 476 } 477 if emailVerified { 478 if hasUserEmailVerifiedChanged { 479 if err := a.VerifyUserEmail(user.Id); err != nil { 480 return err 481 } 482 } 483 } 484 } 485 486 if savedUser == nil { 487 savedUser = user 488 } 489 490 if data.ProfileImage != nil { 491 file, err := os.Open(*data.ProfileImage) 492 if err != nil { 493 mlog.Error("Unable to open the profile image.", mlog.Any("err", err)) 494 } 495 if err := a.SetProfileImageFromFile(savedUser.Id, file); err != nil { 496 mlog.Error("Unable to set the profile image from a file.", mlog.Any("err", err)) 497 } 498 } 499 500 // Preferences. 501 var preferences model.Preferences 502 503 if data.Theme != nil { 504 preferences = append(preferences, model.Preference{ 505 UserId: savedUser.Id, 506 Category: model.PREFERENCE_CATEGORY_THEME, 507 Name: "", 508 Value: *data.Theme, 509 }) 510 } 511 512 if data.UseMilitaryTime != nil { 513 preferences = append(preferences, model.Preference{ 514 UserId: savedUser.Id, 515 Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, 516 Name: model.PREFERENCE_NAME_USE_MILITARY_TIME, 517 Value: *data.UseMilitaryTime, 518 }) 519 } 520 521 if data.CollapsePreviews != nil { 522 preferences = append(preferences, model.Preference{ 523 UserId: savedUser.Id, 524 Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, 525 Name: model.PREFERENCE_NAME_COLLAPSE_SETTING, 526 Value: *data.CollapsePreviews, 527 }) 528 } 529 530 if data.MessageDisplay != nil { 531 preferences = append(preferences, model.Preference{ 532 UserId: savedUser.Id, 533 Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, 534 Name: model.PREFERENCE_NAME_MESSAGE_DISPLAY, 535 Value: *data.MessageDisplay, 536 }) 537 } 538 539 if data.ChannelDisplayMode != nil { 540 preferences = append(preferences, model.Preference{ 541 UserId: savedUser.Id, 542 Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, 543 Name: "channel_display_mode", 544 Value: *data.ChannelDisplayMode, 545 }) 546 } 547 548 if data.TutorialStep != nil { 549 preferences = append(preferences, model.Preference{ 550 UserId: savedUser.Id, 551 Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, 552 Name: savedUser.Id, 553 Value: *data.TutorialStep, 554 }) 555 } 556 557 if data.UseMarkdownPreview != nil { 558 preferences = append(preferences, model.Preference{ 559 UserId: savedUser.Id, 560 Category: model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, 561 Name: "feature_enabled_markdown_preview", 562 Value: *data.UseMarkdownPreview, 563 }) 564 } 565 566 if data.UseFormatting != nil { 567 preferences = append(preferences, model.Preference{ 568 UserId: savedUser.Id, 569 Category: model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, 570 Name: "formatting", 571 Value: *data.UseFormatting, 572 }) 573 } 574 575 if data.ShowUnreadSection != nil { 576 preferences = append(preferences, model.Preference{ 577 UserId: savedUser.Id, 578 Category: model.PREFERENCE_CATEGORY_SIDEBAR_SETTINGS, 579 Name: "show_unread_section", 580 Value: *data.ShowUnreadSection, 581 }) 582 } 583 584 if len(preferences) > 0 { 585 if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil { 586 return model.NewAppError("BulkImport", "app.import.import_user.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError) 587 } 588 } 589 590 return a.ImportUserTeams(savedUser, data.Teams) 591 } 592 593 func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *model.AppError { 594 if data == nil { 595 return nil 596 } 597 598 var teamThemePreferences model.Preferences 599 for _, tdata := range *data { 600 team, err := a.GetTeamByName(*tdata.Name) 601 if err != nil { 602 return err 603 } 604 605 // Team-specific theme Preferences. 606 if tdata.Theme != nil { 607 teamThemePreferences = append(teamThemePreferences, model.Preference{ 608 UserId: user.Id, 609 Category: model.PREFERENCE_CATEGORY_THEME, 610 Name: team.Id, 611 Value: *tdata.Theme, 612 }) 613 } 614 615 var roles string 616 isSchemeUser := true 617 isSchemeAdmin := false 618 619 if tdata.Roles == nil { 620 isSchemeUser = true 621 } else { 622 rawRoles := *tdata.Roles 623 explicitRoles := []string{} 624 for _, role := range strings.Fields(rawRoles) { 625 if role == model.TEAM_USER_ROLE_ID { 626 isSchemeUser = true 627 } else if role == model.TEAM_ADMIN_ROLE_ID { 628 isSchemeAdmin = true 629 } else { 630 explicitRoles = append(explicitRoles, role) 631 } 632 } 633 roles = strings.Join(explicitRoles, " ") 634 } 635 636 var member *model.TeamMember 637 if member, _, err = a.joinUserToTeam(team, user); err != nil { 638 return err 639 } 640 641 if member.ExplicitRoles != roles { 642 if _, err := a.UpdateTeamMemberRoles(team.Id, user.Id, roles); err != nil { 643 return err 644 } 645 } 646 647 if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser { 648 a.UpdateTeamMemberSchemeRoles(team.Id, user.Id, isSchemeUser, isSchemeAdmin) 649 } 650 651 defaultChannel, err := a.GetChannelByName(model.DEFAULT_CHANNEL, team.Id, true) 652 if err != nil { 653 return err 654 } 655 656 if _, err = a.addUserToChannel(user, defaultChannel, member); err != nil { 657 return err 658 } 659 660 if err := a.ImportUserChannels(user, team, member, tdata.Channels); err != nil { 661 return err 662 } 663 } 664 665 if len(teamThemePreferences) > 0 { 666 if result := <-a.Srv.Store.Preference().Save(&teamThemePreferences); result.Err != nil { 667 return model.NewAppError("BulkImport", "app.import.import_user_teams.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError) 668 } 669 } 670 671 return nil 672 } 673 674 func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember *model.TeamMember, data *[]UserChannelImportData) *model.AppError { 675 if data == nil { 676 return nil 677 } 678 679 var preferences model.Preferences 680 681 // Loop through all channels. 682 for _, cdata := range *data { 683 channel, err := a.GetChannelByName(*cdata.Name, team.Id, true) 684 if err != nil { 685 return err 686 } 687 688 var roles string 689 isSchemeUser := true 690 isSchemeAdmin := false 691 692 if cdata.Roles == nil { 693 isSchemeUser = true 694 } else { 695 rawRoles := *cdata.Roles 696 explicitRoles := []string{} 697 for _, role := range strings.Fields(rawRoles) { 698 if role == model.CHANNEL_USER_ROLE_ID { 699 isSchemeUser = true 700 } else if role == model.CHANNEL_ADMIN_ROLE_ID { 701 isSchemeAdmin = true 702 } else { 703 explicitRoles = append(explicitRoles, role) 704 } 705 } 706 roles = strings.Join(explicitRoles, " ") 707 } 708 709 var member *model.ChannelMember 710 member, err = a.GetChannelMember(channel.Id, user.Id) 711 if err != nil { 712 member, err = a.addUserToChannel(user, channel, teamMember) 713 if err != nil { 714 return err 715 } 716 } 717 718 if member.ExplicitRoles != roles { 719 if _, err := a.UpdateChannelMemberRoles(channel.Id, user.Id, roles); err != nil { 720 return err 721 } 722 } 723 724 if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser { 725 a.UpdateChannelMemberSchemeRoles(channel.Id, user.Id, isSchemeUser, isSchemeAdmin) 726 } 727 728 if cdata.NotifyProps != nil { 729 notifyProps := member.NotifyProps 730 731 if cdata.NotifyProps.Desktop != nil { 732 notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop 733 } 734 735 if cdata.NotifyProps.Mobile != nil { 736 notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile 737 } 738 739 if cdata.NotifyProps.MarkUnread != nil { 740 notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread 741 } 742 743 if _, err := a.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id); err != nil { 744 return err 745 } 746 } 747 748 if cdata.Favorite != nil && *cdata.Favorite { 749 preferences = append(preferences, model.Preference{ 750 UserId: user.Id, 751 Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, 752 Name: channel.Id, 753 Value: "true", 754 }) 755 } 756 } 757 758 if len(preferences) > 0 { 759 if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil { 760 return model.NewAppError("BulkImport", "app.import.import_user_channels.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError) 761 } 762 } 763 764 return nil 765 } 766 767 func (a *App) ImportReaction(data *ReactionImportData, post *model.Post, dryRun bool) *model.AppError { 768 if err := validateReactionImportData(data, post.CreateAt); err != nil { 769 return err 770 } 771 772 result := <-a.Srv.Store.User().GetByUsername(*data.User) 773 if result.Err != nil { 774 return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest) 775 } 776 user := result.Data.(*model.User) 777 778 reaction := &model.Reaction{ 779 UserId: user.Id, 780 PostId: post.Id, 781 EmojiName: *data.EmojiName, 782 CreateAt: *data.CreateAt, 783 } 784 if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil { 785 return result.Err 786 } 787 return nil 788 } 789 790 func (a *App) ImportReply(data *ReplyImportData, post *model.Post, teamId string, dryRun bool) *model.AppError { 791 if err := validateReplyImportData(data, post.CreateAt, a.MaxPostSize()); err != nil { 792 return err 793 } 794 795 result := <-a.Srv.Store.User().GetByUsername(*data.User) 796 if result.Err != nil { 797 return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": data.User}, result.Err.Error(), http.StatusBadRequest) 798 } 799 user := result.Data.(*model.User) 800 801 // Check if this post already exists. 802 result = <-a.Srv.Store.Post().GetPostsCreatedAt(post.ChannelId, *data.CreateAt) 803 if result.Err != nil { 804 return result.Err 805 } 806 replies := result.Data.([]*model.Post) 807 808 var reply *model.Post 809 for _, r := range replies { 810 if r.Message == *data.Message && r.RootId == post.Id { 811 reply = r 812 break 813 } 814 } 815 816 if reply == nil { 817 reply = &model.Post{} 818 } 819 reply.UserId = user.Id 820 reply.ChannelId = post.ChannelId 821 reply.ParentId = post.Id 822 reply.RootId = post.Id 823 reply.Message = *data.Message 824 reply.CreateAt = *data.CreateAt 825 826 if data.Attachments != nil { 827 fileIds, err := a.uploadAttachments(data.Attachments, reply, teamId, dryRun) 828 if err != nil { 829 return err 830 } 831 reply.FileIds = append(reply.FileIds, fileIds...) 832 } 833 834 if reply.Id == "" { 835 if result := <-a.Srv.Store.Post().Save(reply); result.Err != nil { 836 return result.Err 837 } 838 } else { 839 if result := <-a.Srv.Store.Post().Overwrite(reply); result.Err != nil { 840 return result.Err 841 } 842 } 843 844 a.UpdateFileInfoWithPostId(reply) 845 846 return nil 847 } 848 849 func (a *App) ImportAttachment(data *AttachmentImportData, post *model.Post, teamId string, dryRun bool) (*model.FileInfo, *model.AppError) { 850 fileUploadError := model.NewAppError("BulkImport", "app.import.attachment.file_upload.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest) 851 file, err := os.Open(*data.Path) 852 if err != nil { 853 return nil, model.NewAppError("BulkImport", "app.import.attachment.bad_file.error", map[string]interface{}{"FilePath": *data.Path}, "", http.StatusBadRequest) 854 } 855 if file != nil { 856 timestamp := utils.TimeFromMillis(post.CreateAt) 857 buf := bytes.NewBuffer(nil) 858 io.Copy(buf, file) 859 860 fileInfo, err := a.DoUploadFile(timestamp, teamId, post.ChannelId, post.UserId, file.Name(), buf.Bytes()) 861 862 if err != nil { 863 fmt.Print(err) 864 return nil, fileUploadError 865 } 866 867 a.HandleImages([]string{fileInfo.PreviewPath}, []string{fileInfo.ThumbnailPath}, [][]byte{buf.Bytes()}) 868 869 mlog.Info(fmt.Sprintf("uploading file with name %s", file.Name())) 870 return fileInfo, nil 871 } 872 return nil, fileUploadError 873 } 874 875 func (a *App) ImportPost(data *PostImportData, dryRun bool) *model.AppError { 876 if err := validatePostImportData(data, a.MaxPostSize()); err != nil { 877 return err 878 } 879 880 // If this is a Dry Run, do not continue any further. 881 if dryRun { 882 return nil 883 } 884 885 result := <-a.Srv.Store.Team().GetByName(*data.Team) 886 if result.Err != nil { 887 return model.NewAppError("BulkImport", "app.import.import_post.team_not_found.error", map[string]interface{}{"TeamName": *data.Team}, result.Err.Error(), http.StatusBadRequest) 888 } 889 team := result.Data.(*model.Team) 890 891 result = <-a.Srv.Store.Channel().GetByName(team.Id, *data.Channel, false) 892 if result.Err != nil { 893 return model.NewAppError("BulkImport", "app.import.import_post.channel_not_found.error", map[string]interface{}{"ChannelName": *data.Channel}, result.Err.Error(), http.StatusBadRequest) 894 } 895 channel := result.Data.(*model.Channel) 896 897 result = <-a.Srv.Store.User().GetByUsername(*data.User) 898 if result.Err != nil { 899 return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, result.Err.Error(), http.StatusBadRequest) 900 } 901 user := result.Data.(*model.User) 902 903 // Check if this post already exists. 904 result = <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt) 905 if result.Err != nil { 906 return result.Err 907 } 908 posts := result.Data.([]*model.Post) 909 910 var post *model.Post 911 for _, p := range posts { 912 if p.Message == *data.Message { 913 post = p 914 break 915 } 916 } 917 918 if post == nil { 919 post = &model.Post{} 920 } 921 922 post.ChannelId = channel.Id 923 post.Message = *data.Message 924 post.UserId = user.Id 925 post.CreateAt = *data.CreateAt 926 927 post.Hashtags, _ = model.ParseHashtags(post.Message) 928 929 if data.Attachments != nil { 930 fileIds, err := a.uploadAttachments(data.Attachments, post, team.Id, dryRun) 931 if err != nil { 932 return err 933 } 934 post.FileIds = append(post.FileIds, fileIds...) 935 } 936 937 if post.Id == "" { 938 if result := <-a.Srv.Store.Post().Save(post); result.Err != nil { 939 return result.Err 940 } 941 } else { 942 if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil { 943 return result.Err 944 } 945 } 946 947 if data.FlaggedBy != nil { 948 var preferences model.Preferences 949 950 for _, username := range *data.FlaggedBy { 951 result := <-a.Srv.Store.User().GetByUsername(username) 952 if result.Err != nil { 953 return model.NewAppError("BulkImport", "app.import.import_post.user_not_found.error", map[string]interface{}{"Username": username}, result.Err.Error(), http.StatusBadRequest) 954 } 955 user := result.Data.(*model.User) 956 957 preferences = append(preferences, model.Preference{ 958 UserId: user.Id, 959 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 960 Name: post.Id, 961 Value: "true", 962 }) 963 } 964 965 if len(preferences) > 0 { 966 if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil { 967 return model.NewAppError("BulkImport", "app.import.import_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError) 968 } 969 } 970 } 971 972 if data.Reactions != nil { 973 for _, reaction := range *data.Reactions { 974 if err := a.ImportReaction(&reaction, post, dryRun); err != nil { 975 return err 976 } 977 } 978 } 979 980 if data.Replies != nil { 981 for _, reply := range *data.Replies { 982 if err := a.ImportReply(&reply, post, team.Id, dryRun); err != nil { 983 return err 984 } 985 } 986 } 987 988 a.UpdateFileInfoWithPostId(post) 989 return nil 990 } 991 992 func (a *App) uploadAttachments(attachments *[]AttachmentImportData, post *model.Post, teamId string, dryRun bool) ([]string, *model.AppError) { 993 fileIds := []string{} 994 for _, attachment := range *attachments { 995 fileInfo, err := a.ImportAttachment(&attachment, post, teamId, dryRun) 996 if err != nil { 997 return nil, err 998 } 999 fileIds = append(fileIds, fileInfo.Id) 1000 } 1001 return fileIds, nil 1002 } 1003 1004 func (a *App) UpdateFileInfoWithPostId(post *model.Post) { 1005 for _, fileId := range post.FileIds { 1006 if result := <-a.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil { 1007 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)) 1008 } 1009 } 1010 } 1011 func (a *App) ImportDirectChannel(data *DirectChannelImportData, dryRun bool) *model.AppError { 1012 if err := validateDirectChannelImportData(data); err != nil { 1013 return err 1014 } 1015 1016 // If this is a Dry Run, do not continue any further. 1017 if dryRun { 1018 return nil 1019 } 1020 1021 var userIds []string 1022 userMap := make(map[string]string) 1023 for _, username := range *data.Members { 1024 result := <-a.Srv.Store.User().GetByUsername(username) 1025 if result.Err != nil { 1026 return model.NewAppError("BulkImport", "app.import.import_direct_channel.member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest) 1027 } 1028 user := result.Data.(*model.User) 1029 userIds = append(userIds, user.Id) 1030 userMap[username] = user.Id 1031 } 1032 1033 var channel *model.Channel 1034 1035 if len(userIds) == 2 { 1036 ch, err := a.createDirectChannel(userIds[0], userIds[1]) 1037 if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR { 1038 return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest) 1039 } 1040 channel = ch 1041 } else { 1042 ch, err := a.createGroupChannel(userIds, userIds[0]) 1043 if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR { 1044 return model.NewAppError("BulkImport", "app.import.import_direct_channel.create_group_channel.error", nil, err.Error(), http.StatusBadRequest) 1045 } 1046 channel = ch 1047 } 1048 1049 var preferences model.Preferences 1050 1051 for _, userId := range userIds { 1052 preferences = append(preferences, model.Preference{ 1053 UserId: userId, 1054 Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, 1055 Name: channel.Id, 1056 Value: "true", 1057 }) 1058 } 1059 1060 if data.FavoritedBy != nil { 1061 for _, favoriter := range *data.FavoritedBy { 1062 preferences = append(preferences, model.Preference{ 1063 UserId: userMap[favoriter], 1064 Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, 1065 Name: channel.Id, 1066 Value: "true", 1067 }) 1068 } 1069 } 1070 1071 if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil { 1072 result.Err.StatusCode = http.StatusBadRequest 1073 return result.Err 1074 } 1075 1076 if data.Header != nil { 1077 channel.Header = *data.Header 1078 if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil { 1079 return model.NewAppError("BulkImport", "app.import.import_direct_channel.update_header_failed.error", nil, result.Err.Error(), http.StatusBadRequest) 1080 } 1081 } 1082 1083 return nil 1084 } 1085 1086 func (a *App) ImportDirectPost(data *DirectPostImportData, dryRun bool) *model.AppError { 1087 if err := validateDirectPostImportData(data, a.MaxPostSize()); err != nil { 1088 return err 1089 } 1090 1091 // If this is a Dry Run, do not continue any further. 1092 if dryRun { 1093 return nil 1094 } 1095 1096 var userIds []string 1097 for _, username := range *data.ChannelMembers { 1098 result := <-a.Srv.Store.User().GetByUsername(username) 1099 if result.Err != nil { 1100 return model.NewAppError("BulkImport", "app.import.import_direct_post.channel_member_not_found.error", nil, result.Err.Error(), http.StatusBadRequest) 1101 } 1102 user := result.Data.(*model.User) 1103 userIds = append(userIds, user.Id) 1104 } 1105 1106 var channel *model.Channel 1107 if len(userIds) == 2 { 1108 ch, err := a.createDirectChannel(userIds[0], userIds[1]) 1109 if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR { 1110 return model.NewAppError("BulkImport", "app.import.import_direct_post.create_direct_channel.error", nil, err.Error(), http.StatusBadRequest) 1111 } 1112 channel = ch 1113 } else { 1114 ch, err := a.createGroupChannel(userIds, userIds[0]) 1115 if err != nil && err.Id != store.CHANNEL_EXISTS_ERROR { 1116 return model.NewAppError("BulkImport", "app.import.import_direct_post.create_group_channel.error", nil, err.Error(), http.StatusBadRequest) 1117 } 1118 channel = ch 1119 } 1120 1121 result := <-a.Srv.Store.User().GetByUsername(*data.User) 1122 if result.Err != nil { 1123 return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": *data.User}, "", http.StatusBadRequest) 1124 } 1125 user := result.Data.(*model.User) 1126 1127 // Check if this post already exists. 1128 result = <-a.Srv.Store.Post().GetPostsCreatedAt(channel.Id, *data.CreateAt) 1129 if result.Err != nil { 1130 return result.Err 1131 } 1132 posts := result.Data.([]*model.Post) 1133 1134 var post *model.Post 1135 for _, p := range posts { 1136 if p.Message == *data.Message { 1137 post = p 1138 break 1139 } 1140 } 1141 1142 if post == nil { 1143 post = &model.Post{} 1144 } 1145 1146 post.ChannelId = channel.Id 1147 post.Message = *data.Message 1148 post.UserId = user.Id 1149 post.CreateAt = *data.CreateAt 1150 1151 post.Hashtags, _ = model.ParseHashtags(post.Message) 1152 1153 if data.Attachments != nil { 1154 fileIds, err := a.uploadAttachments(data.Attachments, post, "noteam", dryRun) 1155 if err != nil { 1156 return err 1157 } 1158 post.FileIds = append(post.FileIds, fileIds...) 1159 } 1160 1161 if post.Id == "" { 1162 if result := <-a.Srv.Store.Post().Save(post); result.Err != nil { 1163 return result.Err 1164 } 1165 } else { 1166 if result := <-a.Srv.Store.Post().Overwrite(post); result.Err != nil { 1167 return result.Err 1168 } 1169 } 1170 1171 if data.FlaggedBy != nil { 1172 var preferences model.Preferences 1173 1174 for _, username := range *data.FlaggedBy { 1175 result := <-a.Srv.Store.User().GetByUsername(username) 1176 if result.Err != nil { 1177 return model.NewAppError("BulkImport", "app.import.import_direct_post.user_not_found.error", map[string]interface{}{"Username": username}, "", http.StatusBadRequest) 1178 } 1179 user := result.Data.(*model.User) 1180 1181 preferences = append(preferences, model.Preference{ 1182 UserId: user.Id, 1183 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 1184 Name: post.Id, 1185 Value: "true", 1186 }) 1187 } 1188 1189 if len(preferences) > 0 { 1190 if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil { 1191 return model.NewAppError("BulkImport", "app.import.import_direct_post.save_preferences.error", nil, result.Err.Error(), http.StatusInternalServerError) 1192 } 1193 } 1194 } 1195 1196 if data.Reactions != nil { 1197 for _, reaction := range *data.Reactions { 1198 if err := a.ImportReaction(&reaction, post, dryRun); err != nil { 1199 return err 1200 } 1201 } 1202 } 1203 1204 if data.Replies != nil { 1205 for _, reply := range *data.Replies { 1206 if err := a.ImportReply(&reply, post, "noteam", dryRun); err != nil { 1207 return err 1208 } 1209 } 1210 } 1211 1212 a.UpdateFileInfoWithPostId(post) 1213 return nil 1214 } 1215 1216 func (a *App) ImportEmoji(data *EmojiImportData, dryRun bool) *model.AppError { 1217 if err := validateEmojiImportData(data); err != nil { 1218 return err 1219 } 1220 1221 // If this is a Dry Run, do not continue any further. 1222 if dryRun { 1223 return nil 1224 } 1225 1226 var emoji *model.Emoji 1227 1228 result := <-a.Srv.Store.Emoji().GetByName(*data.Name) 1229 if result.Err != nil && result.Err.StatusCode != http.StatusNotFound { 1230 return result.Err 1231 } 1232 1233 if result.Data != nil { 1234 emoji = result.Data.(*model.Emoji) 1235 } 1236 1237 alreadyExists := emoji != nil 1238 1239 if !alreadyExists { 1240 emoji = &model.Emoji{ 1241 Name: *data.Name, 1242 } 1243 emoji.PreSave() 1244 } 1245 1246 file, err := os.Open(*data.Image) 1247 if err != nil { 1248 return model.NewAppError("BulkImport", "app.import.emoji.bad_file.error", map[string]interface{}{"EmojiName": *data.Name}, "", http.StatusBadRequest) 1249 } 1250 1251 if _, err := a.WriteFile(file, getEmojiImagePath(emoji.Id)); err != nil { 1252 return err 1253 } 1254 1255 if !alreadyExists { 1256 if result := <-a.Srv.Store.Emoji().Save(emoji); result.Err != nil { 1257 return result.Err 1258 } 1259 } 1260 1261 return nil 1262 }