...

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

Documentation: github.com/google/go-github/v55/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  )
    14  
    15  // TeamsService provides access to the team-related functions
    16  // in the GitHub API.
    17  //
    18  // GitHub API docs: https://docs.github.com/en/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/en/rest/teams/teams#list-teams
    85  func (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/rest/teams/teams#get-a-team-by-name
   109  func (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/rest/teams/teams#get-a-team-by-name
   128  func (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.
   145  type 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  
   171  func (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/rest/teams/teams#create-a-team
   178  func (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.
   197  type 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.
   210  func 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/rest/teams/teams#update-a-team
   224  func (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/rest/teams/teams#update-a-team
   251  func (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/rest/teams/teams#delete-a-team
   278  func (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/rest/teams/teams#delete-a-team
   291  func (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/rest/teams/teams#list-child-teams
   304  func (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/rest/teams/teams#list-child-teams
   328  func (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/rest/teams/teams#list-team-repositories
   352  func (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/rest/teams/teams#list-team-repositories
   380  func (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/rest/teams/teams#check-team-permissions-for-a-repository
   410  func (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/rest/teams/teams#check-team-permissions-for-a-repository
   434  func (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.AddTeamRepoByID and TeamsService.AddTeamRepoBySlug methods.
   455  type 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/rest/teams/teams#add-or-update-team-repository-permissions
   473  func (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/rest/teams/teams#add-or-update-team-repository-permissions
   488  func (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/rest/teams/teams#remove-a-repository-from-a-team
   503  func (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/rest/teams/teams#remove-a-repository-from-a-team
   518  func (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/rest/teams/teams#list-teams-for-the-authenticated-user
   530  func (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/rest/teams/teams#list-team-projects
   554  func (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/rest/teams/teams#list-team-projects
   578  func (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/rest/teams/teams#check-team-permissions-for-a-project
   603  func (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/rest/teams/teams#check-team-permissions-for-a-project
   627  func (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.
   649  type 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/rest/teams/teams#add-or-update-team-project-permissions
   664  func (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/rest/teams/teams#add-or-update-team-project-permissions
   683  func (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/rest/teams/teams#remove-a-project-from-a-team
   705  func (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/rest/teams/teams#remove-a-project-from-a-team
   727  func (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.
   742  type IDPGroupList struct {
   743  	Groups []*IDPGroup `json:"groups"`
   744  }
   745  
   746  // IDPGroup represents an external identity provider (IDP) group.
   747  type 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/rest/teams/team-sync#list-idp-groups-for-an-organization
   756  func (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  
   774  	return groups, resp, nil
   775  }
   776  
   777  // ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub
   778  // given organization and team IDs.
   779  //
   780  // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-a-team
   781  func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) {
   782  	u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID)
   783  
   784  	req, err := s.client.NewRequest("GET", u, nil)
   785  	if err != nil {
   786  		return nil, nil, err
   787  	}
   788  
   789  	groups := new(IDPGroupList)
   790  	resp, err := s.client.Do(ctx, req, groups)
   791  	if err != nil {
   792  		return nil, resp, err
   793  	}
   794  
   795  	return groups, resp, nil
   796  }
   797  
   798  // ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub
   799  // given organization name and team slug.
   800  //
   801  // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-a-team
   802  func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) {
   803  	u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug)
   804  
   805  	req, err := s.client.NewRequest("GET", u, nil)
   806  	if err != nil {
   807  		return nil, nil, err
   808  	}
   809  
   810  	groups := new(IDPGroupList)
   811  	resp, err := s.client.Do(ctx, req, groups)
   812  	if err != nil {
   813  		return nil, resp, err
   814  	}
   815  
   816  	return groups, resp, nil
   817  }
   818  
   819  // CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection
   820  // between a team and an IDP group given organization and team IDs.
   821  //
   822  // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#create-or-update-idp-group-connections
   823  func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) {
   824  	u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID)
   825  
   826  	req, err := s.client.NewRequest("PATCH", u, opts)
   827  	if err != nil {
   828  		return nil, nil, err
   829  	}
   830  
   831  	groups := new(IDPGroupList)
   832  	resp, err := s.client.Do(ctx, req, groups)
   833  	if err != nil {
   834  		return nil, resp, err
   835  	}
   836  
   837  	return groups, resp, nil
   838  }
   839  
   840  // CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection
   841  // between a team and an IDP group given organization name and team slug.
   842  //
   843  // GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#create-or-update-idp-group-connections
   844  func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) {
   845  	u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug)
   846  
   847  	req, err := s.client.NewRequest("PATCH", u, opts)
   848  	if err != nil {
   849  		return nil, nil, err
   850  	}
   851  
   852  	groups := new(IDPGroupList)
   853  	resp, err := s.client.Do(ctx, req, groups)
   854  	if err != nil {
   855  		return nil, resp, err
   856  	}
   857  
   858  	return groups, resp, nil
   859  }
   860  
   861  // ExternalGroupMember represents a member of an external group.
   862  type ExternalGroupMember struct {
   863  	MemberID    *int64  `json:"member_id,omitempty"`
   864  	MemberLogin *string `json:"member_login,omitempty"`
   865  	MemberName  *string `json:"member_name,omitempty"`
   866  	MemberEmail *string `json:"member_email,omitempty"`
   867  }
   868  
   869  // ExternalGroupTeam represents a team connected to an external group.
   870  type ExternalGroupTeam struct {
   871  	TeamID   *int64  `json:"team_id,omitempty"`
   872  	TeamName *string `json:"team_name,omitempty"`
   873  }
   874  
   875  // ExternalGroup represents an external group.
   876  type ExternalGroup struct {
   877  	GroupID   *int64                 `json:"group_id,omitempty"`
   878  	GroupName *string                `json:"group_name,omitempty"`
   879  	UpdatedAt *Timestamp             `json:"updated_at,omitempty"`
   880  	Teams     []*ExternalGroupTeam   `json:"teams,omitempty"`
   881  	Members   []*ExternalGroupMember `json:"members,omitempty"`
   882  }
   883  
   884  // ExternalGroupList represents a list of external groups.
   885  type ExternalGroupList struct {
   886  	Groups []*ExternalGroup `json:"groups"`
   887  }
   888  
   889  // GetExternalGroup fetches an external group.
   890  //
   891  // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#get-an-external-group
   892  func (s *TeamsService) GetExternalGroup(ctx context.Context, org string, groupID int64) (*ExternalGroup, *Response, error) {
   893  	u := fmt.Sprintf("orgs/%v/external-group/%v", org, groupID)
   894  	req, err := s.client.NewRequest("GET", u, nil)
   895  	if err != nil {
   896  		return nil, nil, err
   897  	}
   898  
   899  	externalGroup := new(ExternalGroup)
   900  	resp, err := s.client.Do(ctx, req, externalGroup)
   901  	if err != nil {
   902  		return nil, resp, err
   903  	}
   904  
   905  	return externalGroup, resp, nil
   906  }
   907  
   908  // ListExternalGroupsOptions specifies the optional parameters to the
   909  // TeamsService.ListExternalGroups method.
   910  type ListExternalGroupsOptions struct {
   911  	DisplayName *string `url:"display_name,omitempty"`
   912  
   913  	ListOptions
   914  }
   915  
   916  // ListExternalGroups lists external groups in an organization on GitHub.
   917  //
   918  // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#list-external-groups-in-an-organization
   919  func (s *TeamsService) ListExternalGroups(ctx context.Context, org string, opts *ListExternalGroupsOptions) (*ExternalGroupList, *Response, error) {
   920  	u := fmt.Sprintf("orgs/%v/external-groups", org)
   921  	u, err := addOptions(u, opts)
   922  	if err != nil {
   923  		return nil, nil, err
   924  	}
   925  
   926  	req, err := s.client.NewRequest("GET", u, nil)
   927  	if err != nil {
   928  		return nil, nil, err
   929  	}
   930  
   931  	externalGroups := new(ExternalGroupList)
   932  	resp, err := s.client.Do(ctx, req, externalGroups)
   933  	if err != nil {
   934  		return nil, resp, err
   935  	}
   936  
   937  	return externalGroups, resp, nil
   938  }
   939  
   940  // ListExternalGroupsForTeamBySlug lists external groups connected to a team on GitHub.
   941  //
   942  // GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#list-a-connection-between-an-external-group-and-a-team
   943  func (s *TeamsService) ListExternalGroupsForTeamBySlug(ctx context.Context, org, slug string) (*ExternalGroupList, *Response, error) {
   944  	u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug)
   945  
   946  	req, err := s.client.NewRequest("GET", u, nil)
   947  	if err != nil {
   948  		return nil, nil, err
   949  	}
   950  
   951  	externalGroups := new(ExternalGroupList)
   952  	resp, err := s.client.Do(ctx, req, externalGroups)
   953  	if err != nil {
   954  		return nil, resp, err
   955  	}
   956  
   957  	return externalGroups, resp, nil
   958  }
   959  
   960  // UpdateConnectedExternalGroup updates the connection between an external group and a team.
   961  //
   962  // 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
   963  func (s *TeamsService) UpdateConnectedExternalGroup(ctx context.Context, org, slug string, eg *ExternalGroup) (*ExternalGroup, *Response, error) {
   964  	u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug)
   965  
   966  	req, err := s.client.NewRequest("PATCH", u, eg)
   967  	if err != nil {
   968  		return nil, nil, err
   969  	}
   970  
   971  	externalGroup := new(ExternalGroup)
   972  	resp, err := s.client.Do(ctx, req, externalGroup)
   973  	if err != nil {
   974  		return nil, resp, err
   975  	}
   976  
   977  	return externalGroup, resp, nil
   978  }
   979  
   980  // RemoveConnectedExternalGroup removes the connection between an external group and a team.
   981  //
   982  // 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
   983  func (s *TeamsService) RemoveConnectedExternalGroup(ctx context.Context, org, slug string) (*Response, error) {
   984  	u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug)
   985  
   986  	req, err := s.client.NewRequest("DELETE", u, nil)
   987  	if err != nil {
   988  		return nil, err
   989  	}
   990  
   991  	return s.client.Do(ctx, req, nil)
   992  }
   993  

View as plain text