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