1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2// See LICENSE.txt for license information. 3 4package api4 5 6import ( 7 "encoding/json" 8 "fmt" 9 "io/ioutil" 10 "net/http" 11 "strconv" 12 "strings" 13 14 "github.com/mattermost/mattermost-server/v6/audit" 15 "github.com/mattermost/mattermost-server/v6/model" 16) 17 18func (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 80func 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.PermissionSysconsoleReadUserManagementGroups) { 92 c.SetPermissionError(model.PermissionSysconsoleReadUserManagementGroups) 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 111func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { 112 c.RequireGroupId() 113 if c.Err != nil { 114 return 115 } 116 117 var groupPatch model.GroupPatch 118 if jsonErr := json.NewDecoder(r.Body).Decode(&groupPatch); jsonErr != 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.PermissionSysconsoleWriteUserManagementGroups) { 132 c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementGroups) 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.UserNotifyAll || *groupPatch.Name == model.ChannelMentionsNotifyProp || *groupPatch.Name == model.UserNotifyHere { 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 189func 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 264func 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.PermissionManageSystem) { 288 c.SetPermissionError(model.PermissionManageSystem) 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 307func 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.PermissionSysconsoleReadUserManagementGroups) { 325 c.SetPermissionError(model.PermissionSysconsoleReadUserManagementGroups) 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 344func 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 423func 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 473func 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.PermissionManageTeam) { 477 return c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PermissionManageTeam}) 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.ChannelTypePrivate { 487 permission = model.PermissionManagePrivateChannelMembers 488 } else { 489 permission = model.PermissionManagePublicChannelMembers 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 500func 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.PermissionSysconsoleReadUserManagementGroups) { 512 c.SetPermissionError(model.PermissionSysconsoleReadUserManagementGroups) 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 537func 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.PermissionSysconsoleReadUserManagementGroups) { 549 c.SetPermissionError(model.PermissionSysconsoleReadUserManagementGroups) 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 572func 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.PermissionManageSystem) { 579 c.SetPermissionError(model.PermissionManageSystem) 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 603func 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.ChannelTypePrivate { 621 permission = model.PermissionReadPrivateChannelGroups 622 } else { 623 permission = model.PermissionReadPublicChannelGroups 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 661func 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 703func 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 743func 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.ChannelTypePrivate { 783 permission = model.PermissionManagePrivateChannelMembers 784 } else { 785 permission = model.PermissionManagePublicChannelMembers 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} 818