5
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2024-12-30 19:45:40 +00:00
matterbridge/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrade.go
2022-06-25 00:36:16 +02:00

249 lines
6.9 KiB
Go

// Copyright (c) 2021 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package sqlstore
import (
"database/sql"
)
type upgradeFunc func(*sql.Tx, *Container) error
// Upgrades is a list of functions that will upgrade a database to the latest version.
//
// This may be of use if you want to manage the database fully manually, but in most cases you
// should just call Container.Upgrade to let the library handle everything.
var Upgrades = [...]upgradeFunc{upgradeV1, upgradeV2}
func (c *Container) getVersion() (int, error) {
_, err := c.db.Exec("CREATE TABLE IF NOT EXISTS whatsmeow_version (version INTEGER)")
if err != nil {
return -1, err
}
version := 0
row := c.db.QueryRow("SELECT version FROM whatsmeow_version LIMIT 1")
if row != nil {
_ = row.Scan(&version)
}
return version, nil
}
func (c *Container) setVersion(tx *sql.Tx, version int) error {
_, err := tx.Exec("DELETE FROM whatsmeow_version")
if err != nil {
return err
}
_, err = tx.Exec("INSERT INTO whatsmeow_version (version) VALUES ($1)", version)
return err
}
// Upgrade upgrades the database from the current to the latest version available.
func (c *Container) Upgrade() error {
version, err := c.getVersion()
if err != nil {
return err
}
for ; version < len(Upgrades); version++ {
var tx *sql.Tx
tx, err = c.db.Begin()
if err != nil {
return err
}
migrateFunc := Upgrades[version]
c.log.Infof("Upgrading database to v%d", version+1)
err = migrateFunc(tx, c)
if err != nil {
_ = tx.Rollback()
return err
}
if err = c.setVersion(tx, version+1); err != nil {
return err
}
if err = tx.Commit(); err != nil {
return err
}
}
return nil
}
func upgradeV1(tx *sql.Tx, _ *Container) error {
_, err := tx.Exec(`CREATE TABLE whatsmeow_device (
jid TEXT PRIMARY KEY,
registration_id BIGINT NOT NULL CHECK ( registration_id >= 0 AND registration_id < 4294967296 ),
noise_key bytea NOT NULL CHECK ( length(noise_key) = 32 ),
identity_key bytea NOT NULL CHECK ( length(identity_key) = 32 ),
signed_pre_key bytea NOT NULL CHECK ( length(signed_pre_key) = 32 ),
signed_pre_key_id INTEGER NOT NULL CHECK ( signed_pre_key_id >= 0 AND signed_pre_key_id < 16777216 ),
signed_pre_key_sig bytea NOT NULL CHECK ( length(signed_pre_key_sig) = 64 ),
adv_key bytea NOT NULL,
adv_details bytea NOT NULL,
adv_account_sig bytea NOT NULL CHECK ( length(adv_account_sig) = 64 ),
adv_device_sig bytea NOT NULL CHECK ( length(adv_device_sig) = 64 ),
platform TEXT NOT NULL DEFAULT '',
business_name TEXT NOT NULL DEFAULT '',
push_name TEXT NOT NULL DEFAULT ''
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_identity_keys (
our_jid TEXT,
their_id TEXT,
identity bytea NOT NULL CHECK ( length(identity) = 32 ),
PRIMARY KEY (our_jid, their_id),
FOREIGN KEY (our_jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_pre_keys (
jid TEXT,
key_id INTEGER CHECK ( key_id >= 0 AND key_id < 16777216 ),
key bytea NOT NULL CHECK ( length(key) = 32 ),
uploaded BOOLEAN NOT NULL,
PRIMARY KEY (jid, key_id),
FOREIGN KEY (jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_sessions (
our_jid TEXT,
their_id TEXT,
session bytea,
PRIMARY KEY (our_jid, their_id),
FOREIGN KEY (our_jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_sender_keys (
our_jid TEXT,
chat_id TEXT,
sender_id TEXT,
sender_key bytea NOT NULL,
PRIMARY KEY (our_jid, chat_id, sender_id),
FOREIGN KEY (our_jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_app_state_sync_keys (
jid TEXT,
key_id bytea,
key_data bytea NOT NULL,
timestamp BIGINT NOT NULL,
fingerprint bytea NOT NULL,
PRIMARY KEY (jid, key_id),
FOREIGN KEY (jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_app_state_version (
jid TEXT,
name TEXT,
version BIGINT NOT NULL,
hash bytea NOT NULL CHECK ( length(hash) = 128 ),
PRIMARY KEY (jid, name),
FOREIGN KEY (jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_app_state_mutation_macs (
jid TEXT,
name TEXT,
version BIGINT,
index_mac bytea CHECK ( length(index_mac) = 32 ),
value_mac bytea NOT NULL CHECK ( length(value_mac) = 32 ),
PRIMARY KEY (jid, name, version, index_mac),
FOREIGN KEY (jid, name) REFERENCES whatsmeow_app_state_version(jid, name) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_contacts (
our_jid TEXT,
their_jid TEXT,
first_name TEXT,
full_name TEXT,
push_name TEXT,
business_name TEXT,
PRIMARY KEY (our_jid, their_jid),
FOREIGN KEY (our_jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE TABLE whatsmeow_chat_settings (
our_jid TEXT,
chat_jid TEXT,
muted_until BIGINT NOT NULL DEFAULT 0,
pinned BOOLEAN NOT NULL DEFAULT false,
archived BOOLEAN NOT NULL DEFAULT false,
PRIMARY KEY (our_jid, chat_jid),
FOREIGN KEY (our_jid) REFERENCES whatsmeow_device(jid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
if err != nil {
return err
}
return nil
}
const fillSigKeyPostgres = `
UPDATE whatsmeow_device SET adv_account_sig_key=(
SELECT identity
FROM whatsmeow_identity_keys
WHERE our_jid=whatsmeow_device.jid
AND their_id=concat(split_part(whatsmeow_device.jid, '.', 1), ':0')
);
DELETE FROM whatsmeow_device WHERE adv_account_sig_key IS NULL;
ALTER TABLE whatsmeow_device ALTER COLUMN adv_account_sig_key SET NOT NULL;
`
const fillSigKeySQLite = `
UPDATE whatsmeow_device SET adv_account_sig_key=(
SELECT identity
FROM whatsmeow_identity_keys
WHERE our_jid=whatsmeow_device.jid
AND their_id=substr(whatsmeow_device.jid, 0, instr(whatsmeow_device.jid, '.')) || ':0'
)
`
func upgradeV2(tx *sql.Tx, container *Container) error {
_, err := tx.Exec("ALTER TABLE whatsmeow_device ADD COLUMN adv_account_sig_key bytea CHECK ( length(adv_account_sig_key) = 32 )")
if err != nil {
return err
}
if container.dialect == "postgres" || container.dialect == "pgx" {
_, err = tx.Exec(fillSigKeyPostgres)
} else {
_, err = tx.Exec(fillSigKeySQLite)
}
return err
}