Add option to not set room meta in encrypted rooms

This commit is contained in:
Tulir Asokan 2023-04-14 13:40:34 +03:00
parent ac5ca1965b
commit 0fcb64c1aa
6 changed files with 67 additions and 52 deletions

View file

@ -1,5 +1,5 @@
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge. // mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
// Copyright (C) 2021 Tulir Asokan // Copyright (C) 2023 Tulir Asokan
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU Affero General Public License as published by
@ -99,7 +99,7 @@ type BridgeConfig struct {
DoublePuppetAllowDiscovery bool `yaml:"double_puppet_allow_discovery"` DoublePuppetAllowDiscovery bool `yaml:"double_puppet_allow_discovery"`
LoginSharedSecretMap map[string]string `yaml:"login_shared_secret_map"` LoginSharedSecretMap map[string]string `yaml:"login_shared_secret_map"`
PrivateChatPortalMeta bool `yaml:"private_chat_portal_meta"` PrivateChatPortalMeta string `yaml:"private_chat_portal_meta"`
ParallelMemberSync bool `yaml:"parallel_member_sync"` ParallelMemberSync bool `yaml:"parallel_member_sync"`
BridgeNotices bool `yaml:"bridge_notices"` BridgeNotices bool `yaml:"bridge_notices"`
ResendBridgeInfo bool `yaml:"resend_bridge_info"` ResendBridgeInfo bool `yaml:"resend_bridge_info"`

View file

@ -77,7 +77,15 @@ func DoUpgrade(helper *up.Helper) {
} else { } else {
helper.Copy(up.Map, "bridge", "login_shared_secret_map") helper.Copy(up.Map, "bridge", "login_shared_secret_map")
} }
helper.Copy(up.Bool, "bridge", "private_chat_portal_meta") if legacyPrivateChatPortalMeta, ok := helper.Get(up.Bool, "bridge", "private_chat_portal_meta"); ok {
updatedPrivateChatPortalMeta := "default"
if legacyPrivateChatPortalMeta == "true" {
updatedPrivateChatPortalMeta = "always"
}
helper.Set(up.Str, updatedPrivateChatPortalMeta, "bridge", "private_chat_portal_meta")
} else {
helper.Copy(up.Str, "bridge", "private_chat_portal_meta")
}
helper.Copy(up.Bool, "bridge", "parallel_member_sync") helper.Copy(up.Bool, "bridge", "parallel_member_sync")
helper.Copy(up.Bool, "bridge", "bridge_notices") helper.Copy(up.Bool, "bridge", "bridge_notices")
helper.Copy(up.Bool, "bridge", "resend_bridge_info") helper.Copy(up.Bool, "bridge", "resend_bridge_info")

View file

@ -254,9 +254,11 @@ bridge:
# manually. # manually.
login_shared_secret_map: login_shared_secret_map:
example.com: foobar example.com: foobar
# Should the bridge explicitly set the avatar and room name for private chat portal rooms? # Whether to explicitly set the avatar and room name for private chat portal rooms.
# This is implicitly enabled in encrypted rooms. # If set to `default`, this will be enabled in encrypted rooms and disabled in unencrypted rooms.
private_chat_portal_meta: false # If set to `always`, all DM rooms will have explicit names and avatars set.
# If set to `never`, DM rooms will never have names and avatars set.
private_chat_portal_meta: default
# Should group members be synced in parallel? This makes member sync faster # Should group members be synced in parallel? This makes member sync faster
parallel_member_sync: false parallel_member_sync: false
# Should Matrix m.notice-type messages be bridged? # Should Matrix m.notice-type messages be bridged?

View file

@ -67,16 +67,9 @@ func (br *WABridge) createPrivatePortalFromInvite(roomID id.RoomID, inviter *Use
} }
portal.MXID = roomID portal.MXID = roomID
portal.Topic = PrivateChatTopic portal.Topic = PrivateChatTopic
_, _ = portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
if portal.bridge.Config.Bridge.PrivateChatPortalMeta || br.Config.Bridge.Encryption.Default || encryptionEnabled {
portal.Name = puppet.Displayname portal.Name = puppet.Displayname
portal.AvatarURL = puppet.AvatarURL portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar portal.Avatar = puppet.Avatar
_, _ = portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
_, _ = portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
} else {
portal.Name = ""
}
portal.log.Infofln("Created private chat portal in %s after invite from %s", roomID, inviter.MXID) portal.log.Infofln("Created private chat portal in %s after invite from %s", roomID, inviter.MXID)
intent := puppet.DefaultIntent() intent := puppet.DefaultIntent()
@ -100,6 +93,13 @@ func (br *WABridge) createPrivatePortalFromInvite(roomID id.RoomID, inviter *Use
br.AS.StateStore.SetMembership(roomID, br.Bot.UserID, event.MembershipJoin) br.AS.StateStore.SetMembership(roomID, br.Bot.UserID, event.MembershipJoin)
portal.Encrypted = true portal.Encrypted = true
} }
_, _ = portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
if portal.shouldSetDMRoomMetadata() {
_, err = portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
portal.NameSet = err == nil
_, err = portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
portal.AvatarSet = err == nil
}
portal.Update(nil) portal.Update(nil)
portal.UpdateBridgeInfo() portal.UpdateBridgeInfo()
_, _ = intent.SendNotice(roomID, "Private chat portal created") _, _ = intent.SendNotice(roomID, "Private chat portal created")

View file

@ -1156,7 +1156,7 @@ func (portal *Portal) UpdateName(name string, setBy types.JID, updateInfo bool)
if name == "" && portal.IsBroadcastList() { if name == "" && portal.IsBroadcastList() {
name = UnnamedBroadcastName name = UnnamedBroadcastName
} }
if portal.Name != name || (!portal.NameSet && len(portal.MXID) > 0) { if portal.Name != name || (!portal.NameSet && len(portal.MXID) > 0 && portal.shouldSetDMRoomMetadata()) {
portal.log.Debugfln("Updating name %q -> %q", portal.Name, name) portal.log.Debugfln("Updating name %q -> %q", portal.Name, name)
portal.Name = name portal.Name = name
portal.NameSet = false portal.NameSet = false
@ -1164,7 +1164,9 @@ func (portal *Portal) UpdateName(name string, setBy types.JID, updateInfo bool)
defer portal.Update(nil) defer portal.Update(nil)
} }
if len(portal.MXID) > 0 { if len(portal.MXID) > 0 && !portal.shouldSetDMRoomMetadata() {
portal.UpdateBridgeInfo()
} else if len(portal.MXID) > 0 {
intent := portal.MainIntent() intent := portal.MainIntent()
if !setBy.IsEmpty() { if !setBy.IsEmpty() {
intent = portal.bridge.GetPuppetByJID(setBy).IntentFor(portal) intent = portal.bridge.GetPuppetByJID(setBy).IntentFor(portal)
@ -1497,6 +1499,12 @@ func (portal *Portal) updateChildRooms() {
} }
} }
func (portal *Portal) shouldSetDMRoomMetadata() bool {
return !portal.IsPrivateChat() ||
portal.bridge.Config.Bridge.PrivateChatPortalMeta == "always" ||
(portal.IsEncrypted() && portal.bridge.Config.Bridge.PrivateChatPortalMeta != "never")
}
func (portal *Portal) GetEncryptionEventContent() (evt *event.EncryptionEventContent) { func (portal *Portal) GetEncryptionEventContent() (evt *event.EncryptionEventContent) {
evt = &event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1} evt = &event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1}
if rot := portal.bridge.Config.Bridge.Encryption.Rotation; rot.EnableCustom { if rot := portal.bridge.Config.Bridge.Encryption.Rotation; rot.EnableCustom {
@ -1524,13 +1532,9 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
if portal.IsPrivateChat() { if portal.IsPrivateChat() {
puppet := portal.bridge.GetPuppetByJID(portal.Key.JID) puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
puppet.SyncContact(user, true, false, "creating private chat portal") puppet.SyncContact(user, true, false, "creating private chat portal")
if portal.bridge.Config.Bridge.PrivateChatPortalMeta || portal.bridge.Config.Bridge.Encryption.Default {
portal.Name = puppet.Displayname portal.Name = puppet.Displayname
portal.AvatarURL = puppet.AvatarURL portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar portal.Avatar = puppet.Avatar
} else {
portal.Name = ""
}
portal.Topic = PrivateChatTopic portal.Topic = PrivateChatTopic
} else if portal.IsStatusBroadcastList() { } else if portal.IsStatusBroadcastList() {
if !portal.bridge.Config.Bridge.EnableStatusBroadcast { if !portal.bridge.Config.Bridge.EnableStatusBroadcast {
@ -1616,18 +1620,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
Content: event.Content{Parsed: bridgeInfo}, Content: event.Content{Parsed: bridgeInfo},
StateKey: &bridgeInfoStateKey, StateKey: &bridgeInfoStateKey,
}} }}
if !portal.AvatarURL.IsEmpty() {
initialState = append(initialState, &event.Event{
Type: event.StateRoomAvatar,
Content: event.Content{
Parsed: event.RoomAvatarEventContent{URL: portal.AvatarURL},
},
})
portal.AvatarSet = true
}
var invite []id.UserID var invite []id.UserID
if portal.bridge.Config.Bridge.Encryption.Default { if portal.bridge.Config.Bridge.Encryption.Default {
initialState = append(initialState, &event.Event{ initialState = append(initialState, &event.Event{
Type: event.StateEncryption, Type: event.StateEncryption,
@ -1640,6 +1633,17 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
invite = append(invite, portal.bridge.Bot.UserID) invite = append(invite, portal.bridge.Bot.UserID)
} }
} }
if !portal.AvatarURL.IsEmpty() && portal.shouldSetDMRoomMetadata() {
initialState = append(initialState, &event.Event{
Type: event.StateRoomAvatar,
Content: event.Content{
Parsed: event.RoomAvatarEventContent{URL: portal.AvatarURL},
},
})
portal.AvatarSet = true
} else {
portal.AvatarSet = false
}
creationContent := make(map[string]interface{}) creationContent := make(map[string]interface{})
if !portal.bridge.Config.Bridge.FederateRooms { if !portal.bridge.Config.Bridge.FederateRooms {
@ -1674,7 +1678,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
invite = append(invite, user.MXID) invite = append(invite, user.MXID)
} }
} }
resp, err := intent.CreateRoom(&mautrix.ReqCreateRoom{ req := &mautrix.ReqCreateRoom{
Visibility: "private", Visibility: "private",
Name: portal.Name, Name: portal.Name,
Topic: portal.Topic, Topic: portal.Topic,
@ -1685,14 +1689,18 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
CreationContent: creationContent, CreationContent: creationContent,
BeeperAutoJoinInvites: autoJoinInvites, BeeperAutoJoinInvites: autoJoinInvites,
}) }
if !portal.shouldSetDMRoomMetadata() {
req.Name = ""
}
resp, err := intent.CreateRoom(req)
if err != nil { if err != nil {
return err return err
} }
portal.log.Infoln("Matrix room created:", resp.RoomID) portal.log.Infoln("Matrix room created:", resp.RoomID)
portal.InSpace = false portal.InSpace = false
portal.NameSet = len(portal.Name) > 0 portal.NameSet = len(req.Name) > 0
portal.TopicSet = len(portal.Topic) > 0 portal.TopicSet = len(req.Topic) > 0
portal.MXID = resp.RoomID portal.MXID = resp.RoomID
portal.bridge.portalsLock.Lock() portal.bridge.portalsLock.Lock()
portal.bridge.portalsByMXID[portal.MXID] = portal portal.bridge.portalsByMXID[portal.MXID] = portal

View file

@ -294,29 +294,26 @@ func (puppet *Puppet) UpdateContactInfo() bool {
} }
func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) { func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) {
if puppet.bridge.Config.Bridge.PrivateChatPortalMeta || puppet.bridge.Config.Bridge.Encryption.Allow {
for _, portal := range puppet.bridge.GetAllPortalsByJID(puppet.JID) { for _, portal := range puppet.bridge.GetAllPortalsByJID(puppet.JID) {
if !puppet.bridge.Config.Bridge.PrivateChatPortalMeta && !portal.Encrypted {
continue
}
// Get room create lock to prevent races between receiving contact info and room creation. // Get room create lock to prevent races between receiving contact info and room creation.
portal.roomCreateLock.Lock() portal.roomCreateLock.Lock()
meta(portal) meta(portal)
portal.roomCreateLock.Unlock() portal.roomCreateLock.Unlock()
} }
}
} }
func (puppet *Puppet) updatePortalAvatar() { func (puppet *Puppet) updatePortalAvatar() {
puppet.updatePortalMeta(func(portal *Portal) { puppet.updatePortalMeta(func(portal *Portal) {
if portal.Avatar == puppet.Avatar && portal.AvatarURL == puppet.AvatarURL && portal.AvatarSet { if portal.Avatar == puppet.Avatar && portal.AvatarURL == puppet.AvatarURL && (portal.AvatarSet || !portal.shouldSetDMRoomMetadata()) {
return return
} }
portal.AvatarURL = puppet.AvatarURL portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar portal.Avatar = puppet.Avatar
portal.AvatarSet = false portal.AvatarSet = false
defer portal.Update(nil) defer portal.Update(nil)
if len(portal.MXID) > 0 { if len(portal.MXID) > 0 && !portal.shouldSetDMRoomMetadata() {
portal.UpdateBridgeInfo()
} else if len(portal.MXID) > 0 {
_, err := portal.MainIntent().SetRoomAvatar(portal.MXID, puppet.AvatarURL) _, err := portal.MainIntent().SetRoomAvatar(portal.MXID, puppet.AvatarURL)
if err != nil { if err != nil {
portal.log.Warnln("Failed to set avatar:", err) portal.log.Warnln("Failed to set avatar:", err)