bridgev2: don't change power levels without permission

This commit is contained in:
Tulir Asokan 2024-08-09 22:42:23 +03:00
commit 11f93d735e
2 changed files with 48 additions and 16 deletions

View file

@ -2310,38 +2310,48 @@ type PowerLevelChanges struct {
Custom func(*event.PowerLevelsEventContent) bool
}
func (plc *PowerLevelChanges) Apply(content *event.PowerLevelsEventContent) (changed bool) {
func allowChange(newLevel, oldLevel, actorLevel int) bool {
return newLevel <= actorLevel && oldLevel <= actorLevel
}
func (plc *PowerLevelChanges) Apply(actor id.UserID, content *event.PowerLevelsEventContent) (changed bool) {
if plc == nil || content == nil {
return
}
for evtType, level := range plc.Events {
changed = content.EnsureEventLevel(evtType, level) || changed
changed = content.EnsureEventLevelAs(actor, evtType, level) || changed
}
if plc.UsersDefault != nil {
var actorLevel int
if actor != "" {
actorLevel = content.GetUserLevel(actor)
} else {
actorLevel = (1 << 31) - 1
}
if plc.UsersDefault != nil && allowChange(*plc.UsersDefault, content.UsersDefault, actorLevel) {
changed = content.UsersDefault != *plc.UsersDefault
content.UsersDefault = *plc.UsersDefault
}
if plc.EventsDefault != nil {
if plc.EventsDefault != nil && allowChange(*plc.EventsDefault, content.EventsDefault, actorLevel) {
changed = content.EventsDefault != *plc.EventsDefault
content.EventsDefault = *plc.EventsDefault
}
if plc.StateDefault != nil {
if plc.StateDefault != nil && allowChange(*plc.StateDefault, content.StateDefault(), actorLevel) {
changed = content.StateDefault() != *plc.StateDefault
content.StateDefaultPtr = plc.StateDefault
}
if plc.Invite != nil {
if plc.Invite != nil && allowChange(*plc.Invite, content.Invite(), actorLevel) {
changed = content.Invite() != *plc.Invite
content.InvitePtr = plc.Invite
}
if plc.Kick != nil {
if plc.Kick != nil && allowChange(*plc.Kick, content.Kick(), actorLevel) {
changed = content.Kick() != *plc.Kick
content.KickPtr = plc.Kick
}
if plc.Ban != nil {
if plc.Ban != nil && allowChange(*plc.Ban, content.Ban(), actorLevel) {
changed = content.Ban() != *plc.Ban
content.BanPtr = plc.Ban
}
if plc.Redact != nil {
if plc.Redact != nil && allowChange(*plc.Redact, content.Redact(), actorLevel) {
changed = content.Redact() != *plc.Redact
content.RedactPtr = plc.Redact
}
@ -2545,7 +2555,7 @@ func (portal *Portal) getInitialMemberList(ctx context.Context, members *ChatMem
return
}
}
members.PowerLevels.Apply(pl)
members.PowerLevels.Apply("", pl)
for _, member := range members.Members {
if member.Membership != event.MembershipJoin && member.Membership != "" {
continue
@ -2627,13 +2637,13 @@ func (portal *Portal) syncParticipants(ctx context.Context, members *ChatMemberL
return fmt.Errorf("failed to get current members: %w", err)
}
delete(currentMembers, portal.Bridge.Bot.GetMXID())
powerChanged := members.PowerLevels.Apply(currentPower)
powerChanged := members.PowerLevels.Apply(portal.Bridge.Bot.GetMXID(), currentPower)
syncUser := func(extraUserID id.UserID, member ChatMember, hasIntent bool) bool {
if member.Membership == "" {
member.Membership = event.MembershipJoin
}
if member.PowerLevel != nil {
powerChanged = currentPower.EnsureUserLevel(extraUserID, *member.PowerLevel) || powerChanged
powerChanged = currentPower.EnsureUserLevelAs(portal.Bridge.Bot.GetMXID(), extraUserID, *member.PowerLevel) || powerChanged
}
currentMember, ok := currentMembers[extraUserID]
delete(currentMembers, extraUserID)
@ -3038,7 +3048,9 @@ func (portal *Portal) createMatrixRoomInLoop(ctx context.Context, source *UserLo
event.StateServerACL.Type: 100,
event.StateEncryption.Type: 100,
},
Users: map[id.UserID]int{},
Users: map[id.UserID]int{
portal.Bridge.Bot.GetMXID(): 9001,
},
}
initialMembers, extraFunctionalMembers, err := portal.getInitialMemberList(ctx, info.Members, source, powerLevels)
if err != nil {

View file

@ -134,10 +134,20 @@ func (pl *PowerLevelsEventContent) SetUserLevel(userID id.UserID, level int) {
}
}
func (pl *PowerLevelsEventContent) EnsureUserLevel(userID id.UserID, level int) bool {
existingLevel := pl.GetUserLevel(userID)
func (pl *PowerLevelsEventContent) EnsureUserLevel(target id.UserID, level int) bool {
return pl.EnsureUserLevelAs("", target, level)
}
func (pl *PowerLevelsEventContent) EnsureUserLevelAs(actor, target id.UserID, level int) bool {
existingLevel := pl.GetUserLevel(target)
if actor != "" {
actorLevel := pl.GetUserLevel(actor)
if actorLevel <= existingLevel || actorLevel < level {
return false
}
}
if existingLevel != level {
pl.SetUserLevel(userID, level)
pl.SetUserLevel(target, level)
return true
}
return false
@ -170,7 +180,17 @@ func (pl *PowerLevelsEventContent) SetEventLevel(eventType Type, level int) {
}
func (pl *PowerLevelsEventContent) EnsureEventLevel(eventType Type, level int) bool {
return pl.EnsureEventLevelAs("", eventType, level)
}
func (pl *PowerLevelsEventContent) EnsureEventLevelAs(actor id.UserID, eventType Type, level int) bool {
existingLevel := pl.GetEventLevel(eventType)
if actor != "" {
actorLevel := pl.GetUserLevel(actor)
if existingLevel > actorLevel || level > actorLevel {
return false
}
}
if existingLevel != level {
pl.SetEventLevel(eventType, level)
return true