github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/team.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/base64"
     9  	"encoding/json"
    10  	"fmt"
    11  	"io"
    12  	"io/ioutil"
    13  	"net/http"
    14  	"regexp"
    15  	"strconv"
    16  	"strings"
    17  
    18  	"github.com/masterhung0112/hk_server/v5/audit"
    19  	"github.com/masterhung0112/hk_server/v5/model"
    20  )
    21  
    22  const (
    23  	MaxAddMembersBatch    = 256
    24  	MaximumBulkImportSize = 10 * 1024 * 1024
    25  	groupIDsParamPattern  = "[^a-zA-Z0-9,]*"
    26  )
    27  
    28  var groupIDsQueryParamRegex *regexp.Regexp
    29  
    30  func init() {
    31  	groupIDsQueryParamRegex = regexp.MustCompile(groupIDsParamPattern)
    32  }
    33  
    34  func (api *API) InitTeam() {
    35  	api.BaseRoutes.Teams.Handle("", api.ApiSessionRequired(createTeam)).Methods("POST")
    36  	api.BaseRoutes.Teams.Handle("", api.ApiSessionRequired(getAllTeams)).Methods("GET")
    37  	api.BaseRoutes.Teams.Handle("/{team_id:[A-Za-z0-9]+}/scheme", api.ApiSessionRequired(updateTeamScheme)).Methods("PUT")
    38  	api.BaseRoutes.Teams.Handle("/search", api.ApiSessionRequiredDisableWhenBusy(searchTeams)).Methods("POST")
    39  	api.BaseRoutes.TeamsForUser.Handle("", api.ApiSessionRequired(getTeamsForUser)).Methods("GET")
    40  	api.BaseRoutes.TeamsForUser.Handle("/unread", api.ApiSessionRequired(getTeamsUnreadForUser)).Methods("GET")
    41  
    42  	api.BaseRoutes.Team.Handle("", api.ApiSessionRequired(getTeam)).Methods("GET")
    43  	api.BaseRoutes.Team.Handle("", api.ApiSessionRequired(updateTeam)).Methods("PUT")
    44  	api.BaseRoutes.Team.Handle("", api.ApiSessionRequired(deleteTeam)).Methods("DELETE")
    45  	api.BaseRoutes.Team.Handle("/patch", api.ApiSessionRequired(patchTeam)).Methods("PUT")
    46  	api.BaseRoutes.Team.Handle("/restore", api.ApiSessionRequired(restoreTeam)).Methods("POST")
    47  	api.BaseRoutes.Team.Handle("/privacy", api.ApiSessionRequired(updateTeamPrivacy)).Methods("PUT")
    48  	api.BaseRoutes.Team.Handle("/stats", api.ApiSessionRequired(getTeamStats)).Methods("GET")
    49  	api.BaseRoutes.Team.Handle("/regenerate_invite_id", api.ApiSessionRequired(regenerateTeamInviteId)).Methods("POST")
    50  
    51  	api.BaseRoutes.Team.Handle("/image", api.ApiSessionRequiredTrustRequester(getTeamIcon)).Methods("GET")
    52  	api.BaseRoutes.Team.Handle("/image", api.ApiSessionRequired(setTeamIcon)).Methods("POST")
    53  	api.BaseRoutes.Team.Handle("/image", api.ApiSessionRequired(removeTeamIcon)).Methods("DELETE")
    54  
    55  	api.BaseRoutes.TeamMembers.Handle("", api.ApiSessionRequired(getTeamMembers)).Methods("GET")
    56  	api.BaseRoutes.TeamMembers.Handle("/ids", api.ApiSessionRequired(getTeamMembersByIds)).Methods("POST")
    57  	api.BaseRoutes.TeamMembersForUser.Handle("", api.ApiSessionRequired(getTeamMembersForUser)).Methods("GET")
    58  	api.BaseRoutes.TeamMembers.Handle("", api.ApiSessionRequired(addTeamMember)).Methods("POST")
    59  	api.BaseRoutes.Teams.Handle("/members/invite", api.ApiSessionRequired(addUserToTeamFromInvite)).Methods("POST")
    60  	api.BaseRoutes.TeamMembers.Handle("/batch", api.ApiSessionRequired(addTeamMembers)).Methods("POST")
    61  	api.BaseRoutes.TeamMember.Handle("", api.ApiSessionRequired(removeTeamMember)).Methods("DELETE")
    62  
    63  	api.BaseRoutes.TeamForUser.Handle("/unread", api.ApiSessionRequired(getTeamUnread)).Methods("GET")
    64  
    65  	api.BaseRoutes.TeamByName.Handle("", api.ApiSessionRequired(getTeamByName)).Methods("GET")
    66  	api.BaseRoutes.TeamMember.Handle("", api.ApiSessionRequired(getTeamMember)).Methods("GET")
    67  	api.BaseRoutes.TeamByName.Handle("/exists", api.ApiSessionRequired(teamExists)).Methods("GET")
    68  	api.BaseRoutes.TeamMember.Handle("/roles", api.ApiSessionRequired(updateTeamMemberRoles)).Methods("PUT")
    69  	api.BaseRoutes.TeamMember.Handle("/schemeRoles", api.ApiSessionRequired(updateTeamMemberSchemeRoles)).Methods("PUT")
    70  	api.BaseRoutes.Team.Handle("/import", api.ApiSessionRequired(importTeam)).Methods("POST")
    71  	api.BaseRoutes.Team.Handle("/invite/email", api.ApiSessionRequired(inviteUsersToTeam)).Methods("POST")
    72  	api.BaseRoutes.Team.Handle("/invite-guests/email", api.ApiSessionRequired(inviteGuestsToChannels)).Methods("POST")
    73  	api.BaseRoutes.Teams.Handle("/invites/email", api.ApiSessionRequired(invalidateAllEmailInvites)).Methods("DELETE")
    74  	api.BaseRoutes.Teams.Handle("/invite/{invite_id:[A-Za-z0-9]+}", api.ApiHandler(getInviteInfo)).Methods("GET")
    75  
    76  	api.BaseRoutes.Teams.Handle("/{team_id:[A-Za-z0-9]+}/members_minus_group_members", api.ApiSessionRequired(teamMembersMinusGroupMembers)).Methods("GET")
    77  }
    78  
    79  func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
    80  	team := model.TeamFromJson(r.Body)
    81  	if team == nil {
    82  		c.SetInvalidParam("team")
    83  		return
    84  	}
    85  	team.Email = strings.ToLower(team.Email)
    86  
    87  	auditRec := c.MakeAuditRecord("createTeam", audit.Fail)
    88  	defer c.LogAuditRec(auditRec)
    89  	auditRec.AddMeta("team", team)
    90  
    91  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_CREATE_TEAM) {
    92  		c.Err = model.NewAppError("createTeam", "api.team.is_team_creation_allowed.disabled.app_error", nil, "", http.StatusForbidden)
    93  		return
    94  	}
    95  
    96  	rteam, err := c.App.CreateTeamWithUser(c.AppContext, team, c.AppContext.Session().UserId)
    97  	if err != nil {
    98  		c.Err = err
    99  		return
   100  	}
   101  
   102  	// Don't sanitize the team here since the user will be a team admin and their session won't reflect that yet
   103  
   104  	auditRec.Success()
   105  	auditRec.AddMeta("team", team) // overwrite meta
   106  
   107  	w.WriteHeader(http.StatusCreated)
   108  	w.Write([]byte(rteam.ToJson()))
   109  }
   110  
   111  func getTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   112  	c.RequireTeamId()
   113  	if c.Err != nil {
   114  		return
   115  	}
   116  
   117  	team, err := c.App.GetTeam(c.Params.TeamId)
   118  	if err != nil {
   119  		c.Err = err
   120  		return
   121  	}
   122  
   123  	if (!team.AllowOpenInvite || team.Type != model.TEAM_OPEN) && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PERMISSION_VIEW_TEAM) {
   124  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   125  		return
   126  	}
   127  
   128  	c.App.SanitizeTeam(*c.AppContext.Session(), team)
   129  	w.Write([]byte(team.ToJson()))
   130  }
   131  
   132  func getTeamByName(c *Context, w http.ResponseWriter, r *http.Request) {
   133  	c.RequireTeamName()
   134  	if c.Err != nil {
   135  		return
   136  	}
   137  
   138  	team, err := c.App.GetTeamByName(c.Params.TeamName)
   139  	if err != nil {
   140  		c.Err = err
   141  		return
   142  	}
   143  
   144  	if (!team.AllowOpenInvite || team.Type != model.TEAM_OPEN) && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PERMISSION_VIEW_TEAM) {
   145  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   146  		return
   147  	}
   148  
   149  	c.App.SanitizeTeam(*c.AppContext.Session(), team)
   150  	w.Write([]byte(team.ToJson()))
   151  }
   152  
   153  func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   154  	c.RequireTeamId()
   155  	if c.Err != nil {
   156  		return
   157  	}
   158  
   159  	team := model.TeamFromJson(r.Body)
   160  
   161  	if team == nil {
   162  		c.SetInvalidParam("team")
   163  		return
   164  	}
   165  	team.Email = strings.ToLower(team.Email)
   166  
   167  	// The team being updated in the payload must be the same one as indicated in the URL.
   168  	if team.Id != c.Params.TeamId {
   169  		c.SetInvalidParam("id")
   170  		return
   171  	}
   172  
   173  	auditRec := c.MakeAuditRecord("updateTeam", audit.Fail)
   174  	defer c.LogAuditRec(auditRec)
   175  	auditRec.AddMeta("team", team)
   176  
   177  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   178  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   179  		return
   180  	}
   181  
   182  	updatedTeam, err := c.App.UpdateTeam(team)
   183  	if err != nil {
   184  		c.Err = err
   185  		return
   186  	}
   187  
   188  	auditRec.Success()
   189  	auditRec.AddMeta("update", updatedTeam)
   190  
   191  	c.App.SanitizeTeam(*c.AppContext.Session(), updatedTeam)
   192  	w.Write([]byte(updatedTeam.ToJson()))
   193  }
   194  
   195  func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   196  	c.RequireTeamId()
   197  	if c.Err != nil {
   198  		return
   199  	}
   200  
   201  	team := model.TeamPatchFromJson(r.Body)
   202  
   203  	if team == nil {
   204  		c.SetInvalidParam("team")
   205  		return
   206  	}
   207  
   208  	auditRec := c.MakeAuditRecord("patchTeam", audit.Fail)
   209  	defer c.LogAuditRec(auditRec)
   210  
   211  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   212  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   213  		return
   214  	}
   215  
   216  	if oldTeam, err := c.App.GetTeam(c.Params.TeamId); err == nil {
   217  		auditRec.AddMeta("team", oldTeam)
   218  	}
   219  
   220  	patchedTeam, err := c.App.PatchTeam(c.Params.TeamId, team)
   221  
   222  	if err != nil {
   223  		c.Err = err
   224  		return
   225  	}
   226  
   227  	c.App.SanitizeTeam(*c.AppContext.Session(), patchedTeam)
   228  
   229  	auditRec.Success()
   230  	auditRec.AddMeta("patched", patchedTeam)
   231  	c.LogAudit("")
   232  
   233  	w.Write([]byte(patchedTeam.ToJson()))
   234  }
   235  
   236  func restoreTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   237  	c.RequireTeamId()
   238  	if c.Err != nil {
   239  		return
   240  	}
   241  
   242  	auditRec := c.MakeAuditRecord("restoreTeam", audit.Fail)
   243  	defer c.LogAuditRec(auditRec)
   244  	auditRec.AddMeta("team_id", c.Params.TeamId)
   245  
   246  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   247  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   248  		return
   249  	}
   250  
   251  	err := c.App.RestoreTeam(c.Params.TeamId)
   252  	if err != nil {
   253  		c.Err = err
   254  		return
   255  	}
   256  
   257  	// Return the restored team to be consistent with RestoreChannel.
   258  	team, err := c.App.GetTeam(c.Params.TeamId)
   259  	if err != nil {
   260  		c.Err = err
   261  		return
   262  	}
   263  
   264  	auditRec.AddMeta("team", team)
   265  	auditRec.Success()
   266  
   267  	w.Write([]byte(team.ToJson()))
   268  }
   269  
   270  func updateTeamPrivacy(c *Context, w http.ResponseWriter, r *http.Request) {
   271  	c.RequireTeamId()
   272  	if c.Err != nil {
   273  		return
   274  	}
   275  
   276  	props := model.StringInterfaceFromJson(r.Body)
   277  	privacy, ok := props["privacy"].(string)
   278  	if !ok {
   279  		c.SetInvalidParam("privacy")
   280  		return
   281  	}
   282  
   283  	var openInvite bool
   284  	switch privacy {
   285  	case model.TEAM_OPEN:
   286  		openInvite = true
   287  	case model.TEAM_INVITE:
   288  		openInvite = false
   289  	default:
   290  		c.SetInvalidParam("privacy")
   291  		return
   292  	}
   293  
   294  	auditRec := c.MakeAuditRecord("updateTeamPrivacy", audit.Fail)
   295  	defer c.LogAuditRec(auditRec)
   296  	auditRec.AddMeta("privacy", privacy)
   297  
   298  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   299  		auditRec.AddMeta("team_id", c.Params.TeamId)
   300  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   301  		return
   302  	}
   303  
   304  	if err := c.App.UpdateTeamPrivacy(c.Params.TeamId, privacy, openInvite); err != nil {
   305  		c.Err = err
   306  		return
   307  	}
   308  
   309  	// Return the updated team to be consistent with UpdateChannelPrivacy
   310  	team, err := c.App.GetTeam(c.Params.TeamId)
   311  	if err != nil {
   312  		c.Err = err
   313  		return
   314  	}
   315  
   316  	auditRec.AddMeta("team", team)
   317  	auditRec.Success()
   318  
   319  	w.Write([]byte(team.ToJson()))
   320  }
   321  
   322  func regenerateTeamInviteId(c *Context, w http.ResponseWriter, r *http.Request) {
   323  	c.RequireTeamId()
   324  	if c.Err != nil {
   325  		return
   326  	}
   327  
   328  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   329  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   330  		return
   331  	}
   332  
   333  	auditRec := c.MakeAuditRecord("regenerateTeamInviteId", audit.Fail)
   334  	defer c.LogAuditRec(auditRec)
   335  
   336  	patchedTeam, err := c.App.RegenerateTeamInviteId(c.Params.TeamId)
   337  	if err != nil {
   338  		c.Err = err
   339  		return
   340  	}
   341  
   342  	c.App.SanitizeTeam(*c.AppContext.Session(), patchedTeam)
   343  
   344  	auditRec.Success()
   345  	auditRec.AddMeta("team", patchedTeam)
   346  	c.LogAudit("")
   347  
   348  	w.Write([]byte(patchedTeam.ToJson()))
   349  }
   350  
   351  func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   352  	c.RequireTeamId()
   353  	if c.Err != nil {
   354  		return
   355  	}
   356  
   357  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   358  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   359  		return
   360  	}
   361  
   362  	auditRec := c.MakeAuditRecord("deleteTeam", audit.Fail)
   363  	defer c.LogAuditRec(auditRec)
   364  
   365  	if team, err := c.App.GetTeam(c.Params.TeamId); err == nil {
   366  		auditRec.AddMeta("team", team)
   367  	}
   368  
   369  	var err *model.AppError
   370  	if c.Params.Permanent {
   371  		if *c.App.Config().ServiceSettings.EnableAPITeamDeletion {
   372  			err = c.App.PermanentDeleteTeamId(c.Params.TeamId)
   373  		} else {
   374  			err = model.NewAppError("deleteTeam", "api.user.delete_team.not_enabled.app_error", nil, "teamId="+c.Params.TeamId, http.StatusUnauthorized)
   375  		}
   376  	} else {
   377  		err = c.App.SoftDeleteTeam(c.Params.TeamId)
   378  	}
   379  
   380  	if err != nil {
   381  		c.Err = err
   382  		return
   383  	}
   384  
   385  	auditRec.Success()
   386  	ReturnStatusOK(w)
   387  }
   388  
   389  func getTeamsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
   390  	c.RequireUserId()
   391  	if c.Err != nil {
   392  		return
   393  	}
   394  
   395  	if c.AppContext.Session().UserId != c.Params.UserId && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS) {
   396  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS)
   397  		return
   398  	}
   399  
   400  	teams, err := c.App.GetTeamsForUser(c.Params.UserId)
   401  	if err != nil {
   402  		c.Err = err
   403  		return
   404  	}
   405  
   406  	c.App.SanitizeTeams(*c.AppContext.Session(), teams)
   407  	w.Write([]byte(model.TeamListToJson(teams)))
   408  }
   409  
   410  func getTeamsUnreadForUser(c *Context, w http.ResponseWriter, r *http.Request) {
   411  	c.RequireUserId()
   412  	if c.Err != nil {
   413  		return
   414  	}
   415  
   416  	if c.AppContext.Session().UserId != c.Params.UserId && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) {
   417  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   418  		return
   419  	}
   420  
   421  	// optional team id to be excluded from the result
   422  	teamId := r.URL.Query().Get("exclude_team")
   423  
   424  	unreadTeamsList, err := c.App.GetTeamsUnreadForUser(teamId, c.Params.UserId)
   425  	if err != nil {
   426  		c.Err = err
   427  		return
   428  	}
   429  
   430  	w.Write([]byte(model.TeamsUnreadToJson(unreadTeamsList)))
   431  }
   432  
   433  func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
   434  	c.RequireTeamId().RequireUserId()
   435  	if c.Err != nil {
   436  		return
   437  	}
   438  
   439  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
   440  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   441  		return
   442  	}
   443  
   444  	canSee, err := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, c.Params.UserId)
   445  	if err != nil {
   446  		c.Err = err
   447  		return
   448  	}
   449  
   450  	if !canSee {
   451  		c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
   452  		return
   453  	}
   454  
   455  	team, err := c.App.GetTeamMember(c.Params.TeamId, c.Params.UserId)
   456  	if err != nil {
   457  		c.Err = err
   458  		return
   459  	}
   460  
   461  	w.Write([]byte(team.ToJson()))
   462  }
   463  
   464  func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
   465  	c.RequireTeamId()
   466  	if c.Err != nil {
   467  		return
   468  	}
   469  
   470  	sort := r.URL.Query().Get("sort")
   471  	excludeDeletedUsers := r.URL.Query().Get("exclude_deleted_users")
   472  	excludeDeletedUsersBool, _ := strconv.ParseBool(excludeDeletedUsers)
   473  
   474  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
   475  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   476  		return
   477  	}
   478  
   479  	restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId)
   480  	if err != nil {
   481  		c.Err = err
   482  		return
   483  	}
   484  
   485  	teamMembersGetOptions := &model.TeamMembersGetOptions{
   486  		Sort:                sort,
   487  		ExcludeDeletedUsers: excludeDeletedUsersBool,
   488  		ViewRestrictions:    restrictions,
   489  	}
   490  
   491  	members, err := c.App.GetTeamMembers(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage, teamMembersGetOptions)
   492  	if err != nil {
   493  		c.Err = err
   494  		return
   495  	}
   496  
   497  	w.Write([]byte(model.TeamMembersToJson(members)))
   498  }
   499  
   500  func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) {
   501  	c.RequireUserId()
   502  	if c.Err != nil {
   503  		return
   504  	}
   505  
   506  	if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_READ_OTHER_USERS_TEAMS) {
   507  		c.SetPermissionError(model.PERMISSION_READ_OTHER_USERS_TEAMS)
   508  		return
   509  	}
   510  
   511  	canSee, err := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, c.Params.UserId)
   512  	if err != nil {
   513  		c.Err = err
   514  		return
   515  	}
   516  
   517  	if !canSee {
   518  		c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
   519  		return
   520  	}
   521  
   522  	members, err := c.App.GetTeamMembersForUser(c.Params.UserId)
   523  	if err != nil {
   524  		c.Err = err
   525  		return
   526  	}
   527  
   528  	w.Write([]byte(model.TeamMembersToJson(members)))
   529  }
   530  
   531  func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
   532  	c.RequireTeamId()
   533  	if c.Err != nil {
   534  		return
   535  	}
   536  
   537  	userIds := model.ArrayFromJson(r.Body)
   538  
   539  	if len(userIds) == 0 {
   540  		c.SetInvalidParam("user_ids")
   541  		return
   542  	}
   543  
   544  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
   545  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   546  		return
   547  	}
   548  
   549  	restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId)
   550  	if err != nil {
   551  		c.Err = err
   552  		return
   553  	}
   554  
   555  	members, err := c.App.GetTeamMembersByIds(c.Params.TeamId, userIds, restrictions)
   556  	if err != nil {
   557  		c.Err = err
   558  		return
   559  	}
   560  
   561  	w.Write([]byte(model.TeamMembersToJson(members)))
   562  }
   563  
   564  func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
   565  	c.RequireTeamId()
   566  	if c.Err != nil {
   567  		return
   568  	}
   569  
   570  	var err *model.AppError
   571  	member := model.TeamMemberFromJson(r.Body)
   572  	if member == nil {
   573  		c.Err = model.NewAppError("addTeamMember", "api.team.add_team_member.invalid_body.app_error", nil, "Error in model.TeamMemberFromJson()", http.StatusBadRequest)
   574  		return
   575  	}
   576  	if member.TeamId != c.Params.TeamId {
   577  		c.SetInvalidParam("team_id")
   578  		return
   579  	}
   580  
   581  	if !model.IsValidId(member.UserId) {
   582  		c.SetInvalidParam("user_id")
   583  		return
   584  	}
   585  
   586  	auditRec := c.MakeAuditRecord("addTeamMember", audit.Fail)
   587  	defer c.LogAuditRec(auditRec)
   588  	auditRec.AddMeta("member", member)
   589  
   590  	if member.UserId == c.AppContext.Session().UserId {
   591  		var team *model.Team
   592  		team, err = c.App.GetTeam(member.TeamId)
   593  		if err != nil {
   594  			c.Err = err
   595  			return
   596  		}
   597  
   598  		if team.AllowOpenInvite && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_JOIN_PUBLIC_TEAMS) {
   599  			c.SetPermissionError(model.PERMISSION_JOIN_PUBLIC_TEAMS)
   600  			return
   601  		}
   602  		if !team.AllowOpenInvite && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_JOIN_PRIVATE_TEAMS) {
   603  			c.SetPermissionError(model.PERMISSION_JOIN_PRIVATE_TEAMS)
   604  			return
   605  		}
   606  	} else {
   607  		if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), member.TeamId, model.PERMISSION_ADD_USER_TO_TEAM) {
   608  			c.SetPermissionError(model.PERMISSION_ADD_USER_TO_TEAM)
   609  			return
   610  		}
   611  	}
   612  
   613  	team, err := c.App.GetTeam(member.TeamId)
   614  	if err != nil {
   615  		c.Err = err
   616  		return
   617  	}
   618  	auditRec.AddMeta("team", team)
   619  
   620  	if team.IsGroupConstrained() {
   621  		nonMembers, err := c.App.FilterNonGroupTeamMembers([]string{member.UserId}, team)
   622  		if err != nil {
   623  			if v, ok := err.(*model.AppError); ok {
   624  				c.Err = v
   625  			} else {
   626  				c.Err = model.NewAppError("addTeamMember", "api.team.add_members.error", nil, err.Error(), http.StatusBadRequest)
   627  			}
   628  			return
   629  		}
   630  		if len(nonMembers) > 0 {
   631  			c.Err = model.NewAppError("addTeamMember", "api.team.add_members.user_denied", map[string]interface{}{"UserIDs": nonMembers}, "", http.StatusBadRequest)
   632  			return
   633  		}
   634  	}
   635  
   636  	member, err = c.App.AddTeamMember(c.AppContext, member.TeamId, member.UserId)
   637  
   638  	if err != nil {
   639  		c.Err = err
   640  		return
   641  	}
   642  
   643  	auditRec.Success()
   644  
   645  	w.WriteHeader(http.StatusCreated)
   646  	w.Write([]byte(member.ToJson()))
   647  }
   648  
   649  func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) {
   650  	tokenId := r.URL.Query().Get("token")
   651  	inviteId := r.URL.Query().Get("invite_id")
   652  
   653  	var member *model.TeamMember
   654  	var err *model.AppError
   655  
   656  	auditRec := c.MakeAuditRecord("addUserToTeamFromInvite", audit.Fail)
   657  	defer c.LogAuditRec(auditRec)
   658  	auditRec.AddMeta("invite_id", inviteId)
   659  
   660  	if tokenId != "" {
   661  		member, err = c.App.AddTeamMemberByToken(c.AppContext, c.AppContext.Session().UserId, tokenId)
   662  	} else if inviteId != "" {
   663  		if c.AppContext.Session().Props[model.SESSION_PROP_IS_GUEST] == "true" {
   664  			c.Err = model.NewAppError("addUserToTeamFromInvite", "api.team.add_user_to_team_from_invite.guest.app_error", nil, "", http.StatusForbidden)
   665  			return
   666  		}
   667  
   668  		member, err = c.App.AddTeamMemberByInviteId(c.AppContext, inviteId, c.AppContext.Session().UserId)
   669  	} else {
   670  		err = model.NewAppError("addTeamMember", "api.team.add_user_to_team.missing_parameter.app_error", nil, "", http.StatusBadRequest)
   671  	}
   672  
   673  	if err != nil {
   674  		c.Err = err
   675  		return
   676  	}
   677  
   678  	auditRec.Success()
   679  	if member != nil {
   680  		auditRec.AddMeta("member", member)
   681  	}
   682  
   683  	w.WriteHeader(http.StatusCreated)
   684  	w.Write([]byte(member.ToJson()))
   685  }
   686  
   687  func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
   688  	graceful := r.URL.Query().Get("graceful") != ""
   689  
   690  	c.RequireTeamId()
   691  	if c.Err != nil {
   692  		return
   693  	}
   694  
   695  	var err *model.AppError
   696  	members := model.TeamMembersFromJson(r.Body)
   697  
   698  	if len(members) > MaxAddMembersBatch {
   699  		c.SetInvalidParam("too many members in batch")
   700  		return
   701  	}
   702  
   703  	if len(members) == 0 {
   704  		c.SetInvalidParam("no members in batch")
   705  		return
   706  	}
   707  
   708  	auditRec := c.MakeAuditRecord("addTeamMembers", audit.Fail)
   709  	defer c.LogAuditRec(auditRec)
   710  	auditRec.AddMeta("count", len(members))
   711  
   712  	var memberIDs []string
   713  	for _, member := range members {
   714  		memberIDs = append(memberIDs, member.UserId)
   715  	}
   716  	auditRec.AddMeta("user_ids", memberIDs)
   717  
   718  	team, err := c.App.GetTeam(c.Params.TeamId)
   719  	if err != nil {
   720  		c.Err = err
   721  		return
   722  	}
   723  	auditRec.AddMeta("team", team)
   724  
   725  	if team.IsGroupConstrained() {
   726  		nonMembers, err := c.App.FilterNonGroupTeamMembers(memberIDs, team)
   727  		if err != nil {
   728  			if v, ok := err.(*model.AppError); ok {
   729  				c.Err = v
   730  			} else {
   731  				c.Err = model.NewAppError("addTeamMembers", "api.team.add_members.error", nil, err.Error(), http.StatusBadRequest)
   732  			}
   733  			return
   734  		}
   735  		if len(nonMembers) > 0 {
   736  			c.Err = model.NewAppError("addTeamMembers", "api.team.add_members.user_denied", map[string]interface{}{"UserIDs": nonMembers}, "", http.StatusBadRequest)
   737  			return
   738  		}
   739  	}
   740  
   741  	var userIds []string
   742  	for _, member := range members {
   743  		if member.TeamId != c.Params.TeamId {
   744  			c.SetInvalidParam("team_id for member with user_id=" + member.UserId)
   745  			return
   746  		}
   747  
   748  		if !model.IsValidId(member.UserId) {
   749  			c.SetInvalidParam("user_id")
   750  			return
   751  		}
   752  
   753  		userIds = append(userIds, member.UserId)
   754  	}
   755  
   756  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_ADD_USER_TO_TEAM) {
   757  		c.SetPermissionError(model.PERMISSION_ADD_USER_TO_TEAM)
   758  		return
   759  	}
   760  
   761  	membersWithErrors, err := c.App.AddTeamMembers(c.AppContext, c.Params.TeamId, userIds, c.AppContext.Session().UserId, graceful)
   762  
   763  	if membersWithErrors != nil {
   764  		errList := make([]string, 0, len(membersWithErrors))
   765  		for _, m := range membersWithErrors {
   766  			if m.Error != nil {
   767  				errList = append(errList, model.TeamMemberWithErrorToString(m))
   768  			}
   769  		}
   770  		auditRec.AddMeta("errors", errList)
   771  	}
   772  	if err != nil {
   773  		c.Err = err
   774  		return
   775  	}
   776  
   777  	auditRec.Success()
   778  
   779  	w.WriteHeader(http.StatusCreated)
   780  
   781  	if graceful {
   782  		// in 'graceful' mode we allow a different return value, notifying the client which users were not added
   783  		w.Write([]byte(model.TeamMembersWithErrorToJson(membersWithErrors)))
   784  	} else {
   785  		w.Write([]byte(model.TeamMembersToJson(model.TeamMembersWithErrorToTeamMembers(membersWithErrors))))
   786  	}
   787  
   788  }
   789  
   790  func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
   791  	c.RequireTeamId().RequireUserId()
   792  	if c.Err != nil {
   793  		return
   794  	}
   795  
   796  	auditRec := c.MakeAuditRecord("removeTeamMember", audit.Fail)
   797  	defer c.LogAuditRec(auditRec)
   798  
   799  	if c.AppContext.Session().UserId != c.Params.UserId {
   800  		if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_REMOVE_USER_FROM_TEAM) {
   801  			c.SetPermissionError(model.PERMISSION_REMOVE_USER_FROM_TEAM)
   802  			return
   803  		}
   804  	}
   805  
   806  	team, err := c.App.GetTeam(c.Params.TeamId)
   807  	if err != nil {
   808  		c.Err = err
   809  		return
   810  	}
   811  	auditRec.AddMeta("team", team)
   812  
   813  	user, err := c.App.GetUser(c.Params.UserId)
   814  	if err != nil {
   815  		c.Err = err
   816  		return
   817  	}
   818  	auditRec.AddMeta("user", user)
   819  
   820  	if team.IsGroupConstrained() && (c.Params.UserId != c.AppContext.Session().UserId) && !user.IsBot {
   821  		c.Err = model.NewAppError("removeTeamMember", "api.team.remove_member.group_constrained.app_error", nil, "", http.StatusBadRequest)
   822  		return
   823  	}
   824  
   825  	if err := c.App.RemoveUserFromTeam(c.AppContext, c.Params.TeamId, c.Params.UserId, c.AppContext.Session().UserId); err != nil {
   826  		c.Err = err
   827  		return
   828  	}
   829  
   830  	auditRec.Success()
   831  	ReturnStatusOK(w)
   832  }
   833  
   834  func getTeamUnread(c *Context, w http.ResponseWriter, r *http.Request) {
   835  	c.RequireTeamId().RequireUserId()
   836  	if c.Err != nil {
   837  		return
   838  	}
   839  
   840  	if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) {
   841  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   842  		return
   843  	}
   844  
   845  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
   846  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   847  		return
   848  	}
   849  
   850  	unreadTeam, err := c.App.GetTeamUnread(c.Params.TeamId, c.Params.UserId)
   851  	if err != nil {
   852  		c.Err = err
   853  		return
   854  	}
   855  
   856  	w.Write([]byte(unreadTeam.ToJson()))
   857  }
   858  
   859  func getTeamStats(c *Context, w http.ResponseWriter, r *http.Request) {
   860  	c.RequireTeamId()
   861  	if c.Err != nil {
   862  		return
   863  	}
   864  
   865  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
   866  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   867  		return
   868  	}
   869  
   870  	restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId)
   871  	if err != nil {
   872  		c.Err = err
   873  		return
   874  	}
   875  
   876  	stats, err := c.App.GetTeamStats(c.Params.TeamId, restrictions)
   877  	if err != nil {
   878  		c.Err = err
   879  		return
   880  	}
   881  
   882  	w.Write([]byte(stats.ToJson()))
   883  }
   884  
   885  func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
   886  	c.RequireTeamId().RequireUserId()
   887  	if c.Err != nil {
   888  		return
   889  	}
   890  
   891  	props := model.MapFromJson(r.Body)
   892  
   893  	newRoles := props["roles"]
   894  	if !model.IsValidUserRoles(newRoles) {
   895  		c.SetInvalidParam("team_member_roles")
   896  		return
   897  	}
   898  
   899  	auditRec := c.MakeAuditRecord("updateTeamMemberRoles", audit.Fail)
   900  	defer c.LogAuditRec(auditRec)
   901  	auditRec.AddMeta("roles", newRoles)
   902  
   903  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
   904  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
   905  		return
   906  	}
   907  
   908  	teamMember, err := c.App.UpdateTeamMemberRoles(c.Params.TeamId, c.Params.UserId, newRoles)
   909  	if err != nil {
   910  		c.Err = err
   911  		return
   912  	}
   913  
   914  	auditRec.Success()
   915  	auditRec.AddMeta("member", teamMember)
   916  
   917  	ReturnStatusOK(w)
   918  }
   919  
   920  func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Request) {
   921  	c.RequireTeamId().RequireUserId()
   922  	if c.Err != nil {
   923  		return
   924  	}
   925  
   926  	schemeRoles := model.SchemeRolesFromJson(r.Body)
   927  	if schemeRoles == nil {
   928  		c.SetInvalidParam("scheme_roles")
   929  		return
   930  	}
   931  
   932  	auditRec := c.MakeAuditRecord("updateTeamMemberSchemeRoles", audit.Fail)
   933  	defer c.LogAuditRec(auditRec)
   934  	auditRec.AddMeta("roles", schemeRoles)
   935  
   936  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
   937  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
   938  		return
   939  	}
   940  
   941  	teamMember, err := c.App.UpdateTeamMemberSchemeRoles(c.Params.TeamId, c.Params.UserId, schemeRoles.SchemeGuest, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin)
   942  	if err != nil {
   943  		c.Err = err
   944  		return
   945  	}
   946  
   947  	auditRec.Success()
   948  	auditRec.AddMeta("member", teamMember)
   949  
   950  	ReturnStatusOK(w)
   951  }
   952  
   953  func getAllTeams(c *Context, w http.ResponseWriter, r *http.Request) {
   954  	teams := []*model.Team{}
   955  	var err *model.AppError
   956  	var teamsWithCount *model.TeamsWithCount
   957  
   958  	opts := &model.TeamSearch{}
   959  	if c.Params.ExcludePolicyConstrained {
   960  		if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY) {
   961  			c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY)
   962  			return
   963  		}
   964  		opts.ExcludePolicyConstrained = model.NewBool(true)
   965  	}
   966  	if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY) {
   967  		opts.IncludePolicyID = model.NewBool(true)
   968  	}
   969  
   970  	listPrivate := c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PRIVATE_TEAMS)
   971  	listPublic := c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PUBLIC_TEAMS)
   972  	limit := c.Params.PerPage
   973  	offset := limit * c.Params.Page
   974  	if listPrivate && listPublic {
   975  	} else if listPrivate {
   976  		opts.AllowOpenInvite = model.NewBool(false)
   977  	} else if listPublic {
   978  		opts.AllowOpenInvite = model.NewBool(true)
   979  	} else {
   980  		// The user doesn't have permissions to list private as well as public teams.
   981  		c.Err = model.NewAppError("getAllTeams", "api.team.get_all_teams.insufficient_permissions", nil, "", http.StatusForbidden)
   982  		return
   983  	}
   984  
   985  	if c.Params.IncludeTotalCount {
   986  		teamsWithCount, err = c.App.GetAllTeamsPageWithCount(offset, limit, opts)
   987  	} else {
   988  		teams, err = c.App.GetAllTeamsPage(offset, limit, opts)
   989  	}
   990  	if err != nil {
   991  		c.Err = err
   992  		return
   993  	}
   994  
   995  	c.App.SanitizeTeams(*c.AppContext.Session(), teams)
   996  
   997  	var resBody []byte
   998  
   999  	if c.Params.IncludeTotalCount {
  1000  		resBody = model.TeamsWithCountToJson(teamsWithCount)
  1001  	} else {
  1002  		resBody = model.ToJson(teams)
  1003  	}
  1004  
  1005  	w.Write(resBody)
  1006  }
  1007  
  1008  func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) {
  1009  	props := model.TeamSearchFromJson(r.Body)
  1010  	if props == nil {
  1011  		c.SetInvalidParam("team_search")
  1012  		return
  1013  	}
  1014  	// Only system managers may use the ExcludePolicyConstrained field
  1015  	if props.ExcludePolicyConstrained != nil && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY) {
  1016  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY)
  1017  		return
  1018  	}
  1019  	// policy ID may only be used through the /data_retention/policies endpoint
  1020  	props.PolicyID = nil
  1021  	if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY) {
  1022  		props.IncludePolicyID = model.NewBool(true)
  1023  	}
  1024  
  1025  	var teams []*model.Team
  1026  	var totalCount int64
  1027  	var err *model.AppError
  1028  
  1029  	if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PRIVATE_TEAMS) && c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PUBLIC_TEAMS) {
  1030  		teams, totalCount, err = c.App.SearchAllTeams(props)
  1031  	} else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PRIVATE_TEAMS) {
  1032  		if props.Page != nil || props.PerPage != nil {
  1033  			c.Err = model.NewAppError("searchTeams", "api.team.search_teams.pagination_not_implemented.private_team_search", nil, "", http.StatusNotImplemented)
  1034  			return
  1035  		}
  1036  		teams, err = c.App.SearchPrivateTeams(props)
  1037  	} else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PUBLIC_TEAMS) {
  1038  		if props.Page != nil || props.PerPage != nil {
  1039  			c.Err = model.NewAppError("searchTeams", "api.team.search_teams.pagination_not_implemented.public_team_search", nil, "", http.StatusNotImplemented)
  1040  			return
  1041  		}
  1042  		teams, err = c.App.SearchPublicTeams(props)
  1043  	} else {
  1044  		teams = []*model.Team{}
  1045  	}
  1046  
  1047  	if err != nil {
  1048  		c.Err = err
  1049  		return
  1050  	}
  1051  
  1052  	c.App.SanitizeTeams(*c.AppContext.Session(), teams)
  1053  
  1054  	var payload []byte
  1055  	if props.Page != nil && props.PerPage != nil {
  1056  		twc := map[string]interface{}{"teams": teams, "total_count": totalCount}
  1057  		payload = model.ToJson(twc)
  1058  	} else {
  1059  		payload = []byte(model.TeamListToJson(teams))
  1060  	}
  1061  
  1062  	w.Write(payload)
  1063  }
  1064  
  1065  func teamExists(c *Context, w http.ResponseWriter, r *http.Request) {
  1066  	c.RequireTeamName()
  1067  	if c.Err != nil {
  1068  		return
  1069  	}
  1070  
  1071  	team, err := c.App.GetTeamByName(c.Params.TeamName)
  1072  	if err != nil && err.StatusCode != http.StatusNotFound {
  1073  		c.Err = err
  1074  		return
  1075  	}
  1076  
  1077  	exists := false
  1078  
  1079  	if team != nil {
  1080  		var teamMember *model.TeamMember
  1081  		teamMember, err = c.App.GetTeamMember(team.Id, c.AppContext.Session().UserId)
  1082  		if err != nil && err.StatusCode != http.StatusNotFound {
  1083  			c.Err = err
  1084  			return
  1085  		}
  1086  
  1087  		// Verify that the user can see the team (be a member or have the permission to list the team)
  1088  		if (teamMember != nil && teamMember.DeleteAt == 0) ||
  1089  			(team.AllowOpenInvite && c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PUBLIC_TEAMS)) ||
  1090  			(!team.AllowOpenInvite && c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_LIST_PRIVATE_TEAMS)) {
  1091  			exists = true
  1092  		}
  1093  	}
  1094  
  1095  	resp := map[string]bool{"exists": exists}
  1096  	w.Write([]byte(model.MapBoolToJson(resp)))
  1097  }
  1098  
  1099  func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
  1100  	if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud {
  1101  		c.Err = model.NewAppError("importTeam", "api.restricted_system_admin", nil, "", http.StatusForbidden)
  1102  		return
  1103  	}
  1104  
  1105  	c.RequireTeamId()
  1106  	if c.Err != nil {
  1107  		return
  1108  	}
  1109  
  1110  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_IMPORT_TEAM) {
  1111  		c.SetPermissionError(model.PERMISSION_IMPORT_TEAM)
  1112  		return
  1113  	}
  1114  
  1115  	if err := r.ParseMultipartForm(MaximumBulkImportSize); err != nil {
  1116  		c.Err = model.NewAppError("importTeam", "api.team.import_team.parse.app_error", nil, err.Error(), http.StatusInternalServerError)
  1117  		return
  1118  	}
  1119  
  1120  	importFromArray, ok := r.MultipartForm.Value["importFrom"]
  1121  	if !ok || len(importFromArray) < 1 {
  1122  		c.Err = model.NewAppError("importTeam", "api.team.import_team.no_import_from.app_error", nil, "", http.StatusBadRequest)
  1123  		return
  1124  	}
  1125  	importFrom := importFromArray[0]
  1126  
  1127  	fileSizeStr, ok := r.MultipartForm.Value["filesize"]
  1128  	if !ok || len(fileSizeStr) < 1 {
  1129  		c.Err = model.NewAppError("importTeam", "api.team.import_team.unavailable.app_error", nil, "", http.StatusBadRequest)
  1130  		return
  1131  	}
  1132  
  1133  	fileSize, err := strconv.ParseInt(fileSizeStr[0], 10, 64)
  1134  	if err != nil {
  1135  		c.Err = model.NewAppError("importTeam", "api.team.import_team.integer.app_error", nil, "", http.StatusBadRequest)
  1136  		return
  1137  	}
  1138  
  1139  	fileInfoArray, ok := r.MultipartForm.File["file"]
  1140  	if !ok {
  1141  		c.Err = model.NewAppError("importTeam", "api.team.import_team.no_file.app_error", nil, "", http.StatusBadRequest)
  1142  		return
  1143  	}
  1144  
  1145  	if len(fileInfoArray) <= 0 {
  1146  		c.Err = model.NewAppError("importTeam", "api.team.import_team.array.app_error", nil, "", http.StatusBadRequest)
  1147  		return
  1148  	}
  1149  
  1150  	auditRec := c.MakeAuditRecord("importTeam", audit.Fail)
  1151  	defer c.LogAuditRec(auditRec)
  1152  	auditRec.AddMeta("team_id", c.Params.TeamId)
  1153  
  1154  	fileInfo := fileInfoArray[0]
  1155  
  1156  	fileData, err := fileInfo.Open()
  1157  	if err != nil {
  1158  		c.Err = model.NewAppError("importTeam", "api.team.import_team.open.app_error", nil, err.Error(), http.StatusBadRequest)
  1159  		return
  1160  	}
  1161  	defer fileData.Close()
  1162  	auditRec.AddMeta("filename", fileInfo.Filename)
  1163  	auditRec.AddMeta("filesize", fileSize)
  1164  	auditRec.AddMeta("from", importFrom)
  1165  
  1166  	var log *bytes.Buffer
  1167  	data := map[string]string{}
  1168  	switch importFrom {
  1169  	case "slack":
  1170  		var err *model.AppError
  1171  		if err, log = c.App.SlackImport(c.AppContext, fileData, fileSize, c.Params.TeamId); err != nil {
  1172  			c.Err = err
  1173  			c.Err.StatusCode = http.StatusBadRequest
  1174  		}
  1175  		data["results"] = base64.StdEncoding.EncodeToString(log.Bytes())
  1176  	default:
  1177  		c.Err = model.NewAppError("importTeam", "api.team.import_team.unknown_import_from.app_error", nil, "", http.StatusBadRequest)
  1178  	}
  1179  
  1180  	if c.Err != nil {
  1181  		w.WriteHeader(c.Err.StatusCode)
  1182  		return
  1183  	}
  1184  	auditRec.Success()
  1185  	w.Write([]byte(model.MapToJson(data)))
  1186  }
  1187  
  1188  func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
  1189  	graceful := r.URL.Query().Get("graceful") != ""
  1190  
  1191  	c.RequireTeamId()
  1192  	if c.Err != nil {
  1193  		return
  1194  	}
  1195  
  1196  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_INVITE_USER) {
  1197  		c.SetPermissionError(model.PERMISSION_INVITE_USER)
  1198  		return
  1199  	}
  1200  
  1201  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_ADD_USER_TO_TEAM) {
  1202  		c.SetPermissionError(model.PERMISSION_INVITE_USER)
  1203  		return
  1204  	}
  1205  
  1206  	emailList := model.ArrayFromJson(r.Body)
  1207  
  1208  	for i := range emailList {
  1209  		emailList[i] = strings.ToLower(emailList[i])
  1210  	}
  1211  
  1212  	if len(emailList) == 0 {
  1213  		c.SetInvalidParam("user_email")
  1214  		return
  1215  	}
  1216  
  1217  	auditRec := c.MakeAuditRecord("inviteUsersToTeam", audit.Fail)
  1218  	defer c.LogAuditRec(auditRec)
  1219  	auditRec.AddMeta("team_id", c.Params.TeamId)
  1220  	auditRec.AddMeta("count", len(emailList))
  1221  	auditRec.AddMeta("emails", emailList)
  1222  
  1223  	if graceful {
  1224  		cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
  1225  		var invitesOverLimit []*model.EmailInviteWithError
  1226  		if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && cloudUserLimit > 0 {
  1227  			subscription, subErr := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId)
  1228  			if subErr != nil {
  1229  				c.Err = model.NewAppError(
  1230  					"Api4.inviteUsersToTeam",
  1231  					"api.team.cloud.subscription.error",
  1232  					nil,
  1233  					subErr.Error(),
  1234  					http.StatusInternalServerError)
  1235  				return
  1236  			}
  1237  			if subscription == nil || subscription.IsPaidTier != "true" {
  1238  				emailList, invitesOverLimit, _ = c.App.GetErrorListForEmailsOverLimit(emailList, cloudUserLimit)
  1239  			}
  1240  		}
  1241  
  1242  		// we get the emailList after it has finished checks like the emails over the list
  1243  
  1244  		scheduledAt := model.GetMillis()
  1245  		jobData := map[string]string{
  1246  			"emailList":   model.ArrayToJson(emailList),
  1247  			"teamID":      c.Params.TeamId,
  1248  			"senderID":    c.AppContext.Session().UserId,
  1249  			"scheduledAt": strconv.FormatInt(scheduledAt, 10),
  1250  		}
  1251  
  1252  		// we then manually schedule the job
  1253  		_, e := c.App.Srv().Jobs.CreateJob(model.JOB_TYPE_RESEND_INVITATION_EMAIL, jobData)
  1254  		if e != nil {
  1255  			c.Err = model.NewAppError("Api4.inviteUsersToTeam", e.Id, nil, e.Error(), e.StatusCode)
  1256  			return
  1257  		}
  1258  
  1259  		var invitesWithError []*model.EmailInviteWithError
  1260  		var err *model.AppError
  1261  		if emailList != nil {
  1262  			invitesWithError, err = c.App.InviteNewUsersToTeamGracefully(emailList, c.Params.TeamId, c.AppContext.Session().UserId)
  1263  		}
  1264  
  1265  		if len(invitesOverLimit) > 0 {
  1266  			invitesWithError = append(invitesWithError, invitesOverLimit...)
  1267  		}
  1268  
  1269  		if invitesWithError != nil {
  1270  			errList := make([]string, 0, len(invitesWithError))
  1271  			for _, inv := range invitesWithError {
  1272  				if inv.Error != nil {
  1273  					errList = append(errList, model.EmailInviteWithErrorToString(inv))
  1274  				}
  1275  			}
  1276  			auditRec.AddMeta("errors", errList)
  1277  		}
  1278  		if err != nil {
  1279  			c.Err = err
  1280  			return
  1281  		}
  1282  		// in graceful mode we return both the successful ones and the failed ones
  1283  		w.Write([]byte(model.EmailInviteWithErrorToJson(invitesWithError)))
  1284  	} else {
  1285  		err := c.App.InviteNewUsersToTeam(emailList, c.Params.TeamId, c.AppContext.Session().UserId)
  1286  		if err != nil {
  1287  			c.Err = err
  1288  			return
  1289  		}
  1290  		ReturnStatusOK(w)
  1291  	}
  1292  	auditRec.Success()
  1293  }
  1294  
  1295  func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) {
  1296  	graceful := r.URL.Query().Get("graceful") != ""
  1297  	if c.App.Srv().License() == nil {
  1298  		c.Err = model.NewAppError("Api4.InviteGuestsToChannels", "api.team.invate_guests_to_channels.license.error", nil, "", http.StatusNotImplemented)
  1299  		return
  1300  	}
  1301  
  1302  	if !*c.App.Config().GuestAccountsSettings.Enable {
  1303  		c.Err = model.NewAppError("Api4.InviteGuestsToChannels", "api.team.invate_guests_to_channels.disabled.error", nil, "", http.StatusNotImplemented)
  1304  		return
  1305  	}
  1306  
  1307  	c.RequireTeamId()
  1308  	if c.Err != nil {
  1309  		return
  1310  	}
  1311  
  1312  	auditRec := c.MakeAuditRecord("inviteGuestsToChannels", audit.Fail)
  1313  	defer c.LogAuditRec(auditRec)
  1314  	auditRec.AddMeta("team_id", c.Params.TeamId)
  1315  
  1316  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_INVITE_GUEST) {
  1317  		c.SetPermissionError(model.PERMISSION_INVITE_GUEST)
  1318  		return
  1319  	}
  1320  
  1321  	guestsInvite := model.GuestsInviteFromJson(r.Body)
  1322  	if guestsInvite == nil {
  1323  		c.Err = model.NewAppError("Api4.inviteGuestsToChannels", "api.team.invite_guests_to_channels.invalid_body.app_error", nil, "", http.StatusBadRequest)
  1324  		return
  1325  	}
  1326  
  1327  	for i, email := range guestsInvite.Emails {
  1328  		guestsInvite.Emails[i] = strings.ToLower(email)
  1329  	}
  1330  	if err := guestsInvite.IsValid(); err != nil {
  1331  		c.Err = err
  1332  		return
  1333  	}
  1334  	auditRec.AddMeta("email_count", len(guestsInvite.Emails))
  1335  	auditRec.AddMeta("emails", guestsInvite.Emails)
  1336  	auditRec.AddMeta("channel_count", len(guestsInvite.Channels))
  1337  	auditRec.AddMeta("channels", guestsInvite.Channels)
  1338  
  1339  	if graceful {
  1340  		cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
  1341  		var invitesOverLimit []*model.EmailInviteWithError
  1342  		if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && cloudUserLimit > 0 && c.IsSystemAdmin() {
  1343  			subscription, err := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId)
  1344  			if err != nil {
  1345  				c.Err = model.NewAppError(
  1346  					"Api4.inviteGuestsToChannel",
  1347  					"api.team.cloud.subscription.error",
  1348  					nil,
  1349  					err.Error(),
  1350  					http.StatusInternalServerError)
  1351  				return
  1352  			}
  1353  			if subscription == nil || subscription.IsPaidTier != "true" {
  1354  				guestsInvite.Emails, invitesOverLimit, _ = c.App.GetErrorListForEmailsOverLimit(guestsInvite.Emails, cloudUserLimit)
  1355  			}
  1356  		}
  1357  
  1358  		var invitesWithError []*model.EmailInviteWithError
  1359  		var err *model.AppError
  1360  
  1361  		if guestsInvite.Emails != nil {
  1362  			invitesWithError, err = c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, guestsInvite, c.AppContext.Session().UserId)
  1363  		}
  1364  
  1365  		if len(invitesOverLimit) > 0 {
  1366  			invitesWithError = append(invitesWithError, invitesOverLimit...)
  1367  		}
  1368  
  1369  		if err != nil {
  1370  			errList := make([]string, 0, len(invitesWithError))
  1371  			for _, inv := range invitesWithError {
  1372  				errList = append(errList, model.EmailInviteWithErrorToString(inv))
  1373  			}
  1374  			auditRec.AddMeta("errors", errList)
  1375  			c.Err = err
  1376  			return
  1377  		}
  1378  		// in graceful mode we return both the successful ones and the failed ones
  1379  		w.Write([]byte(model.EmailInviteWithErrorToJson(invitesWithError)))
  1380  	} else {
  1381  		err := c.App.InviteGuestsToChannels(c.Params.TeamId, guestsInvite, c.AppContext.Session().UserId)
  1382  		if err != nil {
  1383  			c.Err = err
  1384  			return
  1385  		}
  1386  		ReturnStatusOK(w)
  1387  	}
  1388  	auditRec.Success()
  1389  }
  1390  
  1391  func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
  1392  	c.RequireInviteId()
  1393  	if c.Err != nil {
  1394  		return
  1395  	}
  1396  
  1397  	team, err := c.App.GetTeamByInviteId(c.Params.InviteId)
  1398  	if err != nil {
  1399  		c.Err = err
  1400  		return
  1401  	}
  1402  
  1403  	if team.Type != model.TEAM_OPEN {
  1404  		c.Err = model.NewAppError("getInviteInfo", "api.team.get_invite_info.not_open_team", nil, "id="+c.Params.InviteId, http.StatusForbidden)
  1405  		return
  1406  	}
  1407  
  1408  	result := map[string]string{}
  1409  	result["display_name"] = team.DisplayName
  1410  	result["description"] = team.Description
  1411  	result["name"] = team.Name
  1412  	result["id"] = team.Id
  1413  	w.Write([]byte(model.MapToJson(result)))
  1414  }
  1415  
  1416  func invalidateAllEmailInvites(c *Context, w http.ResponseWriter, r *http.Request) {
  1417  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_INVALIDATE_EMAIL_INVITE) {
  1418  		c.SetPermissionError(model.PERMISSION_INVALIDATE_EMAIL_INVITE)
  1419  		return
  1420  	}
  1421  
  1422  	auditRec := c.MakeAuditRecord("invalidateAllEmailInvites", audit.Fail)
  1423  	defer c.LogAuditRec(auditRec)
  1424  
  1425  	if err := c.App.InvalidateAllEmailInvites(); err != nil {
  1426  		c.Err = err
  1427  		return
  1428  	}
  1429  
  1430  	auditRec.Success()
  1431  	ReturnStatusOK(w)
  1432  }
  1433  
  1434  func getTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
  1435  	c.RequireTeamId()
  1436  	if c.Err != nil {
  1437  		return
  1438  	}
  1439  
  1440  	team, err := c.App.GetTeam(c.Params.TeamId)
  1441  
  1442  	if err != nil {
  1443  		c.Err = err
  1444  		return
  1445  	}
  1446  
  1447  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) &&
  1448  		(team.Type != model.TEAM_OPEN || !team.AllowOpenInvite) {
  1449  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
  1450  		return
  1451  	}
  1452  
  1453  	etag := strconv.FormatInt(team.LastTeamIconUpdate, 10)
  1454  
  1455  	if c.HandleEtag(etag, "Get Team Icon", w, r) {
  1456  		return
  1457  	}
  1458  
  1459  	img, err := c.App.GetTeamIcon(team)
  1460  	if err != nil {
  1461  		c.Err = err
  1462  		return
  1463  	}
  1464  
  1465  	w.Header().Set("Content-Type", "image/png")
  1466  	w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%v, private", 24*60*60)) // 24 hrs
  1467  	w.Header().Set(model.HEADER_ETAG_SERVER, etag)
  1468  	w.Write(img)
  1469  }
  1470  
  1471  func setTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
  1472  	defer io.Copy(ioutil.Discard, r.Body)
  1473  
  1474  	c.RequireTeamId()
  1475  	if c.Err != nil {
  1476  		return
  1477  	}
  1478  
  1479  	auditRec := c.MakeAuditRecord("setTeamIcon", audit.Fail)
  1480  	defer c.LogAuditRec(auditRec)
  1481  	auditRec.AddMeta("team_id", c.Params.TeamId)
  1482  
  1483  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
  1484  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
  1485  		return
  1486  	}
  1487  
  1488  	if r.ContentLength > *c.App.Config().FileSettings.MaxFileSize {
  1489  		c.Err = model.NewAppError("setTeamIcon", "api.team.set_team_icon.too_large.app_error", nil, "", http.StatusBadRequest)
  1490  		return
  1491  	}
  1492  
  1493  	if err := r.ParseMultipartForm(*c.App.Config().FileSettings.MaxFileSize); err != nil {
  1494  		c.Err = model.NewAppError("setTeamIcon", "api.team.set_team_icon.parse.app_error", nil, err.Error(), http.StatusBadRequest)
  1495  		return
  1496  	}
  1497  
  1498  	m := r.MultipartForm
  1499  
  1500  	imageArray, ok := m.File["image"]
  1501  	if !ok {
  1502  		c.Err = model.NewAppError("setTeamIcon", "api.team.set_team_icon.no_file.app_error", nil, "", http.StatusBadRequest)
  1503  		return
  1504  	}
  1505  
  1506  	if len(imageArray) <= 0 {
  1507  		c.Err = model.NewAppError("setTeamIcon", "api.team.set_team_icon.array.app_error", nil, "", http.StatusBadRequest)
  1508  		return
  1509  	}
  1510  
  1511  	imageData := imageArray[0]
  1512  
  1513  	if err := c.App.SetTeamIcon(c.Params.TeamId, imageData); err != nil {
  1514  		c.Err = err
  1515  		return
  1516  	}
  1517  
  1518  	auditRec.Success()
  1519  	c.LogAudit("")
  1520  
  1521  	ReturnStatusOK(w)
  1522  }
  1523  
  1524  func removeTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
  1525  	c.RequireTeamId()
  1526  	if c.Err != nil {
  1527  		return
  1528  	}
  1529  
  1530  	auditRec := c.MakeAuditRecord("removeTeamIcon", audit.Fail)
  1531  	defer c.LogAuditRec(auditRec)
  1532  	auditRec.AddMeta("team_id", c.Params.TeamId)
  1533  
  1534  	if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
  1535  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
  1536  		return
  1537  	}
  1538  
  1539  	if err := c.App.RemoveTeamIcon(c.Params.TeamId); err != nil {
  1540  		c.Err = err
  1541  		return
  1542  	}
  1543  
  1544  	auditRec.Success()
  1545  	c.LogAudit("")
  1546  
  1547  	ReturnStatusOK(w)
  1548  }
  1549  
  1550  func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
  1551  	c.RequireTeamId()
  1552  	if c.Err != nil {
  1553  		return
  1554  	}
  1555  
  1556  	schemeID := model.SchemeIDFromJson(r.Body)
  1557  	if schemeID == nil || (!model.IsValidId(*schemeID) && *schemeID != "") {
  1558  		c.SetInvalidParam("scheme_id")
  1559  		return
  1560  	}
  1561  
  1562  	auditRec := c.MakeAuditRecord("updateTeamScheme", audit.Fail)
  1563  	defer c.LogAuditRec(auditRec)
  1564  
  1565  	if c.App.Srv().License() == nil {
  1566  		c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.license.error", nil, "", http.StatusNotImplemented)
  1567  		return
  1568  	}
  1569  
  1570  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS) {
  1571  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS)
  1572  		return
  1573  	}
  1574  
  1575  	if *schemeID != "" {
  1576  		scheme, err := c.App.GetScheme(*schemeID)
  1577  		if err != nil {
  1578  			c.Err = err
  1579  			return
  1580  		}
  1581  		auditRec.AddMeta("scheme", scheme)
  1582  
  1583  		if scheme.Scope != model.SCHEME_SCOPE_TEAM {
  1584  			c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.scheme_scope.error", nil, "", http.StatusBadRequest)
  1585  			return
  1586  		}
  1587  	}
  1588  
  1589  	team, err := c.App.GetTeam(c.Params.TeamId)
  1590  	if err != nil {
  1591  		c.Err = err
  1592  		return
  1593  	}
  1594  	auditRec.AddMeta("team", team)
  1595  
  1596  	team.SchemeId = schemeID
  1597  
  1598  	_, err = c.App.UpdateTeamScheme(team)
  1599  	if err != nil {
  1600  		c.Err = err
  1601  		return
  1602  	}
  1603  
  1604  	auditRec.Success()
  1605  	ReturnStatusOK(w)
  1606  }
  1607  
  1608  func teamMembersMinusGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) {
  1609  	c.RequireTeamId()
  1610  	if c.Err != nil {
  1611  		return
  1612  	}
  1613  
  1614  	groupIDsParam := groupIDsQueryParamRegex.ReplaceAllString(c.Params.GroupIDs, "")
  1615  
  1616  	if len(groupIDsParam) < 26 {
  1617  		c.SetInvalidParam("group_ids")
  1618  		return
  1619  	}
  1620  
  1621  	groupIDs := []string{}
  1622  	for _, gid := range strings.Split(c.Params.GroupIDs, ",") {
  1623  		if !model.IsValidId(gid) {
  1624  			c.SetInvalidParam("group_ids")
  1625  			return
  1626  		}
  1627  		groupIDs = append(groupIDs, gid)
  1628  	}
  1629  
  1630  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS) {
  1631  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS)
  1632  		return
  1633  	}
  1634  
  1635  	users, totalCount, err := c.App.TeamMembersMinusGroupMembers(
  1636  		c.Params.TeamId,
  1637  		groupIDs,
  1638  		c.Params.Page,
  1639  		c.Params.PerPage,
  1640  	)
  1641  	if err != nil {
  1642  		c.Err = err
  1643  		return
  1644  	}
  1645  
  1646  	b, marshalErr := json.Marshal(&model.UsersWithGroupsAndCount{
  1647  		Users: users,
  1648  		Count: totalCount,
  1649  	})
  1650  	if marshalErr != nil {
  1651  		c.Err = model.NewAppError("Api4.teamMembersMinusGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
  1652  		return
  1653  	}
  1654  
  1655  	w.Write(b)
  1656  }