WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit b4e6a0b

Browse files
committed
Add patch methods for User & Group
1 parent 5724604 commit b4e6a0b

File tree

4 files changed

+314
-0
lines changed

4 files changed

+314
-0
lines changed

github/enterprise_scim.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ const SCIMSchemasURINamespacesUser = "urn:ietf:params:scim:schemas:core:2.0:User
2222
// This constant represents the standard SCIM namespace for list responses used in paginated queries, as defined by RFC 7644.
2323
const SCIMSchemasURINamespacesListResponse = "urn:ietf:params:scim:api:messages:2.0:ListResponse"
2424

25+
// SCIMSchemasURINamespacesPatchOp is the SCIM schema URI namespace for patch operations.
26+
// This constant represents the standard SCIM namespace for patch operations as defined by RFC 7644.
27+
const SCIMSchemasURINamespacesPatchOp = "urn:ietf:params:scim:api:messages:2.0:PatchOp"
28+
2529
// SCIMEnterpriseGroupAttributes represents supported SCIM Enterprise group attributes.
2630
//
2731
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#supported-scim-group-attributes
@@ -140,6 +144,21 @@ type ListProvisionedSCIMUsersEnterpriseOptions struct {
140144
Count *int `url:"count,omitempty"`
141145
}
142146

147+
// SCIMEnterpriseAttributeOptions represents options for UpdateAttributeSCIMGroup or UpdateAttributeSCIMUser.
148+
//
149+
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#update-an-attribute-for-a-scim-enterprise-group
150+
type SCIMEnterpriseAttributeOptions struct {
151+
Schemas []string `json:"schemas"` // The URIs that are used to indicate the namespaces for a SCIM patch operation.
152+
Operations []SCIMEnterpriseAttributeOperations `json:"Operations"` // Set of operations to be performed.
153+
}
154+
155+
// SCIMEnterpriseAttributeOperations represents operations for UpdateAttributeSCIMGroup or UpdateAttributeSCIMUser.
156+
type SCIMEnterpriseAttributeOperations struct {
157+
Op string `json:"op"` // Can be one of: add, replace, remove
158+
Path *string `json:"path,omitempty"` // Path to the attribute being modified (Filters are not supported).
159+
Value *string `json:"value,omitempty"` // New value for the attribute being modified.
160+
}
161+
143162
// ListProvisionedSCIMGroups lists provisioned SCIM groups in an enterprise.
144163
//
145164
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#list-provisioned-scim-groups-for-an-enterprise
@@ -193,3 +212,47 @@ func (s *EnterpriseService) ListProvisionedSCIMUsers(ctx context.Context, enterp
193212

194213
return users, resp, nil
195214
}
215+
216+
// UpdateAttributeSCIMGroup Update a provisioned group’s individual attributes.
217+
//
218+
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#update-an-attribute-for-a-scim-enterprise-group
219+
//
220+
//meta:operation PATCH /scim/v2/enterprises/{enterprise}/Groups/{scim_group_id}
221+
func (s *EnterpriseService) UpdateAttributeSCIMGroup(ctx context.Context, enterprise, scimGroupID string, opts SCIMEnterpriseAttributeOptions) (*SCIMEnterpriseGroupAttributes, *Response, error) {
222+
u := fmt.Sprintf("scim/v2/enterprises/%v/Groups/%v", enterprise, scimGroupID)
223+
req, err := s.client.NewRequest("PATCH", u, opts)
224+
if err != nil {
225+
return nil, nil, err
226+
}
227+
req.Header.Set("Accept", mediaTypeSCIM)
228+
229+
group := new(SCIMEnterpriseGroupAttributes)
230+
resp, err := s.client.Do(ctx, req, group)
231+
if err != nil {
232+
return nil, resp, err
233+
}
234+
235+
return group, resp, nil
236+
}
237+
238+
// UpdateAttributeSCIMUser Update a provisioned user's individual attributes.
239+
//
240+
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#update-an-attribute-for-a-scim-enterprise-user
241+
//
242+
//meta:operation PATCH /scim/v2/enterprises/{enterprise}/Users/{scim_user_id}
243+
func (s *EnterpriseService) UpdateAttributeSCIMUser(ctx context.Context, enterprise, scimUserID string, opts SCIMEnterpriseAttributeOptions) (*SCIMEnterpriseUserAttributes, *Response, error) {
244+
u := fmt.Sprintf("scim/v2/enterprises/%v/Users/%v", enterprise, scimUserID)
245+
req, err := s.client.NewRequest("PATCH", u, opts)
246+
if err != nil {
247+
return nil, nil, err
248+
}
249+
req.Header.Set("Accept", mediaTypeSCIM)
250+
251+
user := new(SCIMEnterpriseUserAttributes)
252+
resp, err := s.client.Do(ctx, req, user)
253+
if err != nil {
254+
return nil, resp, err
255+
}
256+
257+
return user, resp, nil
258+
}

github/enterprise_scim_test.go

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,37 @@ func TestSCIMEnterpriseGroupAttributes_Marshal(t *testing.T) {
244244
testJSONMarshal(t, u, want)
245245
}
246246

247+
func TestSCIMEnterpriseAttributeOptions_Marshal(t *testing.T) {
248+
t.Parallel()
249+
testJSONMarshal(t, &SCIMEnterpriseAttributeOptions{}, "{}")
250+
251+
u := &SCIMEnterpriseAttributeOptions{
252+
Schemas: []string{"s"},
253+
Operations: []SCIMEnterpriseAttributeOperations{{
254+
Op: "o1",
255+
Path: Ptr("p1"),
256+
Value: Ptr("v1"),
257+
},
258+
{
259+
Op: "o2",
260+
}},
261+
}
262+
263+
want := `{
264+
"schemas": ["s"],
265+
"Operations": [{
266+
"op": "o1",
267+
"path": "p1",
268+
"value": "v1"
269+
},
270+
{
271+
"op": "o2"
272+
}]
273+
}`
274+
275+
testJSONMarshal(t, u, want)
276+
}
277+
247278
func TestEnterpriseService_ListProvisionedSCIMGroups(t *testing.T) {
248279
t.Parallel()
249280
client, mux, _ := setup(t)
@@ -445,3 +476,185 @@ func TestEnterpriseService_ListProvisionedSCIMUsers(t *testing.T) {
445476
return resp, err
446477
})
447478
}
479+
480+
func TestEnterpriseService_UpdateAttributeSCIMGroup(t *testing.T) {
481+
t.Parallel()
482+
client, mux, _ := setup(t)
483+
484+
mux.HandleFunc("/scim/v2/enterprises/ee/Groups/abcd", func(w http.ResponseWriter, r *http.Request) {
485+
testMethod(t, r, "PATCH")
486+
testHeader(t, r, "Accept", mediaTypeSCIM)
487+
testBody(t, r, `{"schemas":["`+SCIMSchemasURINamespacesPatchOp+`"],"Operations":[{"op":"replace","path":"displayName","value":"Employees"}]}`+"\n")
488+
w.WriteHeader(http.StatusOK)
489+
fmt.Fprint(w, `{
490+
"schemas": ["`+SCIMSchemasURINamespacesGroups+`"],
491+
"id": "abcd",
492+
"externalId": "8aa1",
493+
"displayName": "Employees",
494+
"members": [{
495+
"value": "879d",
496+
"$ref": "https://api.github.localhost/scim/v2/enterprises/ee/Users/879d",
497+
"display": "User 1"
498+
}],
499+
"meta": {
500+
"resourceType": "Group",
501+
"created": `+referenceTimeStr+`,
502+
"lastModified": `+referenceTimeStr+`,
503+
"location": "https://api.github.localhost/scim/v2/enterprises/ee/Groups/abcd"
504+
}
505+
}`)
506+
})
507+
want := &SCIMEnterpriseGroupAttributes{
508+
Schemas: []string{SCIMSchemasURINamespacesGroups},
509+
ID: Ptr("abcd"),
510+
ExternalID: Ptr("8aa1"),
511+
DisplayName: Ptr("Employees"),
512+
Members: []*SCIMEnterpriseDisplayReference{{
513+
Value: "879d",
514+
Ref: "https://api.github.localhost/scim/v2/enterprises/ee/Users/879d",
515+
Display: Ptr("User 1"),
516+
}},
517+
Meta: &SCIMEnterpriseMeta{
518+
ResourceType: "Group",
519+
Created: &Timestamp{referenceTime},
520+
LastModified: &Timestamp{referenceTime},
521+
Location: Ptr("https://api.github.localhost/scim/v2/enterprises/ee/Groups/abcd"),
522+
},
523+
}
524+
525+
ctx := t.Context()
526+
input := SCIMEnterpriseAttributeOptions{
527+
Schemas: []string{SCIMSchemasURINamespacesPatchOp},
528+
Operations: []SCIMEnterpriseAttributeOperations{{
529+
Op: "replace",
530+
Path: Ptr("displayName"),
531+
Value: Ptr("Employees"),
532+
}},
533+
}
534+
got, _, err := client.Enterprise.UpdateAttributeSCIMGroup(ctx, "ee", "abcd", input)
535+
if err != nil {
536+
t.Fatalf("Enterprise.UpdateAttributeSCIMGroup returned unexpected error: %v", err)
537+
}
538+
if diff := cmp.Diff(want, got); diff != "" {
539+
t.Errorf("Enterprise.UpdateAttributeSCIMGroup diff mismatch (-want +got):\n%v", diff)
540+
}
541+
542+
const methodName = "UpdateAttributeSCIMGroup"
543+
testBadOptions(t, methodName, func() (err error) {
544+
_, _, err = client.Enterprise.UpdateAttributeSCIMGroup(ctx, "\n", "\n", SCIMEnterpriseAttributeOptions{})
545+
return err
546+
})
547+
548+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
549+
got, resp, err := client.Enterprise.UpdateAttributeSCIMGroup(ctx, "ee", "abcd", input)
550+
if got != nil {
551+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
552+
}
553+
return resp, err
554+
})
555+
}
556+
557+
func TestEnterpriseService_UpdateAttributeSCIMUser(t *testing.T) {
558+
t.Parallel()
559+
client, mux, _ := setup(t)
560+
561+
mux.HandleFunc("/scim/v2/enterprises/ee/Users/7fce", func(w http.ResponseWriter, r *http.Request) {
562+
testMethod(t, r, "PATCH")
563+
testHeader(t, r, "Accept", mediaTypeSCIM)
564+
testBody(t, r, `{"schemas":["`+SCIMSchemasURINamespacesPatchOp+`"],"Operations":[{"op":"replace","path":"emails[type eq 'work'].value","value":"[email protected]"},{"op":"replace","path":"name.familyName","value":"updatedFamilyName"}]}`+"\n")
565+
w.WriteHeader(http.StatusOK)
566+
fmt.Fprint(w, `{
567+
"schemas": ["`+SCIMSchemasURINamespacesUser+`"],
568+
"id": "7fce",
569+
"externalId": "e123",
570+
"active": true,
571+
"userName": "e123",
572+
"name": {
573+
"formatted": "John Doe X",
574+
"familyName": "updatedFamilyName",
575+
"givenName": "John",
576+
"middleName": "X"
577+
},
578+
"displayName": "John Doe",
579+
"emails": [{
580+
"value": "[email protected]",
581+
"type": "work",
582+
"primary": true
583+
}],
584+
"roles": [{
585+
"value": "User",
586+
"primary": false
587+
}],
588+
"meta": {
589+
"resourceType": "User",
590+
"created": `+referenceTimeStr+`,
591+
"lastModified": `+referenceTimeStr+`,
592+
"location": "https://api.github.localhost/scim/v2/enterprises/ee/Users/7fce"
593+
}
594+
}`)
595+
})
596+
want := &SCIMEnterpriseUserAttributes{
597+
Schemas: []string{SCIMSchemasURINamespacesUser},
598+
ID: Ptr("7fce"),
599+
ExternalID: "e123",
600+
Active: true,
601+
UserName: "e123",
602+
DisplayName: "John Doe",
603+
Name: &SCIMEnterpriseUserName{
604+
Formatted: Ptr("John Doe X"),
605+
FamilyName: "updatedFamilyName",
606+
GivenName: "John",
607+
MiddleName: Ptr("X"),
608+
},
609+
Emails: []*SCIMEnterpriseUserEmail{{
610+
611+
Type: "work",
612+
Primary: true,
613+
}},
614+
Roles: []*SCIMEnterpriseUserRole{{
615+
Value: "User",
616+
Primary: Ptr(false),
617+
}},
618+
Meta: &SCIMEnterpriseMeta{
619+
ResourceType: "User",
620+
Created: &Timestamp{referenceTime},
621+
LastModified: &Timestamp{referenceTime},
622+
Location: Ptr("https://api.github.localhost/scim/v2/enterprises/ee/Users/7fce"),
623+
},
624+
}
625+
626+
ctx := t.Context()
627+
input := SCIMEnterpriseAttributeOptions{
628+
Schemas: []string{SCIMSchemasURINamespacesPatchOp},
629+
Operations: []SCIMEnterpriseAttributeOperations{{
630+
Op: "replace",
631+
Path: Ptr("emails[type eq 'work'].value"),
632+
Value: Ptr("[email protected]"),
633+
}, {
634+
Op: "replace",
635+
Path: Ptr("name.familyName"),
636+
Value: Ptr("updatedFamilyName"),
637+
}},
638+
}
639+
got, _, err := client.Enterprise.UpdateAttributeSCIMUser(ctx, "ee", "7fce", input)
640+
if err != nil {
641+
t.Fatalf("Enterprise.UpdateAttributeSCIMUser returned unexpected error: %v", err)
642+
}
643+
if diff := cmp.Diff(want, got); diff != "" {
644+
t.Errorf("Enterprise.UpdateAttributeSCIMUser diff mismatch (-want +got):\n%v", diff)
645+
}
646+
647+
const methodName = "UpdateAttributeSCIMUser"
648+
testBadOptions(t, methodName, func() (err error) {
649+
_, _, err = client.Enterprise.UpdateAttributeSCIMUser(ctx, "\n", "\n", SCIMEnterpriseAttributeOptions{})
650+
return err
651+
})
652+
653+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
654+
got, resp, err := client.Enterprise.UpdateAttributeSCIMUser(ctx, "ee", "7fce", input)
655+
if got != nil {
656+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
657+
}
658+
return resp, err
659+
})
660+
}

github/github-accessors.go

Lines changed: 16 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: 22 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)