treewide: upgrading to latest mautrix standards

Signed-off-by: Sumner Evans <sumner@beeper.com>
This commit is contained in:
Sumner Evans
2022-10-21 14:02:33 -05:00
parent e843faf9b4
commit 715107f5a2
52 changed files with 1887 additions and 6449 deletions

View File

@ -0,0 +1,83 @@
-- v0 -> v1: Latest revision
CREATE TABLE "user" (
mxid TEXT PRIMARY KEY,
gmid TEXT UNIQUE,
auth_token TEXT,
management_room TEXT,
space_room TEXT,
);
CREATE TABLE portal (
gmid TEXT,
receiver TEXT,
mxid TEXT UNIQUE,
name TEXT NOT NULL,
name_set BOOLEAN NOT NULL DEFAULT false,
topic TEXT NOT NULL,
topic_set BOOLEAN NOT NULL DEFAULT false,
avatar TEXT NOT NULL,
avatar_url TEXT,
avatar_set BOOLEAN NOT NULL DEFAULT false,
encrypted BOOLEAN NOT NULL DEFAULT false,
PRIMARY KEY (gmid, receiver)
);
CREATE TABLE puppet (
gmid TEXT PRIMARY KEY,
displayname TEXT,
name_set BOOLEAN NOT NULL DEFAULT false,
avatar TEXT,
avatar_url TEXT,
avatar_set BOOLEAN NOT NULL DEFAULT false,
custom_mxid TEXT,
access_token TEXT,
next_batch TEXT,
enable_presence BOOLEAN NOT NULL DEFAULT true,
enable_receipts BOOLEAN NOT NULL DEFAULT true
);
CREATE TABLE message (
chat_gmid TEXT,
chat_receiver TEXT,
gmid TEXT,
mxid TEXT UNIQUE,
sender TEXT,
timestamp BIGINT,
sent BOOLEAN,
PRIMARY KEY (chat_gmid, chat_receiver, gmid),
FOREIGN KEY (chat_gmid, chat_receiver) REFERENCES portal(gmid, receiver) ON DELETE CASCADE
);
CREATE TABLE reaction (
chat_gmid TEXT,
chat_receiver TEXT,
target_gmid TEXT,
sender TEXT,
mxid TEXT NOT NULL,
gmid TEXT NOT NULL,
PRIMARY KEY (chat_gmid, chat_receiver, target_gmid, sender),
FOREIGN KEY (chat_gmid, chat_receiver, target_gmid) REFERENCES message(chat_gmid, chat_receiver, gmid)
ON DELETE CASCADE ON UPDATE CASCADE
)
CREATE TABLE user_portal (
user_mxid TEXT,
portal_gmid TEXT,
portal_receiver TEXT,
in_space BOOLEAN NOT NULL DEFAULT false,
PRIMARY KEY (user_mxid, portal_gmid, portal_receiver),
FOREIGN KEY (user_mxid) REFERENCES "user"(mxid) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (portal_gmid, portal_receiver) REFERENCES portal(gmid, receiver) ON UPDATE CASCADE ON DELETE CASCADE
);

View File

@ -1,182 +0,0 @@
package upgrades
import (
"gorm.io/gorm"
)
func init() {
upgrades[0] = upgrade{"Initial schema", func(tx *gorm.DB, ctx context) error {
tx.Exec(`CREATE TABLE IF NOT EXISTS portal (
jid VARCHAR(255),
receiver VARCHAR(255),
mxid VARCHAR(255) UNIQUE,
name VARCHAR(255) NOT NULL,
topic VARCHAR(512) NOT NULL,
avatar VARCHAR(255) NOT NULL,
avatar_url VARCHAR(255),
encrypted BOOLEAN NOT NULL DEFAULT false,
PRIMARY KEY (jid, receiver)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS puppet (
jid VARCHAR(255) PRIMARY KEY,
avatar VARCHAR(255),
displayname VARCHAR(255),
name_quality SMALLINT,
custom_mxid VARCHAR(255),
access_token VARCHAR(1023),
next_batch VARCHAR(255),
avatar_url VARCHAR(255),
enable_presence BOOLEAN NOT NULL DEFAULT true,
enable_receipts BOOLEAN NOT NULL DEFAULT true
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS "user" (
mxid VARCHAR(255) PRIMARY KEY,
jid VARCHAR(255) UNIQUE,
management_room VARCHAR(255),
client_id VARCHAR(255),
client_token VARCHAR(255),
server_token VARCHAR(255),
enc_key bytea,
mac_key bytea,
last_connection BIGINT NOT NULL DEFAULT 0
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS "user_portal" (
user_jid VARCHAR(255),
portal_jid VARCHAR(255),
portal_receiver VARCHAR(255),
in_community BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (user_jid, portal_jid, portal_receiver),
FOREIGN KEY (user_jid) REFERENCES "user"(jid) ON DELETE CASCADE,
FOREIGN KEY (portal_jid, portal_receiver) REFERENCES portal(jid, receiver) ON DELETE CASCADE
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS message (
chat_jid VARCHAR(255),
chat_receiver VARCHAR(255),
jid VARCHAR(255),
mxid VARCHAR(255) NOT NULL UNIQUE,
sender VARCHAR(255) NOT NULL,
content bytea NOT NULL,
timestamp BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (chat_jid, chat_receiver, jid),
FOREIGN KEY (chat_jid, chat_receiver) REFERENCES portal(jid, receiver) ON DELETE CASCADE
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS mx_registrations (
user_id VARCHAR(255) PRIMARY KEY
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS mx_room_state (
room_id VARCHAR(255) PRIMARY KEY,
power_levels TEXT
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS mx_user_profile (
room_id VARCHAR(255),
user_id VARCHAR(255),
membership VARCHAR(15) NOT NULL,
PRIMARY KEY (room_id, user_id),
displayname TEXT,
avatar_url VARCHAR(255)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_olm_session (
session_id CHAR(43) NOT NULL,
sender_key CHAR(43) NOT NULL,
session bytea NOT NULL,
created_at timestamp NOT NULL,
last_used timestamp NOT NULL,
account_id TEXT NOT NULL,
PRIMARY KEY (account_id, session_id)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_megolm_inbound_session (
session_id CHAR(43) NOT NULL,
sender_key CHAR(43) NOT NULL,
signing_key CHAR(43) NOT NULL,
room_id TEXT NOT NULL,
session bytea NOT NULL,
forwarding_chains bytea NOT NULL,
account_id TEXT NOT NULL,
withheld_code TEXT,
withheld_reason TEXT,
PRIMARY KEY (session_id, account_id)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_device (
user_id VARCHAR(255),
device_id VARCHAR(255),
identity_key CHAR(43) NOT NULL,
signing_key CHAR(43) NOT NULL,
trust SMALLINT NOT NULL,
deleted BOOLEAN NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id, device_id)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_tracked_user (
user_id VARCHAR(255) PRIMARY KEY
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_message_index (
sender_key CHAR(43),
session_id CHAR(43),
"index" INTEGER,
event_id VARCHAR(255) NOT NULL,
timestamp BIGINT NOT NULL,
PRIMARY KEY (sender_key, session_id, "index")
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_account (
device_id TEXT NOT NULL,
shared BOOLEAN NOT NULL,
sync_token TEXT NOT NULL,
account bytea NOT NULL,
account_id TEXT PRIMARY KEY
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_megolm_outbound_session (
room_id VARCHAR(255) NOT NULL,
session_id CHAR(43) NOT NULL UNIQUE,
session bytea NOT NULL,
shared BOOLEAN NOT NULL,
max_messages INTEGER NOT NULL,
message_count INTEGER NOT NULL,
max_age BIGINT NOT NULL,
created_at timestamp NOT NULL,
last_used timestamp NOT NULL,
account_id TEXT,
PRIMARY KEY (room_id, account_id)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_cross_signing_keys (
user_id TEXT NOT NULL,
usage TEXT NOT NULL,
key CHAR(43) NOT NULL,
PRIMARY KEY (user_id, usage)
)`)
tx.Exec(`CREATE TABLE IF NOT EXISTS crypto_cross_signing_signatures (
signed_user_id TEXT NOT NULL,
signed_key TEXT NOT NULL,
signer_user_id TEXT NOT NULL,
signer_key TEXT NOT NULL,
signature TEXT NOT NULL,
PRIMARY KEY (signed_user_id, signed_key, signer_user_id, signer_key)
)`)
return nil
}}
}

View File

@ -1,123 +1,36 @@
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
// Copyright (C) 2022 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package upgrades
import (
"embed"
"errors"
"fmt"
"strings"
"gorm.io/gorm"
log "maunium.net/go/maulogger/v2"
"maunium.net/go/mautrix/util/dbutil"
)
type Dialect int
var Table dbutil.UpgradeTable
const (
Postgres Dialect = iota
SQLite
)
//go:embed *.sql
var rawUpgrades embed.FS
func (dialect Dialect) String() string {
switch dialect {
case Postgres:
return "postgres"
case SQLite:
return "sqlite3"
default:
return ""
}
}
type upgradeFunc func(*gorm.DB, context) error
type context struct {
dialect Dialect
db *gorm.DB
log log.Logger
}
type upgrade struct {
message string
fn upgradeFunc
}
type version struct {
gorm.Model
V int
}
const NumberOfUpgrades = 1
var upgrades [NumberOfUpgrades]upgrade
var UnsupportedDatabaseVersion = fmt.Errorf("unsupported database version")
func GetVersion(db *gorm.DB) (int, error) {
var ver = version{V: 0}
result := db.FirstOrCreate(&ver, &ver)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) ||
errors.Is(result.Error, gorm.ErrInvalidField) {
db.Create(&ver)
print("create version")
} else {
return 0, result.Error
}
}
return int(ver.V), nil
}
func SetVersion(tx *gorm.DB, newVersion int) error {
err := tx.Where("v IS NOT NULL").Delete(&version{})
if err.Error != nil {
return err.Error
}
val := version{V: newVersion}
tx = tx.Create(&val)
return tx.Error
}
func Run(log log.Logger, dialectName string, db *gorm.DB) error {
var dialect Dialect
switch strings.ToLower(dialectName) {
case "postgres":
dialect = Postgres
case "sqlite3":
dialect = SQLite
default:
return fmt.Errorf("unknown dialect %s", dialectName)
}
db.AutoMigrate(&version{})
version, err := GetVersion(db)
if err != nil {
return err
}
if version > NumberOfUpgrades {
return UnsupportedDatabaseVersion
}
log.Infofln("Database currently on v%d, latest: v%d", version, NumberOfUpgrades)
for i, upgrade := range upgrades[version:] {
log.Infofln("Upgrading database to v%d: %s", version+i+1, upgrade.message)
err = db.Transaction(func(tx *gorm.DB) error {
err = upgrade.fn(tx, context{dialect, db, log})
if err != nil {
return err
}
err = SetVersion(tx, version+i+1)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
}
return nil
func init() {
Table.Register(-1, 35, "Unsupported version", func(tx dbutil.Transaction, database *dbutil.Database) error {
return errors.New("please upgrade to mautrix-whatsapp v0.4.0 before upgrading to a newer version")
})
Table.RegisterFS(rawUpgrades)
}