...

Source file src/github.com/google/go-github/v45/github/teams.go

Documentation: github.com/google/go-github/v45/github

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

View as plain text