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 }