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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.mau.fi/util/dbutil"
|
"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
|
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
|
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) {
|
func (pq *PuppetQuery) Get(ctx context.Context, key Key) (*Puppet, error) {
|
||||||
return pq.QueryOne(ctx, getPuppetQuery, key.ID, key.Receiver)
|
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 {
|
type Puppet struct {
|
||||||
qh *dbutil.QueryHelper[*Puppet]
|
qh *dbutil.QueryHelper[*Puppet]
|
||||||
|
|
||||||
|
@ -67,8 +78,9 @@ type Puppet struct {
|
||||||
func (puppet *Puppet) Scan(row dbutil.Scannable) (*Puppet, error) {
|
func (puppet *Puppet) Scan(row dbutil.Scannable) (*Puppet, error) {
|
||||||
var avatarHash []byte
|
var avatarHash []byte
|
||||||
var avatarUpdateTS int64
|
var avatarUpdateTS int64
|
||||||
|
var phone sql.NullString
|
||||||
err := row.Scan(
|
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,
|
&avatarHash, &puppet.AvatarMXC, &puppet.AvatarSet, &avatarUpdateTS, &puppet.ContactInfoSet,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -77,14 +89,21 @@ func (puppet *Puppet) Scan(row dbutil.Scannable) (*Puppet, error) {
|
||||||
if len(avatarHash) == 32 {
|
if len(avatarHash) == 32 {
|
||||||
puppet.AvatarHash = *(*[32]byte)(avatarHash)
|
puppet.AvatarHash = *(*[32]byte)(avatarHash)
|
||||||
}
|
}
|
||||||
|
puppet.Phone = phone.String
|
||||||
|
if avatarUpdateTS > 0 {
|
||||||
puppet.AvatarUpdateTS = time.UnixMilli(avatarUpdateTS)
|
puppet.AvatarUpdateTS = time.UnixMilli(avatarUpdateTS)
|
||||||
|
}
|
||||||
return puppet, nil
|
return puppet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (puppet *Puppet) sqlVariables() []any {
|
func (puppet *Puppet) sqlVariables() []any {
|
||||||
|
var avatarUpdateTS int64
|
||||||
|
if !puppet.AvatarUpdateTS.IsZero() {
|
||||||
|
avatarUpdateTS = puppet.AvatarUpdateTS.UnixMilli()
|
||||||
|
}
|
||||||
return []any{
|
return []any{
|
||||||
puppet.ID, puppet.Receiver, puppet.Phone, puppet.ContactID, puppet.Name, puppet.NameSet,
|
puppet.ID, puppet.Receiver, dbutil.StrPtr(puppet.Phone), puppet.ContactID, puppet.Name, puppet.NameSet,
|
||||||
puppet.AvatarHash[:], &puppet.AvatarMXC, puppet.AvatarSet, puppet.AvatarUpdateTS.UnixMilli(), puppet.ContactInfoSet,
|
puppet.AvatarHash[:], &puppet.AvatarMXC, puppet.AvatarSet, avatarUpdateTS, puppet.ContactInfoSet,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
-- v0 -> v8: Latest revision
|
-- v0 -> v9: Latest revision
|
||||||
|
|
||||||
CREATE TABLE "user" (
|
CREATE TABLE "user" (
|
||||||
-- only: postgres
|
-- only: postgres
|
||||||
|
@ -23,7 +23,7 @@ CREATE TABLE "user" (
|
||||||
CREATE TABLE puppet (
|
CREATE TABLE puppet (
|
||||||
id TEXT NOT NULL,
|
id TEXT NOT NULL,
|
||||||
receiver BIGINT NOT NULL,
|
receiver BIGINT NOT NULL,
|
||||||
phone TEXT NOT NULL,
|
phone TEXT,
|
||||||
contact_id TEXT NOT NULL,
|
contact_id TEXT NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
name_set BOOLEAN NOT NULL DEFAULT false,
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
idents := []string{
|
idents := make([]string, 0, 2)
|
||||||
fmt.Sprintf("tel:%s", puppet.Phone),
|
if puppet.Phone != "" {
|
||||||
|
idents = append(idents, fmt.Sprintf("tel:%s", puppet.Phone))
|
||||||
}
|
}
|
||||||
if puppet.ContactID != "" {
|
if puppet.ContactID != "" {
|
||||||
idents = append(idents, fmt.Sprintf("gmsg-contact:%s", 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
|
update := false
|
||||||
if contact.ID.Number != "" && puppet.Phone != contact.ID.Number {
|
if contact.ID.Number != "" && puppet.Phone != contact.ID.Number {
|
||||||
|
oldPhone := puppet.Phone
|
||||||
puppet.Phone = contact.ID.Number
|
puppet.Phone = contact.ID.Number
|
||||||
puppet.ContactInfoSet = false
|
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
|
update = true
|
||||||
}
|
}
|
||||||
if contact.ContactID != puppet.ContactID {
|
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() {
|
func (user *User) ResetState() {
|
||||||
|
ctx := context.TODO()
|
||||||
portals := user.bridge.GetAllPortalsForUser(user.RowID)
|
portals := user.bridge.GetAllPortalsForUser(user.RowID)
|
||||||
user.zlog.Debug().Int("portal_count", len(portals)).Msg("Deleting portals")
|
user.zlog.Debug().Int("portal_count", len(portals)).Msg("Deleting portals")
|
||||||
for _, portal := range 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 = ""
|
user.PhoneID = ""
|
||||||
go func() {
|
go func() {
|
||||||
|
|
Loading…
Reference in a new issue