github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/group.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  	"encoding/json"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"github.com/masterhung0112/hk_server/v5/audit"
    15  	"github.com/masterhung0112/hk_server/v5/model"
    16  )
    17  
    18  func (api *API) InitGroup() {
    19  	// GET /api/v4/groups
    20  	api.BaseRoutes.Groups.Handle("", api.ApiSessionRequired(getGroups)).Methods("GET")
    21  
    22  	// GET /api/v4/groups/:group_id
    23  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}",
    24  		api.ApiSessionRequired(getGroup)).Methods("GET")
    25  
    26  	// PUT /api/v4/groups/:group_id/patch
    27  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/patch",
    28  		api.ApiSessionRequired(patchGroup)).Methods("PUT")
    29  
    30  	// POST /api/v4/groups/:group_id/teams/:team_id/link
    31  	// POST /api/v4/groups/:group_id/channels/:channel_id/link
    32  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/link",
    33  		api.ApiSessionRequired(linkGroupSyncable)).Methods("POST")
    34  
    35  	// DELETE /api/v4/groups/:group_id/teams/:team_id/link
    36  	// DELETE /api/v4/groups/:group_id/channels/:channel_id/link
    37  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/link",
    38  		api.ApiSessionRequired(unlinkGroupSyncable)).Methods("DELETE")
    39  
    40  	// GET /api/v4/groups/:group_id/teams/:team_id
    41  	// GET /api/v4/groups/:group_id/channels/:channel_id
    42  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}",
    43  		api.ApiSessionRequired(getGroupSyncable)).Methods("GET")
    44  
    45  	// GET /api/v4/groups/:group_id/teams
    46  	// GET /api/v4/groups/:group_id/channels
    47  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}",
    48  		api.ApiSessionRequired(getGroupSyncables)).Methods("GET")
    49  
    50  	// PUT /api/v4/groups/:group_id/teams/:team_id/patch
    51  	// PUT /api/v4/groups/:group_id/channels/:channel_id/patch
    52  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/patch",
    53  		api.ApiSessionRequired(patchGroupSyncable)).Methods("PUT")
    54  
    55  	// GET /api/v4/groups/:group_id/stats
    56  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/stats",
    57  		api.ApiSessionRequired(getGroupStats)).Methods("GET")
    58  
    59  	// GET /api/v4/groups/:group_id/members?page=0&per_page=100
    60  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members",
    61  		api.ApiSessionRequired(getGroupMembers)).Methods("GET")
    62  
    63  	// GET /api/v4/users/:user_id/groups?page=0&per_page=100
    64  	api.BaseRoutes.Users.Handle("/{user_id:[A-Za-z0-9]+}/groups",
    65  		api.ApiSessionRequired(getGroupsByUserId)).Methods("GET")
    66  
    67  	// GET /api/v4/channels/:channel_id/groups?page=0&per_page=100
    68  	api.BaseRoutes.Channels.Handle("/{channel_id:[A-Za-z0-9]+}/groups",
    69  		api.ApiSessionRequired(getGroupsByChannel)).Methods("GET")
    70  
    71  	// GET /api/v4/teams/:team_id/groups?page=0&per_page=100
    72  	api.BaseRoutes.Teams.Handle("/{team_id:[A-Za-z0-9]+}/groups",
    73  		api.ApiSessionRequired(getGroupsByTeam)).Methods("GET")
    74  
    75  	// GET /api/v4/teams/:team_id/groups_by_channels?page=0&per_page=100
    76  	api.BaseRoutes.Teams.Handle("/{team_id:[A-Za-z0-9]+}/groups_by_channels",
    77  		api.ApiSessionRequired(getGroupsAssociatedToChannelsByTeam)).Methods("GET")
    78  }
    79  
    80  func getGroup(c *Context, w http.ResponseWriter, r *http.Request) {
    81  	c.RequireGroupId()
    82  	if c.Err != nil {
    83  		return
    84  	}
    85  
    86  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
    87  		c.Err = model.NewAppError("Api4.getGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
    88  		return
    89  	}
    90  
    91  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS) {
    92  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS)
    93  		return
    94  	}
    95  
    96  	group, err := c.App.GetGroup(c.Params.GroupId)
    97  	if err != nil {
    98  		c.Err = err
    99  		return
   100  	}
   101  
   102  	b, marshalErr := json.Marshal(group)
   103  	if marshalErr != nil {
   104  		c.Err = model.NewAppError("Api4.getGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   105  		return
   106  	}
   107  
   108  	w.Write(b)
   109  }
   110  
   111  func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) {
   112  	c.RequireGroupId()
   113  	if c.Err != nil {
   114  		return
   115  	}
   116  
   117  	groupPatch := model.GroupPatchFromJson(r.Body)
   118  	if groupPatch == nil {
   119  		c.SetInvalidParam("group")
   120  		return
   121  	}
   122  
   123  	auditRec := c.MakeAuditRecord("patchGroup", audit.Fail)
   124  	defer c.LogAuditRec(auditRec)
   125  
   126  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   127  		c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   128  		return
   129  	}
   130  
   131  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_GROUPS) {
   132  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_GROUPS)
   133  		return
   134  	}
   135  
   136  	group, err := c.App.GetGroup(c.Params.GroupId)
   137  	if err != nil {
   138  		c.Err = err
   139  		return
   140  	}
   141  	auditRec.AddMeta("group", group)
   142  
   143  	if groupPatch.AllowReference != nil && *groupPatch.AllowReference {
   144  		if groupPatch.Name == nil {
   145  			tmp := strings.ReplaceAll(strings.ToLower(group.DisplayName), " ", "-")
   146  			groupPatch.Name = &tmp
   147  		} else {
   148  			if *groupPatch.Name == model.USER_NOTIFY_ALL || *groupPatch.Name == model.CHANNEL_MENTIONS_NOTIFY_PROP || *groupPatch.Name == model.USER_NOTIFY_HERE {
   149  				c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_reserved_name_error", nil, "", http.StatusNotImplemented)
   150  				return
   151  			}
   152  			//check if a user already has this group name
   153  			user, _ := c.App.GetUserByUsername(*groupPatch.Name)
   154  			if user != nil {
   155  				c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_user_name_error", nil, "", http.StatusNotImplemented)
   156  				return
   157  			}
   158  			//check if a mentionable group already has this name
   159  			searchOpts := model.GroupSearchOpts{
   160  				FilterAllowReference: true,
   161  			}
   162  			existingGroup, _ := c.App.GetGroupByName(*groupPatch.Name, searchOpts)
   163  			if existingGroup != nil {
   164  				c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_group_name_error", nil, "", http.StatusNotImplemented)
   165  				return
   166  			}
   167  		}
   168  	}
   169  
   170  	group.Patch(groupPatch)
   171  
   172  	group, err = c.App.UpdateGroup(group)
   173  	if err != nil {
   174  		c.Err = err
   175  		return
   176  	}
   177  	auditRec.AddMeta("patch", group)
   178  
   179  	b, marshalErr := json.Marshal(group)
   180  	if marshalErr != nil {
   181  		c.Err = model.NewAppError("Api4.patchGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   182  		return
   183  	}
   184  
   185  	auditRec.Success()
   186  	w.Write(b)
   187  }
   188  
   189  func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   190  	c.RequireGroupId()
   191  	if c.Err != nil {
   192  		return
   193  	}
   194  
   195  	c.RequireSyncableId()
   196  	if c.Err != nil {
   197  		return
   198  	}
   199  	syncableID := c.Params.SyncableId
   200  
   201  	c.RequireSyncableType()
   202  	if c.Err != nil {
   203  		return
   204  	}
   205  	syncableType := c.Params.SyncableType
   206  
   207  	body, err := ioutil.ReadAll(r.Body)
   208  	if err != nil {
   209  		c.Err = model.NewAppError("Api4.createGroupSyncable", "api.io_error", nil, err.Error(), http.StatusBadRequest)
   210  		return
   211  	}
   212  
   213  	auditRec := c.MakeAuditRecord("linkGroupSyncable", audit.Fail)
   214  	defer c.LogAuditRec(auditRec)
   215  	auditRec.AddMeta("group_id", c.Params.GroupId)
   216  	auditRec.AddMeta("syncable_id", syncableID)
   217  	auditRec.AddMeta("syncable_type", syncableType)
   218  
   219  	var patch *model.GroupSyncablePatch
   220  	err = json.Unmarshal(body, &patch)
   221  	if err != nil || patch == nil {
   222  		c.SetInvalidParam(fmt.Sprintf("Group%s", syncableType.String()))
   223  		return
   224  	}
   225  
   226  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   227  		c.Err = model.NewAppError("Api4.createGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   228  		return
   229  	}
   230  
   231  	appErr := verifyLinkUnlinkPermission(c, syncableType, syncableID)
   232  	if appErr != nil {
   233  		c.Err = appErr
   234  		return
   235  	}
   236  
   237  	groupSyncable := &model.GroupSyncable{
   238  		GroupId:    c.Params.GroupId,
   239  		SyncableId: syncableID,
   240  		Type:       syncableType,
   241  	}
   242  	groupSyncable.Patch(patch)
   243  	groupSyncable, appErr = c.App.UpsertGroupSyncable(groupSyncable)
   244  	if appErr != nil {
   245  		c.Err = appErr
   246  		return
   247  	}
   248  
   249  	c.App.Srv().Go(func() {
   250  		c.App.SyncRolesAndMembership(c.AppContext, syncableID, syncableType, false)
   251  	})
   252  
   253  	w.WriteHeader(http.StatusCreated)
   254  
   255  	b, marshalErr := json.Marshal(groupSyncable)
   256  	if marshalErr != nil {
   257  		c.Err = model.NewAppError("Api4.createGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   258  		return
   259  	}
   260  	auditRec.Success()
   261  	w.Write(b)
   262  }
   263  
   264  func getGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   265  	c.RequireGroupId()
   266  	if c.Err != nil {
   267  		return
   268  	}
   269  
   270  	c.RequireSyncableId()
   271  	if c.Err != nil {
   272  		return
   273  	}
   274  	syncableID := c.Params.SyncableId
   275  
   276  	c.RequireSyncableType()
   277  	if c.Err != nil {
   278  		return
   279  	}
   280  	syncableType := c.Params.SyncableType
   281  
   282  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   283  		c.Err = model.NewAppError("Api4.getGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   284  		return
   285  	}
   286  
   287  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) {
   288  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   289  		return
   290  	}
   291  
   292  	groupSyncable, err := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   293  	if err != nil {
   294  		c.Err = err
   295  		return
   296  	}
   297  
   298  	b, marshalErr := json.Marshal(groupSyncable)
   299  	if marshalErr != nil {
   300  		c.Err = model.NewAppError("Api4.getGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   301  		return
   302  	}
   303  
   304  	w.Write(b)
   305  }
   306  
   307  func getGroupSyncables(c *Context, w http.ResponseWriter, r *http.Request) {
   308  	c.RequireGroupId()
   309  	if c.Err != nil {
   310  		return
   311  	}
   312  
   313  	c.RequireSyncableType()
   314  	if c.Err != nil {
   315  		return
   316  	}
   317  	syncableType := c.Params.SyncableType
   318  
   319  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   320  		c.Err = model.NewAppError("Api4.getGroupSyncables", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   321  		return
   322  	}
   323  
   324  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS) {
   325  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS)
   326  		return
   327  	}
   328  
   329  	groupSyncables, err := c.App.GetGroupSyncables(c.Params.GroupId, syncableType)
   330  	if err != nil {
   331  		c.Err = err
   332  		return
   333  	}
   334  
   335  	b, marshalErr := json.Marshal(groupSyncables)
   336  	if marshalErr != nil {
   337  		c.Err = model.NewAppError("Api4.getGroupSyncables", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   338  		return
   339  	}
   340  
   341  	w.Write(b)
   342  }
   343  
   344  func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   345  	c.RequireGroupId()
   346  	if c.Err != nil {
   347  		return
   348  	}
   349  
   350  	c.RequireSyncableId()
   351  	if c.Err != nil {
   352  		return
   353  	}
   354  	syncableID := c.Params.SyncableId
   355  
   356  	c.RequireSyncableType()
   357  	if c.Err != nil {
   358  		return
   359  	}
   360  	syncableType := c.Params.SyncableType
   361  
   362  	body, err := ioutil.ReadAll(r.Body)
   363  	if err != nil {
   364  		c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.io_error", nil, err.Error(), http.StatusBadRequest)
   365  		return
   366  	}
   367  
   368  	auditRec := c.MakeAuditRecord("patchGroupSyncable", audit.Fail)
   369  	defer c.LogAuditRec(auditRec)
   370  	auditRec.AddMeta("group_id", c.Params.GroupId)
   371  	auditRec.AddMeta("old_syncable_id", syncableID)
   372  	auditRec.AddMeta("old_syncable_type", syncableType)
   373  
   374  	var patch *model.GroupSyncablePatch
   375  	err = json.Unmarshal(body, &patch)
   376  	if err != nil || patch == nil {
   377  		c.SetInvalidParam(fmt.Sprintf("Group[%s]Patch", syncableType.String()))
   378  		return
   379  	}
   380  
   381  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   382  		c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.ldap_groups.license_error", nil, "",
   383  			http.StatusNotImplemented)
   384  		return
   385  	}
   386  
   387  	appErr := verifyLinkUnlinkPermission(c, syncableType, syncableID)
   388  	if appErr != nil {
   389  		c.Err = appErr
   390  		return
   391  	}
   392  
   393  	groupSyncable, appErr := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   394  	if appErr != nil {
   395  		c.Err = appErr
   396  		return
   397  	}
   398  
   399  	groupSyncable.Patch(patch)
   400  
   401  	groupSyncable, appErr = c.App.UpdateGroupSyncable(groupSyncable)
   402  	if appErr != nil {
   403  		c.Err = appErr
   404  		return
   405  	}
   406  
   407  	auditRec.AddMeta("new_syncable_id", groupSyncable.SyncableId)
   408  	auditRec.AddMeta("new_syncable_type", groupSyncable.Type)
   409  
   410  	c.App.Srv().Go(func() {
   411  		c.App.SyncRolesAndMembership(c.AppContext, syncableID, syncableType, false)
   412  	})
   413  
   414  	b, marshalErr := json.Marshal(groupSyncable)
   415  	if marshalErr != nil {
   416  		c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   417  		return
   418  	}
   419  	auditRec.Success()
   420  	w.Write(b)
   421  }
   422  
   423  func unlinkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   424  	c.RequireGroupId()
   425  	if c.Err != nil {
   426  		return
   427  	}
   428  
   429  	c.RequireSyncableId()
   430  	if c.Err != nil {
   431  		return
   432  	}
   433  	syncableID := c.Params.SyncableId
   434  
   435  	c.RequireSyncableType()
   436  	if c.Err != nil {
   437  		return
   438  	}
   439  	syncableType := c.Params.SyncableType
   440  
   441  	auditRec := c.MakeAuditRecord("unlinkGroupSyncable", audit.Fail)
   442  	defer c.LogAuditRec(auditRec)
   443  	auditRec.AddMeta("group_id", c.Params.GroupId)
   444  	auditRec.AddMeta("syncable_id", syncableID)
   445  	auditRec.AddMeta("syncable_type", syncableType)
   446  
   447  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   448  		c.Err = model.NewAppError("Api4.unlinkGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   449  		return
   450  	}
   451  
   452  	err := verifyLinkUnlinkPermission(c, syncableType, syncableID)
   453  	if err != nil {
   454  		c.Err = err
   455  		return
   456  	}
   457  
   458  	_, err = c.App.DeleteGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   459  	if err != nil {
   460  		c.Err = err
   461  		return
   462  	}
   463  
   464  	c.App.Srv().Go(func() {
   465  		c.App.SyncRolesAndMembership(c.AppContext, syncableID, syncableType, false)
   466  	})
   467  
   468  	auditRec.Success()
   469  
   470  	ReturnStatusOK(w)
   471  }
   472  
   473  func verifyLinkUnlinkPermission(c *Context, syncableType model.GroupSyncableType, syncableID string) *model.AppError {
   474  	switch syncableType {
   475  	case model.GroupSyncableTypeTeam:
   476  		if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), syncableID, model.PERMISSION_MANAGE_TEAM) {
   477  			return c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PERMISSION_MANAGE_TEAM})
   478  		}
   479  	case model.GroupSyncableTypeChannel:
   480  		channel, err := c.App.GetChannel(syncableID)
   481  		if err != nil {
   482  			return err
   483  		}
   484  
   485  		var permission *model.Permission
   486  		if channel.Type == model.CHANNEL_PRIVATE {
   487  			permission = model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS
   488  		} else {
   489  			permission = model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS
   490  		}
   491  
   492  		if !c.App.SessionHasPermissionToChannel(*c.AppContext.Session(), syncableID, permission) {
   493  			return c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission})
   494  		}
   495  	}
   496  
   497  	return nil
   498  }
   499  
   500  func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) {
   501  	c.RequireGroupId()
   502  	if c.Err != nil {
   503  		return
   504  	}
   505  
   506  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   507  		c.Err = model.NewAppError("Api4.getGroupMembers", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   508  		return
   509  	}
   510  
   511  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS) {
   512  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS)
   513  		return
   514  	}
   515  
   516  	members, count, err := c.App.GetGroupMemberUsersPage(c.Params.GroupId, c.Params.Page, c.Params.PerPage)
   517  	if err != nil {
   518  		c.Err = err
   519  		return
   520  	}
   521  
   522  	b, marshalErr := json.Marshal(struct {
   523  		Members []*model.User `json:"members"`
   524  		Count   int           `json:"total_member_count"`
   525  	}{
   526  		Members: members,
   527  		Count:   count,
   528  	})
   529  	if marshalErr != nil {
   530  		c.Err = model.NewAppError("Api4.getGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   531  		return
   532  	}
   533  
   534  	w.Write(b)
   535  }
   536  
   537  func getGroupStats(c *Context, w http.ResponseWriter, r *http.Request) {
   538  	c.RequireGroupId()
   539  	if c.Err != nil {
   540  		return
   541  	}
   542  
   543  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   544  		c.Err = model.NewAppError("Api4.getGroupStats", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   545  		return
   546  	}
   547  
   548  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS) {
   549  		c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS)
   550  		return
   551  	}
   552  
   553  	groupID := c.Params.GroupId
   554  	count, err := c.App.GetGroupMemberCount(groupID)
   555  	if err != nil {
   556  		c.Err = err
   557  		return
   558  	}
   559  
   560  	b, marshalErr := json.Marshal(model.GroupStats{
   561  		GroupID:          groupID,
   562  		TotalMemberCount: count,
   563  	})
   564  	if marshalErr != nil {
   565  		c.Err = model.NewAppError("Api4.getGroupStats", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   566  		return
   567  	}
   568  
   569  	w.Write(b)
   570  }
   571  
   572  func getGroupsByUserId(c *Context, w http.ResponseWriter, r *http.Request) {
   573  	c.RequireUserId()
   574  	if c.Err != nil {
   575  		return
   576  	}
   577  
   578  	if c.AppContext.Session().UserId != c.Params.UserId && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) {
   579  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   580  		return
   581  	}
   582  
   583  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   584  		c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   585  		return
   586  	}
   587  
   588  	groups, err := c.App.GetGroupsByUserId(c.Params.UserId)
   589  	if err != nil {
   590  		c.Err = err
   591  		return
   592  	}
   593  
   594  	b, marshalErr := json.Marshal(groups)
   595  	if marshalErr != nil {
   596  		c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   597  		return
   598  	}
   599  
   600  	w.Write(b)
   601  }
   602  
   603  func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) {
   604  	c.RequireChannelId()
   605  	if c.Err != nil {
   606  		return
   607  	}
   608  
   609  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   610  		c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   611  		return
   612  	}
   613  
   614  	channel, err := c.App.GetChannel(c.Params.ChannelId)
   615  	if err != nil {
   616  		c.Err = err
   617  		return
   618  	}
   619  	var permission *model.Permission
   620  	if channel.Type == model.CHANNEL_PRIVATE {
   621  		permission = model.PERMISSION_READ_PRIVATE_CHANNEL_GROUPS
   622  	} else {
   623  		permission = model.PERMISSION_READ_PUBLIC_CHANNEL_GROUPS
   624  	}
   625  	if !c.App.SessionHasPermissionToChannel(*c.AppContext.Session(), c.Params.ChannelId, permission) {
   626  		c.SetPermissionError(permission)
   627  		return
   628  	}
   629  
   630  	opts := model.GroupSearchOpts{
   631  		Q:                    c.Params.Q,
   632  		IncludeMemberCount:   c.Params.IncludeMemberCount,
   633  		FilterAllowReference: c.Params.FilterAllowReference,
   634  	}
   635  	if c.Params.Paginate == nil || *c.Params.Paginate {
   636  		opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage}
   637  	}
   638  
   639  	groups, totalCount, err := c.App.GetGroupsByChannel(c.Params.ChannelId, opts)
   640  	if err != nil {
   641  		c.Err = err
   642  		return
   643  	}
   644  
   645  	b, marshalErr := json.Marshal(struct {
   646  		Groups []*model.GroupWithSchemeAdmin `json:"groups"`
   647  		Count  int                           `json:"total_group_count"`
   648  	}{
   649  		Groups: groups,
   650  		Count:  totalCount,
   651  	})
   652  
   653  	if marshalErr != nil {
   654  		c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   655  		return
   656  	}
   657  
   658  	w.Write(b)
   659  }
   660  
   661  func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   662  	c.RequireTeamId()
   663  	if c.Err != nil {
   664  		return
   665  	}
   666  
   667  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   668  		c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   669  		return
   670  	}
   671  
   672  	opts := model.GroupSearchOpts{
   673  		Q:                    c.Params.Q,
   674  		IncludeMemberCount:   c.Params.IncludeMemberCount,
   675  		FilterAllowReference: c.Params.FilterAllowReference,
   676  	}
   677  	if c.Params.Paginate == nil || *c.Params.Paginate {
   678  		opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage}
   679  	}
   680  
   681  	groups, totalCount, err := c.App.GetGroupsByTeam(c.Params.TeamId, opts)
   682  	if err != nil {
   683  		c.Err = err
   684  		return
   685  	}
   686  
   687  	b, marshalErr := json.Marshal(struct {
   688  		Groups []*model.GroupWithSchemeAdmin `json:"groups"`
   689  		Count  int                           `json:"total_group_count"`
   690  	}{
   691  		Groups: groups,
   692  		Count:  totalCount,
   693  	})
   694  
   695  	if marshalErr != nil {
   696  		c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   697  		return
   698  	}
   699  
   700  	w.Write(b)
   701  }
   702  
   703  func getGroupsAssociatedToChannelsByTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   704  	c.RequireTeamId()
   705  	if c.Err != nil {
   706  		return
   707  	}
   708  
   709  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   710  		c.Err = model.NewAppError("Api4.getGroupsAssociatedToChannelsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   711  		return
   712  	}
   713  
   714  	opts := model.GroupSearchOpts{
   715  		Q:                    c.Params.Q,
   716  		IncludeMemberCount:   c.Params.IncludeMemberCount,
   717  		FilterAllowReference: c.Params.FilterAllowReference,
   718  	}
   719  	if c.Params.Paginate == nil || *c.Params.Paginate {
   720  		opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage}
   721  	}
   722  
   723  	groupsAssociatedByChannelID, err := c.App.GetGroupsAssociatedToChannelsByTeam(c.Params.TeamId, opts)
   724  	if err != nil {
   725  		c.Err = err
   726  		return
   727  	}
   728  
   729  	b, marshalErr := json.Marshal(struct {
   730  		GroupsAssociatedToChannels map[string][]*model.GroupWithSchemeAdmin `json:"groups"`
   731  	}{
   732  		GroupsAssociatedToChannels: groupsAssociatedByChannelID,
   733  	})
   734  
   735  	if marshalErr != nil {
   736  		c.Err = model.NewAppError("Api4.getGroupsAssociatedToChannelsByTeam", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   737  		return
   738  	}
   739  
   740  	w.Write(b)
   741  }
   742  
   743  func getGroups(c *Context, w http.ResponseWriter, r *http.Request) {
   744  	if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
   745  		c.Err = model.NewAppError("Api4.getGroups", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   746  		return
   747  	}
   748  	var teamID, channelID string
   749  
   750  	if id := c.Params.NotAssociatedToTeam; model.IsValidId(id) {
   751  		teamID = id
   752  	}
   753  
   754  	if id := c.Params.NotAssociatedToChannel; model.IsValidId(id) {
   755  		channelID = id
   756  	}
   757  
   758  	opts := model.GroupSearchOpts{
   759  		Q:                         c.Params.Q,
   760  		IncludeMemberCount:        c.Params.IncludeMemberCount,
   761  		FilterAllowReference:      c.Params.FilterAllowReference,
   762  		FilterParentTeamPermitted: c.Params.FilterParentTeamPermitted,
   763  	}
   764  
   765  	if teamID != "" {
   766  		_, err := c.App.GetTeam(teamID)
   767  		if err != nil {
   768  			c.Err = err
   769  			return
   770  		}
   771  
   772  		opts.NotAssociatedToTeam = teamID
   773  	}
   774  
   775  	if channelID != "" {
   776  		channel, err := c.App.GetChannel(channelID)
   777  		if err != nil {
   778  			c.Err = err
   779  			return
   780  		}
   781  		var permission *model.Permission
   782  		if channel.Type == model.CHANNEL_PRIVATE {
   783  			permission = model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS
   784  		} else {
   785  			permission = model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS
   786  		}
   787  		if !c.App.SessionHasPermissionToChannel(*c.AppContext.Session(), channelID, permission) {
   788  			c.SetPermissionError(permission)
   789  			return
   790  		}
   791  		opts.NotAssociatedToChannel = channelID
   792  	}
   793  
   794  	sinceString := r.URL.Query().Get("since")
   795  	if sinceString != "" {
   796  		since, parseError := strconv.ParseInt(sinceString, 10, 64)
   797  		if parseError != nil {
   798  			c.SetInvalidParam("since")
   799  			return
   800  		}
   801  		opts.Since = since
   802  	}
   803  
   804  	groups, err := c.App.GetGroups(c.Params.Page, c.Params.PerPage, opts)
   805  	if err != nil {
   806  		c.Err = err
   807  		return
   808  	}
   809  
   810  	b, marshalErr := json.Marshal(groups)
   811  	if marshalErr != nil {
   812  		c.Err = model.NewAppError("Api4.getGroups", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   813  		return
   814  	}
   815  
   816  	w.Write(b)
   817  }