treewide: upgrading to latest mautrix standards
Signed-off-by: Sumner Evans <sumner@beeper.com>
This commit is contained in:
83
database/upgrades/00-latest-revision.sql
Normal file
83
database/upgrades/00-latest-revision.sql
Normal 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
|
||||
);
|
@ -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
|
||||
}}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
Reference in New Issue
Block a user