Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit ca2ccbf

Browse files
authored
Merge pull request #120 from philips-software/feature/iam-group-members
IAM Group: support for retrieving member details
2 parents 968f68e + 4878cb0 commit ca2ccbf

File tree

4 files changed

+234
-1
lines changed

4 files changed

+234
-1
lines changed

iam/group.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package iam
22

3+
import "time"
4+
35
// Group represents an IAM group resource
46
type Group struct {
57
ID string `json:"id,omitempty" validate:""`
@@ -16,3 +18,75 @@ type GroupResource struct {
1618
OrgID string `json:"orgId"`
1719
GroupDescription string `json:"groupDescription"`
1820
}
21+
22+
// SCIMGroup is the resource returned when getting group resources
23+
type SCIMGroup struct {
24+
Schemas []string `json:"schemas"`
25+
ID string `json:"id"`
26+
DisplayName string `json:"displayName"`
27+
ExtensionGroup ExtensionGroup `json:"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:Group"`
28+
Meta *Meta `json:"meta,omitempty"`
29+
}
30+
31+
type ExtensionGroup struct {
32+
Description string `json:"description"`
33+
Organization Attribute `json:"organization"`
34+
GroupMembers SCIMListResponse `json:"groupMembers"`
35+
}
36+
37+
type ExtensionUser struct {
38+
EmailVerified bool `json:"emailVerified"`
39+
PhoneVerified bool `json:"phoneVerified"`
40+
Organization Attribute `json:"organization"`
41+
}
42+
43+
type SCIMName struct {
44+
FullName string `json:"fullName,omitempty"`
45+
FamilyName string `json:"familyName,omitempty"`
46+
GivenName string `json:"givenName,omitempty"`
47+
MiddleName string `json:"middleName,omitempty"`
48+
}
49+
50+
type SCIMListResponse struct {
51+
Schemas []string `json:"schemas"`
52+
TotalResults int `json:"totalResults"`
53+
StartIndex int `json:"startIndex"`
54+
ItemsPerPage int `json:"itemsPerPage"`
55+
Resources []SCIMListResource `json:"Resources"`
56+
}
57+
58+
type SCIMListResource struct {
59+
Schemas []string `json:"schemas"`
60+
ID string `json:"id"`
61+
Organization Attribute `json:"organization,omitempty"`
62+
Application Attribute `json:"application,omitempty"`
63+
Active bool `json:"active,omitempty"`
64+
SCIMCoreUser
65+
SCIMService
66+
SCIMDevice
67+
ExtensionUser ExtensionUser `json:"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:User,omitempty"`
68+
}
69+
70+
type SCIMService struct {
71+
ServiceId string `json:"serviceId,omitempty"`
72+
ExpiresOn *time.Time `json:"expiresOn,omitempty"`
73+
// Organization
74+
// Application
75+
}
76+
77+
type SCIMDevice struct {
78+
LoginID string `json:"loginId,omitempty"`
79+
// Organization
80+
// Application
81+
// Active
82+
}
83+
84+
type SCIMCoreUser struct {
85+
UserName string `json:"userName,omitempty"`
86+
DisplayName string `json:"displayName,omitempty"`
87+
Name SCIMName `json:"name,omitempty"`
88+
PreferredLanguage string `json:"preferredLanguage,omitempty"`
89+
Locale string `json:"locale,omitempty"`
90+
Emails []Attribute `json:"emails,omitempty"`
91+
PhoneNumbers []Attribute `json:"phoneNumbers,omitempty"`
92+
}

iam/groups_service.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ type GetGroupOptions struct {
2121
MemberID *string `url:"memberId,omitempty"`
2222
}
2323

24+
// SCIMGetGroupOptions describes the query fields to use for querying SCIM Groups
25+
type SCIMGetGroupOptions struct {
26+
IncludeGroupMembersType *string `url:"includeGroupMembersType,omitempty"`
27+
GroupMembersStartIndex *int `url:"groupMembersStartIndex,omitempty"`
28+
GroupMembersCount *int `url:"groupMembersCount,omitempty"`
29+
ExcludedAttributes *string `url:"excludedAttributes,omitempty"`
30+
Attributes *string `url:"attributes,omitempty"`
31+
}
32+
2433
// GroupsService implements actions on Group entities
2534
type GroupsService struct {
2635
client *Client
@@ -347,3 +356,52 @@ func (g *GroupsService) RemoveServices(group Group, services ...string) (MemberR
347356
return g.RemoveIdentities(group, "SERVICE", chunk...)
348357
})
349358
}
359+
360+
// SCIMGetGroupByID gets a group resource via the SCIM API
361+
func (g *GroupsService) SCIMGetGroupByID(id string, opt *SCIMGetGroupOptions, options ...OptionFunc) (*SCIMGroup, *Response, error) {
362+
req, err := g.client.newRequest(IDM, http.MethodGet, "authorize/scim/v2/Groups/"+id, opt, options)
363+
if err != nil {
364+
return nil, nil, err
365+
}
366+
req.Header.Set("api-version", "1")
367+
368+
var res SCIMGroup
369+
370+
resp, err := g.client.do(req, &res)
371+
if err != nil {
372+
return nil, resp, err
373+
}
374+
return &res, resp, err
375+
}
376+
377+
// SCIMGetGroupByIDAll gets all resources from a group via the SCIM API
378+
func (g *GroupsService) SCIMGetGroupByIDAll(id string, opt *SCIMGetGroupOptions, options ...OptionFunc) (*SCIMGroup, *Response, error) {
379+
var scimGroup *SCIMGroup
380+
var resp *Response
381+
var err error
382+
383+
if opt == nil {
384+
opt = &SCIMGetGroupOptions{}
385+
}
386+
count := 100
387+
current := 1
388+
for {
389+
var data *SCIMGroup
390+
opt.GroupMembersCount = &count
391+
opt.GroupMembersStartIndex = &current
392+
data, resp, err = g.SCIMGetGroupByID(id, opt, options...)
393+
if err != nil {
394+
return scimGroup, resp, err
395+
}
396+
if scimGroup == nil { // First
397+
scimGroup = data
398+
} else {
399+
scimGroup.ExtensionGroup.GroupMembers.Resources = append(scimGroup.ExtensionGroup.GroupMembers.Resources, data.ExtensionGroup.GroupMembers.Resources...)
400+
}
401+
current = current + count
402+
if count < data.ExtensionGroup.GroupMembers.TotalResults {
403+
break // Done
404+
}
405+
}
406+
return scimGroup, resp, err
407+
}

iam/groups_service_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,3 +664,104 @@ func TestRemoveServicesAndDevices(t *testing.T) {
664664
assert.NotNil(t, err)
665665
assert.Nil(t, ok)
666666
}
667+
668+
func TestGetSCIMGroup(t *testing.T) {
669+
teardown := setup(t)
670+
defer teardown()
671+
672+
groupID := "dbf1d779-ab9f-4c27-b4aa-ea75f9efbbc0"
673+
muxIDM.HandleFunc("/authorize/scim/v2/Groups/"+groupID, func(w http.ResponseWriter, r *http.Request) {
674+
w.Header().Set("Content-Type", "application/json")
675+
switch r.Method {
676+
case http.MethodGet:
677+
w.WriteHeader(http.StatusOK)
678+
_, _ = io.WriteString(w, `{
679+
"schemas": [
680+
"urn:ietf:params:scim:schemas:core:2.0:Group",
681+
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:Group"
682+
],
683+
"id": "72b8908f-02e5-4939-9e20-ac099ba17e5c",
684+
"displayName": "GroupName",
685+
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:Group": {
686+
"description": "Group Description",
687+
"organization": {
688+
"value": "86d2d0ac-4b12-4546-8d20-4c09a7c87d9c",
689+
"$ref": "https://<idm_base_path>/authorize/scim/v2/Organizations/86d2d0ac-4b12-4546-8d20-4c09a7c87d9c"
690+
},
691+
"groupMembers": {
692+
"schemas": [
693+
"urn:ietf:params:scim:api:messages:2.0:SCIMListResponse"
694+
],
695+
"totalResults": 1,
696+
"startIndex": 1,
697+
"itemsPerPage": 1,
698+
"Resources": [
699+
{
700+
"schemas": [
701+
"urn:ietf:params:scim:schemas:core:2.0:User",
702+
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:User"
703+
],
704+
"id": "72b8908f-02e5-4939-9e20-ac099ba17e5c",
705+
"userName": "wdale",
706+
"name": {
707+
"fullName": "Mr. John Jane Doe, III",
708+
"familyName": "Doe",
709+
"givenName": "John",
710+
"middleName": "Jane"
711+
},
712+
"displayName": "John Doe",
713+
"preferredLanguage": "en-US",
714+
"locale": "en-US",
715+
"active": true,
716+
"emails": [
717+
{
718+
"value": "[email protected]",
719+
"primary": true
720+
}
721+
],
722+
"phoneNumbers": [
723+
{
724+
"value": "555-555-4444",
725+
"type": "work",
726+
"primary": true
727+
}
728+
],
729+
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:User": {
730+
"emailVerified": true,
731+
"phoneVerified": false,
732+
"organization": {
733+
"value": "86d2d0ac-4b12-4546-8d20-4c09a7c87d9c",
734+
"$ref": "https://<idm_base_path>/authorize/scim/v2/Organizations/86d2d0ac-4b12-4546-8d20-4c09a7c87d9c"
735+
}
736+
}
737+
}
738+
]
739+
}
740+
},
741+
"meta": {
742+
"resourceType": "Group",
743+
"created": "2022-03-23T07:09:17.543Z",
744+
"lastModified": "2022-03-23T07:09:30.500Z",
745+
"location": "<idm_base_path>/authorize/scim/v2/Groups/72b8908f-02e5-4939-9e20-ac099ba17e5c",
746+
"version": "W/\"f250dd84f0671c3\""
747+
}
748+
}`)
749+
}
750+
})
751+
var group Group
752+
group.ID = groupID
753+
members := "USER"
754+
scimGroup, resp, err := client.Groups.SCIMGetGroupByID(groupID, &SCIMGetGroupOptions{
755+
IncludeGroupMembersType: &members,
756+
})
757+
if !assert.Nil(t, err) {
758+
return
759+
}
760+
if !assert.NotNil(t, resp) {
761+
return
762+
}
763+
if !assert.NotNil(t, scimGroup) {
764+
return
765+
}
766+
assert.Equal(t, http.StatusOK, resp.StatusCode())
767+
}

internal/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package internal
22

33
const (
4-
LibraryVersion = "0.77.2"
4+
LibraryVersion = "0.77.3"
55
)

0 commit comments

Comments
 (0)