From a438d5b6653c4536c7030a23d985eaba34173bc6 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Wed, 2 Jul 2025 16:47:17 +0300 Subject: [PATCH] Feat: session db methods and try at tx --- handlers/auth.go | 8 +++---- repos/main.go | 3 ++- repos/session.go | 60 ++++++++++++++++++++++++++++++++++++++++++++---- todos.md | 1 + 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/handlers/auth.go b/handlers/auth.go index 5264aa4..8c0e645 100644 --- a/handlers/auth.go +++ b/handlers/auth.go @@ -12,7 +12,6 @@ import ( "html/template" "net/http" "strings" - "time" ) func abortWithError(w http.ResponseWriter, msg string) { @@ -142,11 +141,12 @@ func makeCookie(username string, remote string) (*http.Cookie, error) { // Create a new random session token // sessionToken := xid.New().String() sessionToken := "sessionprefix_" + username - expiresAt := time.Now().Add(time.Duration(cfg.SessionLifetime) * time.Second) + // expiresAt := time.Now().Add(time.Duration(cfg.SessionLifetime) * time.Second) // Set the token in the session map, along with the session information session := &models.Session{ - Username: username, - Expiry: expiresAt, + Username: username, + CookieToken: sessionToken, + Lifetime: uint32(cfg.SessionLifetime / 60), } cookieName := "session_token" // hmac to protect cookies diff --git a/repos/main.go b/repos/main.go index 07db228..ba30738 100644 --- a/repos/main.go +++ b/repos/main.go @@ -15,7 +15,8 @@ type AllRepos interface { } type RepoProvider struct { - DB *sqlx.DB + DB *sqlx.DB + Ext sqlx.Ext } func NewRepoProvider(pathToDB string) *RepoProvider { diff --git a/repos/session.go b/repos/session.go index f814da6..399d40e 100644 --- a/repos/session.go +++ b/repos/session.go @@ -1,9 +1,61 @@ package repos -import "gralias/models" +import ( + "context" + "gralias/models" + "time" + + "github.com/jmoiron/sqlx" +) type SessionsRepo interface { - SessionByToken(token string) (*models.Session, error) - SessionCreate(req *models.Session) error - SessionUpdateLifetime(minutes uint32) error + SessionByToken(ctx context.Context, token string) (*models.Session, error) + SessionCreate(ctx context.Context, session *models.Session) error + SessionUpdate(ctx context.Context, session *models.Session) error + SessionDelete(ctx context.Context, token string) error +} + +func (p *RepoProvider) SessionByToken(ctx context.Context, token string) (*models.Session, error) { + session := &models.Session{} + // The lifetime in the DB is in seconds, but in the model it is in minutes. + err := p.DB.GetContext(ctx, session, `SELECT id, updated_at, lifetime / 60 as lifetime, cookie_token, username FROM sessions WHERE cookie_token = ?`, token) + if err != nil { + return nil, err + } + return session, nil +} + +func (p *RepoProvider) SessionCreate(ctx context.Context, session *models.Session) error { + p.Ext = p.DB + tx, ok := ctx.Value("sqltx").(*sqlx.Tx) + if ok && tx != nil { + // how to know if it is a final exec in chain? + // or is it better to commit outside? + tocommit, ok := ctx.Value("tocommit").(bool) + if ok && tocommit { + defer func() { + if err := tx.Commit(); err != nil { + // log + // return err + } + }() + } + p.Ext = tx + } + // The lifetime in the model is in minutes, but in the DB it is in seconds. + _, err := p.Ext.Exec(`INSERT INTO sessions (updated_at, lifetime, cookie_token, username) VALUES (?, ?, ?, ?)`, + time.Now(), session.Lifetime*60, session.CookieToken, session.Username) + return err +} + +func (p *RepoProvider) SessionUpdate(ctx context.Context, session *models.Session) error { + // The lifetime in the model is in minutes, but in the DB it is in seconds. + _, err := p.DB.ExecContext(ctx, `UPDATE sessions SET updated_at = ?, lifetime = ? WHERE cookie_token = ?`, + time.Now(), session.Lifetime*60, session.CookieToken) + return err +} + +func (p *RepoProvider) SessionDelete(ctx context.Context, token string) error { + _, err := p.DB.ExecContext(ctx, `DELETE FROM sessions WHERE cookie_token = ?`, token) + return err } diff --git a/todos.md b/todos.md index c83baf2..9beda88 100644 --- a/todos.md +++ b/todos.md @@ -1,4 +1,5 @@ ### feats +- implement the db methods for sessions in repos/session.go; + - auto close room if nothing is going on there (hmm) for ~1h; + - words database (file) load and form random 25 words; + - invite link; +