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	"image"
13	"io"
14	"mime/multipart"
15	"net/http"
16	"net/url"
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/model"
23	"github.com/mattermost/mattermost-server/v6/plugin"
24	"github.com/mattermost/mattermost-server/v6/services/users"
25	"github.com/mattermost/mattermost-server/v6/shared/i18n"
26	"github.com/mattermost/mattermost-server/v6/shared/mlog"
27	"github.com/mattermost/mattermost-server/v6/store"
28	"github.com/mattermost/mattermost-server/v6/store/sqlstore"
29)
30
31func (a *App) CreateTeam(c *request.Context, team *model.Team) (*model.Team, *model.AppError) {
32	team.InviteId = ""
33	rteam, err := a.Srv().Store.Team().Save(team)
34	if err != nil {
35		var invErr *store.ErrInvalidInput
36		var appErr *model.AppError
37		switch {
38		case errors.As(err, &invErr):
39			return nil, model.NewAppError("CreateTeam", "app.team.save.existing.app_error", nil, invErr.Error(), http.StatusBadRequest)
40		case errors.As(err, &appErr):
41			return nil, appErr
42		default:
43			return nil, model.NewAppError("CreateTeam", "app.team.save.app_error", nil, err.Error(), http.StatusInternalServerError)
44		}
45	}
46
47	if _, err := a.CreateDefaultChannels(c, rteam.Id); err != nil {
48		return nil, err
49	}
50
51	return rteam, nil
52}
53
54func (a *App) CreateTeamWithUser(c *request.Context, team *model.Team, userID string) (*model.Team, *model.AppError) {
55	user, err := a.GetUser(userID)
56	if err != nil {
57		return nil, err
58	}
59	team.Email = user.Email
60
61	if !a.isTeamEmailAllowed(user, team) {
62		return nil, model.NewAppError("isTeamEmailAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "", http.StatusBadRequest)
63	}
64
65	rteam, err := a.CreateTeam(c, team)
66	if err != nil {
67		return nil, err
68	}
69
70	if _, err := a.JoinUserToTeam(c, rteam, user, ""); err != nil {
71		return nil, err
72	}
73
74	return rteam, nil
75}
76
77func (a *App) normalizeDomains(domains string) []string {
78	// commas and @ signs are optional
79	// can be in the form of "@corp.mattermost.com, mattermost.com mattermost.org" -> corp.mattermost.com mattermost.com mattermost.org
80	return strings.Fields(strings.TrimSpace(strings.ToLower(strings.Replace(strings.Replace(domains, "@", " ", -1), ",", " ", -1))))
81}
82
83func (a *App) isEmailAddressAllowed(email string, allowedDomains []string) bool {
84	for _, restriction := range allowedDomains {
85		domains := a.normalizeDomains(restriction)
86		if len(domains) <= 0 {
87			continue
88		}
89		matched := false
90		for _, d := range domains {
91			if strings.HasSuffix(email, "@"+d) {
92				matched = true
93				break
94			}
95		}
96		if !matched {
97			return false
98		}
99	}
100
101	return true
102}
103
104func (a *App) isTeamEmailAllowed(user *model.User, team *model.Team) bool {
105	if user.IsBot {
106		return true
107	}
108	email := strings.ToLower(user.Email)
109	allowedDomains := a.getAllowedDomains(user, team)
110	return a.isEmailAddressAllowed(email, allowedDomains)
111}
112
113func (a *App) getAllowedDomains(user *model.User, team *model.Team) []string {
114	if user.IsGuest() {
115		return []string{*a.Config().GuestAccountsSettings.RestrictCreationToDomains}
116	}
117	// First check per team allowedDomains, then app wide restrictions
118	return []string{team.AllowedDomains, *a.Config().TeamSettings.RestrictCreationToDomains}
119}
120
121func (a *App) CheckValidDomains(team *model.Team) *model.AppError {
122	validDomains := a.normalizeDomains(*a.Config().TeamSettings.RestrictCreationToDomains)
123	if len(validDomains) > 0 {
124		for _, domain := range a.normalizeDomains(team.AllowedDomains) {
125			matched := false
126			for _, d := range validDomains {
127				if domain == d {
128					matched = true
129					break
130				}
131			}
132			if !matched {
133				err := model.NewAppError("UpdateTeam", "api.team.update_restricted_domains.mismatch.app_error", map[string]interface{}{"Domain": domain}, "", http.StatusBadRequest)
134				return err
135			}
136		}
137	}
138
139	return nil
140}
141
142func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
143	oldTeam, err := a.GetTeam(team.Id)
144	if err != nil {
145		return nil, err
146	}
147
148	if err = a.CheckValidDomains(team); err != nil {
149		return nil, err
150	}
151
152	oldTeam.DisplayName = team.DisplayName
153	oldTeam.Description = team.Description
154	oldTeam.AllowOpenInvite = team.AllowOpenInvite
155	oldTeam.CompanyName = team.CompanyName
156	oldTeam.AllowedDomains = team.AllowedDomains
157	oldTeam.LastTeamIconUpdate = team.LastTeamIconUpdate
158	oldTeam.GroupConstrained = team.GroupConstrained
159
160	oldTeam, err = a.updateTeamUnsanitized(oldTeam)
161	if err != nil {
162		return team, err
163	}
164
165	a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam)
166
167	return oldTeam, nil
168}
169
170func (a *App) updateTeamUnsanitized(team *model.Team) (*model.Team, *model.AppError) {
171	team, err := a.Srv().Store.Team().Update(team)
172	if err != nil {
173		var invErr *store.ErrInvalidInput
174		var appErr *model.AppError
175		switch {
176		case errors.As(err, &invErr):
177			return nil, model.NewAppError("updateTeamUnsanitized", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
178		case errors.As(err, &appErr):
179			return nil, appErr
180		default:
181			return nil, model.NewAppError("updateTeamUnsanitized", "app.team.update.updating.app_error", nil, err.Error(), http.StatusInternalServerError)
182		}
183	}
184
185	return team, nil
186}
187
188// RenameTeam is used to rename the team Name and the DisplayName fields
189func (a *App) RenameTeam(team *model.Team, newTeamName string, newDisplayName string) (*model.Team, *model.AppError) {
190
191	// check if name is occupied
192	_, errnf := a.GetTeamByName(newTeamName)
193
194	// "-" can be used as a newTeamName if only DisplayName change is wanted
195	if errnf == nil && newTeamName != "-" {
196		errbody := fmt.Sprintf("team with name %s already exists", newTeamName)
197		return nil, model.NewAppError("RenameTeam", "app.team.rename_team.name_occupied", nil, errbody, http.StatusBadRequest)
198	}
199
200	if newTeamName != "-" {
201		team.Name = newTeamName
202	}
203
204	if newDisplayName != "" {
205		team.DisplayName = newDisplayName
206	}
207
208	newTeam, err := a.updateTeamUnsanitized(team)
209	if err != nil {
210		return nil, err
211	}
212
213	return newTeam, nil
214}
215
216func (a *App) UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError) {
217	oldTeam, err := a.GetTeam(team.Id)
218	if err != nil {
219		return nil, err
220	}
221
222	oldTeam.SchemeId = team.SchemeId
223
224	oldTeam, nErr := a.Srv().Store.Team().Update(oldTeam)
225	if nErr != nil {
226		var invErr *store.ErrInvalidInput
227		var appErr *model.AppError
228		switch {
229		case errors.As(nErr, &invErr):
230			return nil, model.NewAppError("UpdateTeamScheme", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
231		case errors.As(nErr, &appErr):
232			return nil, appErr
233		default:
234			return nil, model.NewAppError("UpdateTeamScheme", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
235		}
236	}
237
238	a.ClearTeamMembersCache(team.Id)
239
240	a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeamScheme)
241
242	return oldTeam, nil
243}
244
245func (a *App) UpdateTeamPrivacy(teamID string, teamType string, allowOpenInvite bool) *model.AppError {
246	oldTeam, err := a.GetTeam(teamID)
247	if err != nil {
248		return err
249	}
250
251	// Force a regeneration of the invite token if changing a team to restricted.
252	if (allowOpenInvite != oldTeam.AllowOpenInvite || teamType != oldTeam.Type) && (!allowOpenInvite || teamType == model.TeamInvite) {
253		oldTeam.InviteId = model.NewId()
254	}
255
256	oldTeam.Type = teamType
257	oldTeam.AllowOpenInvite = allowOpenInvite
258
259	oldTeam, nErr := a.Srv().Store.Team().Update(oldTeam)
260	if nErr != nil {
261		var invErr *store.ErrInvalidInput
262		var appErr *model.AppError
263		switch {
264		case errors.As(nErr, &invErr):
265			return model.NewAppError("UpdateTeamPrivacy", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
266		case errors.As(nErr, &appErr):
267			return appErr
268		default:
269			return model.NewAppError("UpdateTeamPrivacy", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
270		}
271	}
272
273	a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam)
274
275	return nil
276}
277
278func (a *App) PatchTeam(teamID string, patch *model.TeamPatch) (*model.Team, *model.AppError) {
279	team, err := a.GetTeam(teamID)
280	if err != nil {
281		return nil, err
282	}
283
284	team.Patch(patch)
285	if patch.AllowOpenInvite != nil && !*patch.AllowOpenInvite {
286		team.InviteId = model.NewId()
287	}
288
289	if err = a.CheckValidDomains(team); err != nil {
290		return nil, err
291	}
292
293	team, err = a.updateTeamUnsanitized(team)
294	if err != nil {
295		return team, err
296	}
297
298	a.sendTeamEvent(team, model.WebsocketEventUpdateTeam)
299
300	return team, nil
301}
302
303func (a *App) RegenerateTeamInviteId(teamID string) (*model.Team, *model.AppError) {
304	team, err := a.GetTeam(teamID)
305	if err != nil {
306		return nil, err
307	}
308
309	team.InviteId = model.NewId()
310
311	updatedTeam, nErr := a.Srv().Store.Team().Update(team)
312	if nErr != nil {
313		var invErr *store.ErrInvalidInput
314		var appErr *model.AppError
315		switch {
316		case errors.As(nErr, &invErr):
317			return nil, model.NewAppError("RegenerateTeamInviteId", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
318		case errors.As(nErr, &appErr):
319			return nil, appErr
320		default:
321			return nil, model.NewAppError("RegenerateTeamInviteId", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
322		}
323	}
324
325	a.sendTeamEvent(updatedTeam, model.WebsocketEventUpdateTeam)
326
327	return updatedTeam, nil
328}
329
330func (a *App) sendTeamEvent(team *model.Team, event string) {
331	sanitizedTeam := &model.Team{}
332	*sanitizedTeam = *team
333	sanitizedTeam.Sanitize()
334
335	teamID := "" // no filtering by teamID by default
336	if event == model.WebsocketEventUpdateTeam {
337		// in case of update_team event - we send the message only to members of that team
338		teamID = team.Id
339	}
340	message := model.NewWebSocketEvent(event, teamID, "", "", nil)
341	teamJSON, jsonErr := json.Marshal(team)
342	if jsonErr != nil {
343		mlog.Warn("Failed to encode team to JSON", mlog.Err(jsonErr))
344	}
345	message.Add("team", string(teamJSON))
346	a.Publish(message)
347}
348
349func (a *App) GetSchemeRolesForTeam(teamID string) (string, string, string, *model.AppError) {
350	team, err := a.GetTeam(teamID)
351	if err != nil {
352		return "", "", "", err
353	}
354
355	if team.SchemeId != nil && *team.SchemeId != "" {
356		scheme, err := a.GetScheme(*team.SchemeId)
357		if err != nil {
358			return "", "", "", err
359		}
360		return scheme.DefaultTeamGuestRole, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole, nil
361	}
362
363	return model.TeamGuestRoleId, model.TeamUserRoleId, model.TeamAdminRoleId, nil
364}
365
366func (a *App) UpdateTeamMemberRoles(teamID string, userID string, newRoles string) (*model.TeamMember, *model.AppError) {
367	member, nErr := a.Srv().Store.Team().GetMember(context.Background(), teamID, userID)
368	if nErr != nil {
369		var nfErr *store.ErrNotFound
370		switch {
371		case errors.As(nErr, &nfErr):
372			return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
373		default:
374			return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
375		}
376	}
377
378	if member == nil {
379		return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userID+" teamId="+teamID, http.StatusBadRequest)
380	}
381
382	schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForTeam(teamID)
383	if err != nil {
384		return nil, err
385	}
386
387	prevSchemeGuestValue := member.SchemeGuest
388
389	var newExplicitRoles []string
390	member.SchemeGuest = false
391	member.SchemeUser = false
392	member.SchemeAdmin = false
393
394	for _, roleName := range strings.Fields(newRoles) {
395		var role *model.Role
396		role, err = a.GetRoleByName(context.Background(), roleName)
397		if err != nil {
398			err.StatusCode = http.StatusBadRequest
399			return nil, err
400		}
401		if !role.SchemeManaged {
402			// The role is not scheme-managed, so it's OK to apply it to the explicit roles field.
403			newExplicitRoles = append(newExplicitRoles, roleName)
404		} else {
405			// The role is scheme-managed, so need to check if it is part of the scheme for this channel or not.
406			switch roleName {
407			case schemeAdminRole:
408				member.SchemeAdmin = true
409			case schemeUserRole:
410				member.SchemeUser = true
411			case schemeGuestRole:
412				member.SchemeGuest = true
413			default:
414				// If not part of the scheme for this team, then it is not allowed to apply it as an explicit role.
415				return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest)
416			}
417		}
418	}
419
420	if member.SchemeGuest && member.SchemeUser {
421		return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest)
422	}
423
424	if prevSchemeGuestValue != member.SchemeGuest {
425		return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest)
426	}
427
428	member.ExplicitRoles = strings.Join(newExplicitRoles, " ")
429
430	member, nErr = a.Srv().Store.Team().UpdateMember(member)
431	if nErr != nil {
432		var appErr *model.AppError
433		switch {
434		case errors.As(nErr, &appErr):
435			return nil, appErr
436		default:
437			return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
438		}
439	}
440
441	a.ClearSessionCacheForUser(userID)
442
443	a.sendUpdatedMemberRoleEvent(userID, member)
444
445	return member, nil
446}
447
448func (a *App) UpdateTeamMemberSchemeRoles(teamID string, userID string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.TeamMember, *model.AppError) {
449	member, err := a.GetTeamMember(teamID, userID)
450	if err != nil {
451		return nil, err
452	}
453
454	member.SchemeAdmin = isSchemeAdmin
455	member.SchemeUser = isSchemeUser
456	member.SchemeGuest = isSchemeGuest
457
458	if member.SchemeUser && member.SchemeGuest {
459		return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest)
460	}
461
462	// If the migration is not completed, we also need to check the default team_admin/team_user roles are not present in the roles field.
463	if err = a.IsPhase2MigrationCompleted(); err != nil {
464		member.ExplicitRoles = RemoveRoles([]string{model.TeamGuestRoleId, model.TeamUserRoleId, model.TeamAdminRoleId}, member.ExplicitRoles)
465	}
466
467	member, nErr := a.Srv().Store.Team().UpdateMember(member)
468	if nErr != nil {
469		var appErr *model.AppError
470		switch {
471		case errors.As(nErr, &appErr):
472			return nil, appErr
473		default:
474			return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
475		}
476	}
477
478	a.ClearSessionCacheForUser(userID)
479
480	a.sendUpdatedMemberRoleEvent(userID, member)
481
482	return member, nil
483}
484
485func (a *App) sendUpdatedMemberRoleEvent(userID string, member *model.TeamMember) {
486	message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", userID, nil)
487	tmJSON, jsonErr := json.Marshal(member)
488	if jsonErr != nil {
489		mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr))
490	}
491	message.Add("member", string(tmJSON))
492	a.Publish(message)
493}
494
495func (a *App) AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) {
496	tchan := make(chan store.StoreResult, 1)
497	go func() {
498		team, err := a.Srv().Store.Team().Get(teamID)
499		tchan <- store.StoreResult{Data: team, NErr: err}
500		close(tchan)
501	}()
502
503	uchan := make(chan store.StoreResult, 1)
504	go func() {
505		user, err := a.Srv().Store.User().Get(context.Background(), userID)
506		uchan <- store.StoreResult{Data: user, NErr: err}
507		close(uchan)
508	}()
509
510	result := <-tchan
511	if result.NErr != nil {
512		var nfErr *store.ErrNotFound
513		switch {
514		case errors.As(result.NErr, &nfErr):
515			return nil, nil, model.NewAppError("AddUserToTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
516		default:
517			return nil, nil, model.NewAppError("AddUserToTeam", "app.team.get.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
518		}
519	}
520	team := result.Data.(*model.Team)
521
522	result = <-uchan
523	if result.NErr != nil {
524		var nfErr *store.ErrNotFound
525		switch {
526		case errors.As(result.NErr, &nfErr):
527			return nil, nil, model.NewAppError("AddUserToTeam", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
528		default:
529			return nil, nil, model.NewAppError("AddUserToTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
530		}
531	}
532	user := result.Data.(*model.User)
533
534	teamMember, err := a.JoinUserToTeam(c, team, user, userRequestorId)
535	if err != nil {
536		return nil, nil, err
537	}
538
539	return team, teamMember, nil
540}
541
542func (a *App) AddUserToTeamByTeamId(c *request.Context, teamID string, user *model.User) *model.AppError {
543	team, err := a.Srv().Store.Team().Get(teamID)
544	if err != nil {
545		var nfErr *store.ErrNotFound
546		switch {
547		case errors.As(err, &nfErr):
548			return model.NewAppError("AddUserToTeamByTeamId", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
549		default:
550			return model.NewAppError("AddUserToTeamByTeamId", "app.team.get.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
551		}
552	}
553
554	if _, err := a.JoinUserToTeam(c, team, user, ""); err != nil {
555		return err
556	}
557	return nil
558}
559
560func (a *App) AddUserToTeamByToken(c *request.Context, userID string, tokenID string) (*model.Team, *model.TeamMember, *model.AppError) {
561	token, err := a.Srv().Store.Token().GetByToken(tokenID)
562	if err != nil {
563		return nil, nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, err.Error(), http.StatusBadRequest)
564	}
565
566	if token.Type != TokenTypeTeamInvitation && token.Type != TokenTypeGuestInvitation {
567		return nil, nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest)
568	}
569
570	if model.GetMillis()-token.CreateAt >= InvitationExpiryTime {
571		a.DeleteToken(token)
572		return nil, nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest)
573	}
574
575	tokenData := model.MapFromJSON(strings.NewReader(token.Extra))
576
577	tchan := make(chan store.StoreResult, 1)
578	go func() {
579		team, err := a.Srv().Store.Team().Get(tokenData["teamId"])
580		tchan <- store.StoreResult{Data: team, NErr: err}
581		close(tchan)
582	}()
583
584	uchan := make(chan store.StoreResult, 1)
585	go func() {
586		user, err := a.Srv().Store.User().Get(context.Background(), userID)
587		uchan <- store.StoreResult{Data: user, NErr: err}
588		close(uchan)
589	}()
590
591	result := <-tchan
592	if result.NErr != nil {
593		var nfErr *store.ErrNotFound
594		switch {
595		case errors.As(result.NErr, &nfErr):
596			return nil, nil, model.NewAppError("AddUserToTeamByToken", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
597		default:
598			return nil, nil, model.NewAppError("AddUserToTeamByToken", "app.team.get.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
599		}
600	}
601	team := result.Data.(*model.Team)
602
603	if team.IsGroupConstrained() {
604		return nil, nil, model.NewAppError("AddUserToTeamByToken", "app.team.invite_token.group_constrained.error", nil, "", http.StatusForbidden)
605	}
606
607	result = <-uchan
608	if result.NErr != nil {
609		var nfErr *store.ErrNotFound
610		switch {
611		case errors.As(result.NErr, &nfErr):
612			return nil, nil, model.NewAppError("AddUserToTeamByToken", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
613		default:
614			return nil, nil, model.NewAppError("AddUserToTeamByToken", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
615		}
616	}
617	user := result.Data.(*model.User)
618
619	if user.IsGuest() && token.Type == TokenTypeTeamInvitation {
620		return nil, nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.invalid_invitation_type.app_error", nil, "", http.StatusBadRequest)
621	}
622	if !user.IsGuest() && token.Type == TokenTypeGuestInvitation {
623		return nil, nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.invalid_invitation_type.app_error", nil, "", http.StatusBadRequest)
624	}
625
626	teamMember, appErr := a.JoinUserToTeam(c, team, user, "")
627	if appErr != nil {
628		return nil, nil, appErr
629	}
630
631	if token.Type == TokenTypeGuestInvitation {
632		channels, err := a.Srv().Store.Channel().GetChannelsByIds(strings.Split(tokenData["channels"], " "), false)
633		if err != nil {
634			return nil, nil, model.NewAppError("AddUserToTeamByToken", "app.channel.get_channels_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError)
635		}
636
637		for _, channel := range channels {
638			_, err := a.AddUserToChannel(user, channel, false)
639			if err != nil {
640				mlog.Warn("Error adding user to channel", mlog.Err(err))
641			}
642		}
643	}
644
645	if err := a.DeleteToken(token); err != nil {
646		mlog.Warn("Error while deleting token", mlog.Err(err))
647	}
648
649	return team, teamMember, nil
650}
651
652func (a *App) AddUserToTeamByInviteId(c *request.Context, inviteId string, userID string) (*model.Team, *model.TeamMember, *model.AppError) {
653	tchan := make(chan store.StoreResult, 1)
654	go func() {
655		team, err := a.Srv().Store.Team().GetByInviteId(inviteId)
656		tchan <- store.StoreResult{Data: team, NErr: err}
657		close(tchan)
658	}()
659
660	uchan := make(chan store.StoreResult, 1)
661	go func() {
662		user, err := a.Srv().Store.User().Get(context.Background(), userID)
663		uchan <- store.StoreResult{Data: user, NErr: err}
664		close(uchan)
665	}()
666
667	result := <-tchan
668	if result.NErr != nil {
669		var nfErr *store.ErrNotFound
670		switch {
671		case errors.As(result.NErr, &nfErr):
672			return nil, nil, model.NewAppError("AddUserToTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
673		default:
674			return nil, nil, model.NewAppError("AddUserToTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
675		}
676	}
677	team := result.Data.(*model.Team)
678
679	result = <-uchan
680	if result.NErr != nil {
681		var nfErr *store.ErrNotFound
682		switch {
683		case errors.As(result.NErr, &nfErr):
684			return nil, nil, model.NewAppError("AddUserToTeamByInviteId", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
685		default:
686			return nil, nil, model.NewAppError("AddUserToTeamByInviteId", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
687		}
688	}
689	user := result.Data.(*model.User)
690
691	teamMember, err := a.JoinUserToTeam(c, team, user, "")
692	if err != nil {
693		return nil, nil, err
694	}
695
696	return team, teamMember, nil
697}
698
699// Returns three values:
700// 1. a pointer to the team member, if successful
701// 2. a boolean: true if the user has a non-deleted team member for that team already, otherwise false.
702// 3. a pointer to an AppError if something went wrong.
703func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) {
704	tm := &model.TeamMember{
705		TeamId:      team.Id,
706		UserId:      user.Id,
707		SchemeGuest: user.IsGuest(),
708		SchemeUser:  !user.IsGuest(),
709	}
710
711	if !user.IsGuest() {
712		userShouldBeAdmin, err := a.UserIsInAdminRoleGroup(user.Id, team.Id, model.GroupSyncableTypeTeam)
713		if err != nil {
714			return nil, false, err
715		}
716		tm.SchemeAdmin = userShouldBeAdmin
717	}
718
719	if team.Email == user.Email {
720		tm.SchemeAdmin = true
721	}
722
723	rtm, err := a.Srv().Store.Team().GetMember(context.Background(), team.Id, user.Id)
724	if err != nil {
725		// Membership appears to be missing. Lets try to add.
726		tmr, nErr := a.Srv().Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam)
727		if nErr != nil {
728			var appErr *model.AppError
729			var conflictErr *store.ErrConflict
730			var limitExeededErr *store.ErrLimitExceeded
731			switch {
732			case errors.As(nErr, &appErr): // in case we haven't converted to plain error.
733				return nil, false, appErr
734			case errors.As(nErr, &conflictErr):
735				return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.conflict.app_error", nil, nErr.Error(), http.StatusBadRequest)
736			case errors.As(nErr, &limitExeededErr):
737				return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.max_accounts.app_error", nil, nErr.Error(), http.StatusBadRequest)
738			default: // last fallback in case it doesn't map to an existing app error.
739				return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
740			}
741		}
742		return tmr, false, nil
743	}
744
745	// Membership already exists.  Check if deleted and update, otherwise do nothing
746	// Do nothing if already added
747	if rtm.DeleteAt == 0 {
748		return rtm, true, nil
749	}
750
751	membersCount, err := a.Srv().Store.Team().GetActiveMemberCount(tm.TeamId, nil)
752	if err != nil {
753		return nil, false, model.NewAppError("joinUserToTeam", "app.team.get_active_member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
754	}
755
756	if membersCount >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) {
757		return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest)
758	}
759
760	member, nErr := a.Srv().Store.Team().UpdateMember(tm)
761	if nErr != nil {
762		var appErr *model.AppError
763		switch {
764		case errors.As(nErr, &appErr):
765			return nil, false, appErr
766		default:
767			return nil, false, model.NewAppError("joinUserToTeam", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
768		}
769	}
770
771	return member, false, nil
772}
773
774func (a *App) JoinUserToTeam(c *request.Context, team *model.Team, user *model.User, userRequestorId string) (*model.TeamMember, *model.AppError) {
775	if !a.isTeamEmailAllowed(user, team) {
776		return nil, model.NewAppError("JoinUserToTeam", "api.team.join_user_to_team.allowed_domains.app_error", nil, "", http.StatusBadRequest)
777	}
778	teamMember, alreadyAdded, err := a.joinUserToTeam(team, user)
779	if err != nil {
780		return nil, err
781	}
782	if alreadyAdded {
783		return teamMember, nil
784	}
785
786	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
787		var actor *model.User
788		if userRequestorId != "" {
789			actor, _ = a.GetUser(userRequestorId)
790		}
791
792		a.Srv().Go(func() {
793			pluginContext := pluginContext(c)
794			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
795				hooks.UserHasJoinedTeam(pluginContext, teamMember, actor)
796				return true
797			}, plugin.UserHasJoinedTeamID)
798		})
799	}
800
801	if _, err := a.Srv().Store.User().UpdateUpdateAt(user.Id); err != nil {
802		return nil, model.NewAppError("JoinUserToTeam", "app.user.update_update.app_error", nil, err.Error(), http.StatusInternalServerError)
803	}
804
805	if _, err := a.createInitialSidebarCategories(user.Id, team.Id); err != nil {
806		mlog.Warn(
807			"Encountered an issue creating default sidebar categories.",
808			mlog.String("user_id", user.Id),
809			mlog.String("team_id", team.Id),
810			mlog.Err(err),
811		)
812	}
813
814	shouldBeAdmin := team.Email == user.Email
815
816	if !user.IsGuest() {
817		// Soft error if there is an issue joining the default channels
818		if err := a.JoinDefaultChannels(c, team.Id, user, shouldBeAdmin, userRequestorId); err != nil {
819			mlog.Warn(
820				"Encountered an issue joining default channels.",
821				mlog.String("user_id", user.Id),
822				mlog.String("team_id", team.Id),
823				mlog.Err(err),
824			)
825		}
826	}
827
828	a.ClearSessionCacheForUser(user.Id)
829	a.InvalidateCacheForUser(user.Id)
830	a.invalidateCacheForUserTeams(user.Id)
831
832	message := model.NewWebSocketEvent(model.WebsocketEventAddedToTeam, "", "", user.Id, nil)
833	message.Add("team_id", team.Id)
834	message.Add("user_id", user.Id)
835	a.Publish(message)
836
837	return teamMember, nil
838}
839
840func (a *App) GetTeam(teamID string) (*model.Team, *model.AppError) {
841	team, err := a.Srv().Store.Team().Get(teamID)
842	if err != nil {
843		var nfErr *store.ErrNotFound
844		switch {
845		case errors.As(err, &nfErr):
846			return nil, model.NewAppError("GetTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
847		default:
848			return nil, model.NewAppError("GetTeam", "app.team.get.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
849		}
850	}
851
852	return team, nil
853}
854
855func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) {
856	team, err := a.Srv().Store.Team().GetByName(name)
857	if err != nil {
858		var nfErr *store.ErrNotFound
859		switch {
860		case errors.As(err, &nfErr):
861			return nil, model.NewAppError("GetTeamByName", "app.team.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
862		default:
863			return nil, model.NewAppError("GetTeamByName", "app.team.get_by_name.app_error", nil, err.Error(), http.StatusNotFound)
864		}
865	}
866
867	return team, nil
868}
869
870func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) {
871	team, err := a.Srv().Store.Team().GetByInviteId(inviteId)
872	if err != nil {
873		var nfErr *store.ErrNotFound
874		switch {
875		case errors.As(err, &nfErr):
876			return nil, model.NewAppError("GetTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
877		default:
878			return nil, model.NewAppError("GetTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
879		}
880	}
881
882	return team, nil
883}
884
885func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) {
886	teams, err := a.Srv().Store.Team().GetAll()
887	if err != nil {
888		return nil, model.NewAppError("GetAllTeams", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
889	}
890
891	return teams, nil
892}
893
894func (a *App) GetAllTeamsPage(offset int, limit int, opts *model.TeamSearch) ([]*model.Team, *model.AppError) {
895	teams, err := a.Srv().Store.Team().GetAllPage(offset, limit, opts)
896	if err != nil {
897		return nil, model.NewAppError("GetAllTeamsPage", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
898	}
899
900	return teams, nil
901}
902
903func (a *App) GetAllTeamsPageWithCount(offset int, limit int, opts *model.TeamSearch) (*model.TeamsWithCount, *model.AppError) {
904	totalCount, err := a.Srv().Store.Team().AnalyticsTeamCount(opts)
905	if err != nil {
906		return nil, model.NewAppError("GetAllTeamsPageWithCount", "app.team.analytics_team_count.app_error", nil, err.Error(), http.StatusInternalServerError)
907	}
908	teams, err := a.Srv().Store.Team().GetAllPage(offset, limit, opts)
909	if err != nil {
910		return nil, model.NewAppError("GetAllTeamsPageWithCount", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
911	}
912	return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil
913}
914
915func (a *App) GetAllPrivateTeams() ([]*model.Team, *model.AppError) {
916	teams, err := a.Srv().Store.Team().GetAllPrivateTeamListing()
917	if err != nil {
918		return nil, model.NewAppError("GetAllPrivateTeams", "app.team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
919	}
920
921	return teams, nil
922}
923
924func (a *App) GetAllPublicTeams() ([]*model.Team, *model.AppError) {
925	teams, err := a.Srv().Store.Team().GetAllTeamListing()
926	if err != nil {
927		return nil, model.NewAppError("GetAllPublicTeams", "app.team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
928	}
929
930	return teams, nil
931}
932
933// SearchAllTeams returns a team list and the total count of the results
934func (a *App) SearchAllTeams(searchOpts *model.TeamSearch) ([]*model.Team, int64, *model.AppError) {
935	if searchOpts.IsPaginated() {
936		teams, count, err := a.Srv().Store.Team().SearchAllPaged(searchOpts)
937		if err != nil {
938			return nil, 0, model.NewAppError("SearchAllTeams", "app.team.search_all_team.app_error", nil, err.Error(), http.StatusInternalServerError)
939		}
940
941		return teams, count, nil
942	}
943	results, err := a.Srv().Store.Team().SearchAll(searchOpts)
944	if err != nil {
945		return nil, 0, model.NewAppError("SearchAllTeams", "app.team.search_all_team.app_error", nil, err.Error(), http.StatusInternalServerError)
946	}
947	return results, int64(len(results)), nil
948}
949
950func (a *App) SearchPublicTeams(searchOpts *model.TeamSearch) ([]*model.Team, *model.AppError) {
951	teams, err := a.Srv().Store.Team().SearchOpen(searchOpts)
952	if err != nil {
953		return nil, model.NewAppError("SearchPublicTeams", "app.team.search_open_team.app_error", nil, err.Error(), http.StatusInternalServerError)
954	}
955
956	return teams, nil
957}
958
959func (a *App) SearchPrivateTeams(searchOpts *model.TeamSearch) ([]*model.Team, *model.AppError) {
960	teams, err := a.Srv().Store.Team().SearchPrivate(searchOpts)
961	if err != nil {
962		return nil, model.NewAppError("SearchPrivateTeams", "app.team.search_private_team.app_error", nil, err.Error(), http.StatusInternalServerError)
963	}
964
965	return teams, nil
966}
967
968func (a *App) GetTeamsForUser(userID string) ([]*model.Team, *model.AppError) {
969	teams, err := a.Srv().Store.Team().GetTeamsByUserId(userID)
970	if err != nil {
971		return nil, model.NewAppError("GetTeamsForUser", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
972	}
973
974	return teams, nil
975}
976
977func (a *App) GetTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) {
978	teamMember, err := a.Srv().Store.Team().GetMember(sqlstore.WithMaster(context.Background()), teamID, userID)
979	if err != nil {
980		var nfErr *store.ErrNotFound
981		switch {
982		case errors.As(err, &nfErr):
983			return nil, model.NewAppError("GetTeamMember", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
984		default:
985			return nil, model.NewAppError("GetTeamMember", "app.team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
986		}
987	}
988
989	return teamMember, nil
990}
991
992func (a *App) GetTeamMembersForUser(userID string) ([]*model.TeamMember, *model.AppError) {
993	teamMembers, err := a.Srv().Store.Team().GetTeamsForUser(context.Background(), userID)
994	if err != nil {
995		return nil, model.NewAppError("GetTeamMembersForUser", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
996	}
997
998	return teamMembers, nil
999}
1000
1001func (a *App) GetTeamMembersForUserWithPagination(userID string, page, perPage int) ([]*model.TeamMember, *model.AppError) {
1002	teamMembers, err := a.Srv().Store.Team().GetTeamsForUserWithPagination(userID, page, perPage)
1003	if err != nil {
1004		return nil, model.NewAppError("GetTeamMembersForUserWithPagination", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
1005	}
1006
1007	return teamMembers, nil
1008}
1009
1010func (a *App) GetTeamMembers(teamID string, offset int, limit int, teamMembersGetOptions *model.TeamMembersGetOptions) ([]*model.TeamMember, *model.AppError) {
1011	teamMembers, err := a.Srv().Store.Team().GetMembers(teamID, offset, limit, teamMembersGetOptions)
1012	if err != nil {
1013		return nil, model.NewAppError("GetTeamMembers", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
1014	}
1015
1016	return teamMembers, nil
1017}
1018
1019func (a *App) GetTeamMembersByIds(teamID string, userIDs []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError) {
1020	teamMembers, err := a.Srv().Store.Team().GetMembersByIds(teamID, userIDs, restrictions)
1021	if err != nil {
1022		return nil, model.NewAppError("GetTeamMembersByIds", "app.team.get_members_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError)
1023	}
1024
1025	return teamMembers, nil
1026}
1027
1028func (a *App) GetCommonTeamIDsForTwoUsers(userID, otherUserID string) ([]string, *model.AppError) {
1029	teamIDs, err := a.Srv().Store.Team().GetCommonTeamIDsForTwoUsers(userID, otherUserID)
1030	if err != nil {
1031		return nil, model.NewAppError("GetCommonTeamIDsForUsers", "app.team.get_common_team_ids_for_users.app_error", nil, err.Error(), http.StatusInternalServerError)
1032	}
1033	return teamIDs, nil
1034}
1035
1036func (a *App) AddTeamMember(c *request.Context, teamID, userID string) (*model.TeamMember, *model.AppError) {
1037	_, teamMember, err := a.AddUserToTeam(c, teamID, userID, "")
1038	if err != nil {
1039		return nil, err
1040	}
1041
1042	message := model.NewWebSocketEvent(model.WebsocketEventAddedToTeam, "", "", userID, nil)
1043	message.Add("team_id", teamID)
1044	message.Add("user_id", userID)
1045	a.Publish(message)
1046
1047	return teamMember, nil
1048}
1049
1050func (a *App) AddTeamMembers(c *request.Context, teamID string, userIDs []string, userRequestorId string, graceful bool) ([]*model.TeamMemberWithError, *model.AppError) {
1051	var membersWithErrors []*model.TeamMemberWithError
1052
1053	for _, userID := range userIDs {
1054		_, teamMember, err := a.AddUserToTeam(c, teamID, userID, userRequestorId)
1055		if err != nil {
1056			if graceful {
1057				membersWithErrors = append(membersWithErrors, &model.TeamMemberWithError{
1058					UserId: userID,
1059					Error:  err,
1060				})
1061				continue
1062			}
1063			return nil, err
1064		}
1065
1066		membersWithErrors = append(membersWithErrors, &model.TeamMemberWithError{
1067			UserId: userID,
1068			Member: teamMember,
1069		})
1070
1071		message := model.NewWebSocketEvent(model.WebsocketEventAddedToTeam, "", "", userID, nil)
1072		message.Add("team_id", teamID)
1073		message.Add("user_id", userID)
1074		a.Publish(message)
1075	}
1076
1077	return membersWithErrors, nil
1078}
1079
1080func (a *App) AddTeamMemberByToken(c *request.Context, userID, tokenID string) (*model.TeamMember, *model.AppError) {
1081	_, teamMember, err := a.AddUserToTeamByToken(c, userID, tokenID)
1082	if err != nil {
1083		return nil, err
1084	}
1085
1086	return teamMember, nil
1087}
1088
1089func (a *App) AddTeamMemberByInviteId(c *request.Context, inviteId, userID string) (*model.TeamMember, *model.AppError) {
1090	team, teamMember, err := a.AddUserToTeamByInviteId(c, inviteId, userID)
1091	if err != nil {
1092		return nil, err
1093	}
1094
1095	if team.IsGroupConstrained() {
1096		return nil, model.NewAppError("AddTeamMemberByInviteId", "app.team.invite_id.group_constrained.error", nil, "", http.StatusForbidden)
1097	}
1098
1099	return teamMember, nil
1100}
1101
1102func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.AppError) {
1103	channelUnreads, err := a.Srv().Store.Team().GetChannelUnreadsForTeam(teamID, userID)
1104
1105	if err != nil {
1106		return nil, model.NewAppError("GetTeamUnread", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
1107	}
1108
1109	var teamUnread = &model.TeamUnread{
1110		MsgCount:         0,
1111		MentionCount:     0,
1112		MentionCountRoot: 0,
1113		MsgCountRoot:     0,
1114		TeamId:           teamID,
1115	}
1116	for _, cu := range channelUnreads {
1117		teamUnread.MentionCount += cu.MentionCount
1118		teamUnread.MentionCountRoot += cu.MentionCountRoot
1119
1120		if cu.NotifyProps[model.MarkUnreadNotifyProp] != model.ChannelMarkUnreadMention {
1121			teamUnread.MsgCount += cu.MsgCount
1122			teamUnread.MsgCountRoot += cu.MsgCountRoot
1123		}
1124	}
1125
1126	return teamUnread, nil
1127}
1128
1129func (a *App) RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError {
1130	tchan := make(chan store.StoreResult, 1)
1131	go func() {
1132		team, err := a.Srv().Store.Team().Get(teamID)
1133		tchan <- store.StoreResult{Data: team, NErr: err}
1134		close(tchan)
1135	}()
1136
1137	uchan := make(chan store.StoreResult, 1)
1138	go func() {
1139		user, err := a.Srv().Store.User().Get(context.Background(), userID)
1140		uchan <- store.StoreResult{Data: user, NErr: err}
1141		close(uchan)
1142	}()
1143
1144	result := <-tchan
1145	if result.NErr != nil {
1146		var nfErr *store.ErrNotFound
1147		switch {
1148		case errors.As(result.NErr, &nfErr):
1149			return model.NewAppError("RemoveUserFromTeam", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
1150		default:
1151			return model.NewAppError("RemoveUserFromTeam", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1152		}
1153	}
1154	team := result.Data.(*model.Team)
1155
1156	result = <-uchan
1157	if result.NErr != nil {
1158		var nfErr *store.ErrNotFound
1159		switch {
1160		case errors.As(result.NErr, &nfErr):
1161			return model.NewAppError("RemoveUserFromTeam", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
1162		default:
1163			return model.NewAppError("RemoveUserFromTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1164		}
1165	}
1166	user := result.Data.(*model.User)
1167
1168	if err := a.LeaveTeam(c, team, user, requestorId); err != nil {
1169		return err
1170	}
1171
1172	return nil
1173}
1174
1175func (a *App) RemoveTeamMemberFromTeam(c *request.Context, teamMember *model.TeamMember, requestorId string) *model.AppError {
1176	// Send the websocket message before we actually do the remove so the user being removed gets it.
1177	message := model.NewWebSocketEvent(model.WebsocketEventLeaveTeam, teamMember.TeamId, "", "", nil)
1178	message.Add("user_id", teamMember.UserId)
1179	message.Add("team_id", teamMember.TeamId)
1180	a.Publish(message)
1181
1182	user, nErr := a.Srv().Store.User().Get(context.Background(), teamMember.UserId)
1183	if nErr != nil {
1184		var nfErr *store.ErrNotFound
1185		switch {
1186		case errors.As(nErr, &nfErr):
1187			return model.NewAppError("RemoveTeamMemberFromTeam", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
1188		default:
1189			return model.NewAppError("RemoveTeamMemberFromTeam", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1190		}
1191	}
1192
1193	teamMember.Roles = ""
1194	teamMember.DeleteAt = model.GetMillis()
1195
1196	if _, nErr := a.Srv().Store.Team().UpdateMember(teamMember); nErr != nil {
1197		var appErr *model.AppError
1198		switch {
1199		case errors.As(nErr, &appErr):
1200			return appErr
1201		default:
1202			return model.NewAppError("RemoveTeamMemberFromTeam", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1203		}
1204	}
1205
1206	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
1207		var actor *model.User
1208		if requestorId != "" {
1209			actor, _ = a.GetUser(requestorId)
1210		}
1211
1212		a.Srv().Go(func() {
1213			pluginContext := pluginContext(c)
1214			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
1215				hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
1216				return true
1217			}, plugin.UserHasLeftTeamID)
1218		})
1219	}
1220
1221	if _, err := a.Srv().Store.User().UpdateUpdateAt(user.Id); err != nil {
1222		return model.NewAppError("RemoveTeamMemberFromTeam", "app.user.update_update.app_error", nil, err.Error(), http.StatusInternalServerError)
1223	}
1224
1225	if err := a.Srv().Store.Channel().ClearSidebarOnTeamLeave(user.Id, teamMember.TeamId); err != nil {
1226		return model.NewAppError("RemoveTeamMemberFromTeam", "app.channel.sidebar_categories.app_error", nil, err.Error(), http.StatusInternalServerError)
1227	}
1228
1229	// delete the preferences that set the last channel used in the team and other team specific preferences
1230	if err := a.Srv().Store.Preference().DeleteCategory(user.Id, teamMember.TeamId); err != nil {
1231		return model.NewAppError("RemoveTeamMemberFromTeam", "app.preference.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
1232	}
1233
1234	a.ClearSessionCacheForUser(user.Id)
1235	a.InvalidateCacheForUser(user.Id)
1236	a.invalidateCacheForUserTeams(user.Id)
1237
1238	return nil
1239}
1240
1241func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError {
1242	teamMember, err := a.GetTeamMember(team.Id, user.Id)
1243	if err != nil {
1244		return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
1245	}
1246
1247	var channelList model.ChannelList
1248	var nErr error
1249	if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, true, 0); nErr != nil {
1250		var nfErr *store.ErrNotFound
1251		if errors.As(nErr, &nfErr) {
1252			channelList = model.ChannelList{}
1253		} else {
1254			return model.NewAppError("LeaveTeam", "app.channel.get_channels.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1255		}
1256	}
1257
1258	for _, channel := range channelList {
1259		if !channel.IsGroupOrDirect() {
1260			a.invalidateCacheForChannelMembers(channel.Id)
1261			if nErr = a.Srv().Store.Channel().RemoveMember(channel.Id, user.Id); nErr != nil {
1262				return model.NewAppError("LeaveTeam", "app.channel.remove_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1263			}
1264		}
1265	}
1266
1267	channel, nErr := a.Srv().Store.Channel().GetByName(team.Id, model.DefaultChannelName, false)
1268	if nErr != nil {
1269		var nfErr *store.ErrNotFound
1270		switch {
1271		case errors.As(nErr, &nfErr):
1272			return model.NewAppError("LeaveTeam", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
1273		default:
1274			return model.NewAppError("LeaveTeam", "app.channel.get_by_name.existing.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1275		}
1276	}
1277
1278	if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
1279		if requestorId == user.Id {
1280			if err = a.postLeaveTeamMessage(c, user, channel); err != nil {
1281				mlog.Warn("Failed to post join/leave message", mlog.Err(err))
1282			}
1283		} else {
1284			if err = a.postRemoveFromTeamMessage(c, user, channel); err != nil {
1285				mlog.Warn("Failed to post join/leave message", mlog.Err(err))
1286			}
1287		}
1288	}
1289
1290	if err := a.RemoveTeamMemberFromTeam(c, teamMember, requestorId); err != nil {
1291		return err
1292	}
1293
1294	return nil
1295}
1296
1297func (a *App) postLeaveTeamMessage(c *request.Context, user *model.User, channel *model.Channel) *model.AppError {
1298	post := &model.Post{
1299		ChannelId: channel.Id,
1300		Message:   fmt.Sprintf(i18n.T("api.team.leave.left"), user.Username),
1301		Type:      model.PostTypeLeaveTeam,
1302		UserId:    user.Id,
1303		Props: model.StringInterface{
1304			"username": user.Username,
1305		},
1306	}
1307
1308	if _, err := a.CreatePost(c, post, channel, false, true); err != nil {
1309		return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
1310	}
1311
1312	return nil
1313}
1314
1315func (a *App) postRemoveFromTeamMessage(c *request.Context, user *model.User, channel *model.Channel) *model.AppError {
1316	post := &model.Post{
1317		ChannelId: channel.Id,
1318		Message:   fmt.Sprintf(i18n.T("api.team.remove_user_from_team.removed"), user.Username),
1319		Type:      model.PostTypeRemoveFromTeam,
1320		UserId:    user.Id,
1321		Props: model.StringInterface{
1322			"username": user.Username,
1323		},
1324	}
1325
1326	if _, err := a.CreatePost(c, post, channel, false, true); err != nil {
1327		return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
1328	}
1329
1330	return nil
1331}
1332
1333func (a *App) prepareInviteNewUsersToTeam(teamID, senderId string) (*model.User, *model.Team, *model.AppError) {
1334	tchan := make(chan store.StoreResult, 1)
1335	go func() {
1336		team, err := a.Srv().Store.Team().Get(teamID)
1337		tchan <- store.StoreResult{Data: team, NErr: err}
1338		close(tchan)
1339	}()
1340
1341	uchan := make(chan store.StoreResult, 1)
1342	go func() {
1343		user, err := a.Srv().Store.User().Get(context.Background(), senderId)
1344		uchan <- store.StoreResult{Data: user, NErr: err}
1345		close(uchan)
1346	}()
1347
1348	result := <-tchan
1349	if result.NErr != nil {
1350		var nfErr *store.ErrNotFound
1351		switch {
1352		case errors.As(result.NErr, &nfErr):
1353			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
1354		default:
1355			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1356		}
1357	}
1358	team := result.Data.(*model.Team)
1359
1360	result = <-uchan
1361	if result.NErr != nil {
1362		var nfErr *store.ErrNotFound
1363		switch {
1364		case errors.As(result.NErr, &nfErr):
1365			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
1366		default:
1367			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1368		}
1369	}
1370	user := result.Data.(*model.User)
1371	return user, team, nil
1372}
1373
1374func genEmailInviteWithErrorList(emailList []string) []*model.EmailInviteWithError {
1375	invitesNotSent := make([]*model.EmailInviteWithError, len(emailList))
1376	for i := range emailList {
1377		invite := &model.EmailInviteWithError{
1378			Email: emailList[i],
1379			Error: model.NewAppError("inviteUsersToTeam", "api.team.invite_members.limit_reached.app_error", map[string]interface{}{"Addresses": emailList[i]}, "", http.StatusBadRequest),
1380		}
1381		invitesNotSent[i] = invite
1382	}
1383	return invitesNotSent
1384}
1385
1386func (a *App) GetErrorListForEmailsOverLimit(emailList []string, cloudUserLimit int64) ([]string, []*model.EmailInviteWithError, *model.AppError) {
1387	var invitesNotSent []*model.EmailInviteWithError
1388	if cloudUserLimit <= 0 {
1389		return emailList, invitesNotSent, nil
1390	}
1391	systemUserCount, _ := a.Srv().Store.User().Count(model.UserCountOptions{})
1392	remainingUsers := cloudUserLimit - systemUserCount
1393	if remainingUsers <= 0 {
1394		// No remaining users so all fail
1395		invitesNotSent = genEmailInviteWithErrorList(emailList)
1396		emailList = nil
1397	} else if remainingUsers < int64(len(emailList)) {
1398		// Trim the email list to only invite as many users as are remaining in subscription
1399		// Set graceful errors for the remaining email addresses
1400		emailsAboveLimit := emailList[remainingUsers:]
1401		invitesNotSent = genEmailInviteWithErrorList(emailsAboveLimit)
1402		// If 1 user remaining we have to prevent 0:0 reslicing
1403		if remainingUsers == 1 {
1404			email := emailList[0]
1405			emailList = nil
1406			emailList = append(emailList, email)
1407		} else {
1408			emailList = emailList[:(remainingUsers - 1)]
1409		}
1410	}
1411
1412	return emailList, invitesNotSent, nil
1413}
1414
1415func (a *App) InviteNewUsersToTeamGracefully(emailList []string, teamID, senderId string) ([]*model.EmailInviteWithError, *model.AppError) {
1416	if !*a.Config().ServiceSettings.EnableEmailInvitations {
1417		return nil, model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
1418	}
1419
1420	if len(emailList) == 0 {
1421		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
1422		return nil, err
1423	}
1424	user, team, err := a.prepareInviteNewUsersToTeam(teamID, senderId)
1425	if err != nil {
1426		return nil, err
1427	}
1428	allowedDomains := a.getAllowedDomains(user, team)
1429	var inviteListWithErrors []*model.EmailInviteWithError
1430	var goodEmails []string
1431	for _, email := range emailList {
1432		invite := &model.EmailInviteWithError{
1433			Email: email,
1434			Error: nil,
1435		}
1436		if !a.isEmailAddressAllowed(email, allowedDomains) {
1437			invite.Error = model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": email}, "", http.StatusBadRequest)
1438		} else {
1439			goodEmails = append(goodEmails, email)
1440		}
1441		inviteListWithErrors = append(inviteListWithErrors, invite)
1442	}
1443
1444	if len(goodEmails) > 0 {
1445		nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
1446		eErr := a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, goodEmails, a.GetSiteURL())
1447		if eErr != nil {
1448			switch {
1449			case errors.Is(eErr, email.NoRateLimiterError):
1450				return nil, model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s", user.Id, team.Id), http.StatusInternalServerError)
1451			case errors.Is(eErr, email.SetupRateLimiterError):
1452				return nil, model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, eErr), http.StatusInternalServerError)
1453			default:
1454				return nil, model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, eErr), http.StatusRequestEntityTooLarge)
1455			}
1456		}
1457	}
1458
1459	return inviteListWithErrors, nil
1460}
1461
1462func (a *App) prepareInviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) (*model.User, *model.Team, []*model.Channel, *model.AppError) {
1463	if err := guestsInvite.IsValid(); err != nil {
1464		return nil, nil, nil, err
1465	}
1466
1467	tchan := make(chan store.StoreResult, 1)
1468	go func() {
1469		team, err := a.Srv().Store.Team().Get(teamID)
1470		tchan <- store.StoreResult{Data: team, NErr: err}
1471		close(tchan)
1472	}()
1473	cchan := make(chan store.StoreResult, 1)
1474	go func() {
1475		channels, err := a.Srv().Store.Channel().GetChannelsByIds(guestsInvite.Channels, false)
1476		cchan <- store.StoreResult{Data: channels, NErr: err}
1477		close(cchan)
1478	}()
1479	uchan := make(chan store.StoreResult, 1)
1480	go func() {
1481		user, err := a.Srv().Store.User().Get(context.Background(), senderId)
1482		uchan <- store.StoreResult{Data: user, NErr: err}
1483		close(uchan)
1484	}()
1485
1486	result := <-cchan
1487	if result.NErr != nil {
1488		return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.channel.get_channels_by_ids.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1489	}
1490	channels := result.Data.([]*model.Channel)
1491
1492	result = <-uchan
1493	if result.NErr != nil {
1494		var nfErr *store.ErrNotFound
1495		switch {
1496		case errors.As(result.NErr, &nfErr):
1497			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
1498		default:
1499			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1500		}
1501	}
1502	user := result.Data.(*model.User)
1503
1504	result = <-tchan
1505	if result.NErr != nil {
1506		var nfErr *store.ErrNotFound
1507		switch {
1508		case errors.As(result.NErr, &nfErr):
1509			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
1510		default:
1511			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1512		}
1513	}
1514	team := result.Data.(*model.Team)
1515
1516	for _, channel := range channels {
1517		if channel.TeamId != teamID {
1518			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "api.team.invite_guests.channel_in_invalid_team.app_error", nil, "", http.StatusBadRequest)
1519		}
1520	}
1521	return user, team, channels, nil
1522}
1523
1524func (a *App) InviteGuestsToChannelsGracefully(teamID string, guestsInvite *model.GuestsInvite, senderId string) ([]*model.EmailInviteWithError, *model.AppError) {
1525	if !*a.Config().ServiceSettings.EnableEmailInvitations {
1526		return nil, model.NewAppError("InviteGuestsToChannelsGracefully", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
1527	}
1528
1529	user, team, channels, err := a.prepareInviteGuestsToChannels(teamID, guestsInvite, senderId)
1530	if err != nil {
1531		return nil, err
1532	}
1533
1534	var inviteListWithErrors []*model.EmailInviteWithError
1535	var goodEmails []string
1536	for _, email := range guestsInvite.Emails {
1537		invite := &model.EmailInviteWithError{
1538			Email: email,
1539			Error: nil,
1540		}
1541		if !users.CheckEmailDomain(email, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) {
1542			invite.Error = model.NewAppError("InviteGuestsToChannelsGracefully", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": email}, "", http.StatusBadRequest)
1543		} else {
1544			goodEmails = append(goodEmails, email)
1545		}
1546		inviteListWithErrors = append(inviteListWithErrors, invite)
1547	}
1548
1549	if len(goodEmails) > 0 {
1550		nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
1551		senderProfileImage, _, err := a.GetProfileImage(user)
1552		if err != nil {
1553			a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
1554		}
1555		eErr := a.Srv().EmailService.SendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), guestsInvite.Message)
1556		if eErr != nil {
1557			switch {
1558			case errors.Is(eErr, email.NoRateLimiterError):
1559				return nil, model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s", user.Id, team.Id), http.StatusInternalServerError)
1560			case errors.Is(eErr, email.SetupRateLimiterError):
1561				return nil, model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, eErr), http.StatusInternalServerError)
1562			default:
1563				return nil, model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, eErr), http.StatusRequestEntityTooLarge)
1564			}
1565		}
1566	}
1567
1568	return inviteListWithErrors, nil
1569}
1570
1571func (a *App) InviteNewUsersToTeam(emailList []string, teamID, senderId string) *model.AppError {
1572	if !*a.Config().ServiceSettings.EnableEmailInvitations {
1573		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
1574	}
1575
1576	if len(emailList) == 0 {
1577		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
1578		return err
1579	}
1580
1581	user, team, err := a.prepareInviteNewUsersToTeam(teamID, senderId)
1582	if err != nil {
1583		return err
1584	}
1585
1586	allowedDomains := a.getAllowedDomains(user, team)
1587	var invalidEmailList []string
1588
1589	for _, email := range emailList {
1590		if !a.isEmailAddressAllowed(email, allowedDomains) {
1591			invalidEmailList = append(invalidEmailList, email)
1592		}
1593	}
1594
1595	if len(invalidEmailList) > 0 {
1596		s := strings.Join(invalidEmailList, ", ")
1597		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
1598	}
1599
1600	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
1601	eErr := a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL())
1602	if eErr != nil {
1603		switch {
1604		case errors.Is(eErr, email.NoRateLimiterError):
1605			return model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s", user.Id, team.Id), http.StatusInternalServerError)
1606		case errors.Is(eErr, email.SetupRateLimiterError):
1607			return model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, eErr), http.StatusInternalServerError)
1608		default:
1609			return model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, eErr), http.StatusRequestEntityTooLarge)
1610		}
1611	}
1612
1613	return nil
1614}
1615
1616func (a *App) InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError {
1617	if !*a.Config().ServiceSettings.EnableEmailInvitations {
1618		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
1619	}
1620
1621	user, team, channels, err := a.prepareInviteGuestsToChannels(teamID, guestsInvite, senderId)
1622	if err != nil {
1623		return err
1624	}
1625
1626	var invalidEmailList []string
1627	for _, email := range guestsInvite.Emails {
1628		if !users.CheckEmailDomain(email, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) {
1629			invalidEmailList = append(invalidEmailList, email)
1630		}
1631	}
1632
1633	if len(invalidEmailList) > 0 {
1634		s := strings.Join(invalidEmailList, ", ")
1635		return model.NewAppError("InviteGuestsToChannels", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
1636	}
1637
1638	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
1639	senderProfileImage, _, err := a.GetProfileImage(user)
1640	if err != nil {
1641		a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
1642	}
1643	eErr := a.Srv().EmailService.SendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, guestsInvite.Emails, a.GetSiteURL(), guestsInvite.Message)
1644	if eErr != nil {
1645		switch {
1646		case errors.Is(eErr, email.NoRateLimiterError):
1647			return model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s", user.Id, team.Id), http.StatusInternalServerError)
1648		case errors.Is(eErr, email.SetupRateLimiterError):
1649			return model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, err), http.StatusInternalServerError)
1650		default:
1651			return model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("user_id=%s, team_id=%s, error=%v", user.Id, team.Id, err), http.StatusRequestEntityTooLarge)
1652		}
1653	}
1654
1655	return nil
1656}
1657
1658func (a *App) FindTeamByName(name string) bool {
1659	if _, err := a.Srv().Store.Team().GetByName(name); err != nil {
1660		return false
1661	}
1662	return true
1663}
1664
1665func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userID string, includeCollapsedThreads bool) ([]*model.TeamUnread, *model.AppError) {
1666	data, err := a.Srv().Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userID)
1667	if err != nil {
1668		return nil, model.NewAppError("GetTeamsUnreadForUser", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
1669	}
1670
1671	members := []*model.TeamUnread{}
1672	membersMap := make(map[string]*model.TeamUnread)
1673
1674	unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
1675		tu.MentionCount += cu.MentionCount
1676		tu.MentionCountRoot += cu.MentionCountRoot
1677
1678		if cu.NotifyProps[model.MarkUnreadNotifyProp] != model.ChannelMarkUnreadMention {
1679			tu.MsgCount += cu.MsgCount
1680			tu.MsgCountRoot += cu.MsgCountRoot
1681		}
1682
1683		return tu
1684	}
1685
1686	for i := range data {
1687		id := data[i].TeamId
1688		if mu, ok := membersMap[id]; ok {
1689			membersMap[id] = unreads(data[i], mu)
1690		} else {
1691			membersMap[id] = unreads(data[i], &model.TeamUnread{
1692				MsgCount:           0,
1693				MentionCount:       0,
1694				MentionCountRoot:   0,
1695				MsgCountRoot:       0,
1696				ThreadCount:        0,
1697				ThreadMentionCount: 0,
1698				TeamId:             id,
1699			})
1700		}
1701	}
1702
1703	includeCollapsedThreads = includeCollapsedThreads && *a.Config().ServiceSettings.CollapsedThreads != model.CollapsedThreadsDisabled
1704
1705	for _, member := range membersMap {
1706		if includeCollapsedThreads {
1707			data, err := a.Srv().Store.Thread().GetThreadsForUser(userID, member.TeamId, model.GetUserThreadsOpts{TotalsOnly: true, TeamOnly: true})
1708			if err != nil {
1709				return nil, model.NewAppError("GetTeamsUnreadForUser", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
1710			}
1711			member.ThreadCount = data.TotalUnreadThreads
1712			member.ThreadMentionCount = data.TotalUnreadMentions
1713		}
1714		members = append(members, member)
1715	}
1716
1717	return members, nil
1718}
1719
1720func (a *App) PermanentDeleteTeamId(teamID string) *model.AppError {
1721	team, err := a.GetTeam(teamID)
1722	if err != nil {
1723		return err
1724	}
1725
1726	return a.PermanentDeleteTeam(team)
1727}
1728
1729func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError {
1730	team.DeleteAt = model.GetMillis()
1731	if _, err := a.Srv().Store.Team().Update(team); err != nil {
1732		var invErr *store.ErrInvalidInput
1733		var appErr *model.AppError
1734		switch {
1735		case errors.As(err, &invErr):
1736			return model.NewAppError("PermanentDeleteTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
1737		case errors.As(err, &appErr):
1738			return appErr
1739		default:
1740			return model.NewAppError("PermanentDeleteTeam", "app.team.update.updating.app_error", nil, err.Error(), http.StatusInternalServerError)
1741		}
1742	}
1743
1744	if channels, err := a.Srv().Store.Channel().GetTeamChannels(team.Id); err != nil {
1745		var nfErr *store.ErrNotFound
1746		if !errors.As(err, &nfErr) {
1747			return model.NewAppError("PermanentDeleteTeam", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
1748		}
1749	} else {
1750		for _, c := range channels {
1751			a.PermanentDeleteChannel(c)
1752		}
1753	}
1754
1755	if err := a.Srv().Store.Team().RemoveAllMembersByTeam(team.Id); err != nil {
1756		return model.NewAppError("PermanentDeleteTeam", "app.team.remove_member.app_error", nil, err.Error(), http.StatusInternalServerError)
1757	}
1758
1759	if err := a.Srv().Store.Command().PermanentDeleteByTeam(team.Id); err != nil {
1760		return model.NewAppError("PermanentDeleteTeam", "app.team.permanentdeleteteam.internal_error", nil, err.Error(), http.StatusInternalServerError)
1761	}
1762
1763	if err := a.Srv().Store.Team().PermanentDelete(team.Id); err != nil {
1764		return model.NewAppError("PermanentDeleteTeam", "app.team.permanent_delete.app_error", nil, err.Error(), http.StatusInternalServerError)
1765	}
1766
1767	a.sendTeamEvent(team, model.WebsocketEventDeleteTeam)
1768
1769	return nil
1770}
1771
1772func (a *App) SoftDeleteTeam(teamID string) *model.AppError {
1773	team, err := a.GetTeam(teamID)
1774	if err != nil {
1775		return err
1776	}
1777
1778	team.DeleteAt = model.GetMillis()
1779	team, nErr := a.Srv().Store.Team().Update(team)
1780	if nErr != nil {
1781		var invErr *store.ErrInvalidInput
1782		var appErr *model.AppError
1783		switch {
1784		case errors.As(nErr, &invErr):
1785			return model.NewAppError("SoftDeleteTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
1786		case errors.As(nErr, &appErr):
1787			return appErr
1788		default:
1789			return model.NewAppError("SoftDeleteTeam", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1790		}
1791	}
1792
1793	a.sendTeamEvent(team, model.WebsocketEventDeleteTeam)
1794
1795	return nil
1796}
1797
1798func (a *App) RestoreTeam(teamID string) *model.AppError {
1799	team, err := a.GetTeam(teamID)
1800	if err != nil {
1801		return err
1802	}
1803
1804	team.DeleteAt = 0
1805	team, nErr := a.Srv().Store.Team().Update(team)
1806	if nErr != nil {
1807		var invErr *store.ErrInvalidInput
1808		var appErr *model.AppError
1809		switch {
1810		case errors.As(nErr, &invErr):
1811			return model.NewAppError("RestoreTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
1812		case errors.As(nErr, &appErr):
1813			return appErr
1814		default:
1815			return model.NewAppError("RestoreTeam", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
1816		}
1817	}
1818
1819	a.sendTeamEvent(team, model.WebsocketEventRestoreTeam)
1820	return nil
1821}
1822
1823func (a *App) GetTeamStats(teamID string, restrictions *model.ViewUsersRestrictions) (*model.TeamStats, *model.AppError) {
1824	tchan := make(chan store.StoreResult, 1)
1825	go func() {
1826		totalMemberCount, err := a.Srv().Store.Team().GetTotalMemberCount(teamID, restrictions)
1827		tchan <- store.StoreResult{Data: totalMemberCount, NErr: err}
1828		close(tchan)
1829	}()
1830	achan := make(chan store.StoreResult, 1)
1831	go func() {
1832		memberCount, err := a.Srv().Store.Team().GetActiveMemberCount(teamID, restrictions)
1833		achan <- store.StoreResult{Data: memberCount, NErr: err}
1834		close(achan)
1835	}()
1836
1837	stats := &model.TeamStats{}
1838	stats.TeamId = teamID
1839
1840	result := <-tchan
1841	if result.NErr != nil {
1842		return nil, model.NewAppError("GetTeamStats", "app.team.get_member_count.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1843	}
1844	stats.TotalMemberCount = result.Data.(int64)
1845
1846	result = <-achan
1847	if result.NErr != nil {
1848		return nil, model.NewAppError("GetTeamStats", "app.team.get_active_member_count.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
1849	}
1850	stats.ActiveMemberCount = result.Data.(int64)
1851
1852	return stats, nil
1853}
1854
1855func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
1856	tokenID := query.Get("t")
1857	inviteId := query.Get("id")
1858
1859	if tokenID != "" {
1860		token, err := a.Srv().Store.Token().GetByToken(tokenID)
1861		if err != nil {
1862			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
1863		}
1864
1865		if token.Type != TokenTypeTeamInvitation && token.Type != TokenTypeGuestInvitation {
1866			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
1867		}
1868
1869		if model.GetMillis()-token.CreateAt >= InvitationExpiryTime {
1870			a.DeleteToken(token)
1871			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest)
1872		}
1873
1874		tokenData := model.MapFromJSON(strings.NewReader(token.Extra))
1875
1876		return tokenData["teamId"], nil
1877	}
1878	if inviteId != "" {
1879		team, err := a.Srv().Store.Team().GetByInviteId(inviteId)
1880		if err == nil {
1881			return team.Id, nil
1882		}
1883		// soft fail, so we still create user but don't auto-join team
1884		mlog.Warn("Error getting team by inviteId.", mlog.String("invite_id", inviteId), mlog.Err(err))
1885	}
1886
1887	return "", nil
1888}
1889
1890func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
1891	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam) {
1892		return team
1893	}
1894
1895	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser) {
1896		inviteId := team.InviteId
1897		team.Sanitize()
1898		team.InviteId = inviteId
1899		return team
1900	}
1901
1902	team.Sanitize()
1903
1904	return team
1905}
1906
1907func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team {
1908	for _, team := range teams {
1909		a.SanitizeTeam(session, team)
1910	}
1911
1912	return teams
1913}
1914
1915func (a *App) GetTeamIcon(team *model.Team) ([]byte, *model.AppError) {
1916	if *a.Config().FileSettings.DriverName == "" {
1917		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.filesettings_no_driver.app_error", nil, "", http.StatusNotImplemented)
1918	}
1919
1920	path := "teams/" + team.Id + "/teamIcon.png"
1921	data, err := a.ReadFile(path)
1922	if err != nil {
1923		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.read_file.app_error", nil, err.Error(), http.StatusNotFound)
1924	}
1925
1926	return data, nil
1927}
1928
1929func (a *App) SetTeamIcon(teamID string, imageData *multipart.FileHeader) *model.AppError {
1930	file, err := imageData.Open()
1931	if err != nil {
1932		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.open.app_error", nil, err.Error(), http.StatusBadRequest)
1933	}
1934	defer file.Close()
1935	return a.SetTeamIconFromMultiPartFile(teamID, file)
1936}
1937
1938func (a *App) SetTeamIconFromMultiPartFile(teamID string, file multipart.File) *model.AppError {
1939	team, getTeamErr := a.GetTeam(teamID)
1940
1941	if getTeamErr != nil {
1942		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.get_team.app_error", nil, getTeamErr.Error(), http.StatusBadRequest)
1943	}
1944
1945	if *a.Config().FileSettings.DriverName == "" {
1946		return model.NewAppError("setTeamIcon", "api.team.set_team_icon.storage.app_error", nil, "", http.StatusNotImplemented)
1947	}
1948
1949	if limitErr := checkImageLimits(file, *a.Config().FileSettings.MaxImageResolution); limitErr != nil {
1950		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.check_image_limits.app_error",
1951			nil, limitErr.Error(), http.StatusBadRequest)
1952	}
1953
1954	return a.SetTeamIconFromFile(team, file)
1955}
1956
1957func (a *App) SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppError {
1958	// Decode image into Image object
1959	img, _, err := image.Decode(file)
1960	if err != nil {
1961		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode.app_error", nil, err.Error(), http.StatusBadRequest)
1962	}
1963
1964	orientation, _ := imaging.GetImageOrientation(file)
1965	img = imaging.MakeImageUpright(img, orientation)
1966
1967	// Scale team icon
1968	teamIconWidthAndHeight := 128
1969	img = imaging.FillCenter(img, teamIconWidthAndHeight, teamIconWidthAndHeight)
1970
1971	buf := new(bytes.Buffer)
1972	err = a.srv.imgEncoder.EncodePNG(buf, img)
1973	if err != nil {
1974		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.encode.app_error", nil, err.Error(), http.StatusInternalServerError)
1975	}
1976
1977	path := "teams/" + team.Id + "/teamIcon.png"
1978
1979	if _, err := a.WriteFile(buf, path); err != nil {
1980		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.write_file.app_error", nil, err.Error(), http.StatusInternalServerError)
1981	}
1982
1983	curTime := model.GetMillis()
1984
1985	if err := a.Srv().Store.Team().UpdateLastTeamIconUpdate(team.Id, curTime); err != nil {
1986		return model.NewAppError("SetTeamIcon", "api.team.team_icon.update.app_error", nil, err.Error(), http.StatusBadRequest)
1987	}
1988
1989	// manually set time to avoid possible cluster inconsistencies
1990	team.LastTeamIconUpdate = curTime
1991
1992	a.sendTeamEvent(team, model.WebsocketEventUpdateTeam)
1993
1994	return nil
1995}
1996
1997func (a *App) RemoveTeamIcon(teamID string) *model.AppError {
1998	team, err := a.GetTeam(teamID)
1999	if err != nil {
2000		return model.NewAppError("RemoveTeamIcon", "api.team.remove_team_icon.get_team.app_error", nil, err.Error(), http.StatusBadRequest)
2001	}
2002
2003	if err := a.Srv().Store.Team().UpdateLastTeamIconUpdate(teamID, 0); err != nil {
2004		return model.NewAppError("RemoveTeamIcon", "api.team.team_icon.update.app_error", nil, err.Error(), http.StatusBadRequest)
2005	}
2006
2007	team.LastTeamIconUpdate = 0
2008
2009	a.sendTeamEvent(team, model.WebsocketEventUpdateTeam)
2010
2011	return nil
2012}
2013
2014func (a *App) InvalidateAllEmailInvites() *model.AppError {
2015	if err := a.Srv().Store.Token().RemoveAllTokensByType(TokenTypeTeamInvitation); err != nil {
2016		return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, err.Error(), http.StatusBadRequest)
2017	}
2018	if err := a.Srv().Store.Token().RemoveAllTokensByType(TokenTypeGuestInvitation); err != nil {
2019		return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, err.Error(), http.StatusBadRequest)
2020	}
2021	return nil
2022}
2023
2024func (a *App) ClearTeamMembersCache(teamID string) {
2025	perPage := 100
2026	page := 0
2027
2028	for {
2029		teamMembers, err := a.Srv().Store.Team().GetMembers(teamID, page*perPage, perPage, nil)
2030		if err != nil {
2031			a.Log().Warn("error clearing cache for team members", mlog.String("team_id", teamID), mlog.String("err", err.Error()))
2032			break
2033		}
2034
2035		for _, teamMember := range teamMembers {
2036			a.ClearSessionCacheForUser(teamMember.UserId)
2037
2038			message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", teamMember.UserId, nil)
2039			tmJSON, jsonErr := json.Marshal(teamMember)
2040			if jsonErr != nil {
2041				mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr))
2042			}
2043			message.Add("member", string(tmJSON))
2044			a.Publish(message)
2045		}
2046
2047		length := len(teamMembers)
2048		if length < perPage {
2049			break
2050		}
2051
2052		page++
2053	}
2054}
2055