Skip to content

Commit 67e5f7b

Browse files
feat: Implement Enterprise SCIM - Get a Group or User (#3889)
1 parent e10040d commit 67e5f7b

File tree

4 files changed

+250
-3
lines changed

4 files changed

+250
-3
lines changed

github/enterprise_scim.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ type ListProvisionedSCIMGroupsEnterpriseOptions struct {
7070
// If specified, only results that match the specified filter will be returned.
7171
// Possible filters are `externalId`, `id`, and `displayName`. For example, `externalId eq "a123"`.
7272
Filter *string `url:"filter,omitempty"`
73-
// Excludes the specified attribute from being returned in the results.
73+
// Excludes the specified attributes from being returned in the results.
7474
ExcludedAttributes *string `url:"excludedAttributes,omitempty"`
7575
// Used for pagination: the starting index of the first result to return when paginating through values.
7676
// Default: 1.
@@ -80,6 +80,14 @@ type ListProvisionedSCIMGroupsEnterpriseOptions struct {
8080
Count *int `url:"count,omitempty"`
8181
}
8282

83+
// GetProvisionedSCIMGroupEnterpriseOptions represents query parameters for GetProvisionedSCIMGroup.
84+
//
85+
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#get-scim-provisioning-information-for-an-enterprise-group
86+
type GetProvisionedSCIMGroupEnterpriseOptions struct {
87+
// Excludes the specified attributes from being returned in the results.
88+
ExcludedAttributes *string `url:"excludedAttributes,omitempty"`
89+
}
90+
8391
// SCIMEnterpriseUserAttributes represents supported SCIM enterprise user attributes, and represents the result of calling UpdateSCIMUserAttribute.
8492
//
8593
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#supported-scim-user-attributes
@@ -162,8 +170,9 @@ type SCIMEnterpriseAttributeOperation struct {
162170

163171
// ListProvisionedSCIMGroups lists provisioned SCIM groups in an enterprise.
164172
//
165-
// You can improve query search time by using the `excludedAttributes` query
166-
// parameter with a value of `members` to exclude members from the response.
173+
// You can improve query search time by using the `excludedAttributes` and
174+
// exclude the specified attributes, e.g. `members` to exclude members from the
175+
// response.
167176
//
168177
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#list-provisioned-scim-groups-for-an-enterprise
169178
//
@@ -381,6 +390,60 @@ func (s *EnterpriseService) ProvisionSCIMUser(ctx context.Context, enterprise st
381390
return userProvisioned, resp, nil
382391
}
383392

393+
// GetProvisionedSCIMGroup gets information about a SCIM group.
394+
//
395+
// You can use the `excludedAttributes` from `opts` and exclude the specified
396+
// attributes from being returned in the results. Using this parameter can
397+
// speed up response time.
398+
//
399+
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#get-scim-provisioning-information-for-an-enterprise-group
400+
//
401+
//meta:operation GET /scim/v2/enterprises/{enterprise}/Groups/{scim_group_id}
402+
func (s *EnterpriseService) GetProvisionedSCIMGroup(ctx context.Context, enterprise, scimGroupID string, opts *GetProvisionedSCIMGroupEnterpriseOptions) (*SCIMEnterpriseGroupAttributes, *Response, error) {
403+
u := fmt.Sprintf("scim/v2/enterprises/%v/Groups/%v", enterprise, scimGroupID)
404+
u, err := addOptions(u, opts)
405+
if err != nil {
406+
return nil, nil, err
407+
}
408+
409+
req, err := s.client.NewRequest("GET", u, nil)
410+
if err != nil {
411+
return nil, nil, err
412+
}
413+
req.Header.Set("Accept", mediaTypeSCIM)
414+
415+
group := new(SCIMEnterpriseGroupAttributes)
416+
resp, err := s.client.Do(ctx, req, group)
417+
if err != nil {
418+
return nil, resp, err
419+
}
420+
421+
return group, resp, nil
422+
}
423+
424+
// GetProvisionedSCIMUser gets information about a SCIM user.
425+
//
426+
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#get-scim-provisioning-information-for-an-enterprise-user
427+
//
428+
//meta:operation GET /scim/v2/enterprises/{enterprise}/Users/{scim_user_id}
429+
func (s *EnterpriseService) GetProvisionedSCIMUser(ctx context.Context, enterprise, scimUserID string) (*SCIMEnterpriseUserAttributes, *Response, error) {
430+
u := fmt.Sprintf("scim/v2/enterprises/%v/Users/%v", enterprise, scimUserID)
431+
432+
req, err := s.client.NewRequest("GET", u, nil)
433+
if err != nil {
434+
return nil, nil, err
435+
}
436+
req.Header.Set("Accept", mediaTypeSCIM)
437+
438+
user := new(SCIMEnterpriseUserAttributes)
439+
resp, err := s.client.Do(ctx, req, user)
440+
if err != nil {
441+
return nil, resp, err
442+
}
443+
444+
return user, resp, nil
445+
}
446+
384447
// DeleteSCIMGroup deletes a SCIM group from an enterprise.
385448
//
386449
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#delete-a-scim-group-from-an-enterprise

github/enterprise_scim_test.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ func TestListProvisionedSCIMGroupsEnterpriseOptions_Marshal(t *testing.T) {
182182
testJSONMarshal(t, u, want)
183183
}
184184

185+
func TestGetProvisionedSCIMGroupEnterpriseOptions_Marshal(t *testing.T) {
186+
t.Parallel()
187+
testJSONMarshal(t, &GetProvisionedSCIMGroupEnterpriseOptions{}, "{}")
188+
189+
u := &GetProvisionedSCIMGroupEnterpriseOptions{ExcludedAttributes: Ptr("ea")}
190+
want := `{"excludedAttributes": "ea"}`
191+
testJSONMarshal(t, u, want)
192+
}
193+
185194
func TestListProvisionedSCIMUsersEnterpriseOptions_Marshal(t *testing.T) {
186195
t.Parallel()
187196
testJSONMarshal(t, &ListProvisionedSCIMUsersEnterpriseOptions{}, "{}")
@@ -1014,6 +1023,162 @@ func TestEnterpriseService_ProvisionSCIMUser(t *testing.T) {
10141023
})
10151024
}
10161025

1026+
func TestEnterpriseService_GetProvisionedSCIMGroup(t *testing.T) {
1027+
t.Parallel()
1028+
client, mux, _ := setup(t)
1029+
1030+
mux.HandleFunc("/scim/v2/enterprises/ee/Groups/914a", func(w http.ResponseWriter, r *http.Request) {
1031+
testMethod(t, r, "GET")
1032+
testHeader(t, r, "Accept", mediaTypeSCIM)
1033+
testFormValues(t, r, values{"excludedAttributes": "members,meta"})
1034+
w.WriteHeader(http.StatusOK)
1035+
fmt.Fprint(w, `{
1036+
"schemas": ["`+SCIMSchemasURINamespacesGroups+`"],
1037+
"id": "914a",
1038+
"externalId": "de88",
1039+
"displayName": "gn1",
1040+
"meta": {
1041+
"resourceType": "Group",
1042+
"created": `+referenceTimeStr+`,
1043+
"lastModified": `+referenceTimeStr+`,
1044+
"location": "https://api.github.com/scim/v2/enterprises/ee/Groups/914a"
1045+
},
1046+
"members": [{
1047+
"value": "e7f9",
1048+
"$ref": "https://api.github.com/scim/v2/enterprises/ee/Users/e7f9",
1049+
"display": "d1"
1050+
}]
1051+
}`)
1052+
})
1053+
1054+
ctx := t.Context()
1055+
opts := &GetProvisionedSCIMGroupEnterpriseOptions{ExcludedAttributes: Ptr("members,meta")}
1056+
got, _, err := client.Enterprise.GetProvisionedSCIMGroup(ctx, "ee", "914a", opts)
1057+
if err != nil {
1058+
t.Fatalf("Enterprise.GetProvisionedSCIMGroup returned unexpected error: %v", err)
1059+
}
1060+
1061+
want := &SCIMEnterpriseGroupAttributes{
1062+
ID: Ptr("914a"),
1063+
Meta: &SCIMEnterpriseMeta{
1064+
ResourceType: "Group",
1065+
Created: &Timestamp{referenceTime},
1066+
LastModified: &Timestamp{referenceTime},
1067+
Location: Ptr("https://api.github.com/scim/v2/enterprises/ee/Groups/914a"),
1068+
},
1069+
DisplayName: Ptr("gn1"),
1070+
Schemas: []string{SCIMSchemasURINamespacesGroups},
1071+
ExternalID: Ptr("de88"),
1072+
Members: []*SCIMEnterpriseDisplayReference{{
1073+
Value: "e7f9",
1074+
Ref: Ptr("https://api.github.com/scim/v2/enterprises/ee/Users/e7f9"),
1075+
Display: Ptr("d1"),
1076+
}},
1077+
}
1078+
1079+
if diff := cmp.Diff(want, got); diff != "" {
1080+
t.Fatalf("Enterprise.GetProvisionedSCIMGroup diff mismatch (-want +got):\n%v", diff)
1081+
}
1082+
1083+
const methodName = "GetProvisionedSCIMGroup"
1084+
testBadOptions(t, methodName, func() (err error) {
1085+
_, _, err = client.Enterprise.GetProvisionedSCIMGroup(ctx, "ee", "\n", opts)
1086+
return err
1087+
})
1088+
1089+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
1090+
got, resp, err := client.Enterprise.GetProvisionedSCIMGroup(ctx, "ee", "914a", opts)
1091+
if got != nil {
1092+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
1093+
}
1094+
return resp, err
1095+
})
1096+
}
1097+
1098+
func TestEnterpriseService_GetProvisionedSCIMUser(t *testing.T) {
1099+
t.Parallel()
1100+
client, mux, _ := setup(t)
1101+
1102+
mux.HandleFunc("/scim/v2/enterprises/ee/Users/5fc0", func(w http.ResponseWriter, r *http.Request) {
1103+
testMethod(t, r, "GET")
1104+
testHeader(t, r, "Accept", mediaTypeSCIM)
1105+
w.WriteHeader(http.StatusOK)
1106+
fmt.Fprint(w, `{
1107+
"schemas": ["`+SCIMSchemasURINamespacesUser+`"],
1108+
"id": "5fc0",
1109+
"externalId": "00u1",
1110+
"userName": "octocat@github.com",
1111+
"displayName": "Mona Octocat",
1112+
"name": {
1113+
"givenName": "Mona",
1114+
"familyName": "Octocat",
1115+
"formatted": "Mona Octocat"
1116+
},
1117+
"emails": [
1118+
{
1119+
"value": "octocat@github.com",
1120+
"primary": true
1121+
}
1122+
],
1123+
"active": true,
1124+
"meta": {
1125+
"resourceType": "User",
1126+
"created": `+referenceTimeStr+`,
1127+
"lastModified": `+referenceTimeStr+`,
1128+
"location": "https://api.github.com/scim/v2/enterprises/ee/Users/5fc0"
1129+
}
1130+
}`)
1131+
})
1132+
1133+
ctx := t.Context()
1134+
got, _, err := client.Enterprise.GetProvisionedSCIMUser(ctx, "ee", "5fc0")
1135+
if err != nil {
1136+
t.Fatalf("Enterprise.GetProvisionedSCIMUser returned unexpected error: %v", err)
1137+
}
1138+
1139+
want := &SCIMEnterpriseUserAttributes{
1140+
Schemas: []string{SCIMSchemasURINamespacesUser},
1141+
ID: Ptr("5fc0"),
1142+
ExternalID: "00u1",
1143+
UserName: "octocat@github.com",
1144+
DisplayName: "Mona Octocat",
1145+
Name: &SCIMEnterpriseUserName{
1146+
GivenName: "Mona",
1147+
FamilyName: "Octocat",
1148+
Formatted: Ptr("Mona Octocat"),
1149+
},
1150+
Emails: []*SCIMEnterpriseUserEmail{{
1151+
Value: "octocat@github.com",
1152+
Primary: true,
1153+
}},
1154+
Active: true,
1155+
Meta: &SCIMEnterpriseMeta{
1156+
ResourceType: "User",
1157+
Created: &Timestamp{referenceTime},
1158+
LastModified: &Timestamp{referenceTime},
1159+
Location: Ptr("https://api.github.com/scim/v2/enterprises/ee/Users/5fc0"),
1160+
},
1161+
}
1162+
1163+
if diff := cmp.Diff(want, got); diff != "" {
1164+
t.Fatalf("Enterprise.GetProvisionedSCIMUser diff mismatch (-want +got):\n%v", diff)
1165+
}
1166+
1167+
const methodName = "GetProvisionedSCIMUser"
1168+
testBadOptions(t, methodName, func() (err error) {
1169+
_, _, err = client.Enterprise.GetProvisionedSCIMUser(ctx, "\n", "\n")
1170+
return err
1171+
})
1172+
1173+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
1174+
got, resp, err := client.Enterprise.GetProvisionedSCIMUser(ctx, "ee", "5fc0")
1175+
if got != nil {
1176+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
1177+
}
1178+
return resp, err
1179+
})
1180+
}
1181+
10171182
func TestEnterpriseService_DeleteSCIMGroup(t *testing.T) {
10181183
t.Parallel()
10191184
client, mux, _ := setup(t)

github/github-accessors.go

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

github/github-accessors_test.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)