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