Files
im_server/server/db/adapter.go
T

508 lines
29 KiB
Go

// Package adapter contains the interfaces to be implemented by the database adapter
package adapter
import (
"encoding/json"
"time"
"github.com/tinode/chat/server/auth"
t "github.com/tinode/chat/server/store/types"
)
// Adapter is the interface that must be implemented by a database
// adapter. The current schema supports a single connection by database type.
type Adapter interface {
// General
// Open and configure the adapter
Open(config json.RawMessage) error
// Close the adapter
Close() error
// IsOpen checks if the adapter is ready for use
IsOpen() bool
// GetDbVersion returns current database version.
GetDbVersion() (int, error)
// CheckDbVersion checks if the actual database version matches adapter version.
CheckDbVersion() error
// GetName returns the name of the adapter
GetName() string
// SetMaxResults configures how many results can be returned in a single DB call.
SetMaxResults(val int) error
// CreateDb creates the database optionally dropping an existing database first.
CreateDb(reset bool) error
// UpgradeDb upgrades database to the current adapter version.
UpgradeDb() error
// Version returns adapter version
Version() int
// DB connection stats object.
Stats() any
// User management
// UserCreate creates user record
UserCreate(user *t.User) error
// UserGet returns record for a given user ID
UserGet(uid t.Uid) (*t.User, error)
// UserGetAll returns user records for a given list of user IDs
UserGetAll(ids ...t.Uid) ([]t.User, error)
// UserDelete deletes user record
UserDelete(uid t.Uid, hard bool) error
// UserUpdate updates user record
UserUpdate(uid t.Uid, update map[string]any) error
// UserUpdateTags adds, removes, or resets user's tags
UserUpdateTags(uid t.Uid, add, remove, reset []string) ([]string, error)
// UserGetByCred returns user ID for the given validated credential.
UserGetByCred(method, value string) (t.Uid, error)
// UserUnreadCount returns the total number of unread messages in all topics with
// the R permission. If read fails, the counts are still returned with the original
// user IDs but with the unread count undefined and non-nil error.
UserUnreadCount(ids ...t.Uid) (map[t.Uid]int, error)
// UserGetUnvalidated returns a list of no more than 'limit' uids who never logged in,
// have no validated credentials and which haven't been updated since 'lastUpdatedBefore'.
UserGetUnvalidated(lastUpdatedBefore time.Time, limit int) ([]t.Uid, error)
// Credential management
// CredUpsert adds or updates a credential record. Returns true if record was inserted, false if updated.
CredUpsert(cred *t.Credential) (bool, error)
// CredGetActive returns the currently active credential record for the given method.
CredGetActive(uid t.Uid, method string) (*t.Credential, error)
// CredGetAll returns credential records for the given user and method, validated only or all.
CredGetAll(uid t.Uid, method string, validatedOnly bool) ([]t.Credential, error)
// CredDel deletes credentials for the given method/value. If method is empty, deletes all
// user's credentials.
CredDel(uid t.Uid, method, value string) error
// CredConfirm marks given credential as validated.
CredConfirm(uid t.Uid, method string) error
// CredFail increments count of failed validation attepmts for the given credentials.
CredFail(uid t.Uid, method string) error
// Authentication management for the basic authentication scheme
// AuthGetUniqueRecord returns authentication record for a given unique value i.e. login.
AuthGetUniqueRecord(unique string) (t.Uid, auth.Level, []byte, time.Time, error)
// AuthGetRecord returns authentication record given user ID and method.
AuthGetRecord(user t.Uid, scheme string) (string, auth.Level, []byte, time.Time, error)
// AuthAddRecord creates new authentication record
AuthAddRecord(user t.Uid, scheme, unique string, authLvl auth.Level, secret []byte, expires time.Time) error
// AuthDelScheme deletes an existing authentication scheme for the user.
AuthDelScheme(user t.Uid, scheme string) error
// AuthDelAllRecords deletes all records of a given user.
AuthDelAllRecords(uid t.Uid) (int, error)
// AuthUpdRecord modifies an authentication record. Only non-default/non-zero values are updated.
AuthUpdRecord(user t.Uid, scheme, unique string, authLvl auth.Level, secret []byte, expires time.Time) error
// Topic management
// TopicCreate creates a topic
TopicCreate(topic *t.Topic) error
// TopicCreateP2P creates a p2p topic
TopicCreateP2P(initiator, invited *t.Subscription) error
// TopicGet loads a single topic by name, if it exists. If the topic does not exist the call returns (nil, nil)
TopicGet(topic string) (*t.Topic, error)
// TopicsForUser loads subscriptions for a given user. Reads public value.
// When the 'opts.IfModifiedSince' query is not nil the subscriptions with UpdatedAt > opts.IfModifiedSince
// are returned, where UpdatedAt can be either a subscription, a topic, or a user update timestamp.
// This is need in order to support paginagion of subscriptions: get subscriptions page by page
// from the oldest updates to most recent:
// 1. Client already has subscriptions with the latest update timestamp X.
// 2. Client asks for N updated subscriptions since X. The server returns N with updates between X and Y.
// 3. Client goes to step 1 with X := Y.
TopicsForUser(uid t.Uid, keepDeleted bool, opts *t.QueryOpt) ([]t.Subscription, error)
// UsersForTopic loads users' subscriptions for a given topic. Public is loaded.
UsersForTopic(topic string, keepDeleted bool, opts *t.QueryOpt) ([]t.Subscription, error)
// OwnTopics loads a slice of topic names where the user is the owner.
OwnTopics(uid t.Uid) ([]string, error)
// ChannelsForUser loads a slice of topic names where the user is a channel reader and notifications (P) are enabled.
ChannelsForUser(uid t.Uid) ([]string, error)
// TopicShare creates topic subscriptions.
TopicShare(topic string, subs []*t.Subscription) error
// TopicDelete deletes topic, subscriptions, messages.
TopicDelete(topic string, isChan, hard bool) error
// TopicUpdateOnMessage increments Topic's or User's SeqId value and updates TouchedAt timestamp.
TopicUpdateOnMessage(topic string, msg *t.Message) error
// TopicUpdateSubCnt refreshes denormalized topic subscriber count.
TopicUpdateSubCnt(topic string) error
// TopicUpdate updates topic record.
TopicUpdate(topic string, update map[string]any) error
// TopicOwnerChange updates topic's owner
TopicOwnerChange(topic string, newOwner t.Uid) error
// Topic subscriptions
// SubscriptionGet reads a subscription of a user to a topic
SubscriptionGet(topic string, user t.Uid, keepDeleted bool) (*t.Subscription, error)
// SubsForUser loads all subscriptions of a given user. Does NOT load Public or Private values,
// does not load deleted subscriptions.
SubsForUser(user t.Uid) ([]t.Subscription, error)
// SubsForTopic gets a list of subscriptions to a given topic.. Does NOT load Public value.
SubsForTopic(topic string, keepDeleted bool, opts *t.QueryOpt) ([]t.Subscription, error)
// SubsUpdate updates pasrt of a subscription object. Pass nil for fields which don't need to be updated
SubsUpdate(topic string, user t.Uid, update map[string]any) error
// SubsDelete deletes a single subscription
SubsDelete(topic string, user t.Uid) error
// Search
// Find searches for users or topics given a list of tags.
// - caller is the user or topic who is doing the searching, it will be skipped from results.
// - prefix if present will cause match rank highest in the results.
// - req is a list of required tag sets. Each set is a list of tags. The search will return
// all users/topics which have at least one tag from each set.
// - opt is a list of optional tags; if present the result will rank higher.
// - activeOnly if true will return only active subscriptions.
Find(caller, prefix string, req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error)
// FindOne returns topic or user which matches the given tag.
FindOne(tag string) (string, error)
// Messages
// MessageSave saves message to database
MessageSave(msg *t.Message) error
// MessageGetAll returns messages matching the query
MessageGetAll(topic string, forUser t.Uid, opts *t.QueryOpt) ([]t.Message, error)
// MessageDeleteList marks messages as deleted.
// Soft- or Hard- is defined by forUser value: forUser.IsZero == true is hard.
MessageDeleteList(topic string, toDel *t.DelMessage) error
// MessageGetDeleted returns a list of deleted message Ids.
MessageGetDeleted(topic string, forUser t.Uid, opts *t.QueryOpt) ([]t.DelMessage, error)
// Devices (for push notifications)
// DeviceUpsert creates or updates a device record
DeviceUpsert(uid t.Uid, dev *t.DeviceDef) error
// DeviceGetAll returns all devices for a given set of users
DeviceGetAll(uid ...t.Uid) (map[t.Uid][]t.DeviceDef, int, error)
// DeviceDelete deletes a device record
DeviceDelete(uid t.Uid, deviceID string) error
// File upload records. The files are stored outside of the database.
// FileStartUpload initializes a file upload.
FileStartUpload(fd *t.FileDef) error
// FileFinishUpload marks file upload as completed, successfully or otherwise.
FileFinishUpload(fd *t.FileDef, success bool, size int64) (*t.FileDef, error)
// FileGet fetches a record of a specific file
FileGet(fid string) (*t.FileDef, error)
// FileDeleteUnused deletes records where UseCount is zero. If olderThan is non-zero, deletes
// unused records with UpdatedAt before olderThan.
// Returns array of FileDef.Location of deleted filerecords so actual files can be deleted too.
FileDeleteUnused(olderThan time.Time, limit int) ([]string, error)
// FileLinkAttachments connects given topic or message to the file record IDs from the list.
FileLinkAttachments(topic string, userId, msgId t.Uid, fids []string) error
// Persistent cache management.
// PCacheGet reads a persistent cache entry.
PCacheGet(key string) (string, error)
// PCacheUpsert creates or updates a persistent cache entry.
PCacheUpsert(key string, value string, failOnDuplicate bool) error
// PCacheDelete deletes a single persistent cache entry.
PCacheDelete(key string) error
// PCacheExpire expires older entries with the specified key prefix.
PCacheExpire(keyPrefix string, olderThan time.Time) error
// Testing
// GetTestDB returns a currently open database connection.
GetTestDB() any
}
// TenantAdapter is an optional capability implemented by tenant-aware database adapters.
// Keeping it separate lets adapters be migrated independently while tenant-aware entry
// points fail closed when the configured adapter does not support tenant resolution.
type TenantAdapter interface {
TenantGetByCode(code string) (*t.Tenant, error)
TenantGetByID(id t.TenantID) (*t.Tenant, error)
TenantListActive(limit int) ([]t.Tenant, error)
}
// RegistrationConfigAdapter reads global registration policy from the control database.
type RegistrationConfigAdapter interface {
RegistrationSMSEnabled() (bool, error)
}
// ThirdPartyConfigAdapter reads global third-party integration settings from
// the control database.
type ThirdPartyConfigAdapter interface {
ThirdPartyConfig(group string, keys ...string) (map[string]string, error)
}
// RealNamePolicyConfigAdapter reads tenant-level real-name review policy from
// the control database.
type RealNamePolicyConfigAdapter interface {
RealNamePolicy(t.TenantID) (*t.RealNamePolicy, error)
}
// TenantEntryAdapter stores public tenant entry data before a user is authenticated.
type TenantEntryAdapter interface {
PublicUploadCreate(*t.PublicUpload) (*t.PublicUpload, error)
TenantApplicationCreate(*t.TenantApplication) (*t.TenantApplication, error)
TenantEntryFeedbackCreate(*t.TenantEntryFeedback) (*t.TenantEntryFeedback, error)
}
type TenantInternalAdminQueryAdapter interface {
TenantInternalAdminQuery(tenantID t.TenantID, query string, countQuery string, args []any, page, perPage int) (*t.InternalAdminQueryResult, error)
TenantInternalAdminQueryOne(tenantID t.TenantID, query string, args []any) (map[string]any, error)
}
type TenantSecurityAuditAdapter interface {
TenantLoginAuditCreate(t.TenantID, *t.LoginAuditEvent) error
TenantLoginFailureCreate(t.TenantID, *t.LoginFailureEvent) error
TenantLoginAuditClose(t.TenantID, string, time.Time) error
TenantMessageAdminApply(t.TenantID, *t.MessageAdminAction) error
TenantContentModerationLogCreate(t.TenantID, *t.ContentModerationLog) error
}
// TenantRoutedAdapter can return a tenant-specific adapter, e.g. for the
// "one tenant, one database" deployment model.
type TenantRoutedAdapter interface {
TenantAdapterFor(t.TenantID) (TenantBusinessAdapter, TenantAuthAdapter, error)
}
// TenantRouteCacheInvalidator clears cached tenant routing metadata. A zero
// tenant ID clears every cached route.
type TenantRouteCacheInvalidator interface {
InvalidateTenantRoute(t.TenantID)
}
type TenantMessageBatchAdapter interface {
TenantMessageSaveBatch(t.TenantID, []*t.Message) error
TenantGroupMessageSaveBatch(t.TenantID, []*t.Message) error
}
// TenantMessageSchemaAdapter validates storage contracts required by asynchronous persistence.
type TenantMessageSchemaAdapter interface {
TenantMessageSchemaValidate([]t.TenantID) error
}
// TenantHTTPInfrastructureAdapter is the optional durable infrastructure used
// by Kafka dead-letter handling.
type TenantHTTPInfrastructureAdapter interface {
TenantKafkaConsumeDead(t.TenantID, *t.KafkaDeadLetter, time.Time) error
TenantKafkaDeadLetterList(t.TenantID, t.KafkaDeadLetterListOptions) (*t.KafkaDeadLetterPage, error)
TenantKafkaDeadLetterGet(t.TenantID, string) (*t.KafkaDeadLetter, error)
TenantKafkaDeadLetterMark(t.TenantID, string, string, string, string, time.Time) error
TenantKafkaDeadLetterMarkReplay(t.TenantID, string, string, string, time.Time) (*t.KafkaDeadLetter, error)
}
// TenantRegistrationInviteAdapter stores invitation definitions in the
// registry database and usage details in the selected tenant database.
type TenantRegistrationInviteAdapter interface {
TenantRegistrationInviteCreate(t.TenantID, *t.RegistrationInviteCode) error
TenantRegistrationInviteCreateBatch(t.TenantID, *t.RegistrationInviteBatch, []t.RegistrationInviteCode) error
TenantRegistrationInviteGetByCode(t.TenantID, string) (*t.RegistrationInviteCode, error)
TenantRegistrationInviteList(t.TenantID, t.RegistrationInviteListOptions) (*t.RegistrationInvitePage, error)
TenantRegistrationInviteBatchGet(t.TenantID, int64) (*t.RegistrationInviteBatch, error)
TenantRegistrationInviteBatchGetByIdempotency(t.TenantID, string) (*t.RegistrationInviteBatch, error)
TenantRegistrationInviteRevoke(t.TenantID, int64, time.Time) error
TenantRegistrationInviteBatchRevoke(t.TenantID, int64, time.Time) (int, error)
TenantRegistrationInviteRecordUse(t.TenantID, string, t.Uid, string, time.Time) error
TenantRegistrationInviteSyncUsage(t.TenantID, int64) error
}
// TenantLoginLockoutAdapter persists per-account login failure counters and
// lock state in each tenant business database.
type TenantLoginLockoutAdapter interface {
TenantLoginLockoutGet(t.TenantID, string) (*t.LoginLockout, error)
TenantLoginLockoutRecordFailure(t.TenantID, string, *int64, time.Time, time.Time) (*t.LoginLockout, error)
TenantLoginLockoutLock(t.TenantID, string, time.Time, time.Time) error
TenantLoginLockoutReset(t.TenantID, string) error
TenantLoginLockoutRelease(t.TenantID, string, time.Time) error
}
// TenantAuthAdapter is the tenant-aware authentication and credential capability.
// It is separate from Adapter while the remaining persistence domains are migrated.
type TenantAuthAdapter interface {
TenantAuthGetByLogin(tenantID t.TenantID, login string) (t.Uid, auth.Level, []byte, time.Time, error)
TenantAuthGetRecord(tenantID t.TenantID, user t.Uid) (string, auth.Level, []byte, time.Time, error)
TenantAuthAddRecord(tenantID t.TenantID, user t.Uid, authLvl auth.Level, secret []byte, expires time.Time) error
TenantAuthDeleteRecord(tenantID t.TenantID, user t.Uid) error
TenantAuthUpdateRecord(tenantID t.TenantID, user t.Uid, username string, authLvl auth.Level,
secret []byte, expires time.Time) error
TenantUserGetByCred(tenantID t.TenantID, method, value string) (t.Uid, error)
TenantCredUpsert(tenantID t.TenantID, cred *t.Credential) (bool, error)
TenantCredGetActive(tenantID t.TenantID, uid t.Uid, method string) (*t.Credential, error)
TenantCredGetAll(tenantID t.TenantID, uid t.Uid, method string, validatedOnly bool) ([]t.Credential, error)
TenantCredDel(tenantID t.TenantID, uid t.Uid, method, value string) error
TenantCredConfirm(tenantID t.TenantID, uid t.Uid, method string) error
TenantCredFail(tenantID t.TenantID, uid t.Uid, method string) error
}
// TenantBusinessAdapter is the mandatory tenant-aware persistence capability
// used by request handling code. Adapters which do not implement it fail closed
// at the Store boundary instead of falling back to legacy unscoped queries.
type TenantBusinessAdapter interface {
// TenantBusinessReady reports whether every method below enforces tenant
// isolation in its database queries. Startup is rejected while false.
TenantBusinessReady() bool
TenantUserCreate(t.TenantID, *t.User) error
TenantUserGet(t.TenantID, t.Uid) (*t.User, error)
TenantUserGetAll(t.TenantID, ...t.Uid) ([]t.User, error)
TenantUserGetByPhone(t.TenantID, string) (t.Uid, error)
TenantUserDelete(t.TenantID, t.Uid, bool) error
TenantUserUpdate(t.TenantID, t.Uid, map[string]any) error
TenantUserUpdateTags(t.TenantID, t.Uid, []string, []string, []string) ([]string, error)
TenantUserUnreadCount(t.TenantID, ...t.Uid) (map[t.Uid]int, error)
TenantUserGetUnvalidated(t.TenantID, time.Time, int) ([]t.Uid, error)
TenantTopicCreate(t.TenantID, *t.Topic) error
TenantTopicCreateP2P(t.TenantID, *t.Subscription, *t.Subscription) error
TenantTopicGet(t.TenantID, string) (*t.Topic, error)
TenantTopicsForUser(t.TenantID, t.Uid, bool, *t.QueryOpt) ([]t.Subscription, error)
TenantUsersForTopic(t.TenantID, string, bool, *t.QueryOpt) ([]t.Subscription, error)
TenantOwnTopics(t.TenantID, t.Uid) ([]string, error)
TenantChannelsForUser(t.TenantID, t.Uid) ([]string, error)
TenantTopicShare(t.TenantID, string, []*t.Subscription) error
TenantTopicDelete(t.TenantID, string, bool, bool) error
TenantTopicUpdateOnMessage(t.TenantID, string, *t.Message) error
TenantTopicUpdateSubCnt(t.TenantID, string) error
TenantTopicUpdate(t.TenantID, string, map[string]any) error
TenantTopicBumpMutationVersion(t.TenantID, string, time.Time) (int64, error)
TenantTopicOwnerChange(t.TenantID, string, t.Uid) error
TenantSubscriptionGet(t.TenantID, string, t.Uid, bool) (*t.Subscription, error)
TenantSubsForUser(t.TenantID, t.Uid) ([]t.Subscription, error)
TenantSubsForTopic(t.TenantID, string, bool, *t.QueryOpt) ([]t.Subscription, error)
TenantSubsUpdate(t.TenantID, string, t.Uid, map[string]any) error
TenantSubsDelete(t.TenantID, string, t.Uid) error
TenantFind(t.TenantID, string, string, [][]string, []string, bool) ([]t.Subscription, error)
TenantFindOne(t.TenantID, string) (string, error)
TenantMessageSave(t.TenantID, *t.Message) error
TenantMessageGetByClientID(t.TenantID, t.Uid, string) (*t.Message, error)
TenantMessageGetOne(t.TenantID, string, int64) (*t.Message, error)
TenantMessageRecall(t.TenantID, string, int64, t.Uid, int, time.Time) (*t.Message, error)
TenantMessageEdit(t.TenantID, string, int64, t.Uid, int, t.KVMap, any, string, time.Time) (*t.Message, error)
TenantMessageGetAll(t.TenantID, string, t.Uid, *t.QueryOpt) ([]t.Message, error)
TenantMessageDeleteList(t.TenantID, string, *t.DelMessage) error
TenantMessageGetDeleted(t.TenantID, string, t.Uid, *t.QueryOpt) ([]t.DelMessage, error)
TenantMessageSearch(t.TenantID, string, t.Uid, string, string, string, int) ([]t.Message, string, error)
TenantMessageMutations(t.TenantID, string, t.Uid, int64, int) ([]t.MessageMutation, string, bool, int64, error)
TenantGroupMessageSave(t.TenantID, *t.Message) error
TenantGroupMessageGetByClientID(t.TenantID, string, t.Uid, string) (*t.Message, error)
TenantGroupMessageGetOne(t.TenantID, string, int64) (*t.Message, error)
TenantGroupMessageRecall(t.TenantID, string, int64, t.Uid, int, time.Time) (*t.Message, error)
TenantGroupMessageEdit(t.TenantID, string, int64, t.Uid, int, t.KVMap, any, string, time.Time) (*t.Message, error)
TenantGroupMessageGetAll(t.TenantID, string, t.Uid, *t.QueryOpt) ([]t.Message, error)
TenantGroupMessageDeleteList(t.TenantID, string, *t.DelMessage) error
TenantConversationSettingsGet(t.TenantID, t.Uid, string) (*t.ConversationSettings, error)
TenantConversationSettingsUpdate(t.TenantID, t.Uid, string, t.ConversationSettingsPatch) (*t.ConversationSettings, error)
TenantTopicDraftGet(t.TenantID, t.Uid, string) (*t.TopicDraft, error)
TenantTopicDraftPut(t.TenantID, t.Uid, string, string, []byte, int) (*t.TopicDraft, error)
TenantCallCreate(t.TenantID, *t.CallRecord) error
TenantCallAccept(t.TenantID, string, int64, time.Time) error
TenantCallFinish(t.TenantID, string, int64, string, int64, time.Time) error
TenantCallList(t.TenantID, t.Uid, string, string, int) ([]t.CallRecord, string, error)
TenantGroupSettingsCreate(t.TenantID, *t.GroupSettings) (*t.GroupSettings, error)
TenantGroupSettingsGet(t.TenantID, string) (*t.GroupSettings, error)
TenantGroupSettingsUpdate(t.TenantID, string, t.GroupSettingsPatch) (*t.GroupSettings, error)
TenantGroupDissolve(t.TenantID, string, t.Uid, string, time.Time) (*t.GroupSettings, error)
TenantGroupMemberUpsert(t.TenantID, *t.GroupMember) (*t.GroupMember, error)
TenantGroupMemberGet(t.TenantID, string, t.Uid) (*t.GroupMember, error)
TenantGroupMemberList(t.TenantID, string, t.GroupMemberListOptions) ([]t.GroupMember, string, error)
TenantGroupMemberUpdate(t.TenantID, string, t.Uid, t.GroupMemberPatch) (*t.GroupMember, error)
TenantGroupInvitationCreate(t.TenantID, *t.GroupInvitation) (*t.GroupInvitation, error)
TenantGroupInvitationAccept(t.TenantID, string, t.Uid, any, time.Time) (*t.GroupInvitation, error)
TenantGroupJoinRequestCreate(t.TenantID, *t.GroupJoinRequest) (*t.GroupJoinRequest, error)
TenantGroupJoinRequestList(t.TenantID, string, string, string, int) ([]t.GroupJoinRequest, string, error)
TenantGroupJoinRequestResolve(t.TenantID, string, string, t.Uid, string, string, int, any, time.Time) (*t.GroupJoinRequest, error)
TenantGroupAnnouncementLatest(t.TenantID, string) (*t.GroupAnnouncement, error)
TenantGroupAnnouncementGet(t.TenantID, string, string) (*t.GroupAnnouncement, error)
TenantGroupAnnouncementPut(t.TenantID, *t.GroupAnnouncement, int) (*t.GroupAnnouncement, error)
TenantGroupAnnouncementRead(t.TenantID, string, string, t.Uid, time.Time) error
TenantGroupMuteList(t.TenantID, string, string, int) ([]t.GroupMute, string, error)
TenantGroupMuteGet(t.TenantID, string, t.Uid) (*t.GroupMute, error)
TenantGroupMuteUpsert(t.TenantID, *t.GroupMute) (*t.GroupMute, error)
TenantGroupMuteDelete(t.TenantID, string, t.Uid, t.Uid, time.Time) error
TenantGroupFileList(t.TenantID, string, string, string, string, int) ([]t.GroupFile, string, error)
TenantGroupFileCreate(t.TenantID, *t.GroupFile) (*t.GroupFile, error)
TenantGroupFileDelete(t.TenantID, string, string, t.Uid, bool, time.Time) (*t.GroupFile, error)
TenantGroupCreate(t.TenantID, *t.Topic, t.Uid, any, *t.GroupSettings, []t.Uid, any, time.Time) error
TenantGroupInviteMember(t.TenantID, string, t.Uid, t.Uid, string, string, any, time.Time) (bool, error)
TenantGroupLeave(t.TenantID, string, t.Uid, time.Time) error
TenantGroupRoleUpdate(t.TenantID, string, t.Uid, t.Uid, string, t.AccessMode, time.Time) error
TenantGroupOwnerTransfer(t.TenantID, string, t.Uid, t.Uid, int, time.Time) error
TenantGroupCanPost(t.TenantID, string, t.Uid, bool, time.Time) (bool, error)
TenantUserProfileGet(t.TenantID, t.Uid) (*t.UserProfile, error)
TenantUserProfileUpdate(t.TenantID, t.Uid, t.UserProfilePatch) (*t.UserProfile, error)
TenantUserPrivacyGet(t.TenantID, t.Uid) (*t.UserPrivacySettings, error)
TenantUserPrivacyUpdate(t.TenantID, t.Uid, t.UserPrivacyPatch) (*t.UserPrivacySettings, error)
TenantDevicePushTokenUpsert(t.TenantID, *t.DevicePushToken) (*t.DevicePushToken, error)
TenantRiskChallengeCreate(t.TenantID, *t.RiskChallenge) (*t.RiskChallenge, error)
TenantRiskChallengeConfirm(t.TenantID, t.Uid, string, string, string, time.Time) (*t.RiskChallenge, error)
TenantAbuseReasons(t.TenantID, string) ([]t.AbuseReason, error)
TenantAbuseReportCreate(t.TenantID, *t.AbuseReport, string) (*t.AbuseReport, error)
TenantFeedbackConfigGet(t.TenantID, t.Uid) (*t.FeedbackConfig, error)
TenantFeedbackCreate(t.TenantID, *t.FeedbackSubmission, string) (*t.FeedbackSubmission, error)
TenantFavoriteCreate(t.TenantID, *t.FavoriteItem) (*t.FavoriteItem, error)
TenantFavoriteList(t.TenantID, t.Uid, string, string, string, int) ([]t.FavoriteItem, string, error)
TenantFavoriteGet(t.TenantID, t.Uid, string) (*t.FavoriteItem, error)
TenantFavoriteDelete(t.TenantID, t.Uid, string) error
TenantDeviceUpsert(t.TenantID, t.Uid, *t.DeviceDef) error
TenantDeviceGetAll(t.TenantID, ...t.Uid) (map[t.Uid][]t.DeviceDef, int, error)
TenantDeviceDelete(t.TenantID, t.Uid, string) error
TenantFileStartUpload(t.TenantID, *t.FileDef) error
TenantFileFinishUpload(t.TenantID, *t.FileDef, bool, int64) (*t.FileDef, error)
TenantFileGet(t.TenantID, string) (*t.FileDef, error)
TenantFileDeleteUnused(t.TenantID, time.Time, int) ([]string, error)
TenantFileLinkAttachments(t.TenantID, string, t.Uid, t.Uid, []string) error
TenantFileUserHasAccess(t.TenantID, string, t.Uid) (bool, error)
TenantPCacheGet(t.TenantID, string) (string, error)
TenantPCacheUpsert(t.TenantID, string, string, bool) error
TenantPCacheDelete(t.TenantID, string) error
TenantPCacheExpire(t.TenantID, string, time.Time) error
TenantVerificationCreate(t.TenantID, *t.VerificationCode) error
TenantVerificationGet(t.TenantID, string) (*t.VerificationCode, error)
TenantVerificationGetActive(t.TenantID, string, string, time.Time) (*t.VerificationCode, error)
TenantVerificationFail(t.TenantID, string, t.VerificationState) error
TenantVerificationMarkVerified(t.TenantID, string, string, time.Time) error
TenantVerificationConsume(t.TenantID, string, string, time.Time) error
TenantUserSecurityGetAuthVersion(t.TenantID, t.Uid) (int, error)
TenantUserSecurityBumpAuthVersion(t.TenantID, t.Uid, time.Time) (int, error)
TenantRealNameGet(t.TenantID, t.Uid) (*t.RealNameVerification, error)
TenantRealNameCreate(t.TenantID, *t.RealNameVerification) error
TenantRealNameAppealCreate(t.TenantID, *t.RealNameAppeal) (*t.RealNameAppeal, error)
TenantActionTokenCreate(t.TenantID, *t.ActionToken) error
TenantActionTokenConsume(t.TenantID, t.Uid, string, string, string, time.Time) (*t.ActionToken, error)
TenantIndependentPasswordGet(t.TenantID, t.Uid, string) (*t.IndependentPassword, error)
TenantIndependentPasswordUpsert(t.TenantID, *t.IndependentPassword) error
TenantIndependentPasswordUpdateAttempts(t.TenantID, t.Uid, string, int, *time.Time, time.Time) error
TenantYouthModeGet(t.TenantID, t.Uid) (*t.YouthModeSettings, error)
TenantYouthModeSet(t.TenantID, t.Uid, bool, int, time.Time) (*t.YouthModeSettings, error)
TenantSystemNotificationCreate(t.TenantID, *t.SystemNotification) error
TenantSystemNotificationList(t.TenantID, t.Uid, string, int) ([]t.SystemNotification, string, error)
TenantSystemNotificationUnreadCount(t.TenantID, t.Uid) (int, error)
TenantSystemNotificationUnreadCountByEventPrefix(t.TenantID, t.Uid, string) (int, error)
TenantSystemNotificationMarkRead(t.TenantID, t.Uid, string, time.Time) (*t.SystemNotification, error)
TenantFriendRequestCreate(t.TenantID, *t.FriendRequest) (*t.FriendRequest, error)
TenantFriendRequestList(t.TenantID, t.Uid, string, string, string, int) ([]t.FriendRequestListItem, string, error)
TenantFriendRequestPendingCount(t.TenantID, t.Uid) (int, error)
TenantFriendRequestLatestBetween(t.TenantID, t.Uid, t.Uid) (*t.FriendRequest, error)
TenantFriendRequestAccept(t.TenantID, string, t.Uid, time.Time) (*t.FriendRequest, error)
TenantFriendRequestResolve(t.TenantID, string, t.Uid, string, time.Time) (*t.FriendRequest, error)
TenantFriendshipUpsertPair(t.TenantID, t.Uid, t.Uid, string, time.Time) error
TenantFriendshipList(t.TenantID, t.Uid, string, string, string, int) ([]t.FriendListItem, string, error)
TenantFriendshipGet(t.TenantID, t.Uid, t.Uid) (*t.Friendship, error)
TenantFriendshipUpdateRemark(t.TenantID, t.Uid, t.Uid, string, time.Time) (*t.Friendship, error)
TenantFriendshipDeletePair(t.TenantID, t.Uid, t.Uid, time.Time) error
TenantUserBlockGet(t.TenantID, t.Uid, t.Uid) (*t.UserBlock, error)
TenantUserBlockList(t.TenantID, t.Uid, string, int) ([]t.BlockListItem, string, error)
TenantUserBlockUpsert(t.TenantID, t.Uid, t.Uid, time.Time) (*t.UserBlock, error)
TenantUserBlockDelete(t.TenantID, t.Uid, t.Uid) error
TenantUserSearch(t.TenantID, t.Uid, string, string, string, int) ([]t.User, string, error)
}