mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
Deletes Server/store (SQLiteStore, MemStore, the composed Store interface) and collapses to a single sqlc-backed db package, executing the prior audit's P4 "single data layer" direction (finding #6). SQLiteStore was a pure pass-through to *db.DB, so consumers now depend on narrow interfaces that *db.DB satisfies directly: - service.Store (service/datastore.go, renamed from store/store.go) - ws.EventStore (ws/eventstore.go) - plugin.PluginStore (plugin/pluginstore.go) The event- and plugin-KV methods that lived in the store's SQLite implementation move into the db package (db/event_queries.go, db/plugin_queries.go), keeping their raw-SQL form. Tests: the MemStore-based unit tests now run against a real in-memory SQLite db opened per-test with migrations applied, via package-local seed helpers. Fault-injection tests embed a real *db.DB and override the single method under test, preserving error-path coverage. Full server suite and sqlc-verify are green. Docs: audit finding #6 and A-2026-07-06 marked resolved; decisions D3 updated; architecture server.md / data-model.md diagrams and prose updated to the api -> service -> db layering. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UA17KPvqGBX3XbXYnMf1rA
153 lines
7.1 KiB
Go
153 lines
7.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/owncord/server/db"
|
|
)
|
|
|
|
// Store is the data-access surface the service layer depends on. It is the
|
|
// set of *db.DB methods the services call — no event/plugin/transaction
|
|
// methods, which belong to other layers. *db.DB satisfies this interface
|
|
// directly (D3 removed the former store package's pass-through wrapper), and
|
|
// tests inject fakes that embed a real in-memory *db.DB and override the one
|
|
// method they need to exercise an error path.
|
|
//
|
|
// permissions.NewChecker takes its own narrower interface (permissions.DB),
|
|
// which *db.DB and this Store both satisfy.
|
|
type Store interface {
|
|
// ── Messages / reactions / read-state ──
|
|
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, uploaderID int64, attachmentIDs []string) (int64, error)
|
|
GetAttachmentsByMessageIDs(msgIDs []int64) (map[int64][]db.AttachmentInfo, error)
|
|
|
|
// ── Channels ──
|
|
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)
|
|
|
|
// ── Users ──
|
|
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)
|
|
|
|
// ── Sessions ──
|
|
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)
|
|
|
|
// ── Roles ──
|
|
GetRoleByID(id int64) (*db.Role, error)
|
|
GetRoleForUser(userID int64) (*db.Role, error)
|
|
GetUserWithRole(userID int64) (*db.User, *db.Role, error)
|
|
ListRoles() ([]*db.Role, error)
|
|
|
|
// ── Invites ──
|
|
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
|
|
|
|
// ── Voice ──
|
|
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)
|
|
|
|
// ── Direct messages ──
|
|
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)
|
|
|
|
// ── Blocks ──
|
|
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)
|
|
|
|
// ── Attachments ──
|
|
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)
|
|
|
|
// ── Admin ──
|
|
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)
|
|
|
|
// ── Settings ──
|
|
GetSetting(key string) (string, error)
|
|
SetSetting(key, value string) error
|
|
GetAllSettings() (map[string]string, error)
|
|
}
|