Skip to content

Commit

Permalink
Merge pull request #120 from philips-software/feature/iam-group-members
Browse files Browse the repository at this point in the history
IAM Group: support for retrieving member details
  • Loading branch information
loafoe authored Jan 27, 2023
2 parents 968f68e + 4878cb0 commit ca2ccbf
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 1 deletion.
74 changes: 74 additions & 0 deletions iam/group.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package iam

import "time"

// Group represents an IAM group resource
type Group struct {
ID string `json:"id,omitempty" validate:""`
Expand All @@ -16,3 +18,75 @@ type GroupResource struct {
OrgID string `json:"orgId"`
GroupDescription string `json:"groupDescription"`
}

// SCIMGroup is the resource returned when getting group resources
type SCIMGroup struct {
Schemas []string `json:"schemas"`
ID string `json:"id"`
DisplayName string `json:"displayName"`
ExtensionGroup ExtensionGroup `json:"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:Group"`
Meta *Meta `json:"meta,omitempty"`
}

type ExtensionGroup struct {
Description string `json:"description"`
Organization Attribute `json:"organization"`
GroupMembers SCIMListResponse `json:"groupMembers"`
}

type ExtensionUser struct {
EmailVerified bool `json:"emailVerified"`
PhoneVerified bool `json:"phoneVerified"`
Organization Attribute `json:"organization"`
}

type SCIMName struct {
FullName string `json:"fullName,omitempty"`
FamilyName string `json:"familyName,omitempty"`
GivenName string `json:"givenName,omitempty"`
MiddleName string `json:"middleName,omitempty"`
}

type SCIMListResponse struct {
Schemas []string `json:"schemas"`
TotalResults int `json:"totalResults"`
StartIndex int `json:"startIndex"`
ItemsPerPage int `json:"itemsPerPage"`
Resources []SCIMListResource `json:"Resources"`
}

type SCIMListResource struct {
Schemas []string `json:"schemas"`
ID string `json:"id"`
Organization Attribute `json:"organization,omitempty"`
Application Attribute `json:"application,omitempty"`
Active bool `json:"active,omitempty"`
SCIMCoreUser
SCIMService
SCIMDevice
ExtensionUser ExtensionUser `json:"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:User,omitempty"`
}

type SCIMService struct {
ServiceId string `json:"serviceId,omitempty"`
ExpiresOn *time.Time `json:"expiresOn,omitempty"`
// Organization
// Application
}

type SCIMDevice struct {
LoginID string `json:"loginId,omitempty"`
// Organization
// Application
// Active
}

type SCIMCoreUser struct {
UserName string `json:"userName,omitempty"`
DisplayName string `json:"displayName,omitempty"`
Name SCIMName `json:"name,omitempty"`
PreferredLanguage string `json:"preferredLanguage,omitempty"`
Locale string `json:"locale,omitempty"`
Emails []Attribute `json:"emails,omitempty"`
PhoneNumbers []Attribute `json:"phoneNumbers,omitempty"`
}
58 changes: 58 additions & 0 deletions iam/groups_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ type GetGroupOptions struct {
MemberID *string `url:"memberId,omitempty"`
}

// SCIMGetGroupOptions describes the query fields to use for querying SCIM Groups
type SCIMGetGroupOptions struct {
IncludeGroupMembersType *string `url:"includeGroupMembersType,omitempty"`
GroupMembersStartIndex *int `url:"groupMembersStartIndex,omitempty"`
GroupMembersCount *int `url:"groupMembersCount,omitempty"`
ExcludedAttributes *string `url:"excludedAttributes,omitempty"`
Attributes *string `url:"attributes,omitempty"`
}

// GroupsService implements actions on Group entities
type GroupsService struct {
client *Client
Expand Down Expand Up @@ -347,3 +356,52 @@ func (g *GroupsService) RemoveServices(group Group, services ...string) (MemberR
return g.RemoveIdentities(group, "SERVICE", chunk...)
})
}

// SCIMGetGroupByID gets a group resource via the SCIM API
func (g *GroupsService) SCIMGetGroupByID(id string, opt *SCIMGetGroupOptions, options ...OptionFunc) (*SCIMGroup, *Response, error) {
req, err := g.client.newRequest(IDM, http.MethodGet, "authorize/scim/v2/Groups/"+id, opt, options)
if err != nil {
return nil, nil, err
}
req.Header.Set("api-version", "1")

var res SCIMGroup

resp, err := g.client.do(req, &res)
if err != nil {
return nil, resp, err
}
return &res, resp, err
}

// SCIMGetGroupByIDAll gets all resources from a group via the SCIM API
func (g *GroupsService) SCIMGetGroupByIDAll(id string, opt *SCIMGetGroupOptions, options ...OptionFunc) (*SCIMGroup, *Response, error) {
var scimGroup *SCIMGroup
var resp *Response
var err error

if opt == nil {
opt = &SCIMGetGroupOptions{}
}
count := 100
current := 1
for {
var data *SCIMGroup
opt.GroupMembersCount = &count
opt.GroupMembersStartIndex = &current
data, resp, err = g.SCIMGetGroupByID(id, opt, options...)
if err != nil {
return scimGroup, resp, err
}
if scimGroup == nil { // First
scimGroup = data
} else {
scimGroup.ExtensionGroup.GroupMembers.Resources = append(scimGroup.ExtensionGroup.GroupMembers.Resources, data.ExtensionGroup.GroupMembers.Resources...)
}
current = current + count
if count < data.ExtensionGroup.GroupMembers.TotalResults {
break // Done
}
}
return scimGroup, resp, err
}
101 changes: 101 additions & 0 deletions iam/groups_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,3 +664,104 @@ func TestRemoveServicesAndDevices(t *testing.T) {
assert.NotNil(t, err)
assert.Nil(t, ok)
}

func TestGetSCIMGroup(t *testing.T) {
teardown := setup(t)
defer teardown()

groupID := "dbf1d779-ab9f-4c27-b4aa-ea75f9efbbc0"
muxIDM.HandleFunc("/authorize/scim/v2/Groups/"+groupID, func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case http.MethodGet:
w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(w, `{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group",
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:Group"
],
"id": "72b8908f-02e5-4939-9e20-ac099ba17e5c",
"displayName": "GroupName",
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:Group": {
"description": "Group Description",
"organization": {
"value": "86d2d0ac-4b12-4546-8d20-4c09a7c87d9c",
"$ref": "https://<idm_base_path>/authorize/scim/v2/Organizations/86d2d0ac-4b12-4546-8d20-4c09a7c87d9c"
},
"groupMembers": {
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:SCIMListResponse"
],
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 1,
"Resources": [
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:User"
],
"id": "72b8908f-02e5-4939-9e20-ac099ba17e5c",
"userName": "wdale",
"name": {
"fullName": "Mr. John Jane Doe, III",
"familyName": "Doe",
"givenName": "John",
"middleName": "Jane"
},
"displayName": "John Doe",
"preferredLanguage": "en-US",
"locale": "en-US",
"active": true,
"emails": [
{
"value": "john.doe@example.com",
"primary": true
}
],
"phoneNumbers": [
{
"value": "555-555-4444",
"type": "work",
"primary": true
}
],
"urn:ietf:params:scim:schemas:extension:philips:hsdp:2.0:User": {
"emailVerified": true,
"phoneVerified": false,
"organization": {
"value": "86d2d0ac-4b12-4546-8d20-4c09a7c87d9c",
"$ref": "https://<idm_base_path>/authorize/scim/v2/Organizations/86d2d0ac-4b12-4546-8d20-4c09a7c87d9c"
}
}
}
]
}
},
"meta": {
"resourceType": "Group",
"created": "2022-03-23T07:09:17.543Z",
"lastModified": "2022-03-23T07:09:30.500Z",
"location": "<idm_base_path>/authorize/scim/v2/Groups/72b8908f-02e5-4939-9e20-ac099ba17e5c",
"version": "W/\"f250dd84f0671c3\""
}
}`)
}
})
var group Group
group.ID = groupID
members := "USER"
scimGroup, resp, err := client.Groups.SCIMGetGroupByID(groupID, &SCIMGetGroupOptions{
IncludeGroupMembersType: &members,
})
if !assert.Nil(t, err) {
return
}
if !assert.NotNil(t, resp) {
return
}
if !assert.NotNil(t, scimGroup) {
return
}
assert.Equal(t, http.StatusOK, resp.StatusCode())
}
2 changes: 1 addition & 1 deletion internal/version.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package internal

const (
LibraryVersion = "0.77.2"
LibraryVersion = "0.77.3"
)

0 comments on commit ca2ccbf

Please sign in to comment.