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