Skip to content

Commit

Permalink
added RevokeByUserKey and RevokeByID methods
Browse files Browse the repository at this point in the history
  • Loading branch information
swithek committed Aug 3, 2019
1 parent 73695a2 commit 1773a29
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 7 deletions.
17 changes: 15 additions & 2 deletions manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,20 @@ func (m *Manager) Revoke(ctx context.Context, w http.ResponseWriter) error {
return nil
}

if err := m.store.DeleteByID(ctx, s.ID); err != nil {
if err := m.RevokeByID(ctx, s.ID); err != nil {
return err
}

m.deleteCookie(w)
return nil
}

// RevokeByID deletes session by its ID.
// Function will be no-op and return nil, if no session is found.
func (m *Manager) RevokeByID(ctx context.Context, id string) error {
return m.store.DeleteByID(ctx, id)
}

// RevokeOther deletes all sessions of the same user key as session stored in the
// context currently has. Context session will be excluded.
// Function will be no-op and return nil, if context session is not set.
Expand All @@ -299,14 +305,21 @@ func (m *Manager) RevokeAll(ctx context.Context, w http.ResponseWriter) error {
return nil
}

if err := m.store.DeleteByUserKey(ctx, s.UserKey); err != nil {
if err := m.RevokeByUserKey(ctx, s.UserKey); err != nil {
return err
}

m.deleteCookie(w)
return nil
}

// RevokeByUserKey deletes all sessions under the provided user key.
// This includes context session as well.
// Function will be no-op and return nil, if no sessions are found.
func (m *Manager) RevokeByUserKey(ctx context.Context, key string) error {
return m.store.DeleteByUserKey(ctx, key)
}

// FetchAll retrieves all sessions of the same user key as session stored in the
// context currently has. Session with the same ID as the one stored in the context
// will have its 'Current' field set to true. If no sessions are found or the context
Expand Down
152 changes: 147 additions & 5 deletions manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,79 @@ func TestRevoke(t *testing.T) {
}
}

func TestRevokeByID(t *testing.T) {
type check func(*testing.T, *StoreMock, error)

checks := func(cc ...check) []check { return cc }

hasErr := func(e bool) check {
return func(t *testing.T, _ *StoreMock, err error) {
if e && err == nil {
t.Error("want non-nil, got nil")
} else if !e && err != nil {
t.Errorf("want nil, got %v", err)
}
}
}

wasDeleteByIDCalled := func(count int, id string) check {
return func(t *testing.T, s *StoreMock, _ error) {
ff := s.DeleteByIDCalls()
if len(ff) != count {
t.Errorf("want %d, got %d", count, len(ff))
}

if len(ff) > 0 && ff[0].ID != id {
t.Errorf("want %q, got %q", id, ff[0].ID)
}
}
}

storeStub := func(err error) *StoreMock {
return &StoreMock{
DeleteByIDFunc: func(_ context.Context, _ string) error {
return err
},
}
}

id := "id"
cc := map[string]struct {
Store *StoreMock
ID string
Checks []check
}{
"Error returned by store.DeleteByID": {
Store: storeStub(errors.New("error")),
ID: id,
Checks: checks(
hasErr(true),
wasDeleteByIDCalled(1, id),
),
},
"Successful revoke": {
Store: storeStub(nil),
ID: id,
Checks: checks(
hasErr(false),
wasDeleteByIDCalled(1, id),
),
},
}

for cn, c := range cc {
c := c
t.Run(cn, func(t *testing.T) {
t.Parallel()
m := Manager{store: c.Store}
err := m.RevokeByID(context.Background(), c.ID)
for _, ch := range c.Checks {
ch(t, c.Store, err)
}
})
}
}

func TestRevokeOther(t *testing.T) {
type check func(*testing.T, *StoreMock, error)

Expand Down Expand Up @@ -793,11 +866,7 @@ func TestRevokeAll(t *testing.T) {
t.Errorf("want %d, got %d", count, len(ff))
}

if len(ff) == 0 {
return
}

if ff[0].Key != key {
if len(ff) > 0 && ff[0].Key != key {
t.Errorf("want %q, got %q", key, ff[0].Key)
}
}
Expand Down Expand Up @@ -862,6 +931,79 @@ func TestRevokeAll(t *testing.T) {
}
}

func TestRevokeByUserKey(t *testing.T) {
type check func(*testing.T, *StoreMock, error)

checks := func(cc ...check) []check { return cc }

hasErr := func(e bool) check {
return func(t *testing.T, _ *StoreMock, err error) {
if e && err == nil {
t.Error("want non-nil, got nil")
} else if !e && err != nil {
t.Errorf("want nil, got %v", err)
}
}
}

wasDeleteByUserKeyCalled := func(count int, key string) check {
return func(t *testing.T, s *StoreMock, _ error) {
ff := s.DeleteByUserKeyCalls()
if len(ff) != count {
t.Errorf("want %d, got %d", count, len(ff))
}

if len(ff) > 0 && ff[0].Key != key {
t.Errorf("want %q, got %q", key, ff[0].Key)
}
}
}

storeStub := func(err error) *StoreMock {
return &StoreMock{
DeleteByUserKeyFunc: func(_ context.Context, _ string, _ ...string) error {
return err
},
}
}

key := "key"
cc := map[string]struct {
Store *StoreMock
Key string
Checks []check
}{
"Error returned by store.DeleteByUserKey": {
Store: storeStub(errors.New("error")),
Key: key,
Checks: checks(
hasErr(true),
wasDeleteByUserKeyCalled(1, key),
),
},
"Successful revoke": {
Store: storeStub(nil),
Key: key,
Checks: checks(
hasErr(false),
wasDeleteByUserKeyCalled(1, key),
),
},
}

for cn, c := range cc {
c := c
t.Run(cn, func(t *testing.T) {
t.Parallel()
m := Manager{store: c.Store}
err := m.RevokeByUserKey(context.Background(), c.Key)
for _, ch := range c.Checks {
ch(t, c.Store, err)
}
})
}
}

func TestFetchAll(t *testing.T) {
type check func(*testing.T, *StoreMock, []Session, error)

Expand Down

0 comments on commit 1773a29

Please sign in to comment.