github.com/google/go-github/v49@v49.1.0/github/teams.go (about) 1 // Copyright 2018 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "fmt" 11 "net/http" 12 "strings" 13 "time" 14 ) 15 16 // TeamsService provides access to the team-related functions 17 // in the GitHub API. 18 // 19 // GitHub API docs: https://docs.github.com/en/rest/teams/ 20 type TeamsService service 21 22 // Team represents a team within a GitHub organization. Teams are used to 23 // manage access to an organization's repositories. 24 type Team struct { 25 ID *int64 `json:"id,omitempty"` 26 NodeID *string `json:"node_id,omitempty"` 27 Name *string `json:"name,omitempty"` 28 Description *string `json:"description,omitempty"` 29 URL *string `json:"url,omitempty"` 30 Slug *string `json:"slug,omitempty"` 31 32 // Permission specifies the default permission for repositories owned by the team. 33 Permission *string `json:"permission,omitempty"` 34 35 // Permissions identifies the permissions that a team has on a given 36 // repository. This is only populated when calling Repositories.ListTeams. 37 Permissions map[string]bool `json:"permissions,omitempty"` 38 39 // Privacy identifies the level of privacy this team should have. 40 // Possible values are: 41 // secret - only visible to organization owners and members of this team 42 // closed - visible to all members of this organization 43 // Default is "secret". 44 Privacy *string `json:"privacy,omitempty"` 45 46 MembersCount *int `json:"members_count,omitempty"` 47 ReposCount *int `json:"repos_count,omitempty"` 48 Organization *Organization `json:"organization,omitempty"` 49 HTMLURL *string `json:"html_url,omitempty"` 50 MembersURL *string `json:"members_url,omitempty"` 51 RepositoriesURL *string `json:"repositories_url,omitempty"` 52 Parent *Team `json:"parent,omitempty"` 53 54 // LDAPDN is only available in GitHub Enterprise and when the team 55 // membership is synchronized with LDAP. 56 LDAPDN *string `json:"ldap_dn,omitempty"` 57 } 58 59 func (t Team) String() string { 60 return Stringify(t) 61 } 62 63 // Invitation represents a team member's invitation status. 64 type Invitation struct { 65 ID *int64 `json:"id,omitempty"` 66 NodeID *string `json:"node_id,omitempty"` 67 Login *string `json:"login,omitempty"` 68 Email *string `json:"email,omitempty"` 69 // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. 70 Role *string `json:"role,omitempty"` 71 CreatedAt *time.Time `json:"created_at,omitempty"` 72 Inviter *User `json:"inviter,omitempty"` 73 TeamCount *int `json:"team_count,omitempty"` 74 InvitationTeamURL *string `json:"invitation_team_url,omitempty"` 75 FailedAt *Timestamp `json:"failed_at,omitempty"` 76 FailedReason *string `json:"failed_reason,omitempty"` 77 } 78 79 func (i Invitation) String() string { 80 return Stringify(i) 81 } 82 83 // ListTeams lists all of the teams for an organization. 84 // 85 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-teams 86 func (s *TeamsService) ListTeams(ctx context.Context, org string, opts *ListOptions) ([]*Team, *Response, error) { 87 u := fmt.Sprintf("orgs/%v/teams", org) 88 u, err := addOptions(u, opts) 89 if err != nil { 90 return nil, nil, err 91 } 92 93 req, err := s.client.NewRequest("GET", u, nil) 94 if err != nil { 95 return nil, nil, err 96 } 97 98 var teams []*Team 99 resp, err := s.client.Do(ctx, req, &teams) 100 if err != nil { 101 return nil, resp, err 102 } 103 104 return teams, resp, nil 105 } 106 107 // GetTeamByID fetches a team, given a specified organization ID, by ID. 108 // 109 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#get-a-team-by-name 110 func (s *TeamsService) GetTeamByID(ctx context.Context, orgID, teamID int64) (*Team, *Response, error) { 111 u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) 112 req, err := s.client.NewRequest("GET", u, nil) 113 if err != nil { 114 return nil, nil, err 115 } 116 117 t := new(Team) 118 resp, err := s.client.Do(ctx, req, t) 119 if err != nil { 120 return nil, resp, err 121 } 122 123 return t, resp, nil 124 } 125 126 // GetTeamBySlug fetches a team, given a specified organization name, by slug. 127 // 128 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#get-a-team-by-name 129 func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) { 130 u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) 131 req, err := s.client.NewRequest("GET", u, nil) 132 if err != nil { 133 return nil, nil, err 134 } 135 136 t := new(Team) 137 resp, err := s.client.Do(ctx, req, t) 138 if err != nil { 139 return nil, resp, err 140 } 141 142 return t, resp, nil 143 } 144 145 // NewTeam represents a team to be created or modified. 146 type NewTeam struct { 147 Name string `json:"name"` // Name of the team. (Required.) 148 Description *string `json:"description,omitempty"` 149 Maintainers []string `json:"maintainers,omitempty"` 150 RepoNames []string `json:"repo_names,omitempty"` 151 ParentTeamID *int64 `json:"parent_team_id,omitempty"` 152 153 // Deprecated: Permission is deprecated when creating or editing a team in an org 154 // using the new GitHub permission model. It no longer identifies the 155 // permission a team has on its repos, but only specifies the default 156 // permission a repo is initially added with. Avoid confusion by 157 // specifying a permission value when calling AddTeamRepo. 158 Permission *string `json:"permission,omitempty"` 159 160 // Privacy identifies the level of privacy this team should have. 161 // Possible values are: 162 // secret - only visible to organization owners and members of this team 163 // closed - visible to all members of this organization 164 // Default is "secret". 165 Privacy *string `json:"privacy,omitempty"` 166 167 // LDAPDN may be used in GitHub Enterprise when the team membership 168 // is synchronized with LDAP. 169 LDAPDN *string `json:"ldap_dn,omitempty"` 170 } 171 172 func (s NewTeam) String() string { 173 return Stringify(s) 174 } 175 176 // CreateTeam creates a new team within an organization. 177 // 178 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#create-a-team 179 func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) { 180 u := fmt.Sprintf("orgs/%v/teams", org) 181 req, err := s.client.NewRequest("POST", u, team) 182 if err != nil { 183 return nil, nil, err 184 } 185 186 t := new(Team) 187 resp, err := s.client.Do(ctx, req, t) 188 if err != nil { 189 return nil, resp, err 190 } 191 192 return t, resp, nil 193 } 194 195 // newTeamNoParent is the same as NewTeam but ensures that the 196 // "parent_team_id" field will be null. It is for internal use 197 // only and should not be exported. 198 type newTeamNoParent struct { 199 Name string `json:"name"` 200 Description *string `json:"description,omitempty"` 201 Maintainers []string `json:"maintainers,omitempty"` 202 RepoNames []string `json:"repo_names,omitempty"` 203 ParentTeamID *int64 `json:"parent_team_id"` // This will be "null" 204 Privacy *string `json:"privacy,omitempty"` 205 LDAPDN *string `json:"ldap_dn,omitempty"` 206 } 207 208 // copyNewTeamWithoutParent is used to set the "parent_team_id" 209 // field to "null" after copying the other fields from a NewTeam. 210 // It is for internal use only and should not be exported. 211 func copyNewTeamWithoutParent(team *NewTeam) *newTeamNoParent { 212 return &newTeamNoParent{ 213 Name: team.Name, 214 Description: team.Description, 215 Maintainers: team.Maintainers, 216 RepoNames: team.RepoNames, 217 Privacy: team.Privacy, 218 LDAPDN: team.LDAPDN, 219 } 220 } 221 222 // EditTeamByID edits a team, given an organization ID, selected by ID. 223 // 224 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#update-a-team 225 func (s *TeamsService) EditTeamByID(ctx context.Context, orgID, teamID int64, team NewTeam, removeParent bool) (*Team, *Response, error) { 226 u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) 227 228 var req *http.Request 229 var err error 230 if removeParent { 231 teamRemoveParent := copyNewTeamWithoutParent(&team) 232 req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) 233 } else { 234 req, err = s.client.NewRequest("PATCH", u, team) 235 } 236 if err != nil { 237 return nil, nil, err 238 } 239 240 t := new(Team) 241 resp, err := s.client.Do(ctx, req, t) 242 if err != nil { 243 return nil, resp, err 244 } 245 246 return t, resp, nil 247 } 248 249 // EditTeamBySlug edits a team, given an organization name, by slug. 250 // 251 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#update-a-team 252 func (s *TeamsService) EditTeamBySlug(ctx context.Context, org, slug string, team NewTeam, removeParent bool) (*Team, *Response, error) { 253 u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) 254 255 var req *http.Request 256 var err error 257 if removeParent { 258 teamRemoveParent := copyNewTeamWithoutParent(&team) 259 req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) 260 } else { 261 req, err = s.client.NewRequest("PATCH", u, team) 262 } 263 if err != nil { 264 return nil, nil, err 265 } 266 267 t := new(Team) 268 resp, err := s.client.Do(ctx, req, t) 269 if err != nil { 270 return nil, resp, err 271 } 272 273 return t, resp, nil 274 } 275 276 // DeleteTeamByID deletes a team referenced by ID. 277 // 278 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#delete-a-team 279 func (s *TeamsService) DeleteTeamByID(ctx context.Context, orgID, teamID int64) (*Response, error) { 280 u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) 281 req, err := s.client.NewRequest("DELETE", u, nil) 282 if err != nil { 283 return nil, err 284 } 285 286 return s.client.Do(ctx, req, nil) 287 } 288 289 // DeleteTeamBySlug deletes a team reference by slug. 290 // 291 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#delete-a-team 292 func (s *TeamsService) DeleteTeamBySlug(ctx context.Context, org, slug string) (*Response, error) { 293 u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) 294 req, err := s.client.NewRequest("DELETE", u, nil) 295 if err != nil { 296 return nil, err 297 } 298 299 return s.client.Do(ctx, req, nil) 300 } 301 302 // ListChildTeamsByParentID lists child teams for a parent team given parent ID. 303 // 304 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-child-teams 305 func (s *TeamsService) ListChildTeamsByParentID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Team, *Response, error) { 306 u := fmt.Sprintf("organizations/%v/team/%v/teams", orgID, teamID) 307 u, err := addOptions(u, opts) 308 if err != nil { 309 return nil, nil, err 310 } 311 312 req, err := s.client.NewRequest("GET", u, nil) 313 if err != nil { 314 return nil, nil, err 315 } 316 317 var teams []*Team 318 resp, err := s.client.Do(ctx, req, &teams) 319 if err != nil { 320 return nil, resp, err 321 } 322 323 return teams, resp, nil 324 } 325 326 // ListChildTeamsByParentSlug lists child teams for a parent team given parent slug. 327 // 328 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-child-teams 329 func (s *TeamsService) ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Team, *Response, error) { 330 u := fmt.Sprintf("orgs/%v/teams/%v/teams", org, slug) 331 u, err := addOptions(u, opts) 332 if err != nil { 333 return nil, nil, err 334 } 335 336 req, err := s.client.NewRequest("GET", u, nil) 337 if err != nil { 338 return nil, nil, err 339 } 340 341 var teams []*Team 342 resp, err := s.client.Do(ctx, req, &teams) 343 if err != nil { 344 return nil, resp, err 345 } 346 347 return teams, resp, nil 348 } 349 350 // ListTeamReposByID lists the repositories given a team ID that the specified team has access to. 351 // 352 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-repositories 353 func (s *TeamsService) ListTeamReposByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Repository, *Response, error) { 354 u := fmt.Sprintf("organizations/%v/team/%v/repos", orgID, teamID) 355 u, err := addOptions(u, opts) 356 if err != nil { 357 return nil, nil, err 358 } 359 360 req, err := s.client.NewRequest("GET", u, nil) 361 if err != nil { 362 return nil, nil, err 363 } 364 365 // TODO: remove custom Accept header when topics API fully launches. 366 headers := []string{mediaTypeTopicsPreview} 367 req.Header.Set("Accept", strings.Join(headers, ", ")) 368 369 var repos []*Repository 370 resp, err := s.client.Do(ctx, req, &repos) 371 if err != nil { 372 return nil, resp, err 373 } 374 375 return repos, resp, nil 376 } 377 378 // ListTeamReposBySlug lists the repositories given a team slug that the specified team has access to. 379 // 380 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-repositories 381 func (s *TeamsService) ListTeamReposBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Repository, *Response, error) { 382 u := fmt.Sprintf("orgs/%v/teams/%v/repos", org, slug) 383 u, err := addOptions(u, opts) 384 if err != nil { 385 return nil, nil, err 386 } 387 388 req, err := s.client.NewRequest("GET", u, nil) 389 if err != nil { 390 return nil, nil, err 391 } 392 393 // TODO: remove custom Accept header when topics API fully launches. 394 headers := []string{mediaTypeTopicsPreview} 395 req.Header.Set("Accept", strings.Join(headers, ", ")) 396 397 var repos []*Repository 398 resp, err := s.client.Do(ctx, req, &repos) 399 if err != nil { 400 return nil, resp, err 401 } 402 403 return repos, resp, nil 404 } 405 406 // IsTeamRepoByID checks if a team, given its ID, manages the specified repository. If the 407 // repository is managed by team, a Repository is returned which includes the 408 // permissions team has for that repo. 409 // 410 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository 411 func (s *TeamsService) IsTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Repository, *Response, error) { 412 u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) 413 req, err := s.client.NewRequest("GET", u, nil) 414 if err != nil { 415 return nil, nil, err 416 } 417 418 headers := []string{mediaTypeOrgPermissionRepo} 419 req.Header.Set("Accept", strings.Join(headers, ", ")) 420 421 repository := new(Repository) 422 resp, err := s.client.Do(ctx, req, repository) 423 if err != nil { 424 return nil, resp, err 425 } 426 427 return repository, resp, nil 428 } 429 430 // IsTeamRepoBySlug checks if a team, given its slug, manages the specified repository. If the 431 // repository is managed by team, a Repository is returned which includes the 432 // permissions team has for that repo. 433 // 434 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository 435 func (s *TeamsService) IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Repository, *Response, error) { 436 u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) 437 req, err := s.client.NewRequest("GET", u, nil) 438 if err != nil { 439 return nil, nil, err 440 } 441 442 headers := []string{mediaTypeOrgPermissionRepo} 443 req.Header.Set("Accept", strings.Join(headers, ", ")) 444 445 repository := new(Repository) 446 resp, err := s.client.Do(ctx, req, repository) 447 if err != nil { 448 return nil, resp, err 449 } 450 451 return repository, resp, nil 452 } 453 454 // TeamAddTeamRepoOptions specifies the optional parameters to the 455 // TeamsService.AddTeamRepoByID and TeamsService.AddTeamRepoBySlug methods. 456 type TeamAddTeamRepoOptions struct { 457 // Permission specifies the permission to grant the team on this repository. 458 // Possible values are: 459 // pull - team members can pull, but not push to or administer this repository 460 // push - team members can pull and push, but not administer this repository 461 // admin - team members can pull, push and administer this repository 462 // maintain - team members can manage the repository without access to sensitive or destructive actions. 463 // triage - team members can proactively manage issues and pull requests without write access. 464 // 465 // If not specified, the team's permission attribute will be used. 466 Permission string `json:"permission,omitempty"` 467 } 468 469 // AddTeamRepoByID adds a repository to be managed by the specified team given the team ID. 470 // The specified repository must be owned by the organization to which the team 471 // belongs, or a direct fork of a repository owned by the organization. 472 // 473 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions 474 func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { 475 u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) 476 req, err := s.client.NewRequest("PUT", u, opts) 477 if err != nil { 478 return nil, err 479 } 480 481 return s.client.Do(ctx, req, nil) 482 } 483 484 // AddTeamRepoBySlug adds a repository to be managed by the specified team given the team slug. 485 // The specified repository must be owned by the organization to which the team 486 // belongs, or a direct fork of a repository owned by the organization. 487 // 488 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions 489 func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { 490 u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) 491 req, err := s.client.NewRequest("PUT", u, opts) 492 if err != nil { 493 return nil, err 494 } 495 496 return s.client.Do(ctx, req, nil) 497 } 498 499 // RemoveTeamRepoByID removes a repository from being managed by the specified 500 // team given the team ID. Note that this does not delete the repository, it 501 // just removes it from the team. 502 // 503 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-repository-from-a-team 504 func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Response, error) { 505 u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) 506 req, err := s.client.NewRequest("DELETE", u, nil) 507 if err != nil { 508 return nil, err 509 } 510 511 return s.client.Do(ctx, req, nil) 512 } 513 514 // RemoveTeamRepoBySlug removes a repository from being managed by the specified 515 // team given the team slug. Note that this does not delete the repository, it 516 // just removes it from the team. 517 // 518 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-repository-from-a-team 519 func (s *TeamsService) RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Response, error) { 520 u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) 521 req, err := s.client.NewRequest("DELETE", u, nil) 522 if err != nil { 523 return nil, err 524 } 525 526 return s.client.Do(ctx, req, nil) 527 } 528 529 // ListUserTeams lists a user's teams 530 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-teams-for-the-authenticated-user 531 func (s *TeamsService) ListUserTeams(ctx context.Context, opts *ListOptions) ([]*Team, *Response, error) { 532 u := "user/teams" 533 u, err := addOptions(u, opts) 534 if err != nil { 535 return nil, nil, err 536 } 537 538 req, err := s.client.NewRequest("GET", u, nil) 539 if err != nil { 540 return nil, nil, err 541 } 542 543 var teams []*Team 544 resp, err := s.client.Do(ctx, req, &teams) 545 if err != nil { 546 return nil, resp, err 547 } 548 549 return teams, resp, nil 550 } 551 552 // ListTeamProjectsByID lists the organization projects for a team given the team ID. 553 // 554 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-projects 555 func (s *TeamsService) ListTeamProjectsByID(ctx context.Context, orgID, teamID int64) ([]*Project, *Response, error) { 556 u := fmt.Sprintf("organizations/%v/team/%v/projects", orgID, teamID) 557 558 req, err := s.client.NewRequest("GET", u, nil) 559 if err != nil { 560 return nil, nil, err 561 } 562 563 // TODO: remove custom Accept header when this API fully launches. 564 acceptHeaders := []string{mediaTypeProjectsPreview} 565 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 566 567 var projects []*Project 568 resp, err := s.client.Do(ctx, req, &projects) 569 if err != nil { 570 return nil, resp, err 571 } 572 573 return projects, resp, nil 574 } 575 576 // ListTeamProjectsBySlug lists the organization projects for a team given the team slug. 577 // 578 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-projects 579 func (s *TeamsService) ListTeamProjectsBySlug(ctx context.Context, org, slug string) ([]*Project, *Response, error) { 580 u := fmt.Sprintf("orgs/%v/teams/%v/projects", org, slug) 581 582 req, err := s.client.NewRequest("GET", u, nil) 583 if err != nil { 584 return nil, nil, err 585 } 586 587 // TODO: remove custom Accept header when this API fully launches. 588 acceptHeaders := []string{mediaTypeProjectsPreview} 589 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 590 591 var projects []*Project 592 resp, err := s.client.Do(ctx, req, &projects) 593 if err != nil { 594 return nil, resp, err 595 } 596 597 return projects, resp, nil 598 } 599 600 // ReviewTeamProjectsByID checks whether a team, given its ID, has read, write, or admin 601 // permissions for an organization project. 602 // 603 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-project 604 func (s *TeamsService) ReviewTeamProjectsByID(ctx context.Context, orgID, teamID, projectID int64) (*Project, *Response, error) { 605 u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) 606 req, err := s.client.NewRequest("GET", u, nil) 607 if err != nil { 608 return nil, nil, err 609 } 610 611 // TODO: remove custom Accept header when this API fully launches. 612 acceptHeaders := []string{mediaTypeProjectsPreview} 613 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 614 615 projects := &Project{} 616 resp, err := s.client.Do(ctx, req, &projects) 617 if err != nil { 618 return nil, resp, err 619 } 620 621 return projects, resp, nil 622 } 623 624 // ReviewTeamProjectsBySlug checks whether a team, given its slug, has read, write, or admin 625 // permissions for an organization project. 626 // 627 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-project 628 func (s *TeamsService) ReviewTeamProjectsBySlug(ctx context.Context, org, slug string, projectID int64) (*Project, *Response, error) { 629 u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) 630 req, err := s.client.NewRequest("GET", u, nil) 631 if err != nil { 632 return nil, nil, err 633 } 634 635 // TODO: remove custom Accept header when this API fully launches. 636 acceptHeaders := []string{mediaTypeProjectsPreview} 637 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 638 639 projects := &Project{} 640 resp, err := s.client.Do(ctx, req, &projects) 641 if err != nil { 642 return nil, resp, err 643 } 644 645 return projects, resp, nil 646 } 647 648 // TeamProjectOptions specifies the optional parameters to the 649 // TeamsService.AddTeamProject method. 650 type TeamProjectOptions struct { 651 // Permission specifies the permission to grant to the team for this project. 652 // Possible values are: 653 // "read" - team members can read, but not write to or administer this project. 654 // "write" - team members can read and write, but not administer this project. 655 // "admin" - team members can read, write and administer this project. 656 // 657 Permission *string `json:"permission,omitempty"` 658 } 659 660 // AddTeamProjectByID adds an organization project to a team given the team ID. 661 // To add a project to a team or update the team's permission on a project, the 662 // authenticated user must have admin permissions for the project. 663 // 664 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-project-permissions 665 func (s *TeamsService) AddTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64, opts *TeamProjectOptions) (*Response, error) { 666 u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) 667 req, err := s.client.NewRequest("PUT", u, opts) 668 if err != nil { 669 return nil, err 670 } 671 672 // TODO: remove custom Accept header when this API fully launches. 673 acceptHeaders := []string{mediaTypeProjectsPreview} 674 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 675 676 return s.client.Do(ctx, req, nil) 677 } 678 679 // AddTeamProjectBySlug adds an organization project to a team given the team slug. 680 // To add a project to a team or update the team's permission on a project, the 681 // authenticated user must have admin permissions for the project. 682 // 683 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-project-permissions 684 func (s *TeamsService) AddTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64, opts *TeamProjectOptions) (*Response, error) { 685 u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) 686 req, err := s.client.NewRequest("PUT", u, opts) 687 if err != nil { 688 return nil, err 689 } 690 691 // TODO: remove custom Accept header when this API fully launches. 692 acceptHeaders := []string{mediaTypeProjectsPreview} 693 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 694 695 return s.client.Do(ctx, req, nil) 696 } 697 698 // RemoveTeamProjectByID removes an organization project from a team given team ID. 699 // An organization owner or a team maintainer can remove any project from the team. 700 // To remove a project from a team as an organization member, the authenticated user 701 // must have "read" access to both the team and project, or "admin" access to the team 702 // or project. 703 // Note: This endpoint removes the project from the team, but does not delete it. 704 // 705 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-project-from-a-team 706 func (s *TeamsService) RemoveTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64) (*Response, error) { 707 u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) 708 req, err := s.client.NewRequest("DELETE", u, nil) 709 if err != nil { 710 return nil, err 711 } 712 713 // TODO: remove custom Accept header when this API fully launches. 714 acceptHeaders := []string{mediaTypeProjectsPreview} 715 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 716 717 return s.client.Do(ctx, req, nil) 718 } 719 720 // RemoveTeamProjectBySlug removes an organization project from a team given team slug. 721 // An organization owner or a team maintainer can remove any project from the team. 722 // To remove a project from a team as an organization member, the authenticated user 723 // must have "read" access to both the team and project, or "admin" access to the team 724 // or project. 725 // Note: This endpoint removes the project from the team, but does not delete it. 726 // 727 // GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-project-from-a-team 728 func (s *TeamsService) RemoveTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64) (*Response, error) { 729 u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) 730 req, err := s.client.NewRequest("DELETE", u, nil) 731 if err != nil { 732 return nil, err 733 } 734 735 // TODO: remove custom Accept header when this API fully launches. 736 acceptHeaders := []string{mediaTypeProjectsPreview} 737 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 738 739 return s.client.Do(ctx, req, nil) 740 } 741 742 // IDPGroupList represents a list of external identity provider (IDP) groups. 743 type IDPGroupList struct { 744 Groups []*IDPGroup `json:"groups"` 745 } 746 747 // IDPGroup represents an external identity provider (IDP) group. 748 type IDPGroup struct { 749 GroupID *string `json:"group_id,omitempty"` 750 GroupName *string `json:"group_name,omitempty"` 751 GroupDescription *string `json:"group_description,omitempty"` 752 } 753 754 // ListIDPGroupsInOrganization lists IDP groups available in an organization. 755 // 756 // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-an-organization 757 func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opts *ListCursorOptions) (*IDPGroupList, *Response, error) { 758 u := fmt.Sprintf("orgs/%v/team-sync/groups", org) 759 u, err := addOptions(u, opts) 760 if err != nil { 761 return nil, nil, err 762 } 763 764 req, err := s.client.NewRequest("GET", u, nil) 765 if err != nil { 766 return nil, nil, err 767 } 768 769 groups := new(IDPGroupList) 770 resp, err := s.client.Do(ctx, req, groups) 771 if err != nil { 772 return nil, resp, err 773 } 774 775 return groups, resp, nil 776 } 777 778 // ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub 779 // given organization and team IDs. 780 // 781 // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-a-team 782 func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) { 783 u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) 784 785 req, err := s.client.NewRequest("GET", u, nil) 786 if err != nil { 787 return nil, nil, err 788 } 789 790 groups := new(IDPGroupList) 791 resp, err := s.client.Do(ctx, req, groups) 792 if err != nil { 793 return nil, resp, err 794 } 795 796 return groups, resp, nil 797 } 798 799 // ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub 800 // given organization name and team slug. 801 // 802 // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-a-team 803 func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) { 804 u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) 805 806 req, err := s.client.NewRequest("GET", u, nil) 807 if err != nil { 808 return nil, nil, err 809 } 810 811 groups := new(IDPGroupList) 812 resp, err := s.client.Do(ctx, req, groups) 813 if err != nil { 814 return nil, resp, err 815 } 816 817 return groups, resp, nil 818 } 819 820 // CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection 821 // between a team and an IDP group given organization and team IDs. 822 // 823 // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#create-or-update-idp-group-connections 824 func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) { 825 u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) 826 827 req, err := s.client.NewRequest("PATCH", u, opts) 828 if err != nil { 829 return nil, nil, err 830 } 831 832 groups := new(IDPGroupList) 833 resp, err := s.client.Do(ctx, req, groups) 834 if err != nil { 835 return nil, resp, err 836 } 837 838 return groups, resp, nil 839 } 840 841 // CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection 842 // between a team and an IDP group given organization name and team slug. 843 // 844 // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#create-or-update-idp-group-connections 845 func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) { 846 u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) 847 848 req, err := s.client.NewRequest("PATCH", u, opts) 849 if err != nil { 850 return nil, nil, err 851 } 852 853 groups := new(IDPGroupList) 854 resp, err := s.client.Do(ctx, req, groups) 855 if err != nil { 856 return nil, resp, err 857 } 858 859 return groups, resp, nil 860 } 861 862 // ExternalGroupMember represents a member of an external group. 863 type ExternalGroupMember struct { 864 MemberID *int64 `json:"member_id,omitempty"` 865 MemberLogin *string `json:"member_login,omitempty"` 866 MemberName *string `json:"member_name,omitempty"` 867 MemberEmail *string `json:"member_email,omitempty"` 868 } 869 870 // ExternalGroupTeam represents a team connected to an external group. 871 type ExternalGroupTeam struct { 872 TeamID *int64 `json:"team_id,omitempty"` 873 TeamName *string `json:"team_name,omitempty"` 874 } 875 876 // ExternalGroup represents an external group. 877 type ExternalGroup struct { 878 GroupID *int64 `json:"group_id,omitempty"` 879 GroupName *string `json:"group_name,omitempty"` 880 UpdatedAt *Timestamp `json:"updated_at,omitempty"` 881 Teams []*ExternalGroupTeam `json:"teams,omitempty"` 882 Members []*ExternalGroupMember `json:"members,omitempty"` 883 } 884 885 // ExternalGroupList represents a list of external groups. 886 type ExternalGroupList struct { 887 Groups []*ExternalGroup `json:"groups"` 888 } 889 890 // GetExternalGroup fetches an external group. 891 // 892 // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#get-an-external-group 893 func (s *TeamsService) GetExternalGroup(ctx context.Context, org string, groupID int64) (*ExternalGroup, *Response, error) { 894 u := fmt.Sprintf("orgs/%v/external-group/%v", org, groupID) 895 req, err := s.client.NewRequest("GET", u, nil) 896 if err != nil { 897 return nil, nil, err 898 } 899 900 externalGroup := new(ExternalGroup) 901 resp, err := s.client.Do(ctx, req, externalGroup) 902 if err != nil { 903 return nil, resp, err 904 } 905 906 return externalGroup, resp, nil 907 } 908 909 // ListExternalGroupsOptions specifies the optional parameters to the 910 // TeamsService.ListExternalGroups method. 911 type ListExternalGroupsOptions struct { 912 DisplayName *string `url:"display_name,omitempty"` 913 914 ListOptions 915 } 916 917 // ListExternalGroups lists external groups connected to a team on GitHub. 918 // 919 // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#list-external-groups-in-an-organization 920 func (s *TeamsService) ListExternalGroups(ctx context.Context, org string, opts *ListExternalGroupsOptions) (*ExternalGroupList, *Response, error) { 921 u := fmt.Sprintf("orgs/%v/external-groups", org) 922 u, err := addOptions(u, opts) 923 if err != nil { 924 return nil, nil, err 925 } 926 927 req, err := s.client.NewRequest("GET", u, nil) 928 if err != nil { 929 return nil, nil, err 930 } 931 932 externalGroups := new(ExternalGroupList) 933 resp, err := s.client.Do(ctx, req, externalGroups) 934 if err != nil { 935 return nil, resp, err 936 } 937 938 return externalGroups, resp, nil 939 } 940 941 // UpdateConnectedExternalGroup updates the connection between an external group and a team. 942 // 943 // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#update-the-connection-between-an-external-group-and-a-team 944 func (s *TeamsService) UpdateConnectedExternalGroup(ctx context.Context, org, slug string, eg *ExternalGroup) (*ExternalGroup, *Response, error) { 945 u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) 946 947 req, err := s.client.NewRequest("PATCH", u, eg) 948 if err != nil { 949 return nil, nil, err 950 } 951 952 externalGroup := new(ExternalGroup) 953 resp, err := s.client.Do(ctx, req, externalGroup) 954 if err != nil { 955 return nil, resp, err 956 } 957 958 return externalGroup, resp, nil 959 } 960 961 // RemoveConnectedExternalGroup removes the connection between an external group and a team. 962 // 963 // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#remove-the-connection-between-an-external-group-and-a-team 964 func (s *TeamsService) RemoveConnectedExternalGroup(ctx context.Context, org, slug string) (*Response, error) { 965 u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) 966 967 req, err := s.client.NewRequest("DELETE", u, nil) 968 if err != nil { 969 return nil, err 970 } 971 972 return s.client.Do(ctx, req, nil) 973 }