github.com/xzl8028/xenia-server@v0.0.0-20190809101854-18450a97da63/api4/group.go (about)

     1  // Copyright (c) 2018-present Xenia, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"database/sql"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"net/http"
    12  
    13  	"github.com/xzl8028/xenia-server/model"
    14  )
    15  
    16  const (
    17  	groupMemberActionCreate = iota
    18  	groupMemberActionDelete
    19  )
    20  
    21  func (api *API) InitGroup() {
    22  	// GET /api/v4/groups
    23  	api.BaseRoutes.Groups.Handle("", api.ApiSessionRequired(getGroups)).Methods("GET")
    24  
    25  	// GET /api/v4/groups/:group_id
    26  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}",
    27  		api.ApiSessionRequired(getGroup)).Methods("GET")
    28  
    29  	// PUT /api/v4/groups/:group_id/patch
    30  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/patch",
    31  		api.ApiSessionRequired(patchGroup)).Methods("PUT")
    32  
    33  	// POST /api/v4/groups/:group_id/teams/:team_id/link
    34  	// POST /api/v4/groups/:group_id/channels/:channel_id/link
    35  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/link",
    36  		api.ApiSessionRequired(linkGroupSyncable)).Methods("POST")
    37  
    38  	// DELETE /api/v4/groups/:group_id/teams/:team_id/link
    39  	// DELETE /api/v4/groups/:group_id/channels/:channel_id/link
    40  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/link",
    41  		api.ApiSessionRequired(unlinkGroupSyncable)).Methods("DELETE")
    42  
    43  	// GET /api/v4/groups/:group_id/teams/:team_id
    44  	// GET /api/v4/groups/:group_id/channels/:channel_id
    45  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}",
    46  		api.ApiSessionRequired(getGroupSyncable)).Methods("GET")
    47  
    48  	// GET /api/v4/groups/:group_id/teams
    49  	// GET /api/v4/groups/:group_id/channels
    50  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}",
    51  		api.ApiSessionRequired(getGroupSyncables)).Methods("GET")
    52  
    53  	// PUT /api/v4/groups/:group_id/teams/:team_id/patch
    54  	// PUT /api/v4/groups/:group_id/channels/:channel_id/patch
    55  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/patch",
    56  		api.ApiSessionRequired(patchGroupSyncable)).Methods("PUT")
    57  
    58  	// GET /api/v4/groups/:group_id/members?page=0&per_page=100
    59  	api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members",
    60  		api.ApiSessionRequired(getGroupMembers)).Methods("GET")
    61  
    62  	// GET /api/v4/channels/:channel_id/groups?page=0&per_page=100
    63  	api.BaseRoutes.Channels.Handle("/{channel_id:[A-Za-z0-9]+}/groups",
    64  		api.ApiSessionRequired(getGroupsByChannel)).Methods("GET")
    65  
    66  	// GET /api/v4/teams/:team_id/groups?page=0&per_page=100
    67  	api.BaseRoutes.Teams.Handle("/{team_id:[A-Za-z0-9]+}/groups",
    68  		api.ApiSessionRequired(getGroupsByTeam)).Methods("GET")
    69  }
    70  
    71  func getGroup(c *Context, w http.ResponseWriter, r *http.Request) {
    72  	c.RequireGroupId()
    73  	if c.Err != nil {
    74  		return
    75  	}
    76  
    77  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
    78  		c.Err = model.NewAppError("Api4.getGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
    79  		return
    80  	}
    81  
    82  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
    83  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
    84  		return
    85  	}
    86  
    87  	group, err := c.App.GetGroup(c.Params.GroupId)
    88  	if err != nil {
    89  		c.Err = err
    90  		return
    91  	}
    92  
    93  	b, marshalErr := json.Marshal(group)
    94  	if marshalErr != nil {
    95  		c.Err = model.NewAppError("Api4.getGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
    96  		return
    97  	}
    98  
    99  	w.Write(b)
   100  }
   101  
   102  func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) {
   103  	c.RequireGroupId()
   104  	if c.Err != nil {
   105  		return
   106  	}
   107  
   108  	groupPatch := model.GroupPatchFromJson(r.Body)
   109  	if groupPatch == nil {
   110  		c.SetInvalidParam("group")
   111  		return
   112  	}
   113  
   114  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   115  		c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   116  		return
   117  	}
   118  
   119  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   120  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   121  		return
   122  	}
   123  
   124  	group, err := c.App.GetGroup(c.Params.GroupId)
   125  	if err != nil {
   126  		c.Err = err
   127  		return
   128  	}
   129  
   130  	group.Patch(groupPatch)
   131  
   132  	group, err = c.App.UpdateGroup(group)
   133  	if err != nil {
   134  		c.Err = err
   135  		return
   136  	}
   137  
   138  	b, marshalErr := json.Marshal(group)
   139  	if marshalErr != nil {
   140  		c.Err = model.NewAppError("Api4.patchGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   141  		return
   142  	}
   143  
   144  	w.Write(b)
   145  }
   146  
   147  func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   148  	c.RequireGroupId()
   149  	if c.Err != nil {
   150  		return
   151  	}
   152  
   153  	c.RequireSyncableId()
   154  	if c.Err != nil {
   155  		return
   156  	}
   157  	syncableID := c.Params.SyncableId
   158  
   159  	c.RequireSyncableType()
   160  	if c.Err != nil {
   161  		return
   162  	}
   163  	syncableType := c.Params.SyncableType
   164  
   165  	body, err := ioutil.ReadAll(r.Body)
   166  	if err != nil {
   167  		c.Err = model.NewAppError("Api4.createGroupSyncable", "api.io_error", nil, err.Error(), http.StatusBadRequest)
   168  		return
   169  	}
   170  
   171  	var patch *model.GroupSyncablePatch
   172  	err = json.Unmarshal(body, &patch)
   173  	if err != nil || patch == nil {
   174  		c.SetInvalidParam(fmt.Sprintf("Group%s", syncableType.String()))
   175  		return
   176  	}
   177  
   178  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   179  		c.Err = model.NewAppError("Api4.createGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   180  		return
   181  	}
   182  
   183  	appErr := verifyLinkUnlinkPermission(c, syncableType, syncableID)
   184  	if appErr != nil {
   185  		c.Err = appErr
   186  		return
   187  	}
   188  
   189  	groupSyncable, appErr := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   190  	if appErr != nil && appErr.DetailedError != sql.ErrNoRows.Error() {
   191  		c.Err = appErr
   192  		return
   193  	}
   194  
   195  	if groupSyncable == nil {
   196  		groupSyncable = &model.GroupSyncable{
   197  			GroupId:    c.Params.GroupId,
   198  			SyncableId: syncableID,
   199  			Type:       syncableType,
   200  		}
   201  		groupSyncable.Patch(patch)
   202  		groupSyncable, appErr = c.App.CreateGroupSyncable(groupSyncable)
   203  		if appErr != nil {
   204  			c.Err = appErr
   205  			return
   206  		}
   207  	} else {
   208  		groupSyncable.DeleteAt = 0
   209  		groupSyncable.Patch(patch)
   210  		groupSyncable, appErr = c.App.UpdateGroupSyncable(groupSyncable)
   211  		if appErr != nil {
   212  			c.Err = appErr
   213  			return
   214  		}
   215  	}
   216  
   217  	w.WriteHeader(http.StatusCreated)
   218  
   219  	b, marshalErr := json.Marshal(groupSyncable)
   220  	if marshalErr != nil {
   221  		c.Err = model.NewAppError("Api4.createGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   222  		return
   223  	}
   224  
   225  	w.Write(b)
   226  }
   227  
   228  func getGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   229  	c.RequireGroupId()
   230  	if c.Err != nil {
   231  		return
   232  	}
   233  
   234  	c.RequireSyncableId()
   235  	if c.Err != nil {
   236  		return
   237  	}
   238  	syncableID := c.Params.SyncableId
   239  
   240  	c.RequireSyncableType()
   241  	if c.Err != nil {
   242  		return
   243  	}
   244  	syncableType := c.Params.SyncableType
   245  
   246  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   247  		c.Err = model.NewAppError("Api4.getGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   248  		return
   249  	}
   250  
   251  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   252  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   253  		return
   254  	}
   255  
   256  	groupSyncable, err := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   257  	if err != nil {
   258  		c.Err = err
   259  		return
   260  	}
   261  
   262  	b, marshalErr := json.Marshal(groupSyncable)
   263  	if marshalErr != nil {
   264  		c.Err = model.NewAppError("Api4.getGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   265  		return
   266  	}
   267  
   268  	w.Write(b)
   269  }
   270  
   271  func getGroupSyncables(c *Context, w http.ResponseWriter, r *http.Request) {
   272  	c.RequireGroupId()
   273  	if c.Err != nil {
   274  		return
   275  	}
   276  
   277  	c.RequireSyncableType()
   278  	if c.Err != nil {
   279  		return
   280  	}
   281  	syncableType := c.Params.SyncableType
   282  
   283  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   284  		c.Err = model.NewAppError("Api4.getGroupSyncables", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   285  		return
   286  	}
   287  
   288  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   289  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   290  		return
   291  	}
   292  
   293  	groupSyncables, err := c.App.GetGroupSyncables(c.Params.GroupId, syncableType)
   294  	if err != nil {
   295  		c.Err = err
   296  		return
   297  	}
   298  
   299  	b, marshalErr := json.Marshal(groupSyncables)
   300  	if marshalErr != nil {
   301  		c.Err = model.NewAppError("Api4.getGroupSyncables", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   302  		return
   303  	}
   304  
   305  	w.Write(b)
   306  }
   307  
   308  func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   309  	c.RequireGroupId()
   310  	if c.Err != nil {
   311  		return
   312  	}
   313  
   314  	c.RequireSyncableId()
   315  	if c.Err != nil {
   316  		return
   317  	}
   318  	syncableID := c.Params.SyncableId
   319  
   320  	c.RequireSyncableType()
   321  	if c.Err != nil {
   322  		return
   323  	}
   324  	syncableType := c.Params.SyncableType
   325  
   326  	body, err := ioutil.ReadAll(r.Body)
   327  	if err != nil {
   328  		c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.io_error", nil, err.Error(), http.StatusBadRequest)
   329  		return
   330  	}
   331  
   332  	var patch *model.GroupSyncablePatch
   333  	err = json.Unmarshal(body, &patch)
   334  	if err != nil || patch == nil {
   335  		c.SetInvalidParam(fmt.Sprintf("Group[%s]Patch", syncableType.String()))
   336  		return
   337  	}
   338  
   339  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   340  		c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.ldap_groups.license_error", nil, "",
   341  			http.StatusNotImplemented)
   342  		return
   343  	}
   344  
   345  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   346  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   347  		return
   348  	}
   349  
   350  	groupSyncable, appErr := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   351  	if appErr != nil {
   352  		c.Err = appErr
   353  		return
   354  	}
   355  
   356  	groupSyncable.Patch(patch)
   357  
   358  	groupSyncable, appErr = c.App.UpdateGroupSyncable(groupSyncable)
   359  	if appErr != nil {
   360  		c.Err = appErr
   361  		return
   362  	}
   363  
   364  	b, marshalErr := json.Marshal(groupSyncable)
   365  	if marshalErr != nil {
   366  		c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   367  		return
   368  	}
   369  
   370  	w.Write(b)
   371  }
   372  
   373  func unlinkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
   374  	c.RequireGroupId()
   375  	if c.Err != nil {
   376  		return
   377  	}
   378  
   379  	c.RequireSyncableId()
   380  	if c.Err != nil {
   381  		return
   382  	}
   383  	syncableID := c.Params.SyncableId
   384  
   385  	c.RequireSyncableType()
   386  	if c.Err != nil {
   387  		return
   388  	}
   389  	syncableType := c.Params.SyncableType
   390  
   391  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   392  		c.Err = model.NewAppError("Api4.unlinkGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   393  		return
   394  	}
   395  
   396  	err := verifyLinkUnlinkPermission(c, syncableType, syncableID)
   397  	if err != nil {
   398  		c.Err = err
   399  		return
   400  	}
   401  
   402  	_, err = c.App.DeleteGroupSyncable(c.Params.GroupId, syncableID, syncableType)
   403  	if err != nil {
   404  		c.Err = err
   405  		return
   406  	}
   407  
   408  	ReturnStatusOK(w)
   409  }
   410  
   411  func verifyLinkUnlinkPermission(c *Context, syncableType model.GroupSyncableType, syncableID string) *model.AppError {
   412  	switch syncableType {
   413  	case model.GroupSyncableTypeTeam:
   414  		if !c.App.SessionHasPermissionToTeam(c.App.Session, syncableID, model.PERMISSION_MANAGE_TEAM) {
   415  			return c.App.MakePermissionError(model.PERMISSION_MANAGE_TEAM)
   416  		}
   417  	case model.GroupSyncableTypeChannel:
   418  		channel, err := c.App.GetChannel(syncableID)
   419  		if err != nil {
   420  			return err
   421  		}
   422  
   423  		var permission *model.Permission
   424  		if channel.Type == model.CHANNEL_PRIVATE {
   425  			permission = model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS
   426  		} else {
   427  			permission = model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS
   428  		}
   429  
   430  		if !c.App.SessionHasPermissionToChannel(c.App.Session, syncableID, permission) {
   431  			return c.App.MakePermissionError(permission)
   432  		}
   433  	}
   434  
   435  	return nil
   436  }
   437  
   438  func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) {
   439  	c.RequireGroupId()
   440  	if c.Err != nil {
   441  		return
   442  	}
   443  
   444  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   445  		c.Err = model.NewAppError("Api4.getGroupMembers", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   446  		return
   447  	}
   448  
   449  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   450  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   451  		return
   452  	}
   453  
   454  	members, count, err := c.App.GetGroupMemberUsersPage(c.Params.GroupId, c.Params.Page, c.Params.PerPage)
   455  	if err != nil {
   456  		c.Err = err
   457  		return
   458  	}
   459  
   460  	b, marshalErr := json.Marshal(struct {
   461  		Members []*model.User `json:"members"`
   462  		Count   int           `json:"total_member_count"`
   463  	}{
   464  		Members: members,
   465  		Count:   count,
   466  	})
   467  	if marshalErr != nil {
   468  		c.Err = model.NewAppError("Api4.getGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   469  		return
   470  	}
   471  
   472  	w.Write(b)
   473  }
   474  
   475  func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) {
   476  	c.RequireChannelId()
   477  	if c.Err != nil {
   478  		return
   479  	}
   480  
   481  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   482  		c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   483  		return
   484  	}
   485  
   486  	var permission *model.Permission
   487  	channel, err := c.App.GetChannel(c.Params.ChannelId)
   488  	if err != nil {
   489  		c.Err = err
   490  		return
   491  	}
   492  	if channel.Type == model.CHANNEL_PRIVATE {
   493  		permission = model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS
   494  	} else {
   495  		permission = model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS
   496  	}
   497  	if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, permission) {
   498  		c.SetPermissionError(permission)
   499  		return
   500  	}
   501  
   502  	opts := model.GroupSearchOpts{
   503  		Q:                  c.Params.Q,
   504  		IncludeMemberCount: c.Params.IncludeMemberCount,
   505  	}
   506  	if c.Params.Paginate == nil || *c.Params.Paginate {
   507  		opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage}
   508  	}
   509  
   510  	groups, totalCount, err := c.App.GetGroupsByChannel(c.Params.ChannelId, opts)
   511  	if err != nil {
   512  		c.Err = err
   513  		return
   514  	}
   515  
   516  	b, marshalErr := json.Marshal(struct {
   517  		Groups []*model.Group `json:"groups"`
   518  		Count  int            `json:"total_group_count"`
   519  	}{
   520  		Groups: groups,
   521  		Count:  totalCount,
   522  	})
   523  
   524  	if marshalErr != nil {
   525  		c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   526  		return
   527  	}
   528  
   529  	w.Write(b)
   530  }
   531  
   532  func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) {
   533  	c.RequireTeamId()
   534  	if c.Err != nil {
   535  		return
   536  	}
   537  
   538  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   539  		c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   540  		return
   541  	}
   542  
   543  	if !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
   544  		c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
   545  		return
   546  	}
   547  
   548  	opts := model.GroupSearchOpts{
   549  		Q:                  c.Params.Q,
   550  		IncludeMemberCount: c.Params.IncludeMemberCount,
   551  	}
   552  	if c.Params.Paginate == nil || *c.Params.Paginate {
   553  		opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage}
   554  	}
   555  
   556  	groups, totalCount, err := c.App.GetGroupsByTeam(c.Params.TeamId, opts)
   557  	if err != nil {
   558  		c.Err = err
   559  		return
   560  	}
   561  
   562  	b, marshalErr := json.Marshal(struct {
   563  		Groups []*model.Group `json:"groups"`
   564  		Count  int            `json:"total_group_count"`
   565  	}{
   566  		Groups: groups,
   567  		Count:  totalCount,
   568  	})
   569  
   570  	if marshalErr != nil {
   571  		c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   572  		return
   573  	}
   574  
   575  	w.Write(b)
   576  }
   577  
   578  func getGroups(c *Context, w http.ResponseWriter, r *http.Request) {
   579  	if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
   580  		c.Err = model.NewAppError("Api4.getGroups", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
   581  		return
   582  	}
   583  
   584  	opts := model.GroupSearchOpts{
   585  		Q:                  c.Params.Q,
   586  		IncludeMemberCount: c.Params.IncludeMemberCount,
   587  	}
   588  
   589  	teamID := c.Params.NotAssociatedToTeam
   590  	if len(teamID) == 26 {
   591  		if !c.App.SessionHasPermissionToTeam(c.App.Session, teamID, model.PERMISSION_VIEW_TEAM) {
   592  			c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   593  			return
   594  		}
   595  		opts.NotAssociatedToTeam = teamID
   596  	}
   597  
   598  	channelID := c.Params.NotAssociatedToChannel
   599  	if len(channelID) == 26 {
   600  		channel, err := c.App.GetChannel(channelID)
   601  		if err != nil {
   602  			c.Err = err
   603  			return
   604  		}
   605  		var permission *model.Permission
   606  		if channel.Type == model.CHANNEL_PRIVATE {
   607  			permission = model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS
   608  		} else {
   609  			permission = model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS
   610  		}
   611  		if !c.App.SessionHasPermissionToChannel(c.App.Session, channelID, permission) {
   612  			c.SetPermissionError(permission)
   613  			return
   614  		}
   615  		opts.NotAssociatedToChannel = channelID
   616  	}
   617  
   618  	groups, err := c.App.GetGroups(c.Params.Page, c.Params.PerPage, opts)
   619  	if err != nil {
   620  		c.Err = err
   621  		return
   622  	}
   623  
   624  	b, marshalErr := json.Marshal(groups)
   625  	if marshalErr != nil {
   626  		c.Err = model.NewAppError("Api4.getGroups", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
   627  		return
   628  	}
   629  
   630  	w.Write(b)
   631  }