Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ coverage.out
# intellij files
.idea/
vendor/
.DS_Store
.DS_Store
.vscode
64 changes: 64 additions & 0 deletions github/github-accessors.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions github/github-accessors_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ type Client struct {
Reactions *ReactionsService
Repositories *RepositoriesService
Search *SearchService
SCIM *SCIMService
Teams *TeamsService
Users *UsersService
}
Expand Down Expand Up @@ -309,6 +310,7 @@ func NewClient(httpClient *http.Client) *Client {
c.Reactions = (*ReactionsService)(&c.common)
c.Repositories = (*RepositoriesService)(&c.common)
c.Search = (*SearchService)(&c.common)
c.SCIM = (*SCIMService)(&c.common)
c.Teams = (*TeamsService)(&c.common)
c.Users = (*UsersService)(&c.common)
return c
Expand Down
141 changes: 141 additions & 0 deletions github/scim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package github

import (
"context"
"encoding/json"
"fmt"
)

// SCIMService provides access to SCIM related functions in the
// GitHub API.
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim
type SCIMService service

type SCIMUserAttributes struct {
UserName string `json:"user_name"` // Configured by the admin. Could be an email, login, or username. (Required.)
Name SCIMUserName `json:"name"` // (Required.)
DisplayName *string `json:"display_name,omitempty"` // The name of the user, suitable for display to end-users. (Optional.)
Emails []*SCIMUserEmails `json:"email"` // User emails. (Required.)
Schemas []*string `json:"schemas,omitempty"` // (Optional.)
ExternalID *string `json:"external_id,omitempty"` // (Optional.)
Groups []*string `json:"groups,omitempty"` // (Optional.)
Active bool `json:"active,omitempty"` // (Optional.)
}

type SCIMUserName struct {
GivenName string `json:"given_name"` // The first name of the user. (Required.)
FamilyName string `json:"family_name"` // The last name of the user. (Required.)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, in some places, https://docs.github.com/en/rest/reference/scim#supported-scim-user-attributes says this should be familyName and in other places it says it should be lastName... this looks like a bug in the GitHub API docs, actually.
But maybe we should assume that this should be familyName here since that is listed more times than lastName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah make sense, I will update that.

Formatted *string `json:"formatted,omitempty"` // (Optional.)
}

type SCIMUserEmails struct {
Value string `json:"value"` // (Required.)
Primary bool `json:"primary,omitempty"` // (Optional.)
Type *string `json:"type,omitempty"` // (Optional.)
}

type ListSCIMProvisionedIdentitiesOptions struct {
StartIndex *int `json:"start_index,omitempty"` // Used for pagination: the index of the first result to return. (Optional.)
Count *int `json:"count,omitempty"` // Used for pagination: the number of results to return. (Optional.)
Filter *string `json:"filter,omitempty"` // Filters results using the equals query parameter operator (eq). You can filter results that are equal to id, userName, emails, and external_id. For example, to search for an identity with the userName Octocat, you would use this query: ?filter=userName%20eq%20\"Octocat\". To filter results for the identity with the email [email protected], you would use this query: ?filter=emails%20eq%20\"[email protected]\". (Optional.)
}

// ListSCIMProvisionedIdentities lists SCIM provisioned identities.
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim#list-scim-provisioned-identities
func (s *SCIMService) ListSCIMProvisionedIdentities(ctx context.Context, org string, opts *ListSCIMProvisionedIdentitiesOptions) (*Response, error) {
u := fmt.Sprintf("scim/v2/organizations/%v/Users", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

// ProvisionAndInviteSCIMUser provisions organization membership for a user, and send an activation email to the email address.
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim#provision-and-invite-a-scim-user
func (s *SCIMService) ProvisionAndInviteSCIMUser(ctx context.Context, org string, opts *SCIMUserAttributes) (*Response, error) {
u := fmt.Sprintf("scim/v2/organizations/%v/Users", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, err
}
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

// GetSCIMProvisioningInfoForUser returns SCIM provisioning information for a user
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim#get-scim-provisioning-information-for-a-user
func (s *SCIMService) GetSCIMProvisioningInfoForUser(ctx context.Context, org, scimUserID string) (*Response, error) {
u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

// UpdateProvisionedOrgMembership updates a provisioned organization membership.
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim#update-a-provisioned-organization-membership
func (s *SCIMService) UpdateProvisionedOrgMembership(ctx context.Context, org, scimUserID string, opts *SCIMUserAttributes) (*Response, error) {
u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
u, err := addOptions(u, opts)
if err != nil {
return nil, err
}
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

type UpdateAttributeForSCIMUserOptions struct {
Schemas []*string `json:"schemas"` // (Optional.)
Operations UpdateAttributeForSCIMUserOperations `json:"operations"` // Set of operations to be performed. (Required.)
}

type UpdateAttributeForSCIMUserOperations struct {
Op string `json:"op"` // (Required.)
Path *string `json:"path,omitempty"` // (Optional.)
Value json.RawMessage `json:"value,omitempty"` // (Optional.)
}

// UpdateAttributeForSCIMUser updates an attribute for an SCIM user.
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim#update-an-attribute-for-a-scim-user
func (s *SCIMService) UpdateAttributeForSCIMUser(ctx context.Context, org, scimUserID string, opts *UpdateAttributeForSCIMUserOptions) (*Response, error) {
u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
u, err := addOptions(u, opts)
if err != nil {
return nil, err
}
req, err := s.client.NewRequest("PATCH", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

// DeleteSCIMUserFromOrg deletes SCIM user from an organization
//
// GitHub API docs: https://docs.github.com/en/rest/reference/scim#delete-a-scim-user-from-an-organization
func (s *SCIMService) DeleteSCIMUserFromOrg(ctx context.Context, org, scimUserID string) (*Response, error) {
u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
Loading