auth

Paddy 2014-12-13 Parent:d43c3fbf00f3 Child:09c47387e455

89:229422395721 Go to Latest

auth/session.go

Sort sessions before returning them. When using the memstore, sort sessions by the date they were created, descending, before returning them.

History
paddy@70 1 package auth
paddy@70 2
paddy@70 3 import (
paddy@70 4 "errors"
paddy@89 5 "sort"
paddy@70 6 "time"
paddy@70 7
paddy@70 8 "code.secondbit.org/uuid"
paddy@70 9 )
paddy@70 10
paddy@70 11 var (
paddy@70 12 // ErrNoSessionStore is returned when a Context tries to act on a sessionStore without setting on first.
paddy@70 13 ErrNoSessionStore = errors.New("no sessionStore was specified for the Context")
paddy@70 14 // ErrSessionNotFound is returned when a Session is requested but not found in the sessionStore.
paddy@70 15 ErrSessionNotFound = errors.New("session not found in sessionStore")
paddy@70 16 // ErrInvalidSession is returned when a Session is specified but is not valid.
paddy@70 17 ErrInvalidSession = errors.New("session is not valid")
paddy@77 18 // ErrSessionAlreadyExists is returned when a sessionStore tries to store a Session with an ID that already exists in the sessionStore.
paddy@77 19 ErrSessionAlreadyExists = errors.New("session already exists")
paddy@70 20 )
paddy@70 21
paddy@70 22 // Session represents a user's authenticated session, associating it with a profile
paddy@70 23 // and some audit data.
paddy@70 24 type Session struct {
paddy@70 25 ID string
paddy@70 26 IP string
paddy@70 27 UserAgent string
paddy@70 28 ProfileID uuid.ID
paddy@70 29 Created time.Time
paddy@70 30 Login string
paddy@70 31 Active bool
paddy@70 32 }
paddy@70 33
paddy@89 34 type sortedSessions []Session
paddy@89 35
paddy@89 36 func (s sortedSessions) Len() int {
paddy@89 37 return len(s)
paddy@89 38 }
paddy@89 39
paddy@89 40 func (s sortedSessions) Less(i, j int) bool {
paddy@89 41 return s[i].Created.After(s[j].Created)
paddy@89 42 }
paddy@89 43
paddy@89 44 func (s sortedSessions) Swap(i, j int) {
paddy@89 45 s[i], s[j] = s[j], s[i]
paddy@89 46 }
paddy@89 47
paddy@70 48 type sessionStore interface {
paddy@70 49 createSession(session Session) error
paddy@70 50 getSession(id string) (Session, error)
paddy@70 51 removeSession(id string) error
paddy@70 52 listSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error)
paddy@70 53 }
paddy@77 54
paddy@77 55 func (m *memstore) createSession(session Session) error {
paddy@77 56 m.sessionLock.Lock()
paddy@77 57 defer m.sessionLock.Unlock()
paddy@77 58 if _, ok := m.sessions[session.ID]; ok {
paddy@77 59 return ErrSessionAlreadyExists
paddy@77 60 }
paddy@77 61 m.sessions[session.ID] = session
paddy@77 62 return nil
paddy@77 63 }
paddy@77 64
paddy@77 65 func (m *memstore) getSession(id string) (Session, error) {
paddy@77 66 m.sessionLock.RLock()
paddy@77 67 defer m.sessionLock.RUnlock()
paddy@77 68 if _, ok := m.sessions[id]; !ok {
paddy@77 69 return Session{}, ErrSessionNotFound
paddy@77 70 }
paddy@77 71 return m.sessions[id], nil
paddy@77 72 }
paddy@77 73
paddy@77 74 func (m *memstore) removeSession(id string) error {
paddy@77 75 m.sessionLock.Lock()
paddy@77 76 defer m.sessionLock.Unlock()
paddy@77 77 if _, ok := m.sessions[id]; !ok {
paddy@77 78 return ErrSessionNotFound
paddy@77 79 }
paddy@77 80 delete(m.sessions, id)
paddy@77 81 return nil
paddy@77 82 }
paddy@77 83
paddy@77 84 func (m *memstore) listSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error) {
paddy@77 85 m.sessionLock.RLock()
paddy@77 86 defer m.sessionLock.RUnlock()
paddy@77 87 res := []Session{}
paddy@77 88 for _, session := range m.sessions {
paddy@77 89 if int64(len(res)) >= num {
paddy@77 90 break
paddy@77 91 }
paddy@77 92 if profile != nil && !profile.Equal(session.ProfileID) {
paddy@77 93 continue
paddy@77 94 }
paddy@77 95 if !before.IsZero() && session.Created.After(before) {
paddy@77 96 continue
paddy@77 97 }
paddy@77 98 res = append(res, session)
paddy@77 99 }
paddy@89 100 sorted := sortedSessions(res)
paddy@89 101 sort.Sort(sorted)
paddy@89 102 res = []Session(sorted)
paddy@77 103 return res, nil
paddy@77 104 }