Clear puppet phone numbers when phone ID changes
This commit is contained in:
parent
e3619dbe7b
commit
0456b8c3de
6 changed files with 76 additions and 9 deletions
|
@ -18,6 +18,7 @@ package database
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"go.mau.fi/util/dbutil"
|
||||
|
@ -43,12 +44,22 @@ const (
|
|||
SET phone=$3, contact_id=$4, name=$5, name_set=$6, avatar_hash=$7, avatar_mxc=$8, avatar_set=$9, avatar_update_ts=$10, contact_info_set=$11
|
||||
WHERE id=$1 AND receiver=$2
|
||||
`
|
||||
resetPuppetMetadataQuery = `
|
||||
UPDATE puppet SET phone=NULL, contact_info_set=false, avatar_update_ts=0, contact_id='' WHERE receiver=$1
|
||||
`
|
||||
)
|
||||
|
||||
func (pq *PuppetQuery) Get(ctx context.Context, key Key) (*Puppet, error) {
|
||||
return pq.QueryOne(ctx, getPuppetQuery, key.ID, key.Receiver)
|
||||
}
|
||||
|
||||
// Reset clears the phone number of all puppets, so that puppets can be upserted safely on relogin
|
||||
// even if the internal IDs shuffled around. This does *not* delete the puppets, because otherwise
|
||||
// avatars wouldn't get reset appropriately.
|
||||
func (pq *PuppetQuery) Reset(ctx context.Context, userID int) error {
|
||||
return pq.Exec(ctx, resetPuppetMetadataQuery, userID)
|
||||
}
|
||||
|
||||
type Puppet struct {
|
||||
qh *dbutil.QueryHelper[*Puppet]
|
||||
|
||||
|
@ -67,8 +78,9 @@ type Puppet struct {
|
|||
func (puppet *Puppet) Scan(row dbutil.Scannable) (*Puppet, error) {
|
||||
var avatarHash []byte
|
||||
var avatarUpdateTS int64
|
||||
var phone sql.NullString
|
||||
err := row.Scan(
|
||||
&puppet.ID, &puppet.Receiver, &puppet.Phone, &puppet.ContactID, &puppet.Name, &puppet.NameSet,
|
||||
&puppet.ID, &puppet.Receiver, &phone, &puppet.ContactID, &puppet.Name, &puppet.NameSet,
|
||||
&avatarHash, &puppet.AvatarMXC, &puppet.AvatarSet, &avatarUpdateTS, &puppet.ContactInfoSet,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -77,14 +89,21 @@ func (puppet *Puppet) Scan(row dbutil.Scannable) (*Puppet, error) {
|
|||
if len(avatarHash) == 32 {
|
||||
puppet.AvatarHash = *(*[32]byte)(avatarHash)
|
||||
}
|
||||
puppet.Phone = phone.String
|
||||
if avatarUpdateTS > 0 {
|
||||
puppet.AvatarUpdateTS = time.UnixMilli(avatarUpdateTS)
|
||||
}
|
||||
return puppet, nil
|
||||
}
|
||||
|
||||
func (puppet *Puppet) sqlVariables() []any {
|
||||
var avatarUpdateTS int64
|
||||
if !puppet.AvatarUpdateTS.IsZero() {
|
||||
avatarUpdateTS = puppet.AvatarUpdateTS.UnixMilli()
|
||||
}
|
||||
return []any{
|
||||
puppet.ID, puppet.Receiver, puppet.Phone, puppet.ContactID, puppet.Name, puppet.NameSet,
|
||||
puppet.AvatarHash[:], &puppet.AvatarMXC, puppet.AvatarSet, puppet.AvatarUpdateTS.UnixMilli(), puppet.ContactInfoSet,
|
||||
puppet.ID, puppet.Receiver, dbutil.StrPtr(puppet.Phone), puppet.ContactID, puppet.Name, puppet.NameSet,
|
||||
puppet.AvatarHash[:], &puppet.AvatarMXC, puppet.AvatarSet, avatarUpdateTS, puppet.ContactInfoSet,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-- v0 -> v8: Latest revision
|
||||
-- v0 -> v9: Latest revision
|
||||
|
||||
CREATE TABLE "user" (
|
||||
-- only: postgres
|
||||
|
@ -23,7 +23,7 @@ CREATE TABLE "user" (
|
|||
CREATE TABLE puppet (
|
||||
id TEXT NOT NULL,
|
||||
receiver BIGINT NOT NULL,
|
||||
phone TEXT NOT NULL,
|
||||
phone TEXT,
|
||||
contact_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
name_set BOOLEAN NOT NULL DEFAULT false,
|
||||
|
|
3
database/upgrades/09-phone-optional.postgres.sql
Normal file
3
database/upgrades/09-phone-optional.postgres.sql
Normal file
|
@ -0,0 +1,3 @@
|
|||
-- v9: Make phone nullable for puppets
|
||||
-- transaction: off
|
||||
ALTER TABLE puppet ALTER COLUMN phone DROP NOT NULL;
|
32
database/upgrades/09-phone-optional.sqlite.sql
Normal file
32
database/upgrades/09-phone-optional.sqlite.sql
Normal file
|
@ -0,0 +1,32 @@
|
|||
-- v9: Make phone nullable for puppets
|
||||
-- transaction: off
|
||||
|
||||
PRAGMA foreign_keys = OFF;
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE puppet_new (
|
||||
id TEXT NOT NULL,
|
||||
receiver BIGINT NOT NULL,
|
||||
phone TEXT,
|
||||
contact_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
name_set BOOLEAN NOT NULL DEFAULT false,
|
||||
avatar_hash bytea CHECK ( LENGTH(avatar_hash) = 32 ),
|
||||
avatar_update_ts BIGINT NOT NULL,
|
||||
avatar_mxc TEXT NOT NULL,
|
||||
avatar_set BOOLEAN NOT NULL DEFAULT false,
|
||||
contact_info_set BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
PRIMARY KEY (id, receiver),
|
||||
CONSTRAINT puppet_user_fkey FOREIGN KEY (receiver) REFERENCES "user"(rowid) ON DELETE CASCADE,
|
||||
CONSTRAINT puppet_phone_unique UNIQUE (phone, receiver)
|
||||
);
|
||||
INSERT INTO puppet_new (id, receiver, phone, contact_id, name, name_set, avatar_hash, avatar_update_ts, avatar_mxc, avatar_set, contact_info_set)
|
||||
SELECT id, receiver, phone, contact_id, name, name_set, avatar_hash, avatar_update_ts, avatar_mxc, avatar_set, contact_info_set
|
||||
FROM puppet;
|
||||
DROP TABLE puppet;
|
||||
ALTER TABLE puppet_new RENAME TO puppet;
|
||||
|
||||
PRAGMA foreign_key_check;
|
||||
COMMIT;
|
||||
PRAGMA FOREIGN_KEYS = ON;
|
12
puppet.go
12
puppet.go
|
@ -281,8 +281,9 @@ func (puppet *Puppet) UpdateContactInfo(ctx context.Context) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
idents := []string{
|
||||
fmt.Sprintf("tel:%s", puppet.Phone),
|
||||
idents := make([]string, 0, 2)
|
||||
if puppet.Phone != "" {
|
||||
idents = append(idents, fmt.Sprintf("tel:%s", puppet.Phone))
|
||||
}
|
||||
if puppet.ContactID != "" {
|
||||
idents = append(idents, fmt.Sprintf("gmsg-contact:%s", puppet.ContactID))
|
||||
|
@ -312,8 +313,15 @@ func (puppet *Puppet) Sync(ctx context.Context, source *User, contact *gmproto.P
|
|||
|
||||
update := false
|
||||
if contact.ID.Number != "" && puppet.Phone != contact.ID.Number {
|
||||
oldPhone := puppet.Phone
|
||||
puppet.Phone = contact.ID.Number
|
||||
puppet.ContactInfoSet = false
|
||||
puppet.log = puppet.bridge.ZLog.With().
|
||||
Str("phone", puppet.Phone).
|
||||
Str("puppet_id", puppet.ID).
|
||||
Int("puppet_receiver", puppet.Receiver).
|
||||
Logger()
|
||||
puppet.log.Debug().Str("old_phone", oldPhone).Msg("Phone number changed")
|
||||
update = true
|
||||
}
|
||||
if contact.ContactID != puppet.ContactID {
|
||||
|
|
7
user.go
7
user.go
|
@ -820,10 +820,15 @@ func (user *User) syncHandleEvent(event any) {
|
|||
}
|
||||
|
||||
func (user *User) ResetState() {
|
||||
ctx := context.TODO()
|
||||
portals := user.bridge.GetAllPortalsForUser(user.RowID)
|
||||
user.zlog.Debug().Int("portal_count", len(portals)).Msg("Deleting portals")
|
||||
for _, portal := range portals {
|
||||
portal.Delete(context.TODO())
|
||||
portal.Delete(ctx)
|
||||
}
|
||||
err := user.bridge.DB.Puppet.Reset(ctx, user.RowID)
|
||||
if err != nil {
|
||||
user.zlog.Err(err).Msg("Failed to reset puppet state")
|
||||
}
|
||||
user.PhoneID = ""
|
||||
go func() {
|
||||
|
|
Loading…
Reference in a new issue