1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2// See LICENSE.txt for license information. 3 4package app 5 6import ( 7 "bytes" 8 "context" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "io" 13 "mime/multipart" 14 "net/http" 15 "path/filepath" 16 "strconv" 17 "strings" 18 19 "github.com/mattermost/mattermost-server/v6/app/email" 20 "github.com/mattermost/mattermost-server/v6/app/imaging" 21 "github.com/mattermost/mattermost-server/v6/app/request" 22 "github.com/mattermost/mattermost-server/v6/einterfaces" 23 "github.com/mattermost/mattermost-server/v6/model" 24 "github.com/mattermost/mattermost-server/v6/plugin" 25 "github.com/mattermost/mattermost-server/v6/services/users" 26 "github.com/mattermost/mattermost-server/v6/shared/i18n" 27 "github.com/mattermost/mattermost-server/v6/shared/mfa" 28 "github.com/mattermost/mattermost-server/v6/shared/mlog" 29 "github.com/mattermost/mattermost-server/v6/store" 30) 31 32const ( 33 TokenTypePasswordRecovery = "password_recovery" 34 TokenTypeVerifyEmail = "verify_email" 35 TokenTypeTeamInvitation = "team_invitation" 36 TokenTypeGuestInvitation = "guest_invitation" 37 TokenTypeCWSAccess = "cws_access_token" 38 PasswordRecoverExpiryTime = 1000 * 60 * 60 // 1 hour 39 InvitationExpiryTime = 1000 * 60 * 60 * 48 // 48 hours 40 ImageProfilePixelDimension = 128 41) 42 43func (a *App) CreateUserWithToken(c *request.Context, user *model.User, token *model.Token) (*model.User, *model.AppError) { 44 if err := a.IsUserSignUpAllowed(); err != nil { 45 return nil, err 46 } 47 48 if token.Type != TokenTypeTeamInvitation && token.Type != TokenTypeGuestInvitation { 49 return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest) 50 } 51 52 if model.GetMillis()-token.CreateAt >= InvitationExpiryTime { 53 a.DeleteToken(token) 54 return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest) 55 } 56 57 tokenData := model.MapFromJSON(strings.NewReader(token.Extra)) 58 59 team, nErr := a.Srv().Store.Team().Get(tokenData["teamId"]) 60 if nErr != nil { 61 var nfErr *store.ErrNotFound 62 switch { 63 case errors.As(nErr, &nfErr): 64 return nil, model.NewAppError("CreateUserWithToken", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) 65 default: 66 return nil, model.NewAppError("CreateUserWithToken", "app.team.get.finding.app_error", nil, nErr.Error(), http.StatusInternalServerError) 67 } 68 } 69 70 channels, nErr := a.Srv().Store.Channel().GetChannelsByIds(strings.Split(tokenData["channels"], " "), false) 71 if nErr != nil { 72 return nil, model.NewAppError("CreateUserWithToken", "app.channel.get_channels_by_ids.app_error", nil, nErr.Error(), http.StatusInternalServerError) 73 } 74 75 user.Email = tokenData["email"] 76 user.EmailVerified = true 77 78 var ruser *model.User 79 var err *model.AppError 80 if token.Type == TokenTypeTeamInvitation { 81 ruser, err = a.CreateUser(c, user) 82 } else { 83 ruser, err = a.CreateGuest(c, user) 84 } 85 if err != nil { 86 return nil, err 87 } 88 89 if _, err := a.JoinUserToTeam(c, team, ruser, ""); err != nil { 90 return nil, err 91 } 92 93 a.AddDirectChannels(team.Id, ruser) 94 95 if token.Type == TokenTypeGuestInvitation { 96 for _, channel := range channels { 97 _, err := a.AddChannelMember(c, ruser.Id, channel, ChannelMemberOpts{}) 98 if err != nil { 99 mlog.Warn("Failed to add channel member", mlog.Err(err)) 100 } 101 } 102 } 103 104 if err := a.DeleteToken(token); err != nil { 105 mlog.Warn("Error while deleting token", mlog.Err(err)) 106 } 107 108 return ruser, nil 109} 110 111func (a *App) CreateUserWithInviteId(c *request.Context, user *model.User, inviteId, redirect string) (*model.User, *model.AppError) { 112 if err := a.IsUserSignUpAllowed(); err != nil { 113 return nil, err 114 } 115 116 team, nErr := a.Srv().Store.Team().GetByInviteId(inviteId) 117 if nErr != nil { 118 var nfErr *store.ErrNotFound 119 switch { 120 case errors.As(nErr, &nfErr): 121 return nil, model.NewAppError("CreateUserWithInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound) 122 default: 123 return nil, model.NewAppError("CreateUserWithInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nErr.Error(), http.StatusInternalServerError) 124 } 125 } 126 127 if team.IsGroupConstrained() { 128 return nil, model.NewAppError("CreateUserWithInviteId", "app.team.invite_id.group_constrained.error", nil, "", http.StatusForbidden) 129 } 130 131 if !users.CheckUserDomain(user, team.AllowedDomains) { 132 return nil, model.NewAppError("CreateUserWithInviteId", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": team.AllowedDomains}, "", http.StatusForbidden) 133 } 134 135 user.EmailVerified = false 136 137 ruser, err := a.CreateUser(c, user) 138 if err != nil { 139 return nil, err 140 } 141 142 if _, err := a.JoinUserToTeam(c, team, ruser, ""); err != nil { 143 return nil, err 144 } 145 146 a.AddDirectChannels(team.Id, ruser) 147 148 if err := a.Srv().EmailService.SendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.DisableWelcomeEmail, ruser.Locale, a.GetSiteURL(), redirect); err != nil { 149 mlog.Warn("Failed to send welcome email on create user with inviteId", mlog.Err(err)) 150 } 151 152 return ruser, nil 153} 154 155func (a *App) CreateUserAsAdmin(c *request.Context, user *model.User, redirect string) (*model.User, *model.AppError) { 156 ruser, err := a.CreateUser(c, user) 157 if err != nil { 158 return nil, err 159 } 160 161 if err := a.Srv().EmailService.SendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.DisableWelcomeEmail, ruser.Locale, a.GetSiteURL(), redirect); err != nil { 162 mlog.Warn("Failed to send welcome email to the new user, created by system admin", mlog.Err(err)) 163 } 164 165 return ruser, nil 166} 167 168func (a *App) CreateUserFromSignup(c *request.Context, user *model.User, redirect string) (*model.User, *model.AppError) { 169 if err := a.IsUserSignUpAllowed(); err != nil { 170 return nil, err 171 } 172 173 if !a.IsFirstUserAccount() && !*a.Config().TeamSettings.EnableOpenServer { 174 err := model.NewAppError("CreateUserFromSignup", "api.user.create_user.no_open_server", nil, "email="+user.Email, http.StatusForbidden) 175 return nil, err 176 } 177 178 user.EmailVerified = false 179 180 ruser, err := a.CreateUser(c, user) 181 if err != nil { 182 return nil, err 183 } 184 185 if err := a.Srv().EmailService.SendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.DisableWelcomeEmail, ruser.Locale, a.GetSiteURL(), redirect); err != nil { 186 mlog.Warn("Failed to send welcome email on create user from signup", mlog.Err(err)) 187 } 188 189 return ruser, nil 190} 191 192func (a *App) IsUserSignUpAllowed() *model.AppError { 193 if !*a.Config().EmailSettings.EnableSignUpWithEmail || !*a.Config().TeamSettings.EnableUserCreation { 194 err := model.NewAppError("IsUserSignUpAllowed", "api.user.create_user.signup_email_disabled.app_error", nil, "", http.StatusNotImplemented) 195 return err 196 } 197 return nil 198} 199 200func (a *App) IsFirstUserAccount() bool { 201 return a.srv.userService.IsFirstUserAccount() 202} 203 204// CreateUser creates a user and sets several fields of the returned User struct to 205// their zero values. 206func (a *App) CreateUser(c *request.Context, user *model.User) (*model.User, *model.AppError) { 207 return a.createUserOrGuest(c, user, false) 208} 209 210// CreateGuest creates a guest and sets several fields of the returned User struct to 211// their zero values. 212func (a *App) CreateGuest(c *request.Context, user *model.User) (*model.User, *model.AppError) { 213 return a.createUserOrGuest(c, user, true) 214} 215 216func (a *App) createUserOrGuest(c *request.Context, user *model.User, guest bool) (*model.User, *model.AppError) { 217 ruser, nErr := a.srv.userService.CreateUser(user, users.UserCreateOptions{Guest: guest}) 218 if nErr != nil { 219 var appErr *model.AppError 220 var invErr *store.ErrInvalidInput 221 var nfErr *users.ErrInvalidPassword 222 switch { 223 case errors.As(nErr, &appErr): 224 return nil, appErr 225 case errors.Is(nErr, users.AcceptedDomainError): 226 return nil, model.NewAppError("createUserOrGuest", "api.user.create_user.accepted_domain.app_error", nil, "", http.StatusBadRequest) 227 case errors.As(nErr, &nfErr): 228 return nil, model.NewAppError("createUserOrGuest", "api.user.check_user_password.invalid.app_error", nil, "", http.StatusBadRequest) 229 case errors.Is(nErr, users.UserStoreIsEmptyError): 230 return nil, model.NewAppError("createUserOrGuest", "app.user.store_is_empty.app_error", nil, nErr.Error(), http.StatusInternalServerError) 231 case errors.As(nErr, &invErr): 232 switch invErr.Field { 233 case "email": 234 return nil, model.NewAppError("createUserOrGuest", "app.user.save.email_exists.app_error", nil, invErr.Error(), http.StatusBadRequest) 235 case "username": 236 return nil, model.NewAppError("createUserOrGuest", "app.user.save.username_exists.app_error", nil, invErr.Error(), http.StatusBadRequest) 237 default: 238 return nil, model.NewAppError("createUserOrGuest", "app.user.save.existing.app_error", nil, invErr.Error(), http.StatusBadRequest) 239 } 240 default: 241 return nil, model.NewAppError("createUserOrGuest", "app.user.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 242 } 243 } 244 245 if user.EmailVerified { 246 a.InvalidateCacheForUser(ruser.Id) 247 248 nUser, err := a.srv.userService.GetUser(ruser.Id) 249 if err != nil { 250 var nfErr *store.ErrNotFound 251 switch { 252 case errors.As(err, &nfErr): 253 return nil, model.NewAppError("createUserOrGuest", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 254 default: 255 return nil, model.NewAppError("createUserOrGuest", "app.user.get.app_error", nil, err.Error(), http.StatusInternalServerError) 256 } 257 } 258 259 a.sendUpdatedUserEvent(*nUser) 260 } 261 262 recommendedNextStepsPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceRecommendedNextSteps, Name: "hide", Value: "false"} 263 tutorialStepPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceCategoryTutorialSteps, Name: ruser.Id, Value: "0"} 264 if err := a.Srv().Store.Preference().Save(model.Preferences{recommendedNextStepsPref, tutorialStepPref}); err != nil { 265 mlog.Warn("Encountered error saving user preferences", mlog.Err(err)) 266 } 267 268 go a.UpdateViewedProductNoticesForNewUser(ruser.Id) 269 270 // This message goes to everyone, so the teamID, channelID and userID are irrelevant 271 message := model.NewWebSocketEvent(model.WebsocketEventNewUser, "", "", "", nil) 272 message.Add("user_id", ruser.Id) 273 a.Publish(message) 274 275 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 276 a.Srv().Go(func() { 277 pluginContext := pluginContext(c) 278 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 279 hooks.UserHasBeenCreated(pluginContext, user) 280 return true 281 }, plugin.UserHasBeenCreatedID) 282 }) 283 } 284 285 return ruser, nil 286} 287 288func (a *App) CreateOAuthUser(c *request.Context, service string, userData io.Reader, teamID string, tokenUser *model.User) (*model.User, *model.AppError) { 289 if !*a.Config().TeamSettings.EnableUserCreation { 290 return nil, model.NewAppError("CreateOAuthUser", "api.user.create_user.disabled.app_error", nil, "", http.StatusNotImplemented) 291 } 292 293 provider, e := a.getSSOProvider(service) 294 if e != nil { 295 return nil, e 296 } 297 user, err1 := provider.GetUserFromJSON(userData, tokenUser) 298 if err1 != nil { 299 return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.create.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusInternalServerError) 300 } 301 if user.AuthService == "" { 302 user.AuthService = service 303 } 304 305 found := true 306 count := 0 307 for found { 308 if found = a.srv.userService.IsUsernameTaken(user.Username); found { 309 user.Username = user.Username + strconv.Itoa(count) 310 count++ 311 } 312 } 313 314 userByAuth, _ := a.srv.userService.GetUserByAuth(user.AuthData, service) 315 if userByAuth != nil { 316 return userByAuth, nil 317 } 318 319 userByEmail, _ := a.srv.userService.GetUserByEmail(user.Email) 320 if userByEmail != nil { 321 if userByEmail.AuthService == "" { 322 return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.already_attached.app_error", map[string]interface{}{"Service": service, "Auth": model.UserAuthServiceEmail}, "email="+user.Email, http.StatusBadRequest) 323 } 324 if provider.IsSameUser(userByEmail, user) { 325 if _, err := a.Srv().Store.User().UpdateAuthData(userByEmail.Id, user.AuthService, user.AuthData, "", false); err != nil { 326 // if the user is not updated, write a warning to the log, but don't prevent user login 327 mlog.Warn("Error attempting to update user AuthData", mlog.Err(err)) 328 } 329 return userByEmail, nil 330 } 331 return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.already_attached.app_error", map[string]interface{}{"Service": service, "Auth": userByEmail.AuthService}, "email="+user.Email+" authData="+*user.AuthData, http.StatusBadRequest) 332 } 333 334 user.EmailVerified = true 335 336 ruser, err := a.CreateUser(c, user) 337 if err != nil { 338 return nil, err 339 } 340 341 if teamID != "" { 342 err = a.AddUserToTeamByTeamId(c, teamID, user) 343 if err != nil { 344 return nil, err 345 } 346 347 err = a.AddDirectChannels(teamID, user) 348 if err != nil { 349 mlog.Warn("Failed to add direct channels", mlog.Err(err)) 350 } 351 } 352 353 return ruser, nil 354} 355 356func (a *App) GetUser(userID string) (*model.User, *model.AppError) { 357 user, err := a.srv.userService.GetUser(userID) 358 if err != nil { 359 var nfErr *store.ErrNotFound 360 switch { 361 case errors.As(err, &nfErr): 362 return nil, model.NewAppError("GetUser", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 363 default: 364 return nil, model.NewAppError("GetUser", "app.user.get_by_username.app_error", nil, err.Error(), http.StatusInternalServerError) 365 } 366 } 367 368 return user, nil 369} 370 371func (a *App) GetUserByUsername(username string) (*model.User, *model.AppError) { 372 result, err := a.srv.userService.GetUserByUsername(username) 373 if err != nil { 374 var nfErr *store.ErrNotFound 375 switch { 376 case errors.As(err, &nfErr): 377 return nil, model.NewAppError("GetUserByUsername", "app.user.get_by_username.app_error", nil, nfErr.Error(), http.StatusNotFound) 378 default: 379 return nil, model.NewAppError("GetUserByUsername", "app.user.get_by_username.app_error", nil, err.Error(), http.StatusInternalServerError) 380 } 381 } 382 return result, nil 383} 384 385func (a *App) GetUserByEmail(email string) (*model.User, *model.AppError) { 386 user, err := a.srv.userService.GetUserByEmail(email) 387 if err != nil { 388 var nfErr *store.ErrNotFound 389 switch { 390 case errors.As(err, &nfErr): 391 return nil, model.NewAppError("GetUserByEmail", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 392 default: 393 return nil, model.NewAppError("GetUserByEmail", MissingAccountError, nil, err.Error(), http.StatusInternalServerError) 394 } 395 } 396 return user, nil 397} 398 399func (a *App) GetUserByAuth(authData *string, authService string) (*model.User, *model.AppError) { 400 user, err := a.srv.userService.GetUserByAuth(authData, authService) 401 if err != nil { 402 var invErr *store.ErrInvalidInput 403 var nfErr *store.ErrNotFound 404 switch { 405 case errors.As(err, &invErr): 406 return nil, model.NewAppError("GetUserByAuth", MissingAuthAccountError, nil, invErr.Error(), http.StatusBadRequest) 407 case errors.As(err, &nfErr): 408 return nil, model.NewAppError("GetUserByAuth", MissingAuthAccountError, nil, nfErr.Error(), http.StatusInternalServerError) 409 default: 410 return nil, model.NewAppError("GetUserByAuth", "app.user.get_by_auth.other.app_error", nil, err.Error(), http.StatusInternalServerError) 411 } 412 } 413 414 return user, nil 415} 416 417func (a *App) GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError) { 418 users, err := a.srv.userService.GetUsers(options) 419 if err != nil { 420 return nil, model.NewAppError("GetUsers", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 421 } 422 423 return users, nil 424} 425 426func (a *App) GetUsersPage(options *model.UserGetOptions, asAdmin bool) ([]*model.User, *model.AppError) { 427 users, err := a.srv.userService.GetUsersPage(options, asAdmin) 428 if err != nil { 429 return nil, model.NewAppError("GetUsersPage", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 430 } 431 432 return users, nil 433} 434 435func (a *App) GetUsersEtag(restrictionsHash string) string { 436 return a.srv.userService.GetUsersEtag(restrictionsHash) 437} 438 439func (a *App) GetUsersInTeam(options *model.UserGetOptions) ([]*model.User, *model.AppError) { 440 users, err := a.srv.userService.GetUsersInTeam(options) 441 if err != nil { 442 return nil, model.NewAppError("GetUsersInTeam", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 443 } 444 445 return users, nil 446} 447 448func (a *App) GetUsersNotInTeam(teamID string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) { 449 users, err := a.srv.userService.GetUsersNotInTeam(teamID, groupConstrained, offset, limit, viewRestrictions) 450 if err != nil { 451 return nil, model.NewAppError("GetUsersNotInTeam", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 452 } 453 454 return users, nil 455} 456 457func (a *App) GetUsersInTeamPage(options *model.UserGetOptions, asAdmin bool) ([]*model.User, *model.AppError) { 458 users, err := a.srv.userService.GetUsersInTeamPage(options, asAdmin) 459 if err != nil { 460 return nil, model.NewAppError("GetUsersInTeamPage", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 461 } 462 463 return a.sanitizeProfiles(users, asAdmin), nil 464} 465 466func (a *App) GetUsersNotInTeamPage(teamID string, groupConstrained bool, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) { 467 users, err := a.srv.userService.GetUsersNotInTeamPage(teamID, groupConstrained, page*perPage, perPage, asAdmin, viewRestrictions) 468 if err != nil { 469 return nil, model.NewAppError("GetUsersNotInTeamPage", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 470 } 471 472 return a.sanitizeProfiles(users, asAdmin), nil 473} 474 475func (a *App) GetUsersInTeamEtag(teamID string, restrictionsHash string) string { 476 return a.srv.userService.GetUsersInTeamEtag(teamID, restrictionsHash) 477} 478 479func (a *App) GetUsersNotInTeamEtag(teamID string, restrictionsHash string) string { 480 return a.srv.userService.GetUsersNotInTeamEtag(teamID, restrictionsHash) 481} 482 483func (a *App) GetUsersInChannel(options *model.UserGetOptions) ([]*model.User, *model.AppError) { 484 users, err := a.Srv().Store.User().GetProfilesInChannel(options) 485 if err != nil { 486 return nil, model.NewAppError("GetUsersInChannel", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 487 } 488 489 return users, nil 490} 491 492func (a *App) GetUsersInChannelByStatus(options *model.UserGetOptions) ([]*model.User, *model.AppError) { 493 users, err := a.Srv().Store.User().GetProfilesInChannelByStatus(options) 494 if err != nil { 495 return nil, model.NewAppError("GetUsersInChannelByStatus", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 496 } 497 498 return users, nil 499} 500 501func (a *App) GetUsersInChannelMap(options *model.UserGetOptions, asAdmin bool) (map[string]*model.User, *model.AppError) { 502 users, err := a.GetUsersInChannel(options) 503 if err != nil { 504 return nil, err 505 } 506 507 userMap := make(map[string]*model.User, len(users)) 508 509 for _, user := range users { 510 a.SanitizeProfile(user, asAdmin) 511 userMap[user.Id] = user 512 } 513 514 return userMap, nil 515} 516 517func (a *App) GetUsersInChannelPage(options *model.UserGetOptions, asAdmin bool) ([]*model.User, *model.AppError) { 518 users, err := a.GetUsersInChannel(options) 519 if err != nil { 520 return nil, err 521 } 522 return a.sanitizeProfiles(users, asAdmin), nil 523} 524 525func (a *App) GetUsersInChannelPageByStatus(options *model.UserGetOptions, asAdmin bool) ([]*model.User, *model.AppError) { 526 users, err := a.GetUsersInChannelByStatus(options) 527 if err != nil { 528 return nil, err 529 } 530 return a.sanitizeProfiles(users, asAdmin), nil 531} 532 533func (a *App) GetUsersNotInChannel(teamID string, channelID string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) { 534 users, err := a.Srv().Store.User().GetProfilesNotInChannel(teamID, channelID, groupConstrained, offset, limit, viewRestrictions) 535 if err != nil { 536 return nil, model.NewAppError("GetUsersNotInChannel", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 537 } 538 539 return users, nil 540} 541 542func (a *App) GetUsersNotInChannelMap(teamID string, channelID string, groupConstrained bool, offset int, limit int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) (map[string]*model.User, *model.AppError) { 543 users, err := a.GetUsersNotInChannel(teamID, channelID, groupConstrained, offset, limit, viewRestrictions) 544 if err != nil { 545 return nil, err 546 } 547 548 userMap := make(map[string]*model.User, len(users)) 549 550 for _, user := range users { 551 a.SanitizeProfile(user, asAdmin) 552 userMap[user.Id] = user 553 } 554 555 return userMap, nil 556} 557 558func (a *App) GetUsersNotInChannelPage(teamID string, channelID string, groupConstrained bool, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) { 559 users, err := a.GetUsersNotInChannel(teamID, channelID, groupConstrained, page*perPage, perPage, viewRestrictions) 560 if err != nil { 561 return nil, err 562 } 563 564 return a.sanitizeProfiles(users, asAdmin), nil 565} 566 567func (a *App) GetUsersWithoutTeamPage(options *model.UserGetOptions, asAdmin bool) ([]*model.User, *model.AppError) { 568 users, err := a.srv.userService.GetUsersWithoutTeamPage(options, asAdmin) 569 if err != nil { 570 return nil, model.NewAppError("GetUsersWithoutTeamPage", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 571 } 572 573 return a.sanitizeProfiles(users, asAdmin), nil 574} 575 576func (a *App) GetUsersWithoutTeam(options *model.UserGetOptions) ([]*model.User, *model.AppError) { 577 users, err := a.srv.userService.GetUsersWithoutTeam(options) 578 if err != nil { 579 return nil, model.NewAppError("GetUsersWithoutTeam", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 580 } 581 582 return users, nil 583} 584 585// GetTeamGroupUsers returns the users who are associated to the team via GroupTeams and GroupMembers. 586func (a *App) GetTeamGroupUsers(teamID string) ([]*model.User, *model.AppError) { 587 users, err := a.Srv().Store.User().GetTeamGroupUsers(teamID) 588 if err != nil { 589 return nil, model.NewAppError("GetTeamGroupUsers", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 590 } 591 592 return users, nil 593} 594 595// GetChannelGroupUsers returns the users who are associated to the channel via GroupChannels and GroupMembers. 596func (a *App) GetChannelGroupUsers(channelID string) ([]*model.User, *model.AppError) { 597 users, err := a.Srv().Store.User().GetChannelGroupUsers(channelID) 598 if err != nil { 599 return nil, model.NewAppError("GetChannelGroupUsers", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 600 } 601 602 return users, nil 603} 604 605func (a *App) GetUsersByIds(userIDs []string, options *store.UserGetByIdsOpts) ([]*model.User, *model.AppError) { 606 users, err := a.srv.userService.GetUsersByIds(userIDs, options) 607 if err != nil { 608 return nil, model.NewAppError("GetUsersByIds", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 609 } 610 611 return users, nil 612} 613 614func (a *App) GetUsersByGroupChannelIds(c *request.Context, channelIDs []string, asAdmin bool) (map[string][]*model.User, *model.AppError) { 615 usersByChannelId, err := a.Srv().Store.User().GetProfileByGroupChannelIdsForUser(c.Session().UserId, channelIDs) 616 if err != nil { 617 return nil, model.NewAppError("GetUsersByGroupChannelIds", "app.user.get_profile_by_group_channel_ids_for_user.app_error", nil, err.Error(), http.StatusInternalServerError) 618 } 619 for channelID, userList := range usersByChannelId { 620 usersByChannelId[channelID] = a.sanitizeProfiles(userList, asAdmin) 621 } 622 623 return usersByChannelId, nil 624} 625 626func (a *App) GetUsersByUsernames(usernames []string, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) { 627 users, err := a.srv.userService.GetUsersByUsernames(usernames, &model.UserGetOptions{ViewRestrictions: viewRestrictions}) 628 if err != nil { 629 return nil, model.NewAppError("GetUsersByUsernames", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 630 } 631 return a.sanitizeProfiles(users, asAdmin), nil 632} 633 634func (a *App) sanitizeProfiles(users []*model.User, asAdmin bool) []*model.User { 635 for _, u := range users { 636 a.SanitizeProfile(u, asAdmin) 637 } 638 639 return users 640} 641 642func (a *App) GenerateMfaSecret(userID string) (*model.MfaSecret, *model.AppError) { 643 user, appErr := a.GetUser(userID) 644 if appErr != nil { 645 return nil, appErr 646 } 647 648 if !*a.Config().ServiceSettings.EnableMultifactorAuthentication { 649 return nil, model.NewAppError("GenerateMfaSecret", "mfa.mfa_disabled.app_error", nil, "", http.StatusNotImplemented) 650 } 651 652 mfaSecret, err := a.srv.userService.GenerateMfaSecret(user) 653 if err != nil { 654 return nil, model.NewAppError("GenerateMfaSecret", "mfa.generate_qr_code.create_code.app_error", nil, err.Error(), http.StatusInternalServerError) 655 } 656 657 return mfaSecret, nil 658} 659 660func (a *App) ActivateMfa(userID, token string) *model.AppError { 661 user, appErr := a.GetUser(userID) 662 if appErr != nil { 663 return appErr 664 } 665 666 if user.AuthService != "" && user.AuthService != model.UserAuthServiceLdap { 667 return model.NewAppError("ActivateMfa", "api.user.activate_mfa.email_and_ldap_only.app_error", nil, "", http.StatusBadRequest) 668 } 669 670 if !*a.Config().ServiceSettings.EnableMultifactorAuthentication { 671 return model.NewAppError("ActivateMfa", "mfa.mfa_disabled.app_error", nil, "", http.StatusNotImplemented) 672 } 673 674 if err := a.srv.userService.ActivateMfa(user, token); err != nil { 675 switch { 676 case errors.Is(err, mfa.InvalidToken): 677 return model.NewAppError("ActivateMfa", "mfa.activate.bad_token.app_error", nil, "", http.StatusUnauthorized) 678 default: 679 return model.NewAppError("ActivateMfa", "mfa.activate.app_error", nil, err.Error(), http.StatusInternalServerError) 680 } 681 } 682 683 // Make sure old MFA status is not cached locally or in cluster nodes. 684 a.InvalidateCacheForUser(userID) 685 686 return nil 687} 688 689func (a *App) DeactivateMfa(userID string) *model.AppError { 690 user, appErr := a.GetUser(userID) 691 if appErr != nil { 692 return appErr 693 } 694 695 if err := a.srv.userService.DeactivateMfa(user); err != nil { 696 return model.NewAppError("DeactivateMfa", "mfa.deactivate.app_error", nil, err.Error(), http.StatusInternalServerError) 697 } 698 699 // Make sure old MFA status is not cached locally or in cluster nodes. 700 a.InvalidateCacheForUser(userID) 701 702 return nil 703} 704 705func (a *App) GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) { 706 return a.srv.GetProfileImage(user) 707} 708 709func (a *App) GetDefaultProfileImage(user *model.User) ([]byte, *model.AppError) { 710 return a.srv.GetDefaultProfileImage(user) 711} 712 713func (a *App) SetDefaultProfileImage(user *model.User) *model.AppError { 714 img, appErr := a.GetDefaultProfileImage(user) 715 if appErr != nil { 716 return appErr 717 } 718 719 path := getProfileImagePath(user.Id) 720 if _, err := a.WriteFile(bytes.NewReader(img), path); err != nil { 721 return err 722 } 723 724 if err := a.Srv().Store.User().ResetLastPictureUpdate(user.Id); err != nil { 725 mlog.Warn("Failed to reset last picture update", mlog.Err(err)) 726 } 727 728 a.InvalidateCacheForUser(user.Id) 729 730 updatedUser, appErr := a.GetUser(user.Id) 731 if appErr != nil { 732 mlog.Warn("Error in getting users profile forcing logout", mlog.String("user_id", user.Id), mlog.Err(appErr)) 733 return nil 734 } 735 736 options := a.Config().GetSanitizeOptions() 737 updatedUser.SanitizeProfile(options) 738 739 message := model.NewWebSocketEvent(model.WebsocketEventUserUpdated, "", "", "", nil) 740 message.Add("user", updatedUser) 741 a.Publish(message) 742 743 return nil 744} 745 746func (a *App) SetProfileImage(userID string, imageData *multipart.FileHeader) *model.AppError { 747 file, err := imageData.Open() 748 if err != nil { 749 return model.NewAppError("SetProfileImage", "api.user.upload_profile_user.open.app_error", nil, err.Error(), http.StatusBadRequest) 750 } 751 defer file.Close() 752 return a.SetProfileImageFromMultiPartFile(userID, file) 753} 754 755func (a *App) SetProfileImageFromMultiPartFile(userID string, file multipart.File) *model.AppError { 756 if limitErr := checkImageLimits(file, *a.Config().FileSettings.MaxImageResolution); limitErr != nil { 757 return model.NewAppError("SetProfileImage", "api.user.upload_profile_user.check_image_limits.app_error", nil, "", http.StatusBadRequest) 758 } 759 760 return a.SetProfileImageFromFile(userID, file) 761} 762 763func (a *App) AdjustImage(file io.Reader) (*bytes.Buffer, *model.AppError) { 764 // Decode image into Image object 765 img, _, err := a.srv.imgDecoder.Decode(file) 766 if err != nil { 767 return nil, model.NewAppError("SetProfileImage", "api.user.upload_profile_user.decode.app_error", nil, err.Error(), http.StatusBadRequest) 768 } 769 770 orientation, _ := imaging.GetImageOrientation(file) 771 img = imaging.MakeImageUpright(img, orientation) 772 773 // Scale profile image 774 profileWidthAndHeight := 128 775 img = imaging.FillCenter(img, profileWidthAndHeight, profileWidthAndHeight) 776 777 buf := new(bytes.Buffer) 778 err = a.srv.imgEncoder.EncodePNG(buf, img) 779 if err != nil { 780 return nil, model.NewAppError("SetProfileImage", "api.user.upload_profile_user.encode.app_error", nil, err.Error(), http.StatusInternalServerError) 781 } 782 return buf, nil 783} 784 785func (a *App) SetProfileImageFromFile(userID string, file io.Reader) *model.AppError { 786 buf, err := a.AdjustImage(file) 787 if err != nil { 788 return err 789 } 790 791 path := getProfileImagePath(userID) 792 if storedData, err := a.ReadFile(path); err == nil && bytes.Equal(storedData, buf.Bytes()) { 793 return nil 794 } 795 796 if _, err := a.WriteFile(buf, path); err != nil { 797 return model.NewAppError("SetProfileImage", "api.user.upload_profile_user.upload_profile.app_error", nil, err.Error(), http.StatusInternalServerError) 798 } 799 800 if err := a.Srv().Store.User().UpdateLastPictureUpdate(userID); err != nil { 801 mlog.Warn("Error with updating last picture update", mlog.Err(err)) 802 } 803 a.invalidateUserCacheAndPublish(userID) 804 a.onUserProfileChange(userID) 805 806 return nil 807} 808 809func (a *App) UpdatePasswordAsUser(userID, currentPassword, newPassword string) *model.AppError { 810 user, err := a.GetUser(userID) 811 if err != nil { 812 return err 813 } 814 815 if user == nil { 816 err = model.NewAppError("updatePassword", "api.user.update_password.valid_account.app_error", nil, "", http.StatusBadRequest) 817 return err 818 } 819 820 if user.AuthData != nil && *user.AuthData != "" { 821 err = model.NewAppError("updatePassword", "api.user.update_password.oauth.app_error", nil, "auth_service="+user.AuthService, http.StatusBadRequest) 822 return err 823 } 824 825 if err := a.DoubleCheckPassword(user, currentPassword); err != nil { 826 if err.Id == "api.user.check_user_password.invalid.app_error" { 827 err = model.NewAppError("updatePassword", "api.user.update_password.incorrect.app_error", nil, "", http.StatusBadRequest) 828 } 829 return err 830 } 831 832 T := i18n.GetUserTranslations(user.Locale) 833 834 return a.UpdatePasswordSendEmail(user, newPassword, T("api.user.update_password.menu")) 835} 836 837func (a *App) userDeactivated(c *request.Context, userID string) *model.AppError { 838 a.SetStatusOffline(userID, false) 839 840 user, err := a.GetUser(userID) 841 if err != nil { 842 return err 843 } 844 845 // when disable a user, userDeactivated is called for the user and the 846 // bots the user owns. Only notify once, when the user is the owner, not the 847 // owners bots 848 if !user.IsBot { 849 a.notifySysadminsBotOwnerDeactivated(c, userID) 850 } 851 852 if *a.Config().ServiceSettings.DisableBotsWhenOwnerIsDeactivated { 853 a.disableUserBots(c, userID) 854 } 855 856 return nil 857} 858 859func (a *App) invalidateUserChannelMembersCaches(userID string) *model.AppError { 860 teamsForUser, err := a.GetTeamsForUser(userID) 861 if err != nil { 862 return err 863 } 864 865 for _, team := range teamsForUser { 866 channelsForUser, err := a.GetChannelsForUser(team.Id, userID, false, 0) 867 if err != nil { 868 return err 869 } 870 871 for _, channel := range channelsForUser { 872 a.invalidateCacheForChannelMembers(channel.Id) 873 } 874 } 875 876 return nil 877} 878 879func (a *App) UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError) { 880 user.UpdateAt = model.GetMillis() 881 if active { 882 user.DeleteAt = 0 883 } else { 884 user.DeleteAt = user.UpdateAt 885 } 886 887 userUpdate, err := a.srv.userService.UpdateUser(user, true) 888 if err != nil { 889 var appErr *model.AppError 890 var invErr *store.ErrInvalidInput 891 switch { 892 case errors.As(err, &appErr): 893 return nil, appErr 894 case errors.As(err, &invErr): 895 return nil, model.NewAppError("UpdateActive", "app.user.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 896 default: 897 return nil, model.NewAppError("UpdateActive", "app.user.update.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 898 } 899 } 900 ruser := userUpdate.New 901 902 if !active { 903 if err := a.RevokeAllSessions(ruser.Id); err != nil { 904 return nil, err 905 } 906 if err := a.userDeactivated(c, ruser.Id); err != nil { 907 return nil, err 908 } 909 } 910 911 a.invalidateUserChannelMembersCaches(user.Id) 912 a.InvalidateCacheForUser(user.Id) 913 914 a.sendUpdatedUserEvent(*ruser) 915 916 return ruser, nil 917} 918 919func (a *App) DeactivateGuests(c *request.Context) *model.AppError { 920 userIDs, err := a.srv.userService.DeactivateAllGuests() 921 if err != nil { 922 return model.NewAppError("DeactivateGuests", "app.user.update_active_for_multiple_users.updating.app_error", nil, err.Error(), http.StatusInternalServerError) 923 } 924 925 for _, userID := range userIDs { 926 if err := a.userDeactivated(c, userID); err != nil { 927 return err 928 } 929 } 930 931 a.Srv().Store.Channel().ClearCaches() 932 a.Srv().Store.User().ClearCaches() 933 934 message := model.NewWebSocketEvent(model.WebsocketEventGuestsDeactivated, "", "", "", nil) 935 a.Publish(message) 936 937 return nil 938} 939 940func (a *App) GetSanitizeOptions(asAdmin bool) map[string]bool { 941 return a.srv.userService.GetSanitizeOptions(asAdmin) 942} 943 944func (a *App) SanitizeProfile(user *model.User, asAdmin bool) { 945 options := a.srv.userService.GetSanitizeOptions(asAdmin) 946 947 user.SanitizeProfile(options) 948} 949 950func (a *App) UpdateUserAsUser(user *model.User, asAdmin bool) (*model.User, *model.AppError) { 951 updatedUser, err := a.UpdateUser(user, true) 952 if err != nil { 953 return nil, err 954 } 955 956 return updatedUser, nil 957} 958 959// CheckProviderAttributes returns the empty string if the patch can be applied without 960// overriding attributes set by the user's login provider; otherwise, the name of the offending 961// field is returned. 962func (a *App) CheckProviderAttributes(user *model.User, patch *model.UserPatch) string { 963 tryingToChange := func(userValue *string, patchValue *string) bool { 964 return patchValue != nil && *patchValue != *userValue 965 } 966 967 // If any login provider is used, then the username may not be changed 968 if user.AuthService != "" && tryingToChange(&user.Username, patch.Username) { 969 return "username" 970 } 971 972 LdapSettings := &a.Config().LdapSettings 973 SamlSettings := &a.Config().SamlSettings 974 975 conflictField := "" 976 if a.Ldap() != nil && 977 (user.IsLDAPUser() || (user.IsSAMLUser() && *SamlSettings.EnableSyncWithLdap)) { 978 conflictField = a.Ldap().CheckProviderAttributes(LdapSettings, user, patch) 979 } else if a.Saml() != nil && user.IsSAMLUser() { 980 conflictField = a.Saml().CheckProviderAttributes(SamlSettings, user, patch) 981 } else if user.IsOAuthUser() { 982 if tryingToChange(&user.FirstName, patch.FirstName) || tryingToChange(&user.LastName, patch.LastName) { 983 conflictField = "full name" 984 } 985 } 986 987 return conflictField 988} 989 990func (a *App) PatchUser(userID string, patch *model.UserPatch, asAdmin bool) (*model.User, *model.AppError) { 991 user, err := a.GetUser(userID) 992 if err != nil { 993 return nil, err 994 } 995 996 user.Patch(patch) 997 998 updatedUser, err := a.UpdateUser(user, true) 999 if err != nil { 1000 return nil, err 1001 } 1002 1003 return updatedUser, nil 1004} 1005 1006func (a *App) UpdateUserAuth(userID string, userAuth *model.UserAuth) (*model.UserAuth, *model.AppError) { 1007 userAuth.Password = "" 1008 if _, err := a.Srv().Store.User().UpdateAuthData(userID, userAuth.AuthService, userAuth.AuthData, "", false); err != nil { 1009 var invErr *store.ErrInvalidInput 1010 switch { 1011 case errors.As(err, &invErr): 1012 return nil, model.NewAppError("UpdateUserAuth", "app.user.update_auth_data.email_exists.app_error", nil, invErr.Error(), http.StatusBadRequest) 1013 default: 1014 return nil, model.NewAppError("UpdateUserAuth", "app.user.update_auth_data.app_error", nil, err.Error(), http.StatusInternalServerError) 1015 } 1016 } 1017 1018 return userAuth, nil 1019} 1020 1021func (a *App) sendUpdatedUserEvent(user model.User) { 1022 adminCopyOfUser := user.DeepCopy() 1023 a.SanitizeProfile(adminCopyOfUser, true) 1024 adminMessage := model.NewWebSocketEvent(model.WebsocketEventUserUpdated, "", "", "", nil) 1025 adminMessage.Add("user", adminCopyOfUser) 1026 adminMessage.GetBroadcast().ContainsSensitiveData = true 1027 a.Publish(adminMessage) 1028 1029 a.SanitizeProfile(&user, false) 1030 message := model.NewWebSocketEvent(model.WebsocketEventUserUpdated, "", "", "", nil) 1031 message.Add("user", &user) 1032 message.GetBroadcast().ContainsSanitizedData = true 1033 a.Publish(message) 1034} 1035 1036func (a *App) UpdateUser(user *model.User, sendNotifications bool) (*model.User, *model.AppError) { 1037 prev, err := a.srv.userService.GetUser(user.Id) 1038 if err != nil { 1039 var nfErr *store.ErrNotFound 1040 switch { 1041 case errors.As(err, &nfErr): 1042 return nil, model.NewAppError("UpdateUser", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 1043 default: 1044 return nil, model.NewAppError("UpdateUser", "app.user.get.app_error", nil, err.Error(), http.StatusInternalServerError) 1045 } 1046 } 1047 1048 var newEmail string 1049 if user.Email != prev.Email { 1050 if !users.CheckUserDomain(user, *a.Config().TeamSettings.RestrictCreationToDomains) { 1051 if !prev.IsGuest() && !prev.IsLDAPUser() && !prev.IsSAMLUser() { 1052 return nil, model.NewAppError("UpdateUser", "api.user.update_user.accepted_domain.app_error", nil, "", http.StatusBadRequest) 1053 } 1054 } 1055 1056 if !users.CheckUserDomain(user, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) { 1057 if prev.IsGuest() && !prev.IsLDAPUser() && !prev.IsSAMLUser() { 1058 return nil, model.NewAppError("UpdateUser", "api.user.update_user.accepted_guest_domain.app_error", nil, "", http.StatusBadRequest) 1059 } 1060 } 1061 1062 if *a.Config().EmailSettings.RequireEmailVerification { 1063 newEmail = user.Email 1064 // Don't set new eMail on user account if email verification is required, this will be done as a post-verification action 1065 // to avoid users being able to set non-controlled eMails as their account email 1066 if _, appErr := a.GetUserByEmail(newEmail); appErr == nil { 1067 return nil, model.NewAppError("UpdateUser", "app.user.save.email_exists.app_error", nil, "user_id="+user.Id, http.StatusBadRequest) 1068 } 1069 1070 // When a bot is created, prev.Email will be an autogenerated faked email, 1071 // which will not match a CLI email input during bot to user conversions. 1072 // To update a bot users email, do not set the email to the faked email 1073 // stored in prev.Email. Allow using the email defined in the CLI 1074 if !user.IsBot { 1075 user.Email = prev.Email 1076 } 1077 } 1078 } 1079 1080 userUpdate, err := a.srv.userService.UpdateUser(user, false) 1081 if err != nil { 1082 var appErr *model.AppError 1083 var invErr *store.ErrInvalidInput 1084 var conErr *store.ErrConflict 1085 switch { 1086 case errors.As(err, &appErr): 1087 return nil, appErr 1088 case errors.As(err, &invErr): 1089 return nil, model.NewAppError("UpdateUser", "app.user.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 1090 case errors.As(err, &conErr): 1091 if cErr, ok := err.(*store.ErrConflict); ok && cErr.Resource == "Username" { 1092 return nil, model.NewAppError("UpdateUser", "app.user.save.username_exists.app_error", nil, "", http.StatusBadRequest) 1093 } 1094 return nil, model.NewAppError("UpdateUser", "app.user.save.email_exists.app_error", nil, "", http.StatusBadRequest) 1095 default: 1096 return nil, model.NewAppError("UpdateUser", "app.user.update.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 1097 } 1098 } 1099 1100 if sendNotifications { 1101 if userUpdate.New.Email != userUpdate.Old.Email || newEmail != "" { 1102 if *a.Config().EmailSettings.RequireEmailVerification { 1103 a.Srv().Go(func() { 1104 if err := a.SendEmailVerification(userUpdate.New, newEmail, ""); err != nil { 1105 mlog.Error("Failed to send email verification", mlog.Err(err)) 1106 } 1107 }) 1108 } else { 1109 a.Srv().Go(func() { 1110 if err := a.Srv().EmailService.SendEmailChangeEmail(userUpdate.Old.Email, userUpdate.New.Email, userUpdate.New.Locale, a.GetSiteURL()); err != nil { 1111 mlog.Error("Failed to send email change email", mlog.Err(err)) 1112 } 1113 }) 1114 } 1115 } 1116 1117 if userUpdate.New.Username != userUpdate.Old.Username { 1118 a.Srv().Go(func() { 1119 if err := a.Srv().EmailService.SendChangeUsernameEmail(userUpdate.New.Username, userUpdate.New.Email, userUpdate.New.Locale, a.GetSiteURL()); err != nil { 1120 mlog.Error("Failed to send change username email", mlog.Err(err)) 1121 } 1122 }) 1123 } 1124 a.sendUpdatedUserEvent(*userUpdate.New) 1125 } 1126 1127 a.InvalidateCacheForUser(user.Id) 1128 a.onUserProfileChange(user.Id) 1129 1130 return userUpdate.New, nil 1131} 1132 1133func (a *App) UpdateUserActive(c *request.Context, userID string, active bool) *model.AppError { 1134 user, err := a.GetUser(userID) 1135 1136 if err != nil { 1137 return err 1138 } 1139 if _, err = a.UpdateActive(c, user, active); err != nil { 1140 return err 1141 } 1142 1143 return nil 1144} 1145 1146func (a *App) updateUserNotifyProps(userID string, props map[string]string) *model.AppError { 1147 err := a.srv.userService.UpdateUserNotifyProps(userID, props) 1148 if err != nil { 1149 var appErr *model.AppError 1150 switch { 1151 case errors.As(err, &appErr): 1152 return appErr 1153 default: 1154 return model.NewAppError("UpdateUser", "app.user.update.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 1155 } 1156 } 1157 1158 a.InvalidateCacheForUser(userID) 1159 a.onUserProfileChange(userID) 1160 1161 return nil 1162} 1163 1164func (a *App) UpdateMfa(activate bool, userID, token string) *model.AppError { 1165 if activate { 1166 if err := a.ActivateMfa(userID, token); err != nil { 1167 return err 1168 } 1169 } else { 1170 if err := a.DeactivateMfa(userID); err != nil { 1171 return err 1172 } 1173 } 1174 1175 a.Srv().Go(func() { 1176 user, err := a.GetUser(userID) 1177 if err != nil { 1178 mlog.Error("Failed to get user", mlog.Err(err)) 1179 return 1180 } 1181 1182 if err := a.Srv().EmailService.SendMfaChangeEmail(user.Email, activate, user.Locale, a.GetSiteURL()); err != nil { 1183 mlog.Error("Failed to send mfa change email", mlog.Err(err)) 1184 } 1185 }) 1186 1187 return nil 1188} 1189 1190func (a *App) UpdatePasswordByUserIdSendEmail(userID, newPassword, method string) *model.AppError { 1191 user, err := a.GetUser(userID) 1192 if err != nil { 1193 return err 1194 } 1195 1196 return a.UpdatePasswordSendEmail(user, newPassword, method) 1197} 1198 1199func (a *App) UpdatePassword(user *model.User, newPassword string) *model.AppError { 1200 if err := a.IsPasswordValid(newPassword); err != nil { 1201 return err 1202 } 1203 1204 hashedPassword := model.HashPassword(newPassword) 1205 1206 if err := a.Srv().Store.User().UpdatePassword(user.Id, hashedPassword); err != nil { 1207 return model.NewAppError("UpdatePassword", "api.user.update_password.failed.app_error", nil, err.Error(), http.StatusInternalServerError) 1208 } 1209 1210 a.InvalidateCacheForUser(user.Id) 1211 1212 return nil 1213} 1214 1215func (a *App) UpdatePasswordSendEmail(user *model.User, newPassword, method string) *model.AppError { 1216 if err := a.UpdatePassword(user, newPassword); err != nil { 1217 return err 1218 } 1219 1220 a.Srv().Go(func() { 1221 if err := a.Srv().EmailService.SendPasswordChangeEmail(user.Email, method, user.Locale, a.GetSiteURL()); err != nil { 1222 mlog.Error("Failed to send password change email", mlog.Err(err)) 1223 } 1224 }) 1225 1226 return nil 1227} 1228 1229func (a *App) UpdateHashedPasswordByUserId(userID, newHashedPassword string) *model.AppError { 1230 user, err := a.GetUser(userID) 1231 if err != nil { 1232 return err 1233 } 1234 1235 return a.UpdateHashedPassword(user, newHashedPassword) 1236} 1237 1238func (a *App) UpdateHashedPassword(user *model.User, newHashedPassword string) *model.AppError { 1239 if err := a.Srv().Store.User().UpdatePassword(user.Id, newHashedPassword); err != nil { 1240 return model.NewAppError("UpdatePassword", "api.user.update_password.failed.app_error", nil, err.Error(), http.StatusInternalServerError) 1241 } 1242 1243 a.InvalidateCacheForUser(user.Id) 1244 1245 return nil 1246} 1247 1248func (a *App) ResetPasswordFromToken(userSuppliedTokenString, newPassword string) *model.AppError { 1249 token, err := a.GetPasswordRecoveryToken(userSuppliedTokenString) 1250 if err != nil { 1251 return err 1252 } 1253 if model.GetMillis()-token.CreateAt >= PasswordRecoverExpiryTime { 1254 return model.NewAppError("resetPassword", "api.user.reset_password.link_expired.app_error", nil, "", http.StatusBadRequest) 1255 } 1256 1257 tokenData := struct { 1258 UserId string 1259 Email string 1260 }{} 1261 1262 err2 := json.Unmarshal([]byte(token.Extra), &tokenData) 1263 if err2 != nil { 1264 return model.NewAppError("resetPassword", "api.user.reset_password.token_parse.error", nil, "", http.StatusInternalServerError) 1265 } 1266 1267 user, err := a.GetUser(tokenData.UserId) 1268 if err != nil { 1269 return err 1270 } 1271 1272 if user.Email != tokenData.Email { 1273 return model.NewAppError("resetPassword", "api.user.reset_password.link_expired.app_error", nil, "", http.StatusBadRequest) 1274 } 1275 1276 if user.IsSSOUser() { 1277 return model.NewAppError("ResetPasswordFromCode", "api.user.reset_password.sso.app_error", nil, "userId="+user.Id, http.StatusBadRequest) 1278 } 1279 1280 T := i18n.GetUserTranslations(user.Locale) 1281 1282 if err := a.UpdatePasswordSendEmail(user, newPassword, T("api.user.reset_password.method")); err != nil { 1283 return err 1284 } 1285 1286 if err := a.DeleteToken(token); err != nil { 1287 mlog.Warn("Failed to delete token", mlog.Err(err)) 1288 } 1289 1290 return nil 1291} 1292 1293func (a *App) SendPasswordReset(email string, siteURL string) (bool, *model.AppError) { 1294 user, err := a.GetUserByEmail(email) 1295 if err != nil { 1296 return false, nil 1297 } 1298 1299 if user.AuthData != nil && *user.AuthData != "" { 1300 return false, model.NewAppError("SendPasswordReset", "api.user.send_password_reset.sso.app_error", nil, "userId="+user.Id, http.StatusBadRequest) 1301 } 1302 1303 token, err := a.CreatePasswordRecoveryToken(user.Id, user.Email) 1304 if err != nil { 1305 return false, err 1306 } 1307 1308 result, eErr := a.Srv().EmailService.SendPasswordResetEmail(user.Email, token, user.Locale, siteURL) 1309 if eErr != nil { 1310 return result, model.NewAppError("SendPasswordReset", "api.user.send_password_reset.send.app_error", nil, "err="+eErr.Error(), http.StatusInternalServerError) 1311 } 1312 1313 return result, nil 1314} 1315 1316func (a *App) CreatePasswordRecoveryToken(userID, email string) (*model.Token, *model.AppError) { 1317 tokenExtra := struct { 1318 UserId string 1319 Email string 1320 }{ 1321 userID, 1322 email, 1323 } 1324 jsonData, err := json.Marshal(tokenExtra) 1325 1326 if err != nil { 1327 return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError) 1328 } 1329 1330 token := model.NewToken(TokenTypePasswordRecovery, string(jsonData)) 1331 1332 if err := a.Srv().Store.Token().Save(token); err != nil { 1333 var appErr *model.AppError 1334 switch { 1335 case errors.As(err, &appErr): 1336 return nil, appErr 1337 default: 1338 return nil, model.NewAppError("CreatePasswordRecoveryToken", "app.recover.save.app_error", nil, err.Error(), http.StatusInternalServerError) 1339 } 1340 } 1341 1342 return token, nil 1343} 1344 1345func (a *App) GetPasswordRecoveryToken(token string) (*model.Token, *model.AppError) { 1346 rtoken, err := a.Srv().Store.Token().GetByToken(token) 1347 if err != nil { 1348 return nil, model.NewAppError("GetPasswordRecoveryToken", "api.user.reset_password.invalid_link.app_error", nil, err.Error(), http.StatusBadRequest) 1349 } 1350 if rtoken.Type != TokenTypePasswordRecovery { 1351 return nil, model.NewAppError("GetPasswordRecoveryToken", "api.user.reset_password.broken_token.app_error", nil, "", http.StatusBadRequest) 1352 } 1353 return rtoken, nil 1354} 1355 1356func (a *App) DeleteToken(token *model.Token) *model.AppError { 1357 err := a.Srv().Store.Token().Delete(token.Token) 1358 if err != nil { 1359 return model.NewAppError("DeleteToken", "app.recover.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 1360 } 1361 return nil 1362} 1363 1364func (a *App) UpdateUserRoles(userID string, newRoles string, sendWebSocketEvent bool) (*model.User, *model.AppError) { 1365 user, err := a.GetUser(userID) 1366 if err != nil { 1367 err.StatusCode = http.StatusBadRequest 1368 return nil, err 1369 } 1370 1371 return a.UpdateUserRolesWithUser(user, newRoles, sendWebSocketEvent) 1372} 1373 1374func (a *App) UpdateUserRolesWithUser(user *model.User, newRoles string, sendWebSocketEvent bool) (*model.User, *model.AppError) { 1375 1376 if err := a.CheckRolesExist(strings.Fields(newRoles)); err != nil { 1377 return nil, err 1378 } 1379 1380 user.Roles = newRoles 1381 uchan := make(chan store.StoreResult, 1) 1382 go func() { 1383 userUpdate, err := a.Srv().Store.User().Update(user, true) 1384 uchan <- store.StoreResult{Data: userUpdate, NErr: err} 1385 close(uchan) 1386 }() 1387 1388 schan := make(chan store.StoreResult, 1) 1389 go func() { 1390 id, err := a.Srv().Store.Session().UpdateRoles(user.Id, newRoles) 1391 schan <- store.StoreResult{Data: id, NErr: err} 1392 close(schan) 1393 }() 1394 1395 result := <-uchan 1396 if result.NErr != nil { 1397 var appErr *model.AppError 1398 var invErr *store.ErrInvalidInput 1399 switch { 1400 case errors.As(result.NErr, &appErr): 1401 return nil, appErr 1402 case errors.As(result.NErr, &invErr): 1403 return nil, model.NewAppError("UpdateUserRoles", "app.user.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 1404 default: 1405 return nil, model.NewAppError("UpdateUserRoles", "app.user.update.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1406 } 1407 } 1408 ruser := result.Data.(*model.UserUpdate).New 1409 1410 if result := <-schan; result.NErr != nil { 1411 // soft error since the user roles were still updated 1412 mlog.Warn("Failed during updating user roles", mlog.Err(result.NErr)) 1413 } 1414 1415 a.InvalidateCacheForUser(user.Id) 1416 a.ClearSessionCacheForUser(user.Id) 1417 1418 if sendWebSocketEvent { 1419 message := model.NewWebSocketEvent(model.WebsocketEventUserRoleUpdated, "", "", user.Id, nil) 1420 message.Add("user_id", user.Id) 1421 message.Add("roles", newRoles) 1422 a.Publish(message) 1423 } 1424 1425 return ruser, nil 1426} 1427 1428func (a *App) PermanentDeleteUser(c *request.Context, user *model.User) *model.AppError { 1429 mlog.Warn("Attempting to permanently delete account", mlog.String("user_id", user.Id), mlog.String("user_email", user.Email)) 1430 if user.IsInRole(model.SystemAdminRoleId) { 1431 mlog.Warn("You are deleting a user that is a system administrator. You may need to set another account as the system administrator using the command line tools.", mlog.String("user_email", user.Email)) 1432 } 1433 1434 if _, err := a.UpdateActive(c, user, false); err != nil { 1435 return err 1436 } 1437 1438 if err := a.Srv().Store.Session().PermanentDeleteSessionsByUser(user.Id); err != nil { 1439 return model.NewAppError("PermanentDeleteUser", "app.session.permanent_delete_sessions_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1440 } 1441 1442 if err := a.Srv().Store.UserAccessToken().DeleteAllForUser(user.Id); err != nil { 1443 return model.NewAppError("PermanentDeleteUser", "app.user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 1444 } 1445 1446 if err := a.Srv().Store.OAuth().PermanentDeleteAuthDataByUser(user.Id); err != nil { 1447 return model.NewAppError("PermanentDeleteUser", "app.oauth.permanent_delete_auth_data_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1448 } 1449 1450 if err := a.Srv().Store.Webhook().PermanentDeleteIncomingByUser(user.Id); err != nil { 1451 return model.NewAppError("PermanentDeleteUser", "app.webhooks.permanent_delete_incoming_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1452 } 1453 1454 if err := a.Srv().Store.Webhook().PermanentDeleteOutgoingByUser(user.Id); err != nil { 1455 return model.NewAppError("PermanentDeleteUser", "app.webhooks.permanent_delete_outgoing_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1456 } 1457 1458 if err := a.Srv().Store.Command().PermanentDeleteByUser(user.Id); err != nil { 1459 return model.NewAppError("PermanentDeleteUser", "app.user.permanentdeleteuser.internal_error", nil, err.Error(), http.StatusInternalServerError) 1460 } 1461 1462 if err := a.Srv().Store.Preference().PermanentDeleteByUser(user.Id); err != nil { 1463 return model.NewAppError("PermanentDeleteUser", "app.preference.permanent_delete_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1464 } 1465 1466 if err := a.Srv().Store.Channel().PermanentDeleteMembersByUser(user.Id); err != nil { 1467 return model.NewAppError("PermanentDeleteUser", "app.channel.permanent_delete_members_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1468 } 1469 1470 if err := a.Srv().Store.Group().PermanentDeleteMembersByUser(user.Id); err != nil { 1471 return model.NewAppError("PermanentDeleteUser", "app.group.permanent_delete_members_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1472 } 1473 1474 if err := a.Srv().Store.Post().PermanentDeleteByUser(user.Id); err != nil { 1475 return model.NewAppError("PermanentDeleteUser", "app.post.permanent_delete_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1476 } 1477 1478 if err := a.Srv().Store.Bot().PermanentDelete(user.Id); err != nil { 1479 var invErr *store.ErrInvalidInput 1480 switch { 1481 case errors.As(err, &invErr): 1482 return model.NewAppError("PermanentDeleteUser", "app.bot.permenent_delete.bad_id", map[string]interface{}{"user_id": invErr.Value}, invErr.Error(), http.StatusBadRequest) 1483 default: // last fallback in case it doesn't map to an existing app error. 1484 return model.NewAppError("PermanentDeleteUser", "app.bot.permanent_delete.internal_error", nil, err.Error(), http.StatusInternalServerError) 1485 } 1486 } 1487 1488 infos, err := a.Srv().Store.FileInfo().GetForUser(user.Id) 1489 if err != nil { 1490 mlog.Warn("Error getting file list for user from FileInfoStore", mlog.Err(err)) 1491 } 1492 1493 for _, info := range infos { 1494 res, err := a.FileExists(info.Path) 1495 if err != nil { 1496 mlog.Warn( 1497 "Error checking existence of file", 1498 mlog.String("path", info.Path), 1499 mlog.Err(err), 1500 ) 1501 continue 1502 } 1503 1504 if !res { 1505 mlog.Warn("File not found", mlog.String("path", info.Path)) 1506 continue 1507 } 1508 1509 err = a.RemoveFile(info.Path) 1510 1511 if err != nil { 1512 mlog.Warn( 1513 "Unable to remove file", 1514 mlog.String("path", info.Path), 1515 mlog.Err(err), 1516 ) 1517 } 1518 } 1519 1520 if _, err := a.Srv().Store.FileInfo().PermanentDeleteByUser(user.Id); err != nil { 1521 return model.NewAppError("PermanentDeleteUser", "app.file_info.permanent_delete_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1522 } 1523 1524 if err := a.Srv().Store.User().PermanentDelete(user.Id); err != nil { 1525 return model.NewAppError("PermanentDeleteUser", "app.user.permanent_delete.app_error", nil, err.Error(), http.StatusInternalServerError) 1526 } 1527 1528 if err := a.Srv().Store.Audit().PermanentDeleteByUser(user.Id); err != nil { 1529 return model.NewAppError("PermanentDeleteUser", "app.audit.permanent_delete_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 1530 } 1531 1532 if err := a.Srv().Store.Team().RemoveAllMembersByUser(user.Id); err != nil { 1533 return model.NewAppError("PermanentDeleteUser", "app.team.remove_member.app_error", nil, err.Error(), http.StatusInternalServerError) 1534 } 1535 1536 mlog.Warn("Permanently deleted account", mlog.String("user_email", user.Email), mlog.String("user_id", user.Id)) 1537 1538 return nil 1539} 1540 1541func (a *App) PermanentDeleteAllUsers(c *request.Context) *model.AppError { 1542 users, err := a.Srv().Store.User().GetAll() 1543 if err != nil { 1544 return model.NewAppError("PermanentDeleteAllUsers", "app.user.get.app_error", nil, err.Error(), http.StatusInternalServerError) 1545 } 1546 for _, user := range users { 1547 a.PermanentDeleteUser(c, user) 1548 } 1549 1550 return nil 1551} 1552 1553func (a *App) SendEmailVerification(user *model.User, newEmail, redirect string) *model.AppError { 1554 token, err := a.Srv().EmailService.CreateVerifyEmailToken(user.Id, newEmail) 1555 if err != nil { 1556 switch { 1557 case errors.Is(err, email.CreateEmailTokenError): 1558 return model.NewAppError("CreateVerifyEmailToken", "api.user.create_email_token.error", nil, "", http.StatusInternalServerError) 1559 default: 1560 return model.NewAppError("CreateVerifyEmailToken", "app.recover.save.app_error", nil, err.Error(), http.StatusInternalServerError) 1561 } 1562 } 1563 1564 if _, err := a.GetStatus(user.Id); err != nil { 1565 eErr := a.Srv().EmailService.SendVerifyEmail(newEmail, user.Locale, a.GetSiteURL(), token.Token, redirect) 1566 if eErr != nil { 1567 return model.NewAppError("SendVerifyEmail", "api.user.send_verify_email_and_forget.failed.error", nil, eErr.Error(), http.StatusInternalServerError) 1568 } 1569 return nil 1570 } 1571 1572 if err := a.Srv().EmailService.SendEmailChangeVerifyEmail(newEmail, user.Locale, a.GetSiteURL(), token.Token); err != nil { 1573 return model.NewAppError("sendEmailChangeVerifyEmail", "api.user.send_email_change_verify_email_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1574 } 1575 1576 return nil 1577} 1578 1579func (a *App) VerifyEmailFromToken(userSuppliedTokenString string) *model.AppError { 1580 token, err := a.GetVerifyEmailToken(userSuppliedTokenString) 1581 if err != nil { 1582 return err 1583 } 1584 if model.GetMillis()-token.CreateAt >= PasswordRecoverExpiryTime { 1585 return model.NewAppError("VerifyEmailFromToken", "api.user.verify_email.link_expired.app_error", nil, "", http.StatusBadRequest) 1586 } 1587 1588 tokenData := struct { 1589 UserId string 1590 Email string 1591 }{} 1592 1593 err2 := json.Unmarshal([]byte(token.Extra), &tokenData) 1594 if err2 != nil { 1595 return model.NewAppError("VerifyEmailFromToken", "api.user.verify_email.token_parse.error", nil, "", http.StatusInternalServerError) 1596 } 1597 1598 user, err := a.GetUser(tokenData.UserId) 1599 if err != nil { 1600 return err 1601 } 1602 1603 tokenData.Email = strings.ToLower(tokenData.Email) 1604 if err := a.VerifyUserEmail(tokenData.UserId, tokenData.Email); err != nil { 1605 return err 1606 } 1607 1608 if user.Email != tokenData.Email { 1609 a.Srv().Go(func() { 1610 if err := a.Srv().EmailService.SendEmailChangeEmail(user.Email, tokenData.Email, user.Locale, a.GetSiteURL()); err != nil { 1611 mlog.Error("Failed to send email change email", mlog.Err(err)) 1612 } 1613 }) 1614 } 1615 1616 if err := a.DeleteToken(token); err != nil { 1617 mlog.Warn("Failed to delete token", mlog.Err(err)) 1618 } 1619 1620 return nil 1621} 1622 1623func (a *App) GetVerifyEmailToken(token string) (*model.Token, *model.AppError) { 1624 rtoken, err := a.Srv().Store.Token().GetByToken(token) 1625 if err != nil { 1626 return nil, model.NewAppError("GetVerifyEmailToken", "api.user.verify_email.bad_link.app_error", nil, err.Error(), http.StatusBadRequest) 1627 } 1628 if rtoken.Type != TokenTypeVerifyEmail { 1629 return nil, model.NewAppError("GetVerifyEmailToken", "api.user.verify_email.broken_token.app_error", nil, "", http.StatusBadRequest) 1630 } 1631 return rtoken, nil 1632} 1633 1634// GetTotalUsersStats is used for the DM list total 1635func (a *App) GetTotalUsersStats(viewRestrictions *model.ViewUsersRestrictions) (*model.UsersStats, *model.AppError) { 1636 count, err := a.Srv().Store.User().Count(model.UserCountOptions{ 1637 IncludeBotAccounts: true, 1638 ViewRestrictions: viewRestrictions, 1639 }) 1640 if err != nil { 1641 return nil, model.NewAppError("GetTotalUsersStats", "app.user.get_total_users_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1642 } 1643 stats := &model.UsersStats{ 1644 TotalUsersCount: count, 1645 } 1646 return stats, nil 1647} 1648 1649// GetFilteredUsersStats is used to get a count of users based on the set of filters supported by UserCountOptions. 1650func (a *App) GetFilteredUsersStats(options *model.UserCountOptions) (*model.UsersStats, *model.AppError) { 1651 count, err := a.Srv().Store.User().Count(*options) 1652 if err != nil { 1653 return nil, model.NewAppError("GetFilteredUsersStats", "app.user.get_total_users_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1654 } 1655 stats := &model.UsersStats{ 1656 TotalUsersCount: count, 1657 } 1658 return stats, nil 1659} 1660 1661func (a *App) VerifyUserEmail(userID, email string) *model.AppError { 1662 if _, err := a.Srv().Store.User().VerifyEmail(userID, email); err != nil { 1663 return model.NewAppError("VerifyUserEmail", "app.user.verify_email.app_error", nil, err.Error(), http.StatusInternalServerError) 1664 } 1665 1666 a.InvalidateCacheForUser(userID) 1667 1668 user, err := a.GetUser(userID) 1669 1670 if err != nil { 1671 return err 1672 } 1673 1674 a.sendUpdatedUserEvent(*user) 1675 1676 return nil 1677} 1678 1679func (a *App) SearchUsers(props *model.UserSearch, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1680 if props.WithoutTeam { 1681 return a.SearchUsersWithoutTeam(props.Term, options) 1682 } 1683 if props.InChannelId != "" { 1684 return a.SearchUsersInChannel(props.InChannelId, props.Term, options) 1685 } 1686 if props.NotInChannelId != "" { 1687 return a.SearchUsersNotInChannel(props.TeamId, props.NotInChannelId, props.Term, options) 1688 } 1689 if props.NotInTeamId != "" { 1690 return a.SearchUsersNotInTeam(props.NotInTeamId, props.Term, options) 1691 } 1692 if props.InGroupId != "" { 1693 return a.SearchUsersInGroup(props.InGroupId, props.Term, options) 1694 } 1695 return a.SearchUsersInTeam(props.TeamId, props.Term, options) 1696} 1697 1698func (a *App) SearchUsersInChannel(channelID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1699 term = strings.TrimSpace(term) 1700 users, err := a.Srv().Store.User().SearchInChannel(channelID, term, options) 1701 if err != nil { 1702 return nil, model.NewAppError("SearchUsersInChannel", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1703 } 1704 for _, user := range users { 1705 a.SanitizeProfile(user, options.IsAdmin) 1706 } 1707 1708 return users, nil 1709} 1710 1711func (a *App) SearchUsersNotInChannel(teamID string, channelID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1712 term = strings.TrimSpace(term) 1713 users, err := a.Srv().Store.User().SearchNotInChannel(teamID, channelID, term, options) 1714 if err != nil { 1715 return nil, model.NewAppError("SearchUsersNotInChannel", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1716 } 1717 1718 for _, user := range users { 1719 a.SanitizeProfile(user, options.IsAdmin) 1720 } 1721 1722 return users, nil 1723} 1724 1725func (a *App) SearchUsersInTeam(teamID, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1726 term = strings.TrimSpace(term) 1727 1728 users, err := a.Srv().Store.User().Search(teamID, term, options) 1729 if err != nil { 1730 return nil, model.NewAppError("SearchUsersInTeam", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1731 } 1732 1733 for _, user := range users { 1734 a.SanitizeProfile(user, options.IsAdmin) 1735 } 1736 1737 return users, nil 1738} 1739 1740func (a *App) SearchUsersNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1741 term = strings.TrimSpace(term) 1742 users, err := a.Srv().Store.User().SearchNotInTeam(notInTeamId, term, options) 1743 if err != nil { 1744 return nil, model.NewAppError("SearchUsersNotInTeam", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1745 } 1746 1747 for _, user := range users { 1748 a.SanitizeProfile(user, options.IsAdmin) 1749 } 1750 1751 return users, nil 1752} 1753 1754func (a *App) SearchUsersWithoutTeam(term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1755 term = strings.TrimSpace(term) 1756 users, err := a.Srv().Store.User().SearchWithoutTeam(term, options) 1757 if err != nil { 1758 return nil, model.NewAppError("SearchUsersWithoutTeam", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1759 } 1760 1761 for _, user := range users { 1762 a.SanitizeProfile(user, options.IsAdmin) 1763 } 1764 1765 return users, nil 1766} 1767 1768func (a *App) SearchUsersInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) { 1769 term = strings.TrimSpace(term) 1770 users, err := a.Srv().Store.User().SearchInGroup(groupID, term, options) 1771 if err != nil { 1772 return nil, model.NewAppError("SearchUsersInGroup", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1773 } 1774 1775 for _, user := range users { 1776 a.SanitizeProfile(user, options.IsAdmin) 1777 } 1778 1779 return users, nil 1780} 1781 1782func (a *App) AutocompleteUsersInChannel(teamID string, channelID string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError) { 1783 term = strings.TrimSpace(term) 1784 1785 autocomplete, err := a.Srv().Store.User().AutocompleteUsersInChannel(teamID, channelID, term, options) 1786 if err != nil { 1787 return nil, model.NewAppError("AutocompleteUsersInChannel", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1788 } 1789 1790 for _, user := range autocomplete.InChannel { 1791 a.SanitizeProfile(user, options.IsAdmin) 1792 } 1793 1794 for _, user := range autocomplete.OutOfChannel { 1795 a.SanitizeProfile(user, options.IsAdmin) 1796 } 1797 1798 return autocomplete, nil 1799} 1800 1801func (a *App) AutocompleteUsersInTeam(teamID string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInTeam, *model.AppError) { 1802 term = strings.TrimSpace(term) 1803 1804 users, err := a.Srv().Store.User().Search(teamID, term, options) 1805 if err != nil { 1806 return nil, model.NewAppError("AutocompleteUsersInTeam", "app.user.search.app_error", nil, err.Error(), http.StatusInternalServerError) 1807 } 1808 1809 for _, user := range users { 1810 a.SanitizeProfile(user, options.IsAdmin) 1811 } 1812 1813 autocomplete := &model.UserAutocompleteInTeam{} 1814 autocomplete.InTeam = users 1815 return autocomplete, nil 1816} 1817 1818func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OAuthProvider, service string, tokenUser *model.User) *model.AppError { 1819 oauthUser, err1 := provider.GetUserFromJSON(userData, tokenUser) 1820 if err1 != nil { 1821 return model.NewAppError("UpdateOAuthUserAttrs", "api.user.update_oauth_user_attrs.get_user.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest) 1822 } 1823 1824 userAttrsChanged := false 1825 1826 if oauthUser.Username != user.Username { 1827 if existingUser, _ := a.GetUserByUsername(oauthUser.Username); existingUser == nil { 1828 user.Username = oauthUser.Username 1829 userAttrsChanged = true 1830 } 1831 } 1832 1833 if oauthUser.GetFullName() != user.GetFullName() { 1834 user.FirstName = oauthUser.FirstName 1835 user.LastName = oauthUser.LastName 1836 userAttrsChanged = true 1837 } 1838 1839 if oauthUser.Email != user.Email { 1840 if existingUser, _ := a.GetUserByEmail(oauthUser.Email); existingUser == nil { 1841 user.Email = oauthUser.Email 1842 userAttrsChanged = true 1843 } 1844 } 1845 1846 if user.DeleteAt > 0 { 1847 // Make sure they are not disabled 1848 user.DeleteAt = 0 1849 userAttrsChanged = true 1850 } 1851 1852 if userAttrsChanged { 1853 users, err := a.Srv().Store.User().Update(user, true) 1854 if err != nil { 1855 var appErr *model.AppError 1856 var invErr *store.ErrInvalidInput 1857 switch { 1858 case errors.As(err, &appErr): 1859 return appErr 1860 case errors.As(err, &invErr): 1861 return model.NewAppError("UpdateOAuthUserAttrs", "app.user.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 1862 default: 1863 return model.NewAppError("UpdateOAuthUserAttrs", "app.user.update.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 1864 } 1865 } 1866 1867 user = users.New 1868 a.InvalidateCacheForUser(user.Id) 1869 } 1870 1871 return nil 1872} 1873 1874func (a *App) RestrictUsersGetByPermissions(userID string, options *model.UserGetOptions) (*model.UserGetOptions, *model.AppError) { 1875 restrictions, err := a.GetViewUsersRestrictions(userID) 1876 if err != nil { 1877 return nil, err 1878 } 1879 1880 options.ViewRestrictions = restrictions 1881 return options, nil 1882} 1883 1884// FilterNonGroupTeamMembers returns the subset of the given user IDs of the users who are not members of groups 1885// associated to the team excluding bots. 1886func (a *App) FilterNonGroupTeamMembers(userIDs []string, team *model.Team) ([]string, error) { 1887 teamGroupUsers, err := a.GetTeamGroupUsers(team.Id) 1888 if err != nil { 1889 return nil, err 1890 } 1891 return a.filterNonGroupUsers(userIDs, teamGroupUsers) 1892} 1893 1894// FilterNonGroupChannelMembers returns the subset of the given user IDs of the users who are not members of groups 1895// associated to the channel excluding bots 1896func (a *App) FilterNonGroupChannelMembers(userIDs []string, channel *model.Channel) ([]string, error) { 1897 channelGroupUsers, err := a.GetChannelGroupUsers(channel.Id) 1898 if err != nil { 1899 return nil, err 1900 } 1901 return a.filterNonGroupUsers(userIDs, channelGroupUsers) 1902} 1903 1904// filterNonGroupUsers is a helper function that takes a list of user ids and a list of users 1905// and returns the list of normal users present in userIDs but not in groupUsers. 1906func (a *App) filterNonGroupUsers(userIDs []string, groupUsers []*model.User) ([]string, error) { 1907 nonMemberIds := []string{} 1908 users, err := a.Srv().Store.User().GetProfileByIds(context.Background(), userIDs, nil, false) 1909 if err != nil { 1910 return nil, err 1911 } 1912 1913 for _, user := range users { 1914 userIsMember := user.IsBot 1915 1916 for _, pu := range groupUsers { 1917 if pu.Id == user.Id { 1918 userIsMember = true 1919 break 1920 } 1921 } 1922 if !userIsMember { 1923 nonMemberIds = append(nonMemberIds, user.Id) 1924 } 1925 } 1926 1927 return nonMemberIds, nil 1928} 1929 1930func (a *App) RestrictUsersSearchByPermissions(userID string, options *model.UserSearchOptions) (*model.UserSearchOptions, *model.AppError) { 1931 restrictions, err := a.GetViewUsersRestrictions(userID) 1932 if err != nil { 1933 return nil, err 1934 } 1935 1936 options.ViewRestrictions = restrictions 1937 return options, nil 1938} 1939 1940func (a *App) UserCanSeeOtherUser(userID string, otherUserId string) (bool, *model.AppError) { 1941 if userID == otherUserId { 1942 return true, nil 1943 } 1944 1945 restrictions, err := a.GetViewUsersRestrictions(userID) 1946 if err != nil { 1947 return false, err 1948 } 1949 1950 if restrictions == nil { 1951 return true, nil 1952 } 1953 1954 if len(restrictions.Teams) > 0 { 1955 result, err := a.Srv().Store.Team().UserBelongsToTeams(otherUserId, restrictions.Teams) 1956 if err != nil { 1957 return false, model.NewAppError("UserCanSeeOtherUser", "app.team.user_belongs_to_teams.app_error", nil, err.Error(), http.StatusInternalServerError) 1958 } 1959 if result { 1960 return true, nil 1961 } 1962 } 1963 1964 if len(restrictions.Channels) > 0 { 1965 result, err := a.userBelongsToChannels(otherUserId, restrictions.Channels) 1966 if err != nil { 1967 return false, err 1968 } 1969 if result { 1970 return true, nil 1971 } 1972 } 1973 1974 return false, nil 1975} 1976 1977func (a *App) userBelongsToChannels(userID string, channelIDs []string) (bool, *model.AppError) { 1978 belongs, err := a.Srv().Store.Channel().UserBelongsToChannels(userID, channelIDs) 1979 if err != nil { 1980 return false, model.NewAppError("userBelongsToChannels", "app.channel.user_belongs_to_channels.app_error", nil, err.Error(), http.StatusInternalServerError) 1981 } 1982 1983 return belongs, nil 1984} 1985 1986func (a *App) GetViewUsersRestrictions(userID string) (*model.ViewUsersRestrictions, *model.AppError) { 1987 if a.HasPermissionTo(userID, model.PermissionViewMembers) { 1988 return nil, nil 1989 } 1990 1991 teamIDs, nErr := a.Srv().Store.Team().GetUserTeamIds(userID, true) 1992 if nErr != nil { 1993 return nil, model.NewAppError("GetViewUsersRestrictions", "app.team.get_user_team_ids.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1994 } 1995 1996 teamIDsWithPermission := []string{} 1997 for _, teamID := range teamIDs { 1998 if a.HasPermissionToTeam(userID, teamID, model.PermissionViewMembers) { 1999 teamIDsWithPermission = append(teamIDsWithPermission, teamID) 2000 } 2001 } 2002 2003 userChannelMembers, err := a.Srv().Store.Channel().GetAllChannelMembersForUser(userID, true, true) 2004 if err != nil { 2005 return nil, model.NewAppError("GetViewUsersRestrictions", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError) 2006 } 2007 2008 channelIDs := []string{} 2009 for channelID := range userChannelMembers { 2010 channelIDs = append(channelIDs, channelID) 2011 } 2012 2013 return &model.ViewUsersRestrictions{Teams: teamIDsWithPermission, Channels: channelIDs}, nil 2014} 2015 2016// PromoteGuestToUser Convert user's roles and all his mermbership's roles from 2017// guest roles to regular user roles. 2018func (a *App) PromoteGuestToUser(c *request.Context, user *model.User, requestorId string) *model.AppError { 2019 nErr := a.srv.userService.PromoteGuestToUser(user) 2020 a.InvalidateCacheForUser(user.Id) 2021 if nErr != nil { 2022 return model.NewAppError("PromoteGuestToUser", "app.user.promote_guest.user_update.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2023 } 2024 userTeams, nErr := a.Srv().Store.Team().GetTeamsByUserId(user.Id) 2025 if nErr != nil { 2026 return model.NewAppError("PromoteGuestToUser", "app.team.get_all.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2027 } 2028 2029 for _, team := range userTeams { 2030 // Soft error if there is an issue joining the default channels 2031 if err := a.JoinDefaultChannels(c, team.Id, user, false, requestorId); err != nil { 2032 mlog.Warn("Failed to join default channels", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.String("requestor_id", requestorId), mlog.Err(err)) 2033 } 2034 } 2035 2036 promotedUser, err := a.GetUser(user.Id) 2037 if err != nil { 2038 mlog.Warn("Failed to get user on promote guest to user", mlog.Err(err)) 2039 } else { 2040 a.sendUpdatedUserEvent(*promotedUser) 2041 if uErr := a.srv.userService.UpdateSessionsIsGuest(promotedUser.Id, promotedUser.IsGuest()); uErr != nil { 2042 mlog.Warn("Unable to update user sessions", mlog.String("user_id", promotedUser.Id), mlog.Err(uErr)) 2043 } 2044 } 2045 2046 teamMembers, err := a.GetTeamMembersForUser(user.Id) 2047 if err != nil { 2048 mlog.Warn("Failed to get team members for user on promote guest to user", mlog.Err(err)) 2049 } 2050 2051 for _, member := range teamMembers { 2052 a.sendUpdatedMemberRoleEvent(user.Id, member) 2053 2054 channelMembers, err := a.GetChannelMembersForUser(member.TeamId, user.Id) 2055 if err != nil { 2056 mlog.Warn("Failed to get channel members for user on promote guest to user", mlog.Err(err)) 2057 } 2058 2059 for _, member := range channelMembers { 2060 a.invalidateCacheForChannelMembers(member.ChannelId) 2061 2062 evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil) 2063 memberJSON, jsonErr := json.Marshal(member) 2064 if jsonErr != nil { 2065 mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) 2066 } 2067 evt.Add("channelMember", string(memberJSON)) 2068 a.Publish(evt) 2069 } 2070 } 2071 2072 a.ClearSessionCacheForUser(user.Id) 2073 return nil 2074} 2075 2076// DemoteUserToGuest Convert user's roles and all his mermbership's roles from 2077// regular user roles to guest roles. 2078func (a *App) DemoteUserToGuest(user *model.User) *model.AppError { 2079 demotedUser, nErr := a.srv.userService.DemoteUserToGuest(user) 2080 a.InvalidateCacheForUser(user.Id) 2081 if nErr != nil { 2082 return model.NewAppError("DemoteUserToGuest", "app.user.demote_user_to_guest.user_update.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2083 } 2084 2085 a.sendUpdatedUserEvent(*demotedUser) 2086 if uErr := a.srv.userService.UpdateSessionsIsGuest(demotedUser.Id, demotedUser.IsGuest()); uErr != nil { 2087 mlog.Warn("Unable to update user sessions", mlog.String("user_id", demotedUser.Id), mlog.Err(uErr)) 2088 } 2089 2090 teamMembers, err := a.GetTeamMembersForUser(user.Id) 2091 if err != nil { 2092 mlog.Warn("Failed to get team members for users on demote user to guest", mlog.Err(err)) 2093 } 2094 2095 for _, member := range teamMembers { 2096 a.sendUpdatedMemberRoleEvent(user.Id, member) 2097 2098 channelMembers, err := a.GetChannelMembersForUser(member.TeamId, user.Id) 2099 if err != nil { 2100 mlog.Warn("Failed to get channel members for users on demote user to guest", mlog.Err(err)) 2101 continue 2102 } 2103 2104 for _, member := range channelMembers { 2105 a.invalidateCacheForChannelMembers(member.ChannelId) 2106 2107 evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil) 2108 memberJSON, jsonErr := json.Marshal(member) 2109 if jsonErr != nil { 2110 mlog.Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) 2111 } 2112 evt.Add("channelMember", string(memberJSON)) 2113 a.Publish(evt) 2114 } 2115 } 2116 2117 a.ClearSessionCacheForUser(user.Id) 2118 return nil 2119} 2120 2121func (a *App) PublishUserTyping(userID, channelID, parentId string) *model.AppError { 2122 omitUsers := make(map[string]bool, 1) 2123 omitUsers[userID] = true 2124 2125 event := model.NewWebSocketEvent(model.WebsocketEventTyping, "", channelID, "", omitUsers) 2126 event.Add("parent_id", parentId) 2127 event.Add("user_id", userID) 2128 a.Publish(event) 2129 2130 return nil 2131} 2132 2133// invalidateUserCacheAndPublish Invalidates cache for a user and publishes user updated event 2134func (a *App) invalidateUserCacheAndPublish(userID string) { 2135 a.InvalidateCacheForUser(userID) 2136 2137 user, userErr := a.GetUser(userID) 2138 if userErr != nil { 2139 mlog.Error("Error in getting users profile", mlog.String("user_id", userID), mlog.Err(userErr)) 2140 return 2141 } 2142 2143 options := a.Config().GetSanitizeOptions() 2144 user.SanitizeProfile(options) 2145 2146 message := model.NewWebSocketEvent(model.WebsocketEventUserUpdated, "", "", "", nil) 2147 message.Add("user", user) 2148 a.Publish(message) 2149} 2150 2151// GetKnownUsers returns the list of user ids of users with any direct 2152// relationship with a user. That means any user sharing any channel, including 2153// direct and group channels. 2154func (a *App) GetKnownUsers(userID string) ([]string, *model.AppError) { 2155 users, err := a.Srv().Store.User().GetKnownUsers(userID) 2156 if err != nil { 2157 return nil, model.NewAppError("GetKnownUsers", "app.user.get_known_users.get_users.app_error", nil, err.Error(), http.StatusInternalServerError) 2158 } 2159 2160 return users, nil 2161} 2162 2163// ConvertBotToUser converts a bot to user. 2164func (a *App) ConvertBotToUser(bot *model.Bot, userPatch *model.UserPatch, sysadmin bool) (*model.User, *model.AppError) { 2165 user, nErr := a.Srv().Store.User().Get(context.Background(), bot.UserId) 2166 if nErr != nil { 2167 var nfErr *store.ErrNotFound 2168 switch { 2169 case errors.As(nErr, &nfErr): 2170 return nil, model.NewAppError("ConvertBotToUser", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 2171 default: 2172 return nil, model.NewAppError("ConvertBotToUser", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2173 } 2174 } 2175 2176 if sysadmin && !user.IsInRole(model.SystemAdminRoleId) { 2177 _, appErr := a.UpdateUserRoles( 2178 user.Id, 2179 fmt.Sprintf("%s %s", user.Roles, model.SystemAdminRoleId), 2180 false) 2181 if appErr != nil { 2182 return nil, appErr 2183 } 2184 } 2185 2186 user.Patch(userPatch) 2187 2188 user, err := a.UpdateUser(user, false) 2189 if err != nil { 2190 return nil, err 2191 } 2192 2193 err = a.UpdatePassword(user, *userPatch.Password) 2194 if err != nil { 2195 return nil, err 2196 } 2197 2198 appErr := a.Srv().Store.Bot().PermanentDelete(bot.UserId) 2199 if appErr != nil { 2200 return nil, model.NewAppError("ConvertBotToUser", "app.user.convert_bot_to_user.app_error", nil, err.Error(), http.StatusInternalServerError) 2201 } 2202 2203 return user, nil 2204} 2205 2206func (a *App) GetThreadsForUser(userID, teamID string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) { 2207 threads, err := a.Srv().Store.Thread().GetThreadsForUser(userID, teamID, options) 2208 if err != nil { 2209 return nil, model.NewAppError("GetThreadsForUser", "app.user.get_threads_for_user.app_error", nil, err.Error(), http.StatusInternalServerError) 2210 } 2211 for _, thread := range threads.Threads { 2212 a.sanitizeProfiles(thread.Participants, false) 2213 thread.Post.SanitizeProps() 2214 } 2215 return threads, nil 2216} 2217 2218func (a *App) GetThreadMembershipForUser(userId, threadId string) (*model.ThreadMembership, *model.AppError) { 2219 threadMembership, err := a.Srv().Store.Thread().GetMembershipForUser(userId, threadId) 2220 if err != nil { 2221 return nil, model.NewAppError("GetThreadMembershipForUser", "app.user.get_thread_membership_for_user.app_error", nil, err.Error(), http.StatusInternalServerError) 2222 } 2223 if threadMembership == nil { 2224 return nil, model.NewAppError("GetThreadMembershipForUser", "app.user.get_thread_membership_for_user.not_found", nil, "thread membership not found/followed", http.StatusNotFound) 2225 } 2226 return threadMembership, nil 2227} 2228 2229func (a *App) GetThreadForUser(teamID string, threadMembership *model.ThreadMembership, extended bool) (*model.ThreadResponse, *model.AppError) { 2230 thread, err := a.Srv().Store.Thread().GetThreadForUser(teamID, threadMembership, extended) 2231 if err != nil { 2232 return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.app_error", nil, err.Error(), http.StatusInternalServerError) 2233 } 2234 if thread == nil { 2235 return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.not_found", nil, "thread not found/followed", http.StatusNotFound) 2236 } 2237 a.sanitizeProfiles(thread.Participants, false) 2238 thread.Post.SanitizeProps() 2239 return thread, nil 2240} 2241 2242func (a *App) UpdateThreadsReadForUser(userID, teamID string) *model.AppError { 2243 nErr := a.Srv().Store.Thread().MarkAllAsRead(userID, teamID) 2244 if nErr != nil { 2245 return model.NewAppError("UpdateThreadsReadForUser", "app.user.update_threads_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2246 } 2247 message := model.NewWebSocketEvent(model.WebsocketEventThreadReadChanged, teamID, "", userID, nil) 2248 a.Publish(message) 2249 return nil 2250} 2251 2252func (a *App) UpdateThreadFollowForUser(userID, teamID, threadID string, state bool) *model.AppError { 2253 opts := store.ThreadMembershipOpts{ 2254 Following: state, 2255 IncrementMentions: false, 2256 UpdateFollowing: true, 2257 UpdateViewedTimestamp: state, 2258 UpdateParticipants: false, 2259 } 2260 _, err := a.Srv().Store.Thread().MaintainMembership(userID, threadID, opts) 2261 if err != nil { 2262 return model.NewAppError("UpdateThreadFollowForUser", "app.user.update_thread_follow_for_user.app_error", nil, err.Error(), http.StatusInternalServerError) 2263 } 2264 thread, err := a.Srv().Store.Thread().Get(threadID) 2265 if err != nil { 2266 return model.NewAppError("UpdateThreadFollowForUser", "app.user.update_thread_follow_for_user.app_error", nil, err.Error(), http.StatusInternalServerError) 2267 } 2268 replyCount := int64(0) 2269 if thread != nil { 2270 replyCount = thread.ReplyCount 2271 } 2272 message := model.NewWebSocketEvent(model.WebsocketEventThreadFollowChanged, teamID, "", userID, nil) 2273 message.Add("thread_id", threadID) 2274 message.Add("state", state) 2275 message.Add("reply_count", replyCount) 2276 a.Publish(message) 2277 return nil 2278} 2279 2280func (a *App) UpdateThreadReadForUser(userID, teamID, threadID string, timestamp int64) (*model.ThreadResponse, *model.AppError) { 2281 user, err := a.GetUser(userID) 2282 if err != nil { 2283 return nil, err 2284 } 2285 2286 opts := store.ThreadMembershipOpts{ 2287 Following: true, 2288 UpdateFollowing: true, 2289 } 2290 membership, storeErr := a.Srv().Store.Thread().MaintainMembership(userID, threadID, opts) 2291 if storeErr != nil { 2292 return nil, model.NewAppError("UpdateThreadReadForUser", "app.user.update_thread_read_for_user.app_error", nil, storeErr.Error(), http.StatusInternalServerError) 2293 } 2294 2295 post, err := a.GetSinglePost(threadID) 2296 if err != nil { 2297 return nil, err 2298 } 2299 membership.UnreadMentions, err = a.countThreadMentions(user, post, teamID, timestamp) 2300 if err != nil { 2301 return nil, err 2302 } 2303 _, nErr := a.Srv().Store.Thread().UpdateMembership(membership) 2304 if nErr != nil { 2305 return nil, model.NewAppError("UpdateThreadReadForUser", "app.user.update_thread_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2306 } 2307 2308 membership.LastViewed = timestamp 2309 nErr = a.Srv().Store.Thread().MarkAsRead(userID, threadID, timestamp) 2310 if nErr != nil { 2311 return nil, model.NewAppError("UpdateThreadReadForUser", "app.user.update_thread_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2312 } 2313 thread, err := a.GetThreadForUser(teamID, membership, false) 2314 if err != nil { 2315 return nil, err 2316 } 2317 2318 message := model.NewWebSocketEvent(model.WebsocketEventThreadReadChanged, teamID, "", userID, nil) 2319 message.Add("thread_id", threadID) 2320 message.Add("timestamp", timestamp) 2321 message.Add("unread_mentions", membership.UnreadMentions) 2322 message.Add("unread_replies", thread.UnreadReplies) 2323 message.Add("channel_id", post.ChannelId) 2324 a.Publish(message) 2325 return thread, nil 2326} 2327 2328func getProfileImagePath(userID string) string { 2329 return filepath.Join("users", userID, "profile.png") 2330} 2331