mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-16 18:43:10 -06:00
Add PowerLevelResolver to resolve the powerlevels before a redaction
event
This commit is contained in:
parent
b8aa0c7c92
commit
b8d425165d
|
|
@ -26,14 +26,14 @@ import (
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/roomserver/internal/helpers"
|
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/internal/helpers"
|
||||||
|
|
||||||
userAPI "github.com/matrix-org/dendrite/userapi/api"
|
userAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||||
|
|
||||||
fedapi "github.com/matrix-org/dendrite/federationapi/api"
|
fedapi "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
|
|
@ -275,25 +275,12 @@ func (r *Inputer) processRoomEvent(
|
||||||
|
|
||||||
// Check if the event is allowed by its auth events. If it isn't then
|
// Check if the event is allowed by its auth events. If it isn't then
|
||||||
// we consider the event to be "rejected" — it will still be persisted.
|
// we consider the event to be "rejected" — it will still be persisted.
|
||||||
redactAllowed := true
|
|
||||||
if err = gomatrixserverlib.Allowed(event, &authEvents); err != nil {
|
if err = gomatrixserverlib.Allowed(event, &authEvents); err != nil {
|
||||||
isRejected = true
|
isRejected = true
|
||||||
redactAllowed = false
|
|
||||||
rejectionErr = err
|
rejectionErr = err
|
||||||
logger.WithError(rejectionErr).Warnf("Event %s not allowed by auth events", event.EventID())
|
logger.WithError(rejectionErr).Warnf("Event %s not allowed by auth events", event.EventID())
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.Type() == gomatrixserverlib.MRoomRedaction {
|
|
||||||
ap, _ := authEvents.PowerLevels()
|
|
||||||
if ap != nil {
|
|
||||||
var powerLevels *gomatrixserverlib.PowerLevelContent
|
|
||||||
powerLevels, _ = ap.PowerLevels()
|
|
||||||
if powerLevels != nil {
|
|
||||||
redactAllowed = powerLevels.UserLevel(event.Sender()) >= powerLevels.Redact
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulate the auth event NIDs.
|
// Accumulate the auth event NIDs.
|
||||||
authEventIDs := event.AuthEventIDs()
|
authEventIDs := event.AuthEventIDs()
|
||||||
authEventNIDs := make([]types.EventNID, 0, len(authEventIDs))
|
authEventNIDs := make([]types.EventNID, 0, len(authEventIDs))
|
||||||
|
|
@ -369,22 +356,6 @@ func (r *Inputer) processRoomEvent(
|
||||||
return fmt.Errorf("updater.StoreEvent: %w", err)
|
return fmt.Errorf("updater.StoreEvent: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if storing this event results in it being redacted then do so.
|
|
||||||
var (
|
|
||||||
redactedEventID string
|
|
||||||
redactionEvent *gomatrixserverlib.Event
|
|
||||||
redactedEvent *gomatrixserverlib.Event
|
|
||||||
)
|
|
||||||
if !isRejected && !isCreateEvent {
|
|
||||||
redactionEvent, redactedEvent, err = r.DB.MaybeRedactEvent(ctx, roomInfo, eventNID, event, redactAllowed)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if redactedEvent != nil {
|
|
||||||
redactedEventID = redactedEvent.EventID()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For outliers we can stop after we've stored the event itself as it
|
// For outliers we can stop after we've stored the event itself as it
|
||||||
// doesn't have any associated state to store and we don't need to
|
// doesn't have any associated state to store and we don't need to
|
||||||
// notify anyone about it.
|
// notify anyone about it.
|
||||||
|
|
@ -413,6 +384,23 @@ func (r *Inputer) processRoomEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if storing this event results in it being redacted then do so.
|
||||||
|
var (
|
||||||
|
redactedEventID string
|
||||||
|
redactionEvent *gomatrixserverlib.Event
|
||||||
|
redactedEvent *gomatrixserverlib.Event
|
||||||
|
)
|
||||||
|
if !isRejected && !isCreateEvent {
|
||||||
|
resolver := state.NewStateResolution(r.DB, roomInfo)
|
||||||
|
redactionEvent, redactedEvent, err = r.DB.MaybeRedactEvent(ctx, roomInfo, eventNID, event, &resolver)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if redactedEvent != nil {
|
||||||
|
redactedEventID = redactedEvent.EventID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We stop here if the event is rejected: We've stored it but won't update
|
// We stop here if the event is rejected: We've stored it but won't update
|
||||||
// forward extremities or notify downstream components about it.
|
// forward extremities or notify downstream components about it.
|
||||||
switch {
|
switch {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/roomserver/auth"
|
"github.com/matrix-org/dendrite/roomserver/auth"
|
||||||
"github.com/matrix-org/dendrite/roomserver/internal/helpers"
|
"github.com/matrix-org/dendrite/roomserver/internal/helpers"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/state"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage"
|
"github.com/matrix-org/dendrite/roomserver/storage"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
)
|
)
|
||||||
|
|
@ -629,7 +630,9 @@ func persistEvents(ctx context.Context, db storage.Database, events []*gomatrixs
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev.Unwrap(), true)
|
resolver := state.NewStateResolution(db, roomInfo)
|
||||||
|
|
||||||
|
_, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev.Unwrap(), &resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).WithField("event_id", ev.EventID()).Error("Failed to redact event")
|
logrus.WithError(err).WithField("event_id", ev.EventID()).Error("Failed to redact event")
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,47 @@ func NewStateResolution(db StateResolutionStorage, roomInfo *types.RoomInfo) Sta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PowerLevelResolver interface {
|
||||||
|
Resolve(ctx context.Context, roomInfo *types.RoomInfo, eventID string) (*gomatrixserverlib.PowerLevelContent, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *StateResolution) Resolve(ctx context.Context, roomInfo *types.RoomInfo, eventID string) (*gomatrixserverlib.PowerLevelContent, error) {
|
||||||
|
stateEntries, err := p.LoadStateAtEvent(ctx, eventID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
wantTuple := types.StateKeyTuple{
|
||||||
|
EventTypeNID: types.MRoomPowerLevelsNID,
|
||||||
|
EventStateKeyNID: types.EmptyStateKeyNID,
|
||||||
|
}
|
||||||
|
|
||||||
|
var plNID types.EventNID
|
||||||
|
for _, entry := range stateEntries {
|
||||||
|
if entry.StateKeyTuple == wantTuple {
|
||||||
|
plNID = entry.EventNID
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if plNID == 0 {
|
||||||
|
return nil, fmt.Errorf("unable to find power level event")
|
||||||
|
}
|
||||||
|
|
||||||
|
events, err := p.db.Events(ctx, roomInfo, []types.EventNID{plNID})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(events) == 0 {
|
||||||
|
return nil, fmt.Errorf("unable to find power level event")
|
||||||
|
}
|
||||||
|
powerlevels, err := events[0].PowerLevels()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return powerlevels, nil
|
||||||
|
}
|
||||||
|
|
||||||
// LoadStateAtSnapshot loads the full state of a room at a particular snapshot.
|
// LoadStateAtSnapshot loads the full state of a room at a particular snapshot.
|
||||||
// This is typically the state before an event or the current state of a room.
|
// This is typically the state before an event or the current state of a room.
|
||||||
// Returns a sorted list of state entries or an error if there was a problem talking to the database.
|
// Returns a sorted list of state entries or an error if there was a problem talking to the database.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/state"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
|
|
@ -184,7 +185,7 @@ type Database interface {
|
||||||
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
|
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
|
||||||
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
|
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
|
||||||
MaybeRedactEvent(
|
MaybeRedactEvent(
|
||||||
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event *gomatrixserverlib.Event, redactAllowed bool,
|
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event *gomatrixserverlib.Event, plResolver state.PowerLevelResolver,
|
||||||
) (*gomatrixserverlib.Event, *gomatrixserverlib.Event, error)
|
) (*gomatrixserverlib.Event, *gomatrixserverlib.Event, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,7 +227,7 @@ type EventDatabase interface {
|
||||||
// MaybeRedactEvent returns the redaction event and the redacted event if this call resulted in a redaction, else an error
|
// MaybeRedactEvent returns the redaction event and the redacted event if this call resulted in a redaction, else an error
|
||||||
// (nil if there was nothing to do)
|
// (nil if there was nothing to do)
|
||||||
MaybeRedactEvent(
|
MaybeRedactEvent(
|
||||||
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event *gomatrixserverlib.Event, redactAllowed bool,
|
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event *gomatrixserverlib.Event, plResolver state.PowerLevelResolver,
|
||||||
) (*gomatrixserverlib.Event, *gomatrixserverlib.Event, error)
|
) (*gomatrixserverlib.Event, *gomatrixserverlib.Event, error)
|
||||||
StoreEvent(ctx context.Context, event *gomatrixserverlib.Event, roomInfo *types.RoomInfo, eventTypeNID types.EventTypeNID, eventStateKeyNID types.EventStateKeyNID, authEventNIDs []types.EventNID, isRejected bool) (types.EventNID, types.StateAtEvent, error)
|
StoreEvent(ctx context.Context, event *gomatrixserverlib.Event, roomInfo *types.RoomInfo, eventTypeNID types.EventTypeNID, eventStateKeyNID types.EventStateKeyNID, authEventNIDs []types.EventNID, isRejected bool) (types.EventNID, types.StateAtEvent, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
"github.com/matrix-org/dendrite/internal/caching"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/state"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
)
|
)
|
||||||
|
|
@ -926,7 +927,7 @@ func extractRoomVersionFromCreateEvent(event *gomatrixserverlib.Event) (
|
||||||
//
|
//
|
||||||
// Returns the redaction event and the redacted event if this call resulted in a redaction.
|
// Returns the redaction event and the redacted event if this call resulted in a redaction.
|
||||||
func (d *EventDatabase) MaybeRedactEvent(
|
func (d *EventDatabase) MaybeRedactEvent(
|
||||||
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event *gomatrixserverlib.Event, redactAllowed bool,
|
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event *gomatrixserverlib.Event, plResolver state.PowerLevelResolver,
|
||||||
) (*gomatrixserverlib.Event, *gomatrixserverlib.Event, error) {
|
) (*gomatrixserverlib.Event, *gomatrixserverlib.Event, error) {
|
||||||
var (
|
var (
|
||||||
redactionEvent, redactedEvent *types.Event
|
redactionEvent, redactedEvent *types.Event
|
||||||
|
|
@ -968,8 +969,14 @@ func (d *EventDatabase) MaybeRedactEvent(
|
||||||
|
|
||||||
_, sender1, _ := gomatrixserverlib.SplitID('@', redactedEvent.Sender())
|
_, sender1, _ := gomatrixserverlib.SplitID('@', redactedEvent.Sender())
|
||||||
_, sender2, _ := gomatrixserverlib.SplitID('@', redactionEvent.Sender())
|
_, sender2, _ := gomatrixserverlib.SplitID('@', redactionEvent.Sender())
|
||||||
|
var powerlevels *gomatrixserverlib.PowerLevelContent
|
||||||
|
powerlevels, err = plResolver.Resolve(ctx, roomInfo, redactionEvent.EventID())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case redactAllowed:
|
case powerlevels.UserLevel(redactionEvent.Sender()) >= powerlevels.Redact:
|
||||||
// 1. The power level of the redaction event’s sender is greater than or equal to the redact level.
|
// 1. The power level of the redaction event’s sender is greater than or equal to the redact level.
|
||||||
case sender1 == sender2:
|
case sender1 == sender2:
|
||||||
// 2. The domain of the redaction event’s sender matches that of the original event’s sender.
|
// 2. The domain of the redaction event’s sender matches that of the original event’s sender.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue