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