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