urit/internal/store/store.go
2026-05-02 21:11:50 -04:00

102 lines
4.2 KiB
Go

// Package store defines the storage interface for URIT BBS.
//
// In the original TAG-BBS, data access was done through direct file I/O:
// open("User.Data"), lseek() to a slot offset, read()/write() a raw struct.
// Each data type (users, boards, mail, libraries) had its own flat file.
//
// The Store interface abstracts all of that behind methods that the BBS
// logic calls without knowing whether the backend is SQLite, PostgreSQL,
// or something else entirely. The default implementation is SQLite
// (see sqlite.go), which provides zero-configuration embedded storage.
//
// To add a new backend (e.g., PostgreSQL for clustered deployments),
// implement this interface in a new file and wire it up in the config
// loader. The BBS application code needs zero changes.
package store
import (
"github.com/urit/urit/internal/models"
)
// Store is the complete data access interface for the BBS.
// Every method that can fail returns an error.
type Store interface {
// Lifecycle
Close() error
// Users — replaces Load_Account, Save_Account, Find_Open_Account,
// ForceSave_Account from ACCOUNTS.C
CreateUser(user *models.User) error
GetUser(id int64) (*models.User, error)
GetUserByName(name string) (*models.User, error)
UpdateUser(user *models.User) error
DeleteUser(id int64) error // Soft delete (sets active=false)
HardDeleteUser(id int64) error // Permanent delete (removes record and mail)
ListUsers(offset, limit int) ([]*models.User, error)
ListAllUsers(offset, limit int) ([]*models.User, error)
CountUsers() (int, error)
// Boards — replaces the in-memory linked list of Board_Header
// that was loaded from System.Data at startup
CreateBoard(board *models.Board) error
GetBoard(id int64) (*models.Board, error)
ListBoards() ([]*models.Board, error)
UpdateBoard(board *models.Board) error
DeleteBoard(id int64) error
// Messages — replaces the .Keys + .Data file pair per board
CreateMessage(msg *models.Message) error
GetMessage(id int64) (*models.Message, error)
ListMessages(boardID int64, offset, limit int) ([]*models.Message, error)
ListMessagesSince(boardID int64, since int64) ([]*models.Message, error)
CountMessages(boardID int64) (int, error)
DeleteMessage(id int64) error
// Mail — replaces the Mail .Keys + .Data files
CreateMail(mail *models.Mail) error
GetMail(id int64) (*models.Mail, error)
ListMailFor(userID int64) ([]*models.Mail, error)
CountUnreadMail(userID int64) (int, error)
MarkMailRead(id int64) error
DeleteMail(id int64) error
// Libraries — replaces the in-memory linked list of Library_Header
CreateLibrary(lib *models.Library) error
GetLibrary(id int64) (*models.Library, error)
ListLibraries() ([]*models.Library, error)
UpdateLibrary(lib *models.Library) error
DeleteLibrary(id int64) error
// Library files — replaces the .Keys file per library
CreateLibraryFile(file *models.LibraryFile) error
GetLibraryFile(id int64) (*models.LibraryFile, error)
ListLibraryFiles(libraryID int64, offset, limit int) ([]*models.LibraryFile, error)
CountLibraryFiles(libraryID int64) (int, error)
DeleteLibraryFile(id int64) error
IncrementDownloads(fileID int64) error
// Bulletins — replaces the linked list of Bulletin_Header
CreateBulletin(b *models.Bulletin) error
GetBulletin(id int64) (*models.Bulletin, error)
ListBulletins() ([]*models.Bulletin, error)
UpdateBulletin(b *models.Bulletin) error
DeleteBulletin(id int64) error
// Call log — replaces Append_Stat(STAT_LOGON/LOGOFF) from TAG.C
LogEvent(event string, userID int64, userName string, node int, remoteAddr, detail string) error
ListCallLog(limit int) ([]*models.CallLogEntry, error)
ListCallLogForUser(userID int64, limit int) ([]*models.CallLogEntry, error)
GetLastCaller(excludeUserID int64) (*models.CallLogEntry, error)
// Stats counters — replaces Daily_Statistics/Overall_Statistics
IncrementStat(key string, delta int64) error
GetStat(key string) (int64, error)
GetAllStats() (map[string]int64, error)
// Web sessions — HTTP auth tokens for browser-based library access
CreateWebSession(s *models.WebSession) error
GetWebSession(token string) (*models.WebSession, error)
DeleteWebSession(token string) error
CleanExpiredWebSessions() (int64, error)
}