diff --git a/AUTHORS b/AUTHORS index 5e40cd1f38..a833043b0f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -125,6 +125,7 @@ Derek Jobst DeviousLab Dhi Aurrahman Diego Lapiduz +Diogo Vilela Dmitri Shuralyov dmnlk Don Petersen diff --git a/github/github.go b/github/github.go index 1b41ffdc0e..799608359b 100644 --- a/github/github.go +++ b/github/github.go @@ -179,36 +179,37 @@ type Client struct { common service // Reuse a single struct instead of allocating one for each service on the heap. // Services used for talking to different parts of the GitHub API. - Actions *ActionsService - Activity *ActivityService - Admin *AdminService - Apps *AppsService - Authorizations *AuthorizationsService - Billing *BillingService - Checks *ChecksService - CodeScanning *CodeScanningService - Codespaces *CodespacesService - Dependabot *DependabotService - Enterprise *EnterpriseService - Gists *GistsService - Git *GitService - Gitignores *GitignoresService - Interactions *InteractionsService - IssueImport *IssueImportService - Issues *IssuesService - Licenses *LicensesService - Marketplace *MarketplaceService - Migrations *MigrationService - Organizations *OrganizationsService - Projects *ProjectsService - PullRequests *PullRequestsService - Reactions *ReactionsService - Repositories *RepositoriesService - SCIM *SCIMService - Search *SearchService - SecretScanning *SecretScanningService - Teams *TeamsService - Users *UsersService + Actions *ActionsService + Activity *ActivityService + Admin *AdminService + Apps *AppsService + Authorizations *AuthorizationsService + Billing *BillingService + Checks *ChecksService + CodeScanning *CodeScanningService + Codespaces *CodespacesService + Dependabot *DependabotService + Enterprise *EnterpriseService + Gists *GistsService + Git *GitService + Gitignores *GitignoresService + Interactions *InteractionsService + IssueImport *IssueImportService + Issues *IssuesService + Licenses *LicensesService + Marketplace *MarketplaceService + Migrations *MigrationService + Organizations *OrganizationsService + Projects *ProjectsService + PullRequests *PullRequestsService + Reactions *ReactionsService + Repositories *RepositoriesService + SCIM *SCIMService + Search *SearchService + SecretScanning *SecretScanningService + SecurityAdvisories *SecurityAdvisoriesService + Teams *TeamsService + Users *UsersService } type service struct { @@ -346,6 +347,7 @@ func NewClient(httpClient *http.Client) *Client { c.SCIM = (*SCIMService)(&c.common) c.Search = (*SearchService)(&c.common) c.SecretScanning = (*SecretScanningService)(&c.common) + c.SecurityAdvisories = (*SecurityAdvisoriesService)(&c.common) c.Teams = (*TeamsService)(&c.common) c.Users = (*UsersService)(&c.common) return c diff --git a/github/security_advisories.go b/github/security_advisories.go new file mode 100644 index 0000000000..a75fce54d9 --- /dev/null +++ b/github/security_advisories.go @@ -0,0 +1,37 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +type SecurityAdvisoriesService service + +// RequestCVE requests a Common Vulnerabilities and Exposures (CVE) for a repository security advisory. +// The ghsaID is the GitHub Security Advisory identifier of the advisory. +// +// GitHub API docs: https://docs.github.com/en/rest/security-advisories/repository-advisories#request-a-cve-for-a-repository-security-advisory +func (s *SecurityAdvisoriesService) RequestCVE(ctx context.Context, owner, repo, ghsaID string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories/%v/cve", owner, repo, ghsaID) + + req, err := s.client.NewRequest("POST", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + if _, ok := err.(*AcceptedError); ok { + return resp, nil + } + + return resp, err + } + + return resp, nil +} diff --git a/github/security_advisories_test.go b/github/security_advisories_test.go new file mode 100644 index 0000000000..e4a6fbd7c1 --- /dev/null +++ b/github/security_advisories_test.go @@ -0,0 +1,52 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "net/http" + "testing" +) + +func TestSecurityAdvisoriesService_RequestCVE(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/security-advisories/ghsa_id_ok/cve", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + w.WriteHeader(http.StatusOK) + }) + + mux.HandleFunc("/repos/o/r/security-advisories/ghsa_id_accepted/cve", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + w.WriteHeader(http.StatusAccepted) + }) + + ctx := context.Background() + _, err := client.SecurityAdvisories.RequestCVE(ctx, "o", "r", "ghsa_id_ok") + if err != nil { + t.Errorf("SecurityAdvisoriesService.RequestCVE returned error: %v", err) + } + + _, err = client.SecurityAdvisories.RequestCVE(ctx, "o", "r", "ghsa_id_accepted") + if err != nil { + t.Errorf("SecurityAdvisoriesService.RequestCVE returned error: %v", err) + } + + const methodName = "RequestCVE" + testBadOptions(t, methodName, func() (err error) { + _, err = client.SecurityAdvisories.RequestCVE(ctx, "\n", "\n", "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + resp, err := client.SecurityAdvisories.RequestCVE(ctx, "o", "r", "ghsa_id") + if err == nil { + t.Errorf("testNewRequestAndDoFailure %v should have return err", methodName) + } + return resp, err + }) +}