Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: add Reset method to Session struct in session middleware #2654

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api/middleware/session.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (s *Session) Get(key string) interface{}
func (s *Session) Set(key string, val interface{})
func (s *Session) Delete(key string)
func (s *Session) Destroy() error
func (s *Session) Reset() error
func (s *Session) Regenerate() error
func (s *Session) Save() error
func (s *Session) Fresh() bool
Expand Down
27 changes: 27 additions & 0 deletions middleware/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,33 @@ func (s *Session) Regenerate() error {
return nil
}

// Reset generates a new session id, deletes the old one from storage, and resets the associated data
func (s *Session) Reset() error {
// Reset local data
if s.data != nil {
s.data.Reset()
}
// Reset byte buffer
if s.byteBuffer != nil {
s.byteBuffer.Reset()
}
// Reset expiration
s.exp = 0

// Delete old id from storage
if err := s.config.Storage.Delete(s.id); err != nil {
return err
}

// Expire session
s.delSession()

// Generate a new session, and set session.fresh to true
s.refresh()

return nil
}

// refresh generates a new session, and set session.fresh to be true
func (s *Session) refresh() {
// Create a new id
Expand Down
77 changes: 73 additions & 4 deletions middleware/session/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,11 @@ func Test_Session_Save_Expiration(t *testing.T) {
})
}

// go test -run Test_Session_Reset
func Test_Session_Reset(t *testing.T) {
// go test -run Test_Session_Destroy
func Test_Session_Destroy(t *testing.T) {
t.Parallel()

t.Run("reset from cookie", func(t *testing.T) {
t.Run("destroy from cookie", func(t *testing.T) {
t.Parallel()
// session store
store := New()
Expand All @@ -347,7 +347,7 @@ func Test_Session_Reset(t *testing.T) {
utils.AssertEqual(t, nil, name)
})

t.Run("reset from header", func(t *testing.T) {
t.Run("destroy from header", func(t *testing.T) {
t.Parallel()
// session store
store := New(Config{
Expand Down Expand Up @@ -461,6 +461,75 @@ func Test_Session_Deletes_Single_Key(t *testing.T) {
utils.AssertEqual(t, nil, sess.Get("id"))
}

// go test -run Test_Session_Reset
func Test_Session_Reset(t *testing.T) {
t.Parallel()
// fiber instance
app := fiber.New()

// session store
store := New()

// fiber context
ctx := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(ctx)

t.Run("reset session data and id, and set fresh to be true", func(t *testing.T) {
// a random session uuid
originalSessionUUIDString := ""

// now the session is in the storage
freshSession, err := store.Get(ctx)
utils.AssertEqual(t, nil, err)

originalSessionUUIDString = freshSession.ID()

// set a value
freshSession.Set("name", "fenny")
freshSession.Set("email", "fenny@example.com")

err = freshSession.Save()
utils.AssertEqual(t, nil, err)

// set cookie
ctx.Request().Header.SetCookie(store.sessionName, originalSessionUUIDString)

// as the session is in the storage, session.fresh should be false
acquiredSession, err := store.Get(ctx)
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, false, acquiredSession.Fresh())

err = acquiredSession.Reset()
utils.AssertEqual(t, nil, err)

utils.AssertEqual(t, false, acquiredSession.ID() == originalSessionUUIDString)

// acquiredSession.fresh should be true after resetting
utils.AssertEqual(t, true, acquiredSession.Fresh())

// Check that the session data has been reset
keys := acquiredSession.Keys()
utils.AssertEqual(t, []string{}, keys)

// Set a new value for 'name' and check that it's updated
acquiredSession.Set("name", "john")
utils.AssertEqual(t, "john", acquiredSession.Get("name"))
utils.AssertEqual(t, nil, acquiredSession.Get("email"))

// Save after resetting
err = acquiredSession.Save()
utils.AssertEqual(t, nil, err)

// Check that the session id is not in the header or cookie anymore
utils.AssertEqual(t, "", string(ctx.Response().Header.Peek(store.sessionName)))
utils.AssertEqual(t, "", string(ctx.Request().Header.Peek(store.sessionName)))

// But the new session id should be in the header or cookie
utils.AssertEqual(t, acquiredSession.ID(), string(ctx.Response().Header.Peek(store.sessionName)))
utils.AssertEqual(t, acquiredSession.ID(), string(ctx.Request().Header.Peek(store.sessionName)))
})
}

// go test -run Test_Session_Regenerate
// Regression: https://github.com/gofiber/fiber/issues/1395
func Test_Session_Regenerate(t *testing.T) {
Expand Down
Loading