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