Repository: owncloud/ocis (go)

Issue:
Return surname and givenName in identity.LDAP
The LDAP properties surname and givenName have recently become supported in user creation, but the properties aren't being populate by `getUserByDN` or `createUserModelFromLdap`, and so the properties are invisible in the returns in the graph API.

Add these properties.

Pull request description:
Display surname and givenName attributes.
This PR makes it so that givenName and surname attributes are returned for users.

Fixes #5386

Patch:
diff --git a/changelog/unreleased/enhancement-name-attributes.md b/changelog/unreleased/enhancement-name-attributes.md
new file mode 100644
index 00000000000..6558b927eec
--- /dev/null
+++ b/changelog/unreleased/enhancement-name-attributes.md
@@ -0,0 +1,6 @@
+Enhancement: display surname and givenName attributes
+
+When querying the graph API, the surname and givenName attributes are now displayed for users.
+
+https://github.com/owncloud/ocis/pull/5388
+https://github.com/owncloud/ocis/issues/5386
diff --git a/services/graph/pkg/identity/ldap.go b/services/graph/pkg/identity/ldap.go
index 9f96812ad74..735f4ee6a4d 100644
--- a/services/graph/pkg/identity/ldap.go
+++ b/services/graph/pkg/identity/ldap.go
@@ -18,6 +18,11 @@ import (
 	"golang.org/x/exp/slices"
 )
 
+const (
+	givenNameAttribute = "givenname"
+	surNameAttribute   = "sn"
+)
+
 type LDAP struct {
 	useServerUUID   bool
 	writeEnabled    bool
@@ -46,6 +51,8 @@ type userAttributeMap struct {
 	id          string
 	mail        string
 	userName    string
+	givenName   string
+	surname     string
 }
 
 type groupAttributeMap struct {
@@ -67,6 +74,8 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD
 		id:          config.UserIDAttribute,
 		mail:        config.UserEmailAttribute,
 		userName:    config.UserNameAttribute,
+		givenName:   givenNameAttribute,
+		surname:     surNameAttribute,
 	}
 
 	if config.GroupNameAttribute == "" || config.GroupIDAttribute == "" {
@@ -266,6 +275,8 @@ func (i *LDAP) getUserByDN(dn string) (*ldap.Entry, error) {
 		i.userAttributeMap.id,
 		i.userAttributeMap.mail,
 		i.userAttributeMap.userName,
+		i.userAttributeMap.surname,
+		i.userAttributeMap.givenName,
 	}
 
 	filter := fmt.Sprintf("(objectClass=%s)", i.userObjectClass)
@@ -373,6 +384,8 @@ func (i *LDAP) getLDAPUserByFilter(filter string) (*ldap.Entry, error) {
 		i.userAttributeMap.id,
 		i.userAttributeMap.mail,
 		i.userAttributeMap.userName,
+		i.userAttributeMap.surname,
+		i.userAttributeMap.givenName,
 	}
 	return i.searchLDAPEntryByFilter(i.userBaseDN, attrs, filter)
 }
@@ -430,6 +443,8 @@ func (i *LDAP) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregra
 			i.userAttributeMap.id,
 			i.userAttributeMap.mail,
 			i.userAttributeMap.userName,
+			i.userAttributeMap.surname,
+			i.userAttributeMap.givenName,
 		},
 		nil,
 	)
@@ -932,6 +947,8 @@ func (i *LDAP) createUserModelFromLDAP(e *ldap.Entry) *libregraph.User {
 
 	opsan := e.GetEqualFoldAttributeValue(i.userAttributeMap.userName)
 	id := e.GetEqualFoldAttributeValue(i.userAttributeMap.id)
+	givenName := e.GetEqualFoldAttributeValue(i.userAttributeMap.givenName)
+	surname := e.GetEqualFoldAttributeValue(i.userAttributeMap.surname)
 
 	if id != "" && opsan != "" {
 		return &libregraph.User{
@@ -939,6 +956,8 @@ func (i *LDAP) createUserModelFromLDAP(e *ldap.Entry) *libregraph.User {
 			Mail:                     pointerOrNil(e.GetEqualFoldAttributeValue(i.userAttributeMap.mail)),
 			OnPremisesSamAccountName: &opsan,
 			Id:                       &id,
+			GivenName:                &givenName,
+			Surname:                  &surname,
 		}
 	}
 	i.logger.Warn().Str("dn", e.DN).Msg("Invalid User. Missing username or id attribute")
@@ -991,11 +1010,11 @@ func (i *LDAP) userToLDAPAttrValues(user libregraph.User) (map[string][]string,
 	} else {
 		sn = *user.OnPremisesSamAccountName
 	}
-	attrs["sn"] = []string{sn}
+	attrs[i.userAttributeMap.surname] = []string{sn}
 
 	// When we get a givenName, we set the attribute.
 	if givenName := user.GetGivenName(); givenName != "" {
-		attrs["givenname"] = []string{givenName}
+		attrs[i.userAttributeMap.givenName] = []string{givenName}
 	}
 
 	if !i.usePwModifyExOp && user.PasswordProfile != nil && user.PasswordProfile.Password != nil {


Test patch:
diff --git a/services/graph/pkg/identity/ldap_test.go b/services/graph/pkg/identity/ldap_test.go
index 3feb5188daa..e36466d17e9 100644
--- a/services/graph/pkg/identity/ldap_test.go
+++ b/services/graph/pkg/identity/ldap_test.go
@@ -45,6 +45,8 @@ var userEntry = ldap.NewEntry("uid=user",
 		"displayname": {"DisplayName"},
 		"mail":        {"user@example"},
 		"entryuuid":   {"abcd-defg"},
+		"sn":          {"surname"},
+		"givenname":   {"givenName"},
 	})
 
 var invalidUserEntry = ldap.NewEntry("uid=user",
@@ -136,6 +138,8 @@ func TestCreateUser(t *testing.T) {
 	assert.Equal(t, displayName, newUser.GetDisplayName())
 	assert.Equal(t, mail, newUser.GetMail())
 	assert.Equal(t, userName, newUser.GetOnPremisesSamAccountName())
+	assert.Equal(t, givenName, newUser.GetGivenName())
+	assert.Equal(t, surname, newUser.GetSurname())
 }
 
 func TestCreateUserModelFromLDAP(t *testing.T) {
@@ -359,14 +363,14 @@ func TestGetGroup(t *testing.T) {
 		BaseDN:     "uid=user,ou=people,dc=test",
 		SizeLimit:  1,
 		Filter:     "(objectClass=inetOrgPerson)",
-		Attributes: []string{"displayname", "entryUUID", "mail", "uid"},
+		Attributes: []string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname"},
 		Controls:   []ldap.Control(nil),
 	}
 	sr3 := &ldap.SearchRequest{
 		BaseDN:     "uid=invalid,ou=people,dc=test",
 		SizeLimit:  1,
 		Filter:     "(objectClass=inetOrgPerson)",
-		Attributes: []string{"displayname", "entryUUID", "mail", "uid"},
+		Attributes: []string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname"},
 		Controls:   []ldap.Control(nil),
 	}
 
@@ -454,14 +458,14 @@ func TestGetGroups(t *testing.T) {
 		BaseDN:     "uid=user,ou=people,dc=test",
 		SizeLimit:  1,
 		Filter:     "(objectClass=inetOrgPerson)",
-		Attributes: []string{"displayname", "entryUUID", "mail", "uid"},
+		Attributes: []string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname"},
 		Controls:   []ldap.Control(nil),
 	}
 	sr3 := &ldap.SearchRequest{
 		BaseDN:     "uid=invalid,ou=people,dc=test",
 		SizeLimit:  1,
 		Filter:     "(objectClass=inetOrgPerson)",
-		Attributes: []string{"displayname", "entryUUID", "mail", "uid"},
+		Attributes: []string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname"},
 		Controls:   []ldap.Control(nil),
 	}