sessions: Can store values

This commit is contained in:
nemunaire 2022-09-04 11:12:37 +02:00
parent de4bb43e86
commit 4baa665693
3 changed files with 50 additions and 14 deletions

9
api.go
View File

@ -69,12 +69,13 @@ func adminRestricted(u *User, c *gin.Context) bool {
func authMiddleware(access ...func(*User, *gin.Context) bool) gin.HandlerFunc { func authMiddleware(access ...func(*User, *gin.Context) bool) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
var user *User = nil var user *User = nil
var session *Session = nil
if cookie, err := c.Request.Cookie("auth"); err == nil { if cookie, err := c.Request.Cookie("auth"); err == nil {
if sessionid, err := base64.StdEncoding.DecodeString(cookie.Value); err != nil { if sessionid, err := base64.StdEncoding.DecodeString(cookie.Value); err != nil {
eraseCookie(c) eraseCookie(c)
c.AbortWithStatusJSON(http.StatusNotAcceptable, gin.H{"errmsg": err.Error()}) c.AbortWithStatusJSON(http.StatusNotAcceptable, gin.H{"errmsg": err.Error()})
return return
} else if session, err := getSession(sessionid); err != nil { } else if session, err = getSession(sessionid); err != nil {
eraseCookie(c) eraseCookie(c)
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": err.Error()}) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": err.Error()})
return return
@ -97,9 +98,15 @@ func authMiddleware(access ...func(*User, *gin.Context) bool) gin.HandlerFunc {
} }
// Retrieve corresponding user // Retrieve corresponding user
c.Set("Session", session)
c.Set("LoggedUser", user) c.Set("LoggedUser", user)
// We are now ready to continue // We are now ready to continue
c.Next() c.Next()
// On return, check if the session has changed
if session != nil && session.HasChanged() {
session.Update()
}
} }
} }

1
db.go
View File

@ -72,6 +72,7 @@ CREATE TABLE IF NOT EXISTS user_sessions(
id_session BLOB(255) NOT NULL, id_session BLOB(255) NOT NULL,
id_user INTEGER, id_user INTEGER,
time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
val TEXT NOT NULL DEFAULT '{}',
FOREIGN KEY(id_user) REFERENCES users(id_user) FOREIGN KEY(id_user) REFERENCES users(id_user)
) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin;
`); err != nil { `); err != nil {

View File

@ -2,6 +2,7 @@ package main
import ( import (
"crypto/rand" "crypto/rand"
"encoding/json"
"time" "time"
) )
@ -9,11 +10,16 @@ type Session struct {
Id []byte `json:"id"` Id []byte `json:"id"`
IdUser *int64 `json:"login"` IdUser *int64 `json:"login"`
Time time.Time `json:"time"` Time time.Time `json:"time"`
changed bool
Values map[string]interface{} `json:"values"`
} }
func getSession(id []byte) (s *Session, err error) { func getSession(id []byte) (s *Session, err error) {
s = new(Session) s = new(Session)
err = DBQueryRow("SELECT id_session, id_user, time FROM user_sessions WHERE id_session=?", id).Scan(&s.Id, &s.IdUser, &s.Time) var val string
err = DBQueryRow("SELECT id_session, id_user, time, val FROM user_sessions WHERE id_session=?", id).Scan(&s.Id, &s.IdUser, &s.Time, &val)
err = json.Unmarshal([]byte(val), &s.Values)
return return
} }
@ -21,32 +27,54 @@ func NewSession() (*Session, error) {
session_id := make([]byte, 255) session_id := make([]byte, 255)
if _, err := rand.Read(session_id); err != nil { if _, err := rand.Read(session_id); err != nil {
return nil, err return nil, err
} else if _, err := DBExec("INSERT INTO user_sessions (id_session, time) VALUES (?, ?)", session_id, time.Now()); err != nil { } else if _, err := DBExec("INSERT INTO user_sessions (id_session, time, val) VALUES (?, ?, '{}')", session_id, time.Now()); err != nil {
return nil, err return nil, err
} else { } else {
return &Session{session_id, nil, time.Now()}, nil return &Session{session_id, nil, time.Now(), false, map[string]interface{}{}}, nil
} }
} }
func (user User) NewSession() (*Session, error) { func (user *User) NewSession() (*Session, error) {
session_id := make([]byte, 255) session_id := make([]byte, 255)
if _, err := rand.Read(session_id); err != nil { if _, err := rand.Read(session_id); err != nil {
return nil, err return nil, err
} else if _, err := DBExec("INSERT INTO user_sessions (id_session, id_user, time) VALUES (?, ?, ?)", session_id, user.Id, time.Now()); err != nil { } else if _, err := DBExec("INSERT INTO user_sessions (id_session, id_user, time, val) VALUES (?, ?, ?, '{}')", session_id, user.Id, time.Now()); err != nil {
return nil, err return nil, err
} else { } else {
return &Session{session_id, &user.Id, time.Now()}, nil return &Session{session_id, &user.Id, time.Now(), false, map[string]interface{}{}}, nil
} }
} }
func (s Session) SetUser(user *User) (*Session, error) { func (s *Session) SetUser(user *User) (*Session, error) {
s.IdUser = &user.Id s.IdUser = &user.Id
_, err := s.Update() _, err := s.Update()
return &s, err s.changed = false
return s, err
} }
func (s Session) Update() (int64, error) { func (s *Session) GetKey(key string) (v interface{}, ok bool) {
if res, err := DBExec("UPDATE user_sessions SET id_user = ?, time = ? WHERE id_session = ?", s.IdUser, s.Time, s.Id); err != nil { v, ok = s.Values[key]
return
}
func (s *Session) DeleteKey(key string) {
delete(s.Values, key)
s.changed = true
}
func (s *Session) SetKey(key string, val interface{}) {
s.Values[key] = val
s.changed = true
}
func (s *Session) HasChanged() bool {
return s.changed
}
func (s *Session) Update() (int64, error) {
if val, err := json.Marshal(s.Values); err != nil {
return 0, err
} else if res, err := DBExec("UPDATE user_sessions SET id_user = ?, time = ?, val = ? WHERE id_session = ?", s.IdUser, s.Time, string(val), s.Id); err != nil {
return 0, err return 0, err
} else if nb, err := res.RowsAffected(); err != nil { } else if nb, err := res.RowsAffected(); err != nil {
return 0, err return 0, err