diff --git a/auth_manager.go b/auth_manager.go index 211c297236a..d0f2497681e 100644 --- a/auth_manager.go +++ b/auth_manager.go @@ -211,16 +211,16 @@ func (b *DefaultSessionManager) ResetQuota(keyName string, session *user.Session func (b *DefaultSessionManager) UpdateSession(keyName string, session *user.SessionState, resetTTLTo int64, hashed bool) error { - // async update and return if needed + // async update if b.asyncWrites { sessionUpdate := &SessionUpdate{ isHashed: hashed, keyVal: keyName, - session: session, + session: session.Clone(), // send clone of session in update to prevent concurrent map access ttl: resetTTLTo, } - // send sessionupdate object through channel to pool + // send sessionUpdate object through channel to pool defaultSessionUpdater.updateChan <- sessionUpdate return nil diff --git a/user/session.go b/user/session.go index 92cdce6014e..c423a220cbb 100644 --- a/user/session.go +++ b/user/session.go @@ -91,6 +91,61 @@ type SessionState struct { keyHash string } +// Clone returns deep copy of the given session +func (s *SessionState) Clone() *SessionState { + clonedSession := &SessionState{} + *clonedSession = *s + + // copy AccessRights map + clonedSession.AccessRights = map[string]AccessDefinition{} + for apiID, access := range s.AccessRights { + clonedAccess := access + // copy versions + clonedAccess.Versions = make([]string, len(access.Versions)) + copy(clonedAccess.Versions, access.Versions) + // copy AllowedURLs + clonedAccess.AllowedURLs = make([]AccessSpec, len(access.AllowedURLs)) + copy(clonedAccess.AllowedURLs, access.AllowedURLs) + for index, url := range access.AllowedURLs { + clonedAccess.AllowedURLs[index].Methods = make([]string, len(url.Methods)) + copy(clonedAccess.AllowedURLs[index].Methods, url.Methods) + } + // copy API limit + if access.Limit != nil { + clonedAccess.Limit = &APILimit{} + *clonedAccess.Limit = *access.Limit + } + + clonedSession.AccessRights[apiID] = clonedAccess + } + + // copy OauthKeys map + clonedSession.OauthKeys = map[string]string{} + for key, val := range s.OauthKeys { + clonedSession.OauthKeys[key] = val + } + + // copy ApplyPolicies slice + clonedSession.ApplyPolicies = make([]string, len(s.ApplyPolicies)) + copy(clonedSession.ApplyPolicies, s.ApplyPolicies) + + // copy TriggerLimits slice + clonedSession.Monitor.TriggerLimits = make([]float64, len(s.Monitor.TriggerLimits)) + copy(clonedSession.Monitor.TriggerLimits, s.Monitor.TriggerLimits) + + // copy MetaData map + clonedSession.MetaData = map[string]interface{}{} + for key, val := range s.MetaData { + clonedSession.MetaData[key] = val + } + + // copy Tags slice + clonedSession.Tags = make([]string, len(s.Tags)) + copy(clonedSession.Tags, s.Tags) + + return clonedSession +} + func (s *SessionState) KeyHash() string { if s.keyHash == "" { panic("KeyHash cache not found. You should call `SetKeyHash` before.")