Skip to content

Commit

Permalink
Clean up Redis hashes when deleting/anonymizing users #4621
Browse files Browse the repository at this point in the history
ref DEV-1809
  • Loading branch information
tung2744 authored Aug 20, 2024
2 parents 85177c9 + 1ece042 commit 8927ca8
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 2 deletions.
30 changes: 28 additions & 2 deletions pkg/lib/facade/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ type OAuthService interface {
type SessionManager interface {
Delete(session session.ListableSession) error
List(userID string) ([]session.ListableSession, error)
CleanUpForDeletingUserID(userID string) error
}

type StdAttrsService interface {
Expand Down Expand Up @@ -671,7 +672,7 @@ func (c *Coordinator) UserDelete(userID string, isScheduledDeletion bool) error
}

// Sessions:
if err = c.terminateAllSessions(userID); err != nil {
if err = c.terminateAllSessionsAndCleanUp(userID); err != nil {
return err
}

Expand Down Expand Up @@ -826,6 +827,31 @@ func (c *Coordinator) markOAuthEmailAsVerified(info *identity.Info) error {
return nil
}

func (c *Coordinator) terminateAllSessionsAndCleanUp(userID string) error {
err := c.terminateAllSessions(userID)
if err != nil {
return err
}

// According to https://redis.io/docs/latest/commands/hdel/
// When the last field of a Redis hash is deleted, the hash is deleted.
// So in most case, we do not actually need this.
// However, List() does not actually return every key that the Redis hash has,
// so having CleanUpForDeletingUserID ensures we delete the hash.

err = c.IDPSessions.CleanUpForDeletingUserID(userID)
if err != nil {
return err
}

err = c.OAuthSessions.CleanUpForDeletingUserID(userID)
if err != nil {
return err
}

return nil
}

func (c *Coordinator) terminateAllSessions(userID string) error {
idpSessions, err := c.IDPSessions.List(userID)
if err != nil {
Expand Down Expand Up @@ -1062,7 +1088,7 @@ func (c *Coordinator) UserAnonymize(userID string, IsScheduledAnonymization bool
}

// Sessions:
if err = c.terminateAllSessions(userID); err != nil {
if err = c.terminateAllSessionsAndCleanUp(userID); err != nil {
return err
}

Expand Down
14 changes: 14 additions & 0 deletions pkg/lib/oauth/redis/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -727,3 +727,17 @@ func (s *Store) ConsumePreAuthenticatedURLToken(tokenHash string) (*oauth.PreAut

return t, nil
}

func (s *Store) CleanUpForDeletingUserID(userID string) (err error) {
ctx := context.Background()
listKey := offlineGrantListKey(string(s.AppID), userID)

err = s.Redis.WithConn(func(conn *goredis.Conn) error {
_, err := conn.Del(ctx, listKey).Result()
if err != nil {
return err
}
return nil
})
return
}
4 changes: 4 additions & 0 deletions pkg/lib/oauth/session_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,7 @@ func (m *SessionManager) TerminateAllExcept(userID string, currentSession sessio

return deletedSessions, nil
}

func (m *SessionManager) CleanUpForDeletingUserID(userID string) error {
return m.Store.CleanUpForDeletingUserID(userID)
}
2 changes: 2 additions & 0 deletions pkg/lib/oauth/store_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type OfflineGrantStore interface {

ListOfflineGrants(userID string) ([]*OfflineGrant, error)
ListClientOfflineGrants(clientID string, userID string) ([]*OfflineGrant, error)

CleanUpForDeletingUserID(userID string) error
}

type IDPSessionProvider interface {
Expand Down
14 changes: 14 additions & 0 deletions pkg/lib/oauth/store_grant_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/lib/session/idpsession/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ func (m *Manager) TerminateAllExcept(userID string, currentSession session.Resol

return deletedSessions, nil
}

func (m *Manager) CleanUpForDeletingUserID(userID string) error {
return m.Store.CleanUpForDeletingUserID(userID)
}
2 changes: 2 additions & 0 deletions pkg/lib/session/idpsession/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ type Store interface {
Delete(*IDPSession) error
// List lists the sessions belonging to the user, in ascending creation time order
List(userID string) ([]*IDPSession, error)
// CleanUpForDeletingUserID cleans up for a deleting user ID.
CleanUpForDeletingUserID(userID string) error
}
14 changes: 14 additions & 0 deletions pkg/lib/session/idpsession/store_mock_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions pkg/lib/session/idpsession/store_redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,19 @@ func (s *StoreRedis) Delete(session *IDPSession) (err error) {
return
}

func (s *StoreRedis) CleanUpForDeletingUserID(userID string) (err error) {
ctx := context.Background()
listKey := sessionListKey(s.AppID, userID)
err = s.Redis.WithConn(func(conn *goredis.Conn) error {
_, err := conn.Del(ctx, listKey).Result()
if err != nil {
return err
}
return nil
})
return
}

//nolint:gocognit
func (s *StoreRedis) List(userID string) (sessions []*IDPSession, err error) {
ctx := context.Background()
Expand Down

0 comments on commit 8927ca8

Please sign in to comment.