Files
Warp/server/internal/storage/pocketbase/pocketbase.go
T
tajniak81andClaude Opus 5.5 a94794b866
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
Phase 9: application services and admin completion
Implements PLAN.md Phase 9. internal/appservice reads registration files
(appservice.config_files), matches namespaces the way Synapse does
(anchored at the start), and delivers events to each service as
transactions read from the roomserver's event stream at a cursor kept in
appservice_state. A transaction in flight is recorded, so after a restart
it is resent under the same ID; failures back off from 2s to 5m, and a
successful ping cuts the backoff short.

In the Client-Server API an as_token acts as the service's sender or, with
?user_id=, as any existing user in its namespace. Services register and
log in their users with m.login.application_service; exclusive user and
alias namespaces are refused to everybody else with M_EXCLUSIVE. Unknown
aliases and users in a namespace are asked of the service first. The
ping endpoint reports M_URL_NOT_SET, M_BAD_STATUS, M_CONNECTION_FAILED
and M_CONNECTION_TIMEOUT. Services' own requests, and their users' when
rate_limited is false, skip the rate limiter.

Users can change their password (POST /account/password) and deactivate
their account (POST /account/deactivate), both behind the password.
Deactivation revokes tokens, deletes devices, optionally erases the
profile and leaves every room through a new userapi.AccountObserver.

The admin API is complete: user detail, the admin flag, deactivation and
reactivation, password resets, devices, media quotas
(media.max_user_storage_bytes plus per-user overrides), registration
tokens with use limits and expiry (registration.require_token), server
notices (internal/servernotices, server_notices.*), an editor for the
federation allow/deny lists persisted in server_settings, a delivery view
of the application services, and an audit log of every change.

Migration 0011 adds the registration token, server notice room, media
quota, audit log and appservice cursor tables. Policy lists are now
returned sorted. The Complement entrypoint loads the registrations
Complement mounts in /complement/appservice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:58:28 +02:00

751 lines
27 KiB
Go

// Package pocketbase is the placeholder for the PocketBase storage driver.
//
// The plan (PLAN.md section 4) is an appliance deployment: one binary that
// also brings admin auth, a filesystem abstraction for media (local or S3)
// and realtime for the admin panel. The event DAG is a poor fit for
// PocketBase's record model, so the roomserver and syncapi tables will use
// its underlying dbx connection directly rather than its collection API.
//
// Until that work starts (Phase 10) the driver is compiled in, registered
// and fails loudly, so that `database.driver: pocketbase` is a clear error
// instead of an unknown-driver one, and so the interface stays honest:
// every method the other drivers implement exists here too.
package pocketbase
import (
"context"
"fmt"
"log/slog"
"github.com/dariuszjaniak/warp/server/internal/storage"
)
func init() {
storage.Register(storage.DriverPocketBase, Open)
}
// Database is the not-yet-implemented PocketBase driver.
type Database struct{}
// Open always fails with storage.ErrNotImplemented.
func Open(context.Context, storage.Config, *slog.Logger) (storage.Database, error) {
return nil, fmt.Errorf(
"pocketbase driver is not implemented yet (planned for Phase 10); use %q or %q: %w",
storage.DriverSQLite, storage.DriverPostgres, storage.ErrNotImplemented)
}
// Driver implements storage.Database.
func (*Database) Driver() string { return storage.DriverPocketBase }
// Ping implements storage.Database.
func (*Database) Ping(context.Context) error { return storage.ErrNotImplemented }
// Migrate implements storage.Database.
func (*Database) Migrate(context.Context) error { return storage.ErrNotImplemented }
// PendingMigrations implements storage.Database.
func (*Database) PendingMigrations(context.Context) ([]string, error) {
return nil, storage.ErrNotImplemented
}
// Settings implements storage.Database.
func (*Database) Settings() storage.SettingsStore { return notImplementedSettings{} }
// Users implements storage.Database.
func (*Database) Users() storage.UserStore { return notImplementedUsers{} }
// Rooms implements storage.Database.
func (*Database) Rooms() storage.RoomStore { return notImplementedRooms{} }
// Sync implements storage.Database.
func (*Database) Sync() storage.SyncStore { return notImplementedSync{} }
// Federation implements storage.Database.
func (*Database) Federation() storage.FederationStore { return notImplementedFederation{} }
// Media implements storage.Database.
func (*Database) Media() storage.MediaStore { return notImplementedMedia{} }
// Keys implements storage.Database.
func (*Database) Keys() storage.KeyStore { return notImplementedKeys{} }
// Push implements storage.Database.
func (*Database) Push() storage.PushStore { return notImplementedPush{} }
// Admin implements storage.Database.
func (*Database) Admin() storage.AdminStore { return notImplementedAdmin{} }
// AppServices implements storage.Database.
func (*Database) AppServices() storage.AppServiceStore { return notImplementedAppServices{} }
// Close implements storage.Database.
func (*Database) Close() error { return nil }
// notImplementedSettings satisfies storage.SettingsStore by refusing every
// call, so a partially wired-up PocketBase deployment cannot silently lose
// an admin's federation switch.
type notImplementedSettings struct{}
func (notImplementedSettings) Get(context.Context, string) (string, bool, error) {
return "", false, storage.ErrNotImplemented
}
func (notImplementedSettings) GetAll(context.Context) (map[string]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSettings) Set(context.Context, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedSettings) Delete(context.Context, string) error {
return storage.ErrNotImplemented
}
// notImplementedUsers satisfies storage.UserStore the same way: a
// half-wired PocketBase deployment must not accept a registration it cannot
// store, or hand out an access token it cannot look up again.
type notImplementedUsers struct{}
func (notImplementedUsers) CreateAccount(context.Context, storage.NewAccount) (storage.Account, error) {
return storage.Account{}, storage.ErrNotImplemented
}
func (notImplementedUsers) Account(context.Context, string) (storage.Account, error) {
return storage.Account{}, storage.ErrNotImplemented
}
func (notImplementedUsers) PasswordHash(context.Context, string) (string, error) {
return "", storage.ErrNotImplemented
}
func (notImplementedUsers) SetPasswordHash(context.Context, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) SetAdmin(context.Context, string, bool) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) SetDisplayName(context.Context, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) SetDeactivated(context.Context, string, bool) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) SetAvatarURL(context.Context, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) ListAccounts(context.Context, storage.AccountFilter) ([]storage.Account, int, error) {
return nil, 0, storage.ErrNotImplemented
}
func (notImplementedUsers) Stats(context.Context) (storage.Stats, error) {
return storage.Stats{}, storage.ErrNotImplemented
}
func (notImplementedUsers) CreateSession(context.Context, storage.NewSession) (storage.Device, error) {
return storage.Device{}, storage.ErrNotImplemented
}
func (notImplementedUsers) RefreshSession(context.Context, storage.RefreshedSession) (storage.TokenInfo, error) {
return storage.TokenInfo{}, storage.ErrNotImplemented
}
func (notImplementedUsers) TokenInfo(context.Context, string) (storage.TokenInfo, error) {
return storage.TokenInfo{}, storage.ErrNotImplemented
}
func (notImplementedUsers) TouchDevice(context.Context, string, string, string, string, int64) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) Device(context.Context, string, string) (storage.Device, error) {
return storage.Device{}, storage.ErrNotImplemented
}
func (notImplementedUsers) Devices(context.Context, string) ([]storage.Device, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedUsers) SetDeviceDisplayName(context.Context, string, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedUsers) DeleteDevices(context.Context, string, []string) (int, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedUsers) DeleteAllDevices(context.Context, string) (int, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedUsers) AccountData(context.Context, string, string, string) ([]byte, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedUsers) SetAccountData(context.Context, string, string, string, []byte) error {
return storage.ErrNotImplemented
}
// notImplementedRooms satisfies storage.RoomStore the same way. It matters
// more here than anywhere else: a room whose create event was accepted and
// not stored would hand a client a room ID that refers to nothing.
type notImplementedRooms struct{}
func (notImplementedRooms) CreateRoom(context.Context, storage.NewRoom) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) Room(context.Context, string) (storage.Room, error) {
return storage.Room{}, storage.ErrNotImplemented
}
func (notImplementedRooms) Write(context.Context, storage.RoomWrite) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedRooms) Event(context.Context, string, string) (storage.StoredEvent, error) {
return storage.StoredEvent{}, storage.ErrNotImplemented
}
func (notImplementedRooms) EventsByID(context.Context, string, []string) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) CurrentState(context.Context, string) ([]storage.StateEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) CurrentStateEvents(context.Context, string) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) CurrentStateEvent(context.Context, string, string, string) (storage.StoredEvent, error) {
return storage.StoredEvent{}, storage.ErrNotImplemented
}
func (notImplementedRooms) StateBefore(context.Context, string, string) ([]storage.StateEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) Extremities(context.Context, string) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) Members(context.Context, string, []string) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) MembershipEntries(context.Context, string, []string) ([]storage.MembershipEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) Membership(context.Context, string, string) (storage.MembershipEntry, error) {
return storage.MembershipEntry{}, storage.ErrNotImplemented
}
func (notImplementedRooms) RoomsForUser(context.Context, string, []string) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) MembershipsForUser(context.Context, string, []string) ([]storage.SyncMembership, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) UserMembershipEvents(context.Context, string, string) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) MaxStreamOrdering(context.Context) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedRooms) StreamEvents(context.Context, int64, int64, int) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) Timeline(context.Context, storage.TimelineRequest) ([]storage.StoredEvent, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) RoomsWithEvents(context.Context, []string, int64, int64) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) StateAtStream(context.Context, string, int64) ([]storage.StateEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) TransactionEvent(context.Context, storage.TransactionRef) (string, error) {
return "", storage.ErrNotImplemented
}
func (notImplementedRooms) CreateAlias(context.Context, storage.RoomAlias) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) DeleteAlias(context.Context, string) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) Alias(context.Context, string) (storage.RoomAlias, error) {
return storage.RoomAlias{}, storage.ErrNotImplemented
}
func (notImplementedRooms) AliasesForRoom(context.Context, string) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) SetPublished(context.Context, string, bool) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) PublishedRooms(context.Context, storage.RoomFilter) ([]storage.RoomSummary, int, error) {
return nil, 0, storage.ErrNotImplemented
}
func (notImplementedRooms) ListRooms(context.Context, storage.RoomFilter) ([]storage.RoomSummary, int, error) {
return nil, 0, storage.ErrNotImplemented
}
func (notImplementedRooms) RoomSummary(context.Context, string) (storage.RoomSummary, error) {
return storage.RoomSummary{}, storage.ErrNotImplemented
}
func (notImplementedRooms) PurgeRoom(context.Context, string) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) RoomStats(context.Context) (storage.RoomStats, error) {
return storage.RoomStats{}, storage.ErrNotImplemented
}
func (notImplementedRooms) WriteOutliers(context.Context, string, []storage.StoredEvent) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) WriteBackfill(context.Context, string, []storage.BackfillEvent) error {
return storage.ErrNotImplemented
}
func (notImplementedRooms) InviteState(context.Context, string, string) ([]byte, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) HasJoinedMemberOn(context.Context, string, string) (bool, error) {
return false, storage.ErrNotImplemented
}
func (notImplementedRooms) EventByID(context.Context, string) (storage.StoredEvent, error) {
return storage.StoredEvent{}, storage.ErrNotImplemented
}
func (notImplementedRooms) UsersSharingRooms(context.Context, string) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedRooms) MemberChanges(context.Context, []string, int64, int64) ([]storage.MemberChange, error) {
return nil, storage.ErrNotImplemented
}
// notImplementedFederation satisfies storage.FederationStore the same way.
// A queue that accepted events and never stored them would lose them the
// moment federation was switched on.
type notImplementedFederation struct{}
func (notImplementedFederation) StoreServerKeys(context.Context, []storage.ServerKey) error {
return storage.ErrNotImplemented
}
func (notImplementedFederation) ServerKeys(context.Context, string, []string) ([]storage.ServerKey, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedFederation) Enqueue(context.Context, []storage.QueuedItem) ([]storage.QueuedItem, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedFederation) Queued(context.Context, string, string, int) ([]storage.QueuedItem, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedFederation) Dequeue(context.Context, []int64) error {
return storage.ErrNotImplemented
}
func (notImplementedFederation) QueuedDestinations(context.Context) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedFederation) Destination(context.Context, string) (storage.Destination, error) {
return storage.Destination{}, storage.ErrNotImplemented
}
func (notImplementedFederation) SetDestination(context.Context, storage.Destination) error {
return storage.ErrNotImplemented
}
func (notImplementedFederation) Destinations(context.Context) ([]storage.DestinationSummary, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedFederation) InboundTransaction(context.Context, string, string) ([]byte, bool, error) {
return nil, false, storage.ErrNotImplemented
}
func (notImplementedFederation) RecordInboundTransaction(context.Context, string, string, []byte, int64) error {
return storage.ErrNotImplemented
}
// notImplementedSync satisfies storage.SyncStore the same way. A sync that
// returned an empty success would be worse than an error: a client would
// take it for "nothing has happened" and stop asking.
type notImplementedSync struct{}
func (notImplementedSync) StreamPositions(context.Context) (storage.StreamPositions, error) {
return storage.StreamPositions{}, storage.ErrNotImplemented
}
func (notImplementedSync) SetReceipt(context.Context, storage.Receipt) (int64, bool, error) {
return 0, false, storage.ErrNotImplemented
}
func (notImplementedSync) Receipts(context.Context, []string, int64, int64) ([]storage.Receipt, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSync) ReceiptsForUser(context.Context, string, []string) ([]storage.Receipt, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSync) SendToDevice(context.Context, []storage.NewToDeviceMessage) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedSync) ToDeviceMessages(context.Context, string, string, int64, int64, int) ([]storage.ToDeviceMessage, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSync) DeleteToDeviceMessages(context.Context, string, string, int64) error {
return storage.ErrNotImplemented
}
func (notImplementedSync) SetPresence(context.Context, storage.PresenceState) (int64, bool, error) {
return 0, false, storage.ErrNotImplemented
}
func (notImplementedSync) Presence(context.Context, string) (storage.PresenceState, error) {
return storage.PresenceState{}, storage.ErrNotImplemented
}
func (notImplementedSync) PresenceForUsers(context.Context, []string, int64, int64) ([]storage.PresenceState, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSync) AccountDataChanges(context.Context, string, int64, int64) ([]storage.AccountDataEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSync) AccountDataAt(context.Context, string, int64) ([]storage.AccountDataEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedSync) SaveFilter(context.Context, string, []byte, int64) (string, error) {
return "", storage.ErrNotImplemented
}
func (notImplementedSync) Filter(context.Context, string, string) ([]byte, error) {
return nil, storage.ErrNotImplemented
}
// notImplementedMedia satisfies storage.MediaStore the same way. An upload
// whose metadata was not stored would hand the client an mxc:// URI that
// refers to nothing.
type notImplementedMedia struct{}
func (notImplementedMedia) CreateMedia(context.Context, storage.Media) error {
return storage.ErrNotImplemented
}
func (notImplementedMedia) Media(context.Context, string, string) (storage.Media, error) {
return storage.Media{}, storage.ErrNotImplemented
}
func (notImplementedMedia) CompleteUpload(context.Context, string, string, storage.MediaContent) error {
return storage.ErrNotImplemented
}
func (notImplementedMedia) PendingUploads(context.Context, string, int64) (int, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedMedia) DeleteExpiredUploads(context.Context, int64) (int, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedMedia) Thumbnail(context.Context, string, string, int, int, string) (storage.Thumbnail, error) {
return storage.Thumbnail{}, storage.ErrNotImplemented
}
func (notImplementedMedia) MediaUsage(context.Context, string, string) (storage.MediaUsage, error) {
return storage.MediaUsage{}, storage.ErrNotImplemented
}
func (notImplementedMedia) MediaQuota(context.Context, string) (int64, bool, error) {
return 0, false, storage.ErrNotImplemented
}
func (notImplementedMedia) SetMediaQuota(context.Context, string, int64) error {
return storage.ErrNotImplemented
}
func (notImplementedMedia) DeleteMediaQuota(context.Context, string) error {
return storage.ErrNotImplemented
}
func (notImplementedMedia) StoreThumbnail(context.Context, storage.Thumbnail) error {
return storage.ErrNotImplemented
}
// Compile-time proof that the stub keeps up with the interfaces.
var (
_ storage.Database = (*Database)(nil)
_ storage.UserStore = notImplementedUsers{}
_ storage.RoomStore = notImplementedRooms{}
_ storage.SyncStore = notImplementedSync{}
_ storage.FederationStore = notImplementedFederation{}
_ storage.MediaStore = notImplementedMedia{}
_ storage.KeyStore = notImplementedKeys{}
)
// notImplementedKeys satisfies storage.KeyStore the same way. A key upload
// that reported success and kept nothing would leave every message sent to
// the device undecryptable.
type notImplementedKeys struct{}
func (notImplementedKeys) SetDeviceKeys(context.Context, storage.DeviceKeys) (storage.DeviceListUpdate, error) {
return storage.DeviceListUpdate{}, storage.ErrNotImplemented
}
func (notImplementedKeys) DeviceKeys(context.Context, string, []string) ([]storage.DeviceKeys, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) DeleteDeviceKeys(context.Context, string, []string) ([]storage.DeviceListUpdate, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) AddOneTimeKeys(context.Context, string, string, []storage.OneTimeKey) error {
return storage.ErrNotImplemented
}
func (notImplementedKeys) OneTimeKeyCounts(context.Context, string, string) (map[string]int, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) SetFallbackKeys(context.Context, string, string, []storage.OneTimeKey) error {
return storage.ErrNotImplemented
}
func (notImplementedKeys) UnusedFallbackKeyTypes(context.Context, string, string) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) ClaimKey(context.Context, string, string, string) (storage.ClaimedKey, bool, error) {
return storage.ClaimedKey{}, false, storage.ErrNotImplemented
}
func (notImplementedKeys) SetCrossSigningKeys(context.Context, string, map[string][]byte) (storage.DeviceListUpdate, error) {
return storage.DeviceListUpdate{}, storage.ErrNotImplemented
}
func (notImplementedKeys) CrossSigningKeys(context.Context, string) (map[string][]byte, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) AddSignatures(context.Context, []storage.KeySignature) ([]storage.DeviceListUpdate, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) Signatures(context.Context, string) ([]storage.KeySignature, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) MarkDeviceListsChanged(context.Context, []string) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedKeys) DeviceListChanges(context.Context, []string, int64, int64) ([]storage.DeviceListChange, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) DeviceListPosition(context.Context, string) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedKeys) CreateBackup(context.Context, string, string, []byte) (string, error) {
return "", storage.ErrNotImplemented
}
func (notImplementedKeys) Backup(context.Context, string, string) (storage.BackupVersion, error) {
return storage.BackupVersion{}, storage.ErrNotImplemented
}
func (notImplementedKeys) UpdateBackup(context.Context, string, string, []byte) error {
return storage.ErrNotImplemented
}
func (notImplementedKeys) DeleteBackup(context.Context, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedKeys) PutBackupKeys(context.Context, string, string, []storage.BackupKey) (storage.BackupVersion, error) {
return storage.BackupVersion{}, storage.ErrNotImplemented
}
func (notImplementedKeys) BackupKeys(context.Context, string, string, string, string) ([]storage.BackupKey, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) DeleteBackupKeys(context.Context, string, string, string, string) (storage.BackupVersion, error) {
return storage.BackupVersion{}, storage.ErrNotImplemented
}
func (notImplementedKeys) RemoteKeys(context.Context, string) (storage.RemoteKeys, bool, error) {
return storage.RemoteKeys{}, false, storage.ErrNotImplemented
}
func (notImplementedKeys) SetRemoteKeys(context.Context, storage.RemoteKeys) (bool, error) {
return false, storage.ErrNotImplemented
}
func (notImplementedKeys) UpdateRemoteDevice(context.Context, storage.RemoteDeviceUpdate) (storage.RemoteUpdateResult, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedKeys) SetRemoteCrossSigningKeys(context.Context, string, map[string][]byte) (bool, error) {
return false, storage.ErrNotImplemented
}
func (notImplementedKeys) RemoteKeyUsers(context.Context) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedKeys) DeleteRemoteKeys(context.Context, []string) error {
return storage.ErrNotImplemented
}
// notImplementedPush is the push store until the driver has one.
type notImplementedPush struct{}
func (notImplementedPush) Pushers(context.Context, string) ([]storage.Pusher, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedPush) SetPusher(context.Context, storage.Pusher, bool) error {
return storage.ErrNotImplemented
}
func (notImplementedPush) DeletePusher(context.Context, string, string, string) error {
return storage.ErrNotImplemented
}
func (notImplementedPush) DeletePushersForDevices(context.Context, string, []string) error {
return storage.ErrNotImplemented
}
func (notImplementedPush) AddNotifications(context.Context, []storage.NewNotification) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedPush) MarkNotificationsRead(context.Context, string, string, int64) (int64, bool, error) {
return 0, false, storage.ErrNotImplemented
}
func (notImplementedPush) NotificationCounts(context.Context, string, []string) (map[string]storage.NotificationCounts, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedPush) NotificationCountChanges(context.Context, string, int64, int64) ([]string, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedPush) UnreadNotifications(context.Context, string) (int, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedPush) Notifications(context.Context, string, int64, int, bool) ([]storage.Notification, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedPush) PruneNotifications(context.Context, int64) (int64, error) {
return 0, storage.ErrNotImplemented
}
// notImplementedAdmin is the admin store until the driver has one.
type notImplementedAdmin struct{}
func (notImplementedAdmin) CreateRegistrationToken(context.Context, storage.RegistrationToken) error {
return storage.ErrNotImplemented
}
func (notImplementedAdmin) RegistrationToken(context.Context, string) (storage.RegistrationToken, error) {
return storage.RegistrationToken{}, storage.ErrNotImplemented
}
func (notImplementedAdmin) RegistrationTokens(context.Context) ([]storage.RegistrationToken, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedAdmin) UpdateRegistrationToken(context.Context, string, *int, int64) error {
return storage.ErrNotImplemented
}
func (notImplementedAdmin) DeleteRegistrationToken(context.Context, string) error {
return storage.ErrNotImplemented
}
func (notImplementedAdmin) UseRegistrationToken(context.Context, string, int64) error {
return storage.ErrNotImplemented
}
func (notImplementedAdmin) ReleaseRegistrationToken(context.Context, string) error {
return storage.ErrNotImplemented
}
func (notImplementedAdmin) AppendAudit(context.Context, storage.AuditEntry) (int64, error) {
return 0, storage.ErrNotImplemented
}
func (notImplementedAdmin) AuditLog(context.Context, storage.AuditFilter) ([]storage.AuditEntry, error) {
return nil, storage.ErrNotImplemented
}
func (notImplementedAdmin) ServerNoticeRoom(context.Context, string) (string, error) {
return "", storage.ErrNotImplemented
}
func (notImplementedAdmin) SetServerNoticeRoom(context.Context, string, string) error {
return storage.ErrNotImplemented
}
// notImplementedAppServices is the application service store until the
// driver has one.
type notImplementedAppServices struct{}
func (notImplementedAppServices) AppServiceState(context.Context, string, int64) (storage.AppServiceState, error) {
return storage.AppServiceState{}, storage.ErrNotImplemented
}
func (notImplementedAppServices) BeginTransaction(context.Context, string, int64, int64) error {
return storage.ErrNotImplemented
}
func (notImplementedAppServices) CompleteTransaction(context.Context, string, int64) error {
return storage.ErrNotImplemented
}