diff --git a/github/github-accessors.go b/github/github-accessors.go index e6f349436b..a825ebfc50 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -5412,6 +5412,22 @@ func (i *Invitation) GetEmail() string { return *i.Email } +// GetFailedAt returns the FailedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedAt() Timestamp { + if i == nil || i.FailedAt == nil { + return Timestamp{} + } + return *i.FailedAt +} + +// GetFailedReason returns the FailedReason field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedReason() string { + if i == nil || i.FailedReason == nil { + return "" + } + return *i.FailedReason +} + // GetID returns the ID field if it's non-nil, zero value otherwise. func (i *Invitation) GetID() int64 { if i == nil || i.ID == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 2c449f8b2d..b5dd546b99 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -6397,6 +6397,26 @@ func TestInvitation_GetEmail(tt *testing.T) { i.GetEmail() } +func TestInvitation_GetFailedAt(tt *testing.T) { + var zeroValue Timestamp + i := &Invitation{FailedAt: &zeroValue} + i.GetFailedAt() + i = &Invitation{} + i.GetFailedAt() + i = nil + i.GetFailedAt() +} + +func TestInvitation_GetFailedReason(tt *testing.T) { + var zeroValue string + i := &Invitation{FailedReason: &zeroValue} + i.GetFailedReason() + i = &Invitation{} + i.GetFailedReason() + i = nil + i.GetFailedReason() +} + func TestInvitation_GetID(tt *testing.T) { var zeroValue int64 i := &Invitation{ID: &zeroValue} diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go index b1dceb0c95..cf0c7ebe81 100644 --- a/github/github-stringify_test.go +++ b/github/github-stringify_test.go @@ -624,8 +624,10 @@ func TestInvitation_String(t *testing.T) { Inviter: &User{}, TeamCount: Int(0), InvitationTeamURL: String(""), + FailedAt: &Timestamp{}, + FailedReason: String(""), } - want := `github.Invitation{ID:0, NodeID:"", Login:"", Email:"", Role:"", Inviter:github.User{}, TeamCount:0, InvitationTeamURL:""}` + want := `github.Invitation{ID:0, NodeID:"", Login:"", Email:"", Role:"", Inviter:github.User{}, TeamCount:0, InvitationTeamURL:"", FailedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, FailedReason:""}` if got := v.String(); got != want { t.Errorf("Invitation.String = %v, want %v", got, want) } diff --git a/github/orgs_members.go b/github/orgs_members.go index 311ebc68f8..f3a2f17c08 100644 --- a/github/orgs_members.go +++ b/github/orgs_members.go @@ -362,3 +362,27 @@ func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, } return orgInvitationTeams, resp, nil } + +// ListFailedOrgInvitations returns a list of failed inviatations. +// +// GitHub API docs: https://docs.github.com/en/rest/reference/orgs#list-failed-organization-invitations +func (s *OrganizationsService) ListFailedOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/failed_invitations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var failedInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &failedInvitations) + if err != nil { + return nil, resp, err + } + + return failedInvitations, resp, nil +} diff --git a/github/orgs_members_test.go b/github/orgs_members_test.go index ec41b3d78b..7172b4c30c 100644 --- a/github/orgs_members_test.go +++ b/github/orgs_members_test.go @@ -744,3 +744,108 @@ func TestOrganizationsService_ListOrgInvitationTeams(t *testing.T) { return resp, err }) } + +func TestOrganizationsService_ListFailedOrgInvitations(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/orgs/o/failed_invitations", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testFormValues(t, r, values{"page": "2", "per_page": "1"}) + fmt.Fprint(w, `[ + { + "id":1, + "login":"monalisa", + "node_id":"MDQ6VXNlcjE=", + "email":"octocat@github.com", + "role":"direct_member", + "created_at":"2016-11-30T06:46:10Z", + "failed_at":"2017-01-02T01:10:00Z", + "failed_reason":"the reason", + "inviter":{ + "login":"other_user", + "id":1, + "node_id":"MDQ6VXNlcjE=", + "avatar_url":"https://github.com/images/error/other_user_happy.gif", + "gravatar_id":"", + "url":"https://api.github.com/users/other_user", + "html_url":"https://github.com/other_user", + "followers_url":"https://api.github.com/users/other_user/followers", + "following_url":"https://api.github.com/users/other_user/following{/other_user}", + "gists_url":"https://api.github.com/users/other_user/gists{/gist_id}", + "starred_url":"https://api.github.com/users/other_user/starred{/owner}{/repo}", + "subscriptions_url":"https://api.github.com/users/other_user/subscriptions", + "organizations_url":"https://api.github.com/users/other_user/orgs", + "repos_url":"https://api.github.com/users/other_user/repos", + "events_url":"https://api.github.com/users/other_user/events{/privacy}", + "received_events_url":"https://api.github.com/users/other_user/received_events", + "type":"User", + "site_admin":false + }, + "team_count":2, + "invitation_team_url":"https://api.github.com/organizations/2/invitations/1/teams" + } + ]`) + }) + + opts := &ListOptions{Page: 2, PerPage: 1} + ctx := context.Background() + failedInvitations, _, err := client.Organizations.ListFailedOrgInvitations(ctx, "o", opts) + if err != nil { + t.Errorf("Organizations.ListFailedOrgInvitations returned error: %v", err) + } + + createdAt := time.Date(2016, time.November, 30, 6, 46, 10, 0, time.UTC) + want := []*Invitation{ + { + ID: Int64(1), + Login: String("monalisa"), + NodeID: String("MDQ6VXNlcjE="), + Email: String("octocat@github.com"), + Role: String("direct_member"), + FailedAt: &Timestamp{time.Date(2017, time.January, 2, 1, 10, 0, 0, time.UTC)}, + FailedReason: String("the reason"), + CreatedAt: &createdAt, + Inviter: &User{ + Login: String("other_user"), + ID: Int64(1), + NodeID: String("MDQ6VXNlcjE="), + AvatarURL: String("https://github.com/images/error/other_user_happy.gif"), + GravatarID: String(""), + URL: String("https://api.github.com/users/other_user"), + HTMLURL: String("https://github.com/other_user"), + FollowersURL: String("https://api.github.com/users/other_user/followers"), + FollowingURL: String("https://api.github.com/users/other_user/following{/other_user}"), + GistsURL: String("https://api.github.com/users/other_user/gists{/gist_id}"), + StarredURL: String("https://api.github.com/users/other_user/starred{/owner}{/repo}"), + SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"), + OrganizationsURL: String("https://api.github.com/users/other_user/orgs"), + ReposURL: String("https://api.github.com/users/other_user/repos"), + EventsURL: String("https://api.github.com/users/other_user/events{/privacy}"), + ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events"), + Type: String("User"), + SiteAdmin: Bool(false), + }, + TeamCount: Int(2), + InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"), + }, + } + + if !reflect.DeepEqual(failedInvitations, want) { + t.Errorf("Organizations.ListFailedOrgInvitations returned %+v, want %+v", failedInvitations, want) + } + + const methodName = "ListFailedOrgInvitations" + testBadOptions(t, methodName, func() error { + _, _, err := client.Organizations.ListFailedOrgInvitations(ctx, "\n", opts) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Organizations.ListFailedOrgInvitations(ctx, "o", opts) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} diff --git a/github/teams.go b/github/teams.go index 2e1cd3dafe..3893d34771 100644 --- a/github/teams.go +++ b/github/teams.go @@ -71,6 +71,8 @@ type Invitation struct { Inviter *User `json:"inviter,omitempty"` TeamCount *int `json:"team_count,omitempty"` InvitationTeamURL *string `json:"invitation_team_url,omitempty"` + FailedAt *Timestamp `json:"failed_at,omitempty"` + FailedReason *string `json:"failed_reason,omitempty"` } func (i Invitation) String() string {