@@ -576,7 +576,10 @@ func (g *GraphQuery) fetchGroupMembers(ctx context.Context, client *msgraphsdk.G
576576 // See: https://developer.microsoft.com/en-us/graph/known-issues/?search=25984
577577 requestConfig := & groups.GroupItemRequestBuilderGetRequestConfiguration {
578578 QueryParameters : & groups.GroupItemRequestBuilderGetQueryParameters {
579- Expand : []string {"members" },
579+ // Explicitly select the standard member fields via a nested $select so
580+ // that user properties such as mail and userPrincipalName are returned
581+ // for the expanded members (see issue #115).
582+ Expand : []string {"members($select=id,displayName,mail,userPrincipalName,appId)" },
580583 },
581584 }
582585
@@ -639,24 +642,47 @@ func (g *GraphQuery) extractStringProperty(additionalData map[string]interface{}
639642 return "" , false
640643}
641644
642- // extractUserProperties extracts user-specific properties from additionalData
643- func (g * GraphQuery ) extractUserProperties (additionalData map [string ]interface {}, memberMap map [string ]interface {}) {
644- // Extract mail property
645- if mail , ok := g .extractStringProperty (additionalData , "mail" ); ok {
646- memberMap ["mail" ] = mail
645+ // extractUserProperties extracts user-specific properties.
646+ // Members expanded via $expand are deserialized into typed objects, so the
647+ // values live on the typed getters rather than in additionalData. We prefer
648+ // the typed getters and fall back to additionalData for plain DirectoryObjects.
649+ func (g * GraphQuery ) extractUserProperties (member models.DirectoryObjectable , additionalData map [string ]interface {}, memberMap map [string ]interface {}) {
650+ if user , ok := member .(models.Userable ); ok {
651+ if mail := ptr .Deref (user .GetMail (), "" ); mail != "" {
652+ memberMap ["mail" ] = mail
653+ }
654+ if upn := ptr .Deref (user .GetUserPrincipalName (), "" ); upn != "" {
655+ memberMap ["userPrincipalName" ] = upn
656+ }
647657 }
648658
649- // Extract userPrincipalName property
650- if upn , ok := g .extractStringProperty (additionalData , "userPrincipalName" ); ok {
651- memberMap ["userPrincipalName" ] = upn
659+ // Fall back to additionalData when the typed getters did not provide a value.
660+ if _ , ok := memberMap ["mail" ]; ! ok {
661+ if mail , found := g .extractStringProperty (additionalData , "mail" ); found {
662+ memberMap ["mail" ] = mail
663+ }
664+ }
665+ if _ , ok := memberMap ["userPrincipalName" ]; ! ok {
666+ if upn , found := g .extractStringProperty (additionalData , "userPrincipalName" ); found {
667+ memberMap ["userPrincipalName" ] = upn
668+ }
652669 }
653670}
654671
655- // extractServicePrincipalProperties extracts service principal specific properties
656- func (g * GraphQuery ) extractServicePrincipalProperties (additionalData map [string ]interface {}, memberMap map [string ]interface {}) {
657- // Extract appId property
658- if appID , ok := g .extractStringProperty (additionalData , "appId" ); ok {
659- memberMap ["appId" ] = appID
672+ // extractServicePrincipalProperties extracts service principal specific properties.
673+ // As with users, prefer the typed getter and fall back to additionalData.
674+ func (g * GraphQuery ) extractServicePrincipalProperties (member models.DirectoryObjectable , additionalData map [string ]interface {}, memberMap map [string ]interface {}) {
675+ if sp , ok := member .(models.ServicePrincipalable ); ok {
676+ if appID := ptr .Deref (sp .GetAppId (), "" ); appID != "" {
677+ memberMap ["appId" ] = appID
678+ }
679+ }
680+
681+ // Fall back to additionalData when the typed getter did not provide a value.
682+ if _ , ok := memberMap ["appId" ]; ! ok {
683+ if appID , found := g .extractStringProperty (additionalData , "appId" ); found {
684+ memberMap ["appId" ] = appID
685+ }
660686 }
661687}
662688
@@ -710,9 +736,9 @@ func (g *GraphQuery) processMember(member models.DirectoryObjectable) map[string
710736 // Extract type-specific properties
711737 switch memberType {
712738 case userType :
713- g .extractUserProperties (additionalData , memberMap )
739+ g .extractUserProperties (member , additionalData , memberMap )
714740 case servicePrincipalType :
715- g .extractServicePrincipalProperties (additionalData , memberMap )
741+ g .extractServicePrincipalProperties (member , additionalData , memberMap )
716742 }
717743
718744 return memberMap
0 commit comments