// Copyright 2021 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" "encoding/json" "fmt" ) // SCIMService provides access to SCIM related functions in the // GitHub API. // // GitHub API docs: https://docs.github.com/rest/scim?apiVersion=2022-11-28 type SCIMService service // SCIMUserAttributes represents supported SCIM User attributes. // // GitHub Enterprise Cloud API docs: https://docs.github.com/rest/scim?apiVersion=2022-11-28#supported-scim-user-attributes // GitHub Enterprise Server API docs: https://docs.github.com/en/enterprise-server@latest/rest/enterprise-admin/scim?apiVersion=2022-11-28#supported-scim-user-attributes type SCIMUserAttributes struct { UserName string `json:"userName"` // Configured by the admin. Could be an email, login, or username. (Required.) Name SCIMUserName `json:"name"` // (Required.) DisplayName *string `json:"displayName,omitempty"` // The name of the user, suitable for display to end-users. (Optional.) Emails []*SCIMUserEmail `json:"emails"` // User emails. (Required.) Schemas []string `json:"schemas,omitempty"` // (Optional.) ExternalID *string `json:"externalId,omitempty"` // (Optional.) Groups []string `json:"groups,omitempty"` // (Optional.) Roles []*SCIMUserRole `json:"roles,omitempty"` // (Optional, GHES only.) Active *bool `json:"active,omitempty"` // (Optional.) // Only populated as a result of calling ListSCIMProvisionedIdentitiesOptions or GetSCIMProvisioningInfoForUser: ID *string `json:"id,omitempty"` Meta *SCIMMeta `json:"meta,omitempty"` } // SCIMUserName represents SCIM user information. type SCIMUserName struct { GivenName string `json:"givenName"` // The first name of the user. (Required.) FamilyName string `json:"familyName"` // The family name of the user. (Required.) Formatted *string `json:"formatted,omitempty"` // (Optional.) } // SCIMUserEmail represents SCIM user email. type SCIMUserEmail struct { Value string `json:"value"` // (Required.) Primary *bool `json:"primary,omitempty"` // (Optional.) Type *string `json:"type,omitempty"` // (Optional.) } // SCIMUserRole is an enterprise-wide role granted to the user. This is only // supported in GitHub Enterprise Server, and not GitHub Enterprise Cloud. // See the docs for allowed role names. // // https://docs.github.com/en/enterprise-server@latest/rest/enterprise-admin/scim?apiVersion=2022-11-28#provision-a-scim-enterprise-user type SCIMUserRole struct { Value string `json:"value"` // (Required.) Display *string `json:"display,omitempty"` // (Optional.) Type *string `json:"type,omitempty"` // (Optional.) Primary *bool `json:"primary,omitempty"` // (Optional.) } // SCIMMeta represents metadata about the SCIM resource. type SCIMMeta struct { ResourceType *string `json:"resourceType,omitempty"` Created *Timestamp `json:"created,omitempty"` LastModified *Timestamp `json:"lastModified,omitempty"` Location *string `json:"location,omitempty"` } // SCIMProvisionedIdentities represents the result of calling ListSCIMProvisionedIdentities. type SCIMProvisionedIdentities struct { Schemas []string `json:"schemas,omitempty"` TotalResults *int `json:"totalResults,omitempty"` ItemsPerPage *int `json:"itemsPerPage,omitempty"` StartIndex *int `json:"startIndex,omitempty"` Resources []*SCIMUserAttributes `json:"Resources,omitempty"` } // ListSCIMProvisionedIdentitiesOptions represents options for ListSCIMProvisionedIdentities. // // GitHub API docs: https://docs.github.com/rest/scim#list-scim-provisioned-identities--parameters type ListSCIMProvisionedIdentitiesOptions struct { StartIndex *int `url:"startIndex,omitempty"` // Used for pagination: the index of the first result to return. (Optional.) Count *int `url:"count,omitempty"` // Used for pagination: the number of results to return. (Optional.) // Filter 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 octocat@github.com, you would use this query: ?filter=emails%20eq%20\"octocat@github.com\". // (Optional.) Filter *string `url:"filter,omitempty"` } // ListSCIMProvisionedIdentities lists SCIM provisioned identities. // // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#list-scim-provisioned-identities // //meta:operation GET /scim/v2/organizations/{org}/Users func (s *SCIMService) ListSCIMProvisionedIdentities(ctx context.Context, org string, opts *ListSCIMProvisionedIdentitiesOptions) (*SCIMProvisionedIdentities, *Response, error) { u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) u, err := addOptions(u, opts) if err != nil { return nil, nil, err } req, err := s.client.NewRequest(ctx, "GET", u, nil) if err != nil { return nil, nil, err } var identities *SCIMProvisionedIdentities resp, err := s.client.Do(req, &identities) if err != nil { return nil, resp, err } return identities, resp, nil } // ProvisionAndInviteSCIMUser provisions organization membership for a user, and sends an activation email to the email address. // // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#provision-and-invite-a-scim-user // //meta:operation POST /scim/v2/organizations/{org}/Users func (s *SCIMService) ProvisionAndInviteSCIMUser(ctx context.Context, org string, body *SCIMUserAttributes) (*SCIMUserAttributes, *Response, error) { u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) req, err := s.client.NewRequest(ctx, "POST", u, body) if err != nil { return nil, nil, err } var user *SCIMUserAttributes resp, err := s.client.Do(req, &user) if err != nil { return nil, resp, err } return user, resp, nil } // GetSCIMProvisioningInfoForUser returns SCIM provisioning information for a user. // // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#get-scim-provisioning-information-for-a-user // //meta:operation GET /scim/v2/organizations/{org}/Users/{scim_user_id} func (s *SCIMService) GetSCIMProvisioningInfoForUser(ctx context.Context, org, scimUserID string) (*SCIMUserAttributes, *Response, error) { u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) req, err := s.client.NewRequest(ctx, "GET", u, nil) if err != nil { return nil, nil, err } var user *SCIMUserAttributes resp, err := s.client.Do(req, &user) if err != nil { return nil, resp, err } return user, resp, nil } // UpdateProvisionedOrgMembershipRequest represents the body of a request to // update a provisioned organization membership. type UpdateProvisionedOrgMembershipRequest struct { UserName string `json:"userName"` // Configured by the admin. Could be an email, login, or username. (Required.) Name SCIMUserName `json:"name"` // (Required.) DisplayName *string `json:"displayName,omitempty"` // The name of the user, suitable for display to end-users. (Optional.) Emails []*SCIMUserEmail `json:"emails"` // User emails. (Required.) Schemas []string `json:"schemas,omitempty"` // (Optional.) ExternalID *string `json:"externalId,omitempty"` // (Optional.) Groups []string `json:"groups,omitempty"` // (Optional.) Active *bool `json:"active,omitempty"` // (Optional.) } // UpdateProvisionedOrgMembership updates a provisioned organization membership. // // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#update-a-provisioned-organization-membership // //meta:operation PUT /scim/v2/organizations/{org}/Users/{scim_user_id} func (s *SCIMService) UpdateProvisionedOrgMembership(ctx context.Context, org, scimUserID string, body UpdateProvisionedOrgMembershipRequest) (*SCIMUserAttributes, *Response, error) { u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) req, err := s.client.NewRequest(ctx, "PUT", u, body) if err != nil { return nil, nil, err } var user *SCIMUserAttributes resp, err := s.client.Do(req, &user) if err != nil { return nil, resp, err } return user, resp, nil } // UpdateAttributeForSCIMUserRequest represents the body of a request to update an // attribute for a SCIM user. // // GitHub API docs: https://docs.github.com/rest/scim#update-an-attribute-for-a-scim-user--parameters type UpdateAttributeForSCIMUserRequest struct { Schemas []string `json:"schemas,omitempty"` // (Optional.) Operations []*UpdateAttributeForSCIMUserOperations `json:"Operations"` // Set of operations to be performed. (Required.) } // UpdateAttributeForSCIMUserOperations represents operations for UpdateAttributeForSCIMUser. 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/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#update-an-attribute-for-a-scim-user // //meta:operation PATCH /scim/v2/organizations/{org}/Users/{scim_user_id} func (s *SCIMService) UpdateAttributeForSCIMUser(ctx context.Context, org, scimUserID string, body UpdateAttributeForSCIMUserRequest) (*SCIMUserAttributes, *Response, error) { u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) req, err := s.client.NewRequest(ctx, "PATCH", u, body) if err != nil { return nil, nil, err } var user *SCIMUserAttributes resp, err := s.client.Do(req, &user) if err != nil { return nil, resp, err } return user, resp, nil } // DeleteSCIMUserFromOrg deletes SCIM user from an organization. // // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#delete-a-scim-user-from-an-organization // //meta:operation DELETE /scim/v2/organizations/{org}/Users/{scim_user_id} 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(ctx, "DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(req, nil) }