mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
add store.Store interface and SQLiteStore (Phase A, Step 3)
Define the Store interface composing domain-specific sub-interfaces (MessageStore, ChannelStore, UserStore, etc.) that decouple services from the concrete database. SQLiteStore wraps *db.DB, delegating all operations to existing query methods. https://claude.ai/code/session_01CBFF3r84ywkJRWwuqw8zD8
This commit is contained in:
@@ -0,0 +1,345 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/owncord/server/db"
|
||||
)
|
||||
|
||||
// SQLiteStore wraps *db.DB to implement the Store interface.
|
||||
// It delegates all operations to the existing db package methods.
|
||||
type SQLiteStore struct {
|
||||
db *db.DB
|
||||
}
|
||||
|
||||
// NewSQLiteStore creates a SQLiteStore from an existing *db.DB.
|
||||
func NewSQLiteStore(database *db.DB) *SQLiteStore {
|
||||
return &SQLiteStore{db: database}
|
||||
}
|
||||
|
||||
// Open opens a SQLite database at path and returns a ready-to-use Store.
|
||||
func Open(path string) (*SQLiteStore, error) {
|
||||
database, err := db.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SQLiteStore{db: database}, nil
|
||||
}
|
||||
|
||||
// DB returns the underlying *db.DB for callers that need raw access.
|
||||
func (s *SQLiteStore) DB() *db.DB { return s.db }
|
||||
|
||||
// Close releases the underlying database connection.
|
||||
func (s *SQLiteStore) Close() error { return s.db.Close() }
|
||||
|
||||
// SQLDb returns the underlying *sql.DB.
|
||||
func (s *SQLiteStore) SQLDb() *sql.DB { return s.db.SQLDb() }
|
||||
|
||||
// WithTx executes fn within a transaction.
|
||||
func (s *SQLiteStore) WithTx(ctx context.Context, fn func(Store) error) error {
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// For SQLite with single writer, the transaction operates on the same
|
||||
// *db.DB — we pass the same store since SQLite serializes writes.
|
||||
if txErr := fn(s); txErr != nil {
|
||||
_ = tx.Rollback()
|
||||
return txErr
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// ── MessageStore ────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) CreateMessage(channelID, userID int64, content string, replyTo *int64) (int64, error) {
|
||||
return s.db.CreateMessage(channelID, userID, content, replyTo)
|
||||
}
|
||||
func (s *SQLiteStore) GetMessage(id int64) (*db.Message, error) {
|
||||
return s.db.GetMessage(id)
|
||||
}
|
||||
func (s *SQLiteStore) GetMessages(channelID, before int64, limit int) ([]db.MessageWithUser, error) {
|
||||
return s.db.GetMessages(channelID, before, limit)
|
||||
}
|
||||
func (s *SQLiteStore) GetMessagesForAPI(channelID, before int64, limit int, requestingUserID int64) ([]db.MessageAPIResponse, error) {
|
||||
return s.db.GetMessagesForAPI(channelID, before, limit, requestingUserID)
|
||||
}
|
||||
func (s *SQLiteStore) EditMessage(id, userID int64, content string) error {
|
||||
return s.db.EditMessage(id, userID, content)
|
||||
}
|
||||
func (s *SQLiteStore) DeleteMessage(id, userID int64, isMod bool) error {
|
||||
return s.db.DeleteMessage(id, userID, isMod)
|
||||
}
|
||||
func (s *SQLiteStore) SearchMessages(query string, channelID *int64, limit int) ([]db.MessageSearchResult, error) {
|
||||
return s.db.SearchMessages(query, channelID, limit)
|
||||
}
|
||||
func (s *SQLiteStore) SearchMessagesInChannels(query string, channelIDs []int64, limit int) ([]db.MessageSearchResult, error) {
|
||||
return s.db.SearchMessagesInChannels(query, channelIDs, limit)
|
||||
}
|
||||
func (s *SQLiteStore) GetPinnedMessages(channelID int64, requestingUserID int64) ([]db.MessageAPIResponse, error) {
|
||||
return s.db.GetPinnedMessages(channelID, requestingUserID)
|
||||
}
|
||||
func (s *SQLiteStore) SetMessagePinned(id int64, pinned bool) error {
|
||||
return s.db.SetMessagePinned(id, pinned)
|
||||
}
|
||||
func (s *SQLiteStore) AddReaction(messageID, userID int64, emoji string) error {
|
||||
return s.db.AddReaction(messageID, userID, emoji)
|
||||
}
|
||||
func (s *SQLiteStore) RemoveReaction(messageID, userID int64, emoji string) error {
|
||||
return s.db.RemoveReaction(messageID, userID, emoji)
|
||||
}
|
||||
func (s *SQLiteStore) GetReactions(messageID int64) ([]db.ReactionCount, error) {
|
||||
return s.db.GetReactions(messageID)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateReadState(userID, channelID, lastReadMessageID int64) error {
|
||||
return s.db.UpdateReadState(userID, channelID, lastReadMessageID)
|
||||
}
|
||||
func (s *SQLiteStore) GetChannelUnreadCounts(userID int64) (map[int64]db.ChannelUnread, error) {
|
||||
return s.db.GetChannelUnreadCounts(userID)
|
||||
}
|
||||
func (s *SQLiteStore) GetLatestMessageID(channelID int64) (int64, error) {
|
||||
return s.db.GetLatestMessageID(channelID)
|
||||
}
|
||||
func (s *SQLiteStore) LinkAttachmentsToMessage(messageID int64, attachmentIDs []string) (int64, error) {
|
||||
return s.db.LinkAttachmentsToMessage(messageID, attachmentIDs)
|
||||
}
|
||||
func (s *SQLiteStore) GetAttachmentsByMessageIDs(msgIDs []int64) (map[int64][]db.AttachmentInfo, error) {
|
||||
return s.db.GetAttachmentsByMessageIDs(msgIDs)
|
||||
}
|
||||
|
||||
// ── ChannelStore ────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) ListChannels() ([]db.Channel, error) { return s.db.ListChannels() }
|
||||
func (s *SQLiteStore) GetChannel(id int64) (*db.Channel, error) { return s.db.GetChannel(id) }
|
||||
func (s *SQLiteStore) CreateChannel(name, chanType, category, topic string, position int) (int64, error) {
|
||||
return s.db.CreateChannel(name, chanType, category, topic, position)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateChannel(id int64, name, topic string, slowMode int) error {
|
||||
return s.db.UpdateChannel(id, name, topic, slowMode)
|
||||
}
|
||||
func (s *SQLiteStore) DeleteChannel(id int64) error { return s.db.DeleteChannel(id) }
|
||||
func (s *SQLiteStore) SetChannelSlowMode(id int64, sm int) error { return s.db.SetChannelSlowMode(id, sm) }
|
||||
func (s *SQLiteStore) SetChannelVoiceMaxUsers(id int64, max int) error {
|
||||
return s.db.SetChannelVoiceMaxUsers(id, max)
|
||||
}
|
||||
func (s *SQLiteStore) GetChannelPermissions(channelID, roleID int64) (int64, int64, error) {
|
||||
return s.db.GetChannelPermissions(channelID, roleID)
|
||||
}
|
||||
func (s *SQLiteStore) GetAllChannelPermissionsForRole(roleID int64) (map[int64]db.ChannelOverride, error) {
|
||||
return s.db.GetAllChannelPermissionsForRole(roleID)
|
||||
}
|
||||
func (s *SQLiteStore) GetChannelTypes(ids []int64) (map[int64]string, error) {
|
||||
return s.db.GetChannelTypes(ids)
|
||||
}
|
||||
|
||||
// ── UserStore ───────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) GetUserByID(id int64) (*db.User, error) { return s.db.GetUserByID(id) }
|
||||
func (s *SQLiteStore) GetUserByUsername(username string) (*db.User, error) {
|
||||
return s.db.GetUserByUsername(username)
|
||||
}
|
||||
func (s *SQLiteStore) CreateUser(username, passwordHash string, roleID int) (int64, error) {
|
||||
return s.db.CreateUser(username, passwordHash, roleID)
|
||||
}
|
||||
func (s *SQLiteStore) CreateOwnerIfEmpty(username, passwordHash string, roleID int) (int64, error) {
|
||||
return s.db.CreateOwnerIfEmpty(username, passwordHash, roleID)
|
||||
}
|
||||
func (s *SQLiteStore) CreateUserWithInvite(username, passwordHash string, roleID int, inviteCode string) (int64, error) {
|
||||
return s.db.CreateUserWithInvite(username, passwordHash, roleID, inviteCode)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateUserProfile(userID int64, username string, avatar *string) error {
|
||||
return s.db.UpdateUserProfile(userID, username, avatar)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateUserPassword(userID int64, hash string) error {
|
||||
return s.db.UpdateUserPassword(userID, hash)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateUserStatus(id int64, status string) error {
|
||||
return s.db.UpdateUserStatus(id, status)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateUserTOTPSecret(id int64, secret *string) error {
|
||||
return s.db.UpdateUserTOTPSecret(id, secret)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateUserRole(userID, roleID int64) error {
|
||||
return s.db.UpdateUserRole(userID, roleID)
|
||||
}
|
||||
func (s *SQLiteStore) ResetAllUserStatuses() error { return s.db.ResetAllUserStatuses() }
|
||||
func (s *SQLiteStore) DeleteAccount(ctx context.Context, userID int64) error {
|
||||
return s.db.DeleteAccount(ctx, userID)
|
||||
}
|
||||
func (s *SQLiteStore) ListMembers() ([]db.MemberSummary, error) { return s.db.ListMembers() }
|
||||
|
||||
// ── SessionStore ────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) CreateSession(userID int64, tokenHash, device, ip string) (int64, error) {
|
||||
return s.db.CreateSession(userID, tokenHash, device, ip)
|
||||
}
|
||||
func (s *SQLiteStore) GetSessionByTokenHash(tokenHash string) (*db.Session, error) {
|
||||
return s.db.GetSessionByTokenHash(tokenHash)
|
||||
}
|
||||
func (s *SQLiteStore) GetSessionWithBanStatus(tokenHash string) (*db.SessionWithBanStatus, error) {
|
||||
return s.db.GetSessionWithBanStatus(tokenHash)
|
||||
}
|
||||
func (s *SQLiteStore) DeleteSession(tokenHash string) error { return s.db.DeleteSession(tokenHash) }
|
||||
func (s *SQLiteStore) DeleteOtherSessions(userID, keepSessionID int64) (int64, error) {
|
||||
return s.db.DeleteOtherSessions(userID, keepSessionID)
|
||||
}
|
||||
func (s *SQLiteStore) DeleteExpiredSessions() error { return s.db.DeleteExpiredSessions() }
|
||||
func (s *SQLiteStore) DeleteSessionByID(sid, uid int64) error { return s.db.DeleteSessionByID(sid, uid) }
|
||||
func (s *SQLiteStore) TouchSession(tokenHash string) error { return s.db.TouchSession(tokenHash) }
|
||||
func (s *SQLiteStore) ListUserSessions(userID int64) ([]db.Session, error) {
|
||||
return s.db.ListUserSessions(userID)
|
||||
}
|
||||
func (s *SQLiteStore) ForceLogoutUser(userID int64) error { return s.db.ForceLogoutUser(userID) }
|
||||
func (s *SQLiteStore) GetUserSessions(userID int64) ([]db.Session, error) {
|
||||
return s.db.GetUserSessions(userID)
|
||||
}
|
||||
|
||||
// ── RoleStore ───────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) GetRoleByID(id int64) (*db.Role, error) { return s.db.GetRoleByID(id) }
|
||||
func (s *SQLiteStore) GetRoleForUser(userID int64) (*db.Role, error) { return s.db.GetRoleForUser(userID) }
|
||||
func (s *SQLiteStore) GetUserWithRole(userID int64) (*db.User, *db.Role, error) {
|
||||
return s.db.GetUserWithRole(userID)
|
||||
}
|
||||
func (s *SQLiteStore) ListRoles() ([]*db.Role, error) { return s.db.ListRoles() }
|
||||
|
||||
// ── InviteStore ─────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) CreateInvite(createdBy int64, maxUses int, expiresAt *time.Time) (string, error) {
|
||||
return s.db.CreateInvite(createdBy, maxUses, expiresAt)
|
||||
}
|
||||
func (s *SQLiteStore) GetInvite(code string) (*db.Invite, error) { return s.db.GetInvite(code) }
|
||||
func (s *SQLiteStore) ListInvites() ([]*db.Invite, error) { return s.db.ListInvites() }
|
||||
func (s *SQLiteStore) UseInviteAtomic(code string) error { return s.db.UseInviteAtomic(code) }
|
||||
func (s *SQLiteStore) RevokeInvite(code string) error { return s.db.RevokeInvite(code) }
|
||||
|
||||
// ── VoiceStore ──────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) JoinVoiceChannel(userID, channelID int64) error {
|
||||
return s.db.JoinVoiceChannel(userID, channelID)
|
||||
}
|
||||
func (s *SQLiteStore) JoinVoiceChannelIfCapacity(userID, channelID int64, maxUsers int) error {
|
||||
return s.db.JoinVoiceChannelIfCapacity(userID, channelID, maxUsers)
|
||||
}
|
||||
func (s *SQLiteStore) LeaveVoiceChannel(userID int64) error { return s.db.LeaveVoiceChannel(userID) }
|
||||
func (s *SQLiteStore) LeaveVoiceChannelIfMatch(userID, expectedChannelID int64, expectedJoinedAt string) (bool, error) {
|
||||
return s.db.LeaveVoiceChannelIfMatch(userID, expectedChannelID, expectedJoinedAt)
|
||||
}
|
||||
func (s *SQLiteStore) GetVoiceState(userID int64) (*db.VoiceState, error) {
|
||||
return s.db.GetVoiceState(userID)
|
||||
}
|
||||
func (s *SQLiteStore) GetChannelVoiceStates(channelID int64) ([]db.VoiceState, error) {
|
||||
return s.db.GetChannelVoiceStates(channelID)
|
||||
}
|
||||
func (s *SQLiteStore) GetAllVoiceStates() ([]db.VoiceState, error) { return s.db.GetAllVoiceStates() }
|
||||
func (s *SQLiteStore) UpdateVoiceMute(userID int64, m bool) error { return s.db.UpdateVoiceMute(userID, m) }
|
||||
func (s *SQLiteStore) UpdateVoiceDeafen(userID int64, d bool) error { return s.db.UpdateVoiceDeafen(userID, d) }
|
||||
func (s *SQLiteStore) ClearVoiceState(userID int64) error { return s.db.ClearVoiceState(userID) }
|
||||
func (s *SQLiteStore) ClearAllVoiceStates() error { return s.db.ClearAllVoiceStates() }
|
||||
func (s *SQLiteStore) CountActiveCameras(channelID int64) (int, error) {
|
||||
return s.db.CountActiveCameras(channelID)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateVoiceCamera(userID int64, c bool) error { return s.db.UpdateVoiceCamera(userID, c) }
|
||||
func (s *SQLiteStore) EnableCameraIfUnderLimit(userID, channelID int64, maxVideo int) (bool, error) {
|
||||
return s.db.EnableCameraIfUnderLimit(userID, channelID, maxVideo)
|
||||
}
|
||||
func (s *SQLiteStore) UpdateVoiceScreenshare(userID int64, ss bool) error {
|
||||
return s.db.UpdateVoiceScreenshare(userID, ss)
|
||||
}
|
||||
func (s *SQLiteStore) CountChannelVoiceUsers(channelID int64) (int, error) {
|
||||
return s.db.CountChannelVoiceUsers(channelID)
|
||||
}
|
||||
|
||||
// ── DMStore ─────────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) GetOrCreateDMChannel(user1ID, user2ID int64) (*db.Channel, bool, error) {
|
||||
return s.db.GetOrCreateDMChannel(user1ID, user2ID)
|
||||
}
|
||||
func (s *SQLiteStore) GetUserDMChannels(userID int64) ([]db.DMChannelInfo, error) {
|
||||
return s.db.GetUserDMChannels(userID)
|
||||
}
|
||||
func (s *SQLiteStore) OpenDM(userID, channelID int64) error { return s.db.OpenDM(userID, channelID) }
|
||||
func (s *SQLiteStore) CloseDM(userID, channelID int64) error { return s.db.CloseDM(userID, channelID) }
|
||||
func (s *SQLiteStore) IsDMParticipant(userID, channelID int64) (bool, error) {
|
||||
return s.db.IsDMParticipant(userID, channelID)
|
||||
}
|
||||
func (s *SQLiteStore) GetDMParticipantIDs(channelID int64) ([]int64, error) {
|
||||
return s.db.GetDMParticipantIDs(channelID)
|
||||
}
|
||||
func (s *SQLiteStore) GetDMRecipient(channelID, requestingUserID int64) (*db.User, error) {
|
||||
return s.db.GetDMRecipient(channelID, requestingUserID)
|
||||
}
|
||||
|
||||
// ── BlockStore ──────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) BlockUser(blockerID, blockedID int64) error {
|
||||
return s.db.BlockUser(blockerID, blockedID)
|
||||
}
|
||||
func (s *SQLiteStore) UnblockUser(blockerID, blockedID int64) error {
|
||||
return s.db.UnblockUser(blockerID, blockedID)
|
||||
}
|
||||
func (s *SQLiteStore) IsBlocked(blockerID, blockedID int64) (bool, error) {
|
||||
return s.db.IsBlocked(blockerID, blockedID)
|
||||
}
|
||||
func (s *SQLiteStore) IsEitherBlocked(userA, userB int64) (bool, error) {
|
||||
return s.db.IsEitherBlocked(userA, userB)
|
||||
}
|
||||
func (s *SQLiteStore) ListBlockedUsers(blockerID int64) ([]int64, error) {
|
||||
return s.db.ListBlockedUsers(blockerID)
|
||||
}
|
||||
|
||||
// ── AttachmentStore ─────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) CreateAttachment(id string, uploaderID int64, filename, storedAs, mimeType string, size int64, width, height *int) error {
|
||||
return s.db.CreateAttachment(id, uploaderID, filename, storedAs, mimeType, size, width, height)
|
||||
}
|
||||
func (s *SQLiteStore) GetAttachmentByID(id string) (*db.Attachment, error) {
|
||||
return s.db.GetAttachmentByID(id)
|
||||
}
|
||||
func (s *SQLiteStore) GetAttachmentWithChannel(id string) (*db.AttachmentAccess, error) {
|
||||
return s.db.GetAttachmentWithChannel(id)
|
||||
}
|
||||
func (s *SQLiteStore) DeleteOrphanedAttachments(cutoff string) ([]string, error) {
|
||||
return s.db.DeleteOrphanedAttachments(cutoff)
|
||||
}
|
||||
|
||||
// ── AdminStore ──────────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) UserCount() (int64, error) { return s.db.UserCount() }
|
||||
func (s *SQLiteStore) GetServerStats() (*db.ServerStats, error) { return s.db.GetServerStats() }
|
||||
func (s *SQLiteStore) ListAllUsers(limit, offset int) ([]db.UserWithRole, error) {
|
||||
return s.db.ListAllUsers(limit, offset)
|
||||
}
|
||||
func (s *SQLiteStore) BanUser(id int64, reason string, expires *time.Time) error {
|
||||
return s.db.BanUser(id, reason, expires)
|
||||
}
|
||||
func (s *SQLiteStore) UnbanUser(id int64) error { return s.db.UnbanUser(id) }
|
||||
func (s *SQLiteStore) LogAudit(actorID int64, action, targetType string, targetID int64, detail string) error {
|
||||
return s.db.LogAudit(actorID, action, targetType, targetID, detail)
|
||||
}
|
||||
func (s *SQLiteStore) GetAuditLog(limit, offset int) ([]db.AuditEntry, error) {
|
||||
return s.db.GetAuditLog(limit, offset)
|
||||
}
|
||||
func (s *SQLiteStore) AdminCreateChannel(name, chanType, category, topic string, position int) (int64, error) {
|
||||
return s.db.AdminCreateChannel(name, chanType, category, topic, position)
|
||||
}
|
||||
func (s *SQLiteStore) AdminUpdateChannel(id int64, name, topic string, slowMode, position int, archived bool) error {
|
||||
return s.db.AdminUpdateChannel(id, name, topic, slowMode, position, archived)
|
||||
}
|
||||
func (s *SQLiteStore) AdminDeleteChannel(id int64) error { return s.db.AdminDeleteChannel(id) }
|
||||
func (s *SQLiteStore) BackupTo(path string) error { return s.db.BackupTo(path) }
|
||||
func (s *SQLiteStore) BackupToSafe(path, safeRoot string) error {
|
||||
return s.db.BackupToSafe(path, safeRoot)
|
||||
}
|
||||
func (s *SQLiteStore) CountUsersWithoutTOTP() (int, error) { return s.db.CountUsersWithoutTOTP() }
|
||||
|
||||
// ── SettingsStore ───────────────────────────────────────────────────────────
|
||||
|
||||
func (s *SQLiteStore) GetSetting(key string) (string, error) { return s.db.GetSetting(key) }
|
||||
func (s *SQLiteStore) SetSetting(key, value string) error { return s.db.SetSetting(key, value) }
|
||||
func (s *SQLiteStore) GetAllSettings() (map[string]string, error) { return s.db.GetAllSettings() }
|
||||
|
||||
// Compile-time interface check.
|
||||
var _ Store = (*SQLiteStore)(nil)
|
||||
@@ -0,0 +1,196 @@
|
||||
// Package store defines the database abstraction layer for OwnCord.
|
||||
// The Store interface decouples services from the concrete database
|
||||
// implementation, enabling SQLite (default) and future PostgreSQL support.
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/owncord/server/db"
|
||||
)
|
||||
|
||||
// Store is the top-level interface combining all domain-specific stores.
|
||||
// Services accept Store instead of *db.DB, enabling swappable backends.
|
||||
type Store interface {
|
||||
MessageStore
|
||||
ChannelStore
|
||||
UserStore
|
||||
SessionStore
|
||||
RoleStore
|
||||
InviteStore
|
||||
VoiceStore
|
||||
DMStore
|
||||
BlockStore
|
||||
AttachmentStore
|
||||
AdminStore
|
||||
SettingsStore
|
||||
|
||||
// Close releases the underlying database connection.
|
||||
Close() error
|
||||
|
||||
// WithTx executes fn within a transaction. The transaction is committed
|
||||
// if fn returns nil, rolled back otherwise.
|
||||
WithTx(ctx context.Context, fn func(Store) error) error
|
||||
|
||||
// Raw access for callers that need it (migration, backup, etc.).
|
||||
SQLDb() *sql.DB
|
||||
}
|
||||
|
||||
// MessageStore handles message CRUD, reactions, search, and read state.
|
||||
type MessageStore interface {
|
||||
CreateMessage(channelID, userID int64, content string, replyTo *int64) (int64, error)
|
||||
GetMessage(id int64) (*db.Message, error)
|
||||
GetMessages(channelID, before int64, limit int) ([]db.MessageWithUser, error)
|
||||
GetMessagesForAPI(channelID, before int64, limit int, requestingUserID int64) ([]db.MessageAPIResponse, error)
|
||||
EditMessage(id, userID int64, content string) error
|
||||
DeleteMessage(id, userID int64, isMod bool) error
|
||||
SearchMessages(query string, channelID *int64, limit int) ([]db.MessageSearchResult, error)
|
||||
SearchMessagesInChannels(query string, channelIDs []int64, limit int) ([]db.MessageSearchResult, error)
|
||||
GetPinnedMessages(channelID int64, requestingUserID int64) ([]db.MessageAPIResponse, error)
|
||||
SetMessagePinned(id int64, pinned bool) error
|
||||
AddReaction(messageID, userID int64, emoji string) error
|
||||
RemoveReaction(messageID, userID int64, emoji string) error
|
||||
GetReactions(messageID int64) ([]db.ReactionCount, error)
|
||||
UpdateReadState(userID, channelID, lastReadMessageID int64) error
|
||||
GetChannelUnreadCounts(userID int64) (map[int64]db.ChannelUnread, error)
|
||||
GetLatestMessageID(channelID int64) (int64, error)
|
||||
LinkAttachmentsToMessage(messageID int64, attachmentIDs []string) (int64, error)
|
||||
GetAttachmentsByMessageIDs(msgIDs []int64) (map[int64][]db.AttachmentInfo, error)
|
||||
}
|
||||
|
||||
// ChannelStore handles channel CRUD and permission overrides.
|
||||
type ChannelStore interface {
|
||||
ListChannels() ([]db.Channel, error)
|
||||
GetChannel(id int64) (*db.Channel, error)
|
||||
CreateChannel(name, chanType, category, topic string, position int) (int64, error)
|
||||
UpdateChannel(id int64, name, topic string, slowMode int) error
|
||||
DeleteChannel(id int64) error
|
||||
SetChannelSlowMode(id int64, slowMode int) error
|
||||
SetChannelVoiceMaxUsers(id int64, maxUsers int) error
|
||||
GetChannelPermissions(channelID, roleID int64) (allow, deny int64, err error)
|
||||
GetAllChannelPermissionsForRole(roleID int64) (map[int64]db.ChannelOverride, error)
|
||||
GetChannelTypes(ids []int64) (map[int64]string, error)
|
||||
}
|
||||
|
||||
// UserStore handles user lookup and profile operations.
|
||||
type UserStore interface {
|
||||
GetUserByID(id int64) (*db.User, error)
|
||||
GetUserByUsername(username string) (*db.User, error)
|
||||
CreateUser(username, passwordHash string, roleID int) (int64, error)
|
||||
CreateOwnerIfEmpty(username, passwordHash string, roleID int) (int64, error)
|
||||
CreateUserWithInvite(username, passwordHash string, roleID int, inviteCode string) (int64, error)
|
||||
UpdateUserProfile(userID int64, username string, avatar *string) error
|
||||
UpdateUserPassword(userID int64, newPasswordHash string) error
|
||||
UpdateUserStatus(id int64, status string) error
|
||||
UpdateUserTOTPSecret(id int64, secret *string) error
|
||||
UpdateUserRole(userID, roleID int64) error
|
||||
ResetAllUserStatuses() error
|
||||
DeleteAccount(ctx context.Context, userID int64) error
|
||||
ListMembers() ([]db.MemberSummary, error)
|
||||
}
|
||||
|
||||
// SessionStore handles authentication session management.
|
||||
type SessionStore interface {
|
||||
CreateSession(userID int64, tokenHash, device, ip string) (int64, error)
|
||||
GetSessionByTokenHash(tokenHash string) (*db.Session, error)
|
||||
GetSessionWithBanStatus(tokenHash string) (*db.SessionWithBanStatus, error)
|
||||
DeleteSession(tokenHash string) error
|
||||
DeleteOtherSessions(userID, keepSessionID int64) (int64, error)
|
||||
DeleteExpiredSessions() error
|
||||
DeleteSessionByID(sessionID, userID int64) error
|
||||
TouchSession(tokenHash string) error
|
||||
ListUserSessions(userID int64) ([]db.Session, error)
|
||||
ForceLogoutUser(userID int64) error
|
||||
GetUserSessions(userID int64) ([]db.Session, error)
|
||||
}
|
||||
|
||||
// RoleStore handles role lookups.
|
||||
type RoleStore interface {
|
||||
GetRoleByID(id int64) (*db.Role, error)
|
||||
GetRoleForUser(userID int64) (*db.Role, error)
|
||||
GetUserWithRole(userID int64) (*db.User, *db.Role, error)
|
||||
ListRoles() ([]*db.Role, error)
|
||||
}
|
||||
|
||||
// InviteStore handles invite management.
|
||||
type InviteStore interface {
|
||||
CreateInvite(createdBy int64, maxUses int, expiresAt *time.Time) (string, error)
|
||||
GetInvite(code string) (*db.Invite, error)
|
||||
ListInvites() ([]*db.Invite, error)
|
||||
UseInviteAtomic(code string) error
|
||||
RevokeInvite(code string) error
|
||||
}
|
||||
|
||||
// VoiceStore handles voice state management.
|
||||
type VoiceStore interface {
|
||||
JoinVoiceChannel(userID, channelID int64) error
|
||||
JoinVoiceChannelIfCapacity(userID, channelID int64, maxUsers int) error
|
||||
LeaveVoiceChannel(userID int64) error
|
||||
LeaveVoiceChannelIfMatch(userID, expectedChannelID int64, expectedJoinedAt string) (bool, error)
|
||||
GetVoiceState(userID int64) (*db.VoiceState, error)
|
||||
GetChannelVoiceStates(channelID int64) ([]db.VoiceState, error)
|
||||
GetAllVoiceStates() ([]db.VoiceState, error)
|
||||
UpdateVoiceMute(userID int64, muted bool) error
|
||||
UpdateVoiceDeafen(userID int64, deafened bool) error
|
||||
ClearVoiceState(userID int64) error
|
||||
ClearAllVoiceStates() error
|
||||
CountActiveCameras(channelID int64) (int, error)
|
||||
UpdateVoiceCamera(userID int64, camera bool) error
|
||||
EnableCameraIfUnderLimit(userID, channelID int64, maxVideo int) (bool, error)
|
||||
UpdateVoiceScreenshare(userID int64, screenshare bool) error
|
||||
CountChannelVoiceUsers(channelID int64) (int, error)
|
||||
}
|
||||
|
||||
// DMStore handles direct message channels.
|
||||
type DMStore interface {
|
||||
GetOrCreateDMChannel(user1ID, user2ID int64) (*db.Channel, bool, error)
|
||||
GetUserDMChannels(userID int64) ([]db.DMChannelInfo, error)
|
||||
OpenDM(userID, channelID int64) error
|
||||
CloseDM(userID, channelID int64) error
|
||||
IsDMParticipant(userID, channelID int64) (bool, error)
|
||||
GetDMParticipantIDs(channelID int64) ([]int64, error)
|
||||
GetDMRecipient(channelID, requestingUserID int64) (*db.User, error)
|
||||
}
|
||||
|
||||
// BlockStore handles user blocks.
|
||||
type BlockStore interface {
|
||||
BlockUser(blockerID, blockedID int64) error
|
||||
UnblockUser(blockerID, blockedID int64) error
|
||||
IsBlocked(blockerID, blockedID int64) (bool, error)
|
||||
IsEitherBlocked(userA, userB int64) (bool, error)
|
||||
ListBlockedUsers(blockerID int64) ([]int64, error)
|
||||
}
|
||||
|
||||
// AttachmentStore handles file attachment metadata.
|
||||
type AttachmentStore interface {
|
||||
CreateAttachment(id string, uploaderID int64, filename, storedAs, mimeType string, size int64, width, height *int) error
|
||||
GetAttachmentByID(id string) (*db.Attachment, error)
|
||||
GetAttachmentWithChannel(id string) (*db.AttachmentAccess, error)
|
||||
DeleteOrphanedAttachments(cutoff string) ([]string, error)
|
||||
}
|
||||
|
||||
// AdminStore handles admin operations.
|
||||
type AdminStore interface {
|
||||
UserCount() (int64, error)
|
||||
GetServerStats() (*db.ServerStats, error)
|
||||
ListAllUsers(limit, offset int) ([]db.UserWithRole, error)
|
||||
BanUser(id int64, reason string, expires *time.Time) error
|
||||
UnbanUser(id int64) error
|
||||
LogAudit(actorID int64, action, targetType string, targetID int64, detail string) error
|
||||
GetAuditLog(limit, offset int) ([]db.AuditEntry, error)
|
||||
AdminCreateChannel(name, chanType, category, topic string, position int) (int64, error)
|
||||
AdminUpdateChannel(id int64, name, topic string, slowMode, position int, archived bool) error
|
||||
AdminDeleteChannel(id int64) error
|
||||
BackupTo(path string) error
|
||||
BackupToSafe(path, safeRoot string) error
|
||||
CountUsersWithoutTOTP() (int, error)
|
||||
}
|
||||
|
||||
// SettingsStore handles server settings.
|
||||
type SettingsStore interface {
|
||||
GetSetting(key string) (string, error)
|
||||
SetSetting(key, value string) error
|
||||
GetAllSettings() (map[string]string, error)
|
||||
}
|
||||
Reference in New Issue
Block a user