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