From 231128950f94db98eddfb68f578b09e332605935 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Thu, 19 Sep 2024 10:39:44 +0200 Subject: [PATCH] feat(graph): expose 'signinactivity' for users --- services/graph/pkg/identity/ldap.go | 27 ++++++++++++++++++++++++ services/graph/pkg/identity/ldap_test.go | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/services/graph/pkg/identity/ldap.go b/services/graph/pkg/identity/ldap.go index 85fd159256..0f890c50e5 100644 --- a/services/graph/pkg/identity/ldap.go +++ b/services/graph/pkg/identity/ldap.go @@ -86,6 +86,7 @@ type userAttributeMap struct { accountEnabled string userType string identities string + lastSignIn string } type ldapAttributeValues map[string][]string @@ -120,6 +121,7 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD surname: surNameAttribute, userType: config.UserTypeAttribute, identities: identitiesAttribute, + lastSignIn: lastSignAttribute, } if config.GroupNameAttribute == "" || config.GroupIDAttribute == "" { @@ -831,6 +833,17 @@ func (i *LDAP) createUserModelFromLDAP(e *ldap.Entry) *libregraph.User { if len(identities) > 0 { user.SetIdentities(identities) } + + lastSignIn, err := i.getLastSignTime(e) + switch { + case err == nil: + signinActivity := libregraph.SignInActivity{ + LastSuccessfulSignInDateTime: lastSignIn, + } + user.SetSignInActivity(signinActivity) + case !errors.Is(err, errNotSet): + i.logger.Warn().Err(err).Str("dn", e.DN).Msg("Error getting last signin timestamp") + } return user } i.logger.Warn().Str("dn", e.DN).Msg("Invalid User. Missing username or id attribute") @@ -914,6 +927,7 @@ func (i *LDAP) getUserAttrTypesForSearch() []string { i.userAttributeMap.accountEnabled, i.userAttributeMap.userType, i.userAttributeMap.identities, + i.userAttributeMap.lastSignIn, } } @@ -1259,6 +1273,19 @@ func (i *LDAP) mapLDAPError(err error, errmap ldapResultToErrMap) errorcode.Erro return errorcode.New(errorcode.GeneralException, err.Error()) } +func (i *LDAP) getLastSignTime(e *ldap.Entry) (*time.Time, error) { + dateString := e.GetEqualFoldAttributeValue(i.userAttributeMap.lastSignIn) + if dateString == "" { + return nil, errNotSet + } + t, err := time.Parse(ldapDateFormat, dateString) + if err != nil { + err = fmt.Errorf("error parsing LDAP date: '%s': %w", dateString, err) + return nil, err + } + return &t, nil +} + func isUserEnabledUpdate(user libregraph.UserUpdate) bool { switch { case user.Id != nil, user.DisplayName != nil, diff --git a/services/graph/pkg/identity/ldap_test.go b/services/graph/pkg/identity/ldap_test.go index 730cd2a83d..f9465c0f60 100644 --- a/services/graph/pkg/identity/ldap_test.go +++ b/services/graph/pkg/identity/ldap_test.go @@ -72,7 +72,7 @@ var invalidUserEntry = ldap.NewEntry("uid=user", var logger = log.NewLogger(log.Level("debug")) -var ldapUserAttributes = []string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname", "userEnabledAttribute", "userTypeAttribute", "oCExternalIdentity"} +var ldapUserAttributes = []string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname", "userEnabledAttribute", "userTypeAttribute", "oCExternalIdentity", "oCLastSignInTimestamp"} func TestNewLDAPBackend(t *testing.T) { l := &mocks.Client{}