Rework db package to make it testable

This commit is contained in:
2024-11-21 22:36:12 +01:00
parent 2faefb6db5
commit 807e96a76c
16 changed files with 274 additions and 161 deletions

View File

@@ -1,3 +1,4 @@
// Package db provides the database access layer for the application. It contains methods for interacting with the database, such as creating, updating, and deleting records.
package db
import (
@@ -5,18 +6,75 @@ import (
"fmt"
"novamd/internal/crypto"
"novamd/internal/models"
_ "github.com/mattn/go-sqlite3" // SQLite driver
)
// DB represents the database connection
type DB struct {
// UserStore defines the methods for interacting with user data in the database
type UserStore interface {
CreateUser(user *models.User) (*models.User, error)
GetUserByEmail(email string) (*models.User, error)
GetUserByID(userID int) (*models.User, error)
GetAllUsers() ([]*models.User, error)
UpdateUser(user *models.User) error
DeleteUser(userID int) error
UpdateLastWorkspace(userID int, workspaceName string) error
GetLastWorkspaceName(userID int) (string, error)
CountAdminUsers() (int, error)
}
// WorkspaceStore defines the methods for interacting with workspace data in the database
type WorkspaceStore interface {
CreateWorkspace(workspace *models.Workspace) error
GetWorkspaceByID(workspaceID int) (*models.Workspace, error)
GetWorkspaceByName(userID int, workspaceName string) (*models.Workspace, error)
GetWorkspacesByUserID(userID int) ([]*models.Workspace, error)
UpdateWorkspace(workspace *models.Workspace) error
DeleteWorkspace(workspaceID int) error
UpdateWorkspaceSettings(workspace *models.Workspace) error
DeleteWorkspaceTx(tx *sql.Tx, workspaceID int) error
UpdateLastWorkspaceTx(tx *sql.Tx, userID, workspaceID int) error
UpdateLastOpenedFile(workspaceID int, filePath string) error
GetLastOpenedFile(workspaceID int) (string, error)
GetAllWorkspaces() ([]*models.Workspace, error)
}
// SessionStore defines the methods for interacting with jwt sessions in the database
type SessionStore interface {
CreateSession(session *models.Session) error
GetSessionByRefreshToken(refreshToken string) (*models.Session, error)
DeleteSession(sessionID string) error
CleanExpiredSessions() error
}
// SystemStore defines the methods for interacting with system settings and stats in the database
type SystemStore interface {
GetSystemStats() (*UserStats, error)
EnsureJWTSecret() (string, error)
GetSystemSetting(key string) (string, error)
SetSystemSetting(key, value string) error
}
// Database defines the methods for interacting with the database
type Database interface {
UserStore
WorkspaceStore
SessionStore
SystemStore
Begin() (*sql.Tx, error)
Close() error
Migrate() error
}
// database represents the database connection
type database struct {
*sql.DB
crypto *crypto.Crypto
}
// Init initializes the database connection
func Init(dbPath string, encryptionKey string) (*DB, error) {
func Init(dbPath string, encryptionKey string) (Database, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
@@ -32,7 +90,7 @@ func Init(dbPath string, encryptionKey string) (*DB, error) {
return nil, fmt.Errorf("failed to initialize encryption: %w", err)
}
database := &DB{
database := &database{
DB: db,
crypto: cryptoService,
}
@@ -45,19 +103,19 @@ func Init(dbPath string, encryptionKey string) (*DB, error) {
}
// Close closes the database connection
func (db *DB) Close() error {
func (db *database) Close() error {
return db.DB.Close()
}
// Helper methods for token encryption/decryption
func (db *DB) encryptToken(token string) (string, error) {
func (db *database) encryptToken(token string) (string, error) {
if token == "" {
return "", nil
}
return db.crypto.Encrypt(token)
}
func (db *DB) decryptToken(token string) (string, error) {
func (db *database) decryptToken(token string) (string, error) {
if token == "" {
return "", nil
}