package storage import ( "context" "github.com/valkey-io/valkey-go" "go.uber.org/zap" "ms-auth/internal/lib" "ms-auth/internal/models" "time" ) type SessionStorage struct { db valkey.Client cfg lib.Config logger *zap.Logger } func NewSessionStorage(db valkey.Client, cfg lib.Config, logger *zap.Logger) *SessionStorage { return &SessionStorage{ db: db, cfg: cfg, logger: logger, } } const sessionLifetime = time.Minute * 40 func (storage *SessionStorage) CreateSession(ctx context.Context, userId int32) error { session := models.NewSession(userId) resp := storage.db.Do(ctx, storage.db. B().Set(). Key(string(*session.UserId)). Value(*session.Id). Nx(). Exat(time.Now().Add(sessionLifetime)). Build(), ) if err := resp.Error(); err != nil { return lib.ErrInternal } return nil } func (storage *SessionStorage) ReadSessionByToken(ctx context.Context, token string) (*models.Session, error) { session, err := models.Parse(token, storage.cfg.JWTSecret) if err != nil { return nil, err } sessionRecord, err := storage.ReadSessionByUserId(ctx, *session.UserId) if err != nil { return nil, err } if *session.Id != *sessionRecord.Id { return nil, lib.ErrInternal } return session, err } func (storage *SessionStorage) ReadSessionByUserId(ctx context.Context, userId int32) (*models.Session, error) { resp := storage.db.Do(ctx, storage.db.B().Get().Key(string(userId)).Build()) if err := resp.Error(); err != nil { return nil, lib.ErrInternal } id, err := resp.ToString() if err != nil { return nil, lib.ErrInternal } return &models.Session{ Id: &id, UserId: &userId, }, err } func (storage *SessionStorage) UpdateSession(ctx context.Context, session *models.Session) error { resp := storage.db.Do(ctx, storage.db. B().Set(). Key(string(*session.UserId)). Value(*session.Id). Xx(). Exat(time.Now().Add(sessionLifetime)). Build(), ) if err := resp.Error(); err != nil { return lib.ErrInternal } return nil } func (storage *SessionStorage) DeleteSessionByToken(ctx context.Context, token string) error { session, err := models.Parse(token, storage.cfg.JWTSecret) if err != nil { return err } err = storage.DeleteSessionByUserId(ctx, *session.UserId) if err != nil { return err } return nil } func (storage *SessionStorage) DeleteSessionByUserId(ctx context.Context, userId int32) error { resp := storage.db.Do(ctx, storage.db. B().Del(). Key(string(userId)). Build(), ) if err := resp.Error(); err != nil { return lib.ErrInternal } return nil }