Move setting history visibility to own migration, be more restrictive

This commit is contained in:
Till Faelligen 2022-08-01 12:07:38 +02:00
parent e84fbf5061
commit 3a006495a9
No known key found for this signature in database
GPG key ID: 3DF82D8AB9211D4E
4 changed files with 88 additions and 44 deletions

View file

@ -34,6 +34,26 @@ func UpAddHistoryVisibilityColumnOutputRoomEvents(ctx context.Context, tx *sql.T
return nil return nil
} }
// UpSetHistoryVisibility sets the history visibility for already stored events.
func UpSetHistoryVisibility(ctx context.Context, tx *sql.Tx) error {
// get the current room history visibilities
historyVisibilities, err := currentHistoryVisibilities(ctx, tx)
if err != nil {
return err
}
// update the history visibility
for roomID, hisVis := range historyVisibilities {
_, err = tx.ExecContext(ctx, `UPDATE syncapi_output_room_events SET history_visibility = $1
WHERE type IN ('m.room.message', 'm.room.encrypted') AND room_id = $2 AND history_visibility <> $1`, hisVis, roomID)
if err != nil {
return fmt.Errorf("failed to update history visibility: %w", err)
}
}
return nil
}
func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.Tx) error { func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, ` _, err := tx.ExecContext(ctx, `
ALTER TABLE syncapi_current_room_state ADD COLUMN IF NOT EXISTS history_visibility SMALLINT NOT NULL DEFAULT 2; ALTER TABLE syncapi_current_room_state ADD COLUMN IF NOT EXISTS history_visibility SMALLINT NOT NULL DEFAULT 2;
@ -43,13 +63,19 @@ func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.T
return fmt.Errorf("failed to execute upgrade: %w", err) return fmt.Errorf("failed to execute upgrade: %w", err)
} }
// get the current room history visibility return nil
rows, err := tx.Query(`SELECT DISTINCT room_id, headered_event_json FROM syncapi_current_room_state }
// currentHistoryVisibilities returns a map from roomID to current history visibility.
// If the history visibility was changed after room creation, defaults to joined.
func currentHistoryVisibilities(ctx context.Context, tx *sql.Tx) (map[string]gomatrixserverlib.HistoryVisibility, error) {
rows, err := tx.QueryContext(ctx, `SELECT DISTINCT room_id, headered_event_json FROM syncapi_current_room_state
WHERE type = 'm.room.history_visibility' AND state_key = ''; WHERE type = 'm.room.history_visibility' AND state_key = '';
`) `)
if err != nil { if err != nil {
return fmt.Errorf("failed to query current room state: %w", err) return nil, fmt.Errorf("failed to query current room state: %w", err)
} }
defer rows.Close() // nolint: errcheck
var eventBytes []byte var eventBytes []byte
var roomID string var roomID string
var event gomatrixserverlib.HeaderedEvent var event gomatrixserverlib.HeaderedEvent
@ -57,27 +83,17 @@ func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.T
historyVisibilities := make(map[string]gomatrixserverlib.HistoryVisibility) historyVisibilities := make(map[string]gomatrixserverlib.HistoryVisibility)
for rows.Next() { for rows.Next() {
if err = rows.Scan(&roomID, &eventBytes); err != nil { if err = rows.Scan(&roomID, &eventBytes); err != nil {
return fmt.Errorf("failed to scan row: %w", err) return nil, fmt.Errorf("failed to scan row: %w", err)
} }
if err = json.Unmarshal(eventBytes, &event); err != nil { if err = json.Unmarshal(eventBytes, &event); err != nil {
return fmt.Errorf("failed to unmarshal event: %w", err) return nil, fmt.Errorf("failed to unmarshal event: %w", err)
} }
historyVisibilities[roomID] = gomatrixserverlib.HistoryVisibilityShared historyVisibilities[roomID] = gomatrixserverlib.HistoryVisibilityJoined
if hisVis, err = event.HistoryVisibility(); err == nil { if hisVis, err = event.HistoryVisibility(); err == nil && event.Depth() < 10 {
historyVisibilities[roomID] = hisVis historyVisibilities[roomID] = hisVis
} }
} }
return historyVisibilities, nil
// update the history visibility
for roomID, hisVis = range historyVisibilities {
_, err = tx.Exec(`UPDATE syncapi_output_room_events SET history_visibility = $1
WHERE type IN ('m.room.message', 'm.room.encrypted') AND room_id = $2`, hisVis, roomID)
if err != nil {
return fmt.Errorf("failed to update history visibility: %w", err)
}
}
return nil
} }
func DownAddHistoryVisibilityColumn(ctx context.Context, tx *sql.Tx) error { func DownAddHistoryVisibilityColumn(ctx context.Context, tx *sql.Tx) error {

View file

@ -191,10 +191,16 @@ func NewPostgresEventsTable(db *sql.DB) (tables.Events, error) {
} }
m := sqlutil.NewMigrator(db) m := sqlutil.NewMigrator(db)
m.AddMigrations(sqlutil.Migration{ m.AddMigrations(
Version: "syncapi: add history visibility column (output_room_events)", sqlutil.Migration{
Up: deltas.UpAddHistoryVisibilityColumnOutputRoomEvents, Version: "syncapi: add history visibility column (output_room_events)",
}) Up: deltas.UpAddHistoryVisibilityColumnOutputRoomEvents,
},
sqlutil.Migration{
Version: "syncapi: set history visibility for existing events",
Up: deltas.UpSetHistoryVisibility,
},
)
err = m.Up(context.Background()) err = m.Up(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -40,6 +40,26 @@ func UpAddHistoryVisibilityColumnOutputRoomEvents(ctx context.Context, tx *sql.T
return nil return nil
} }
// UpSetHistoryVisibility sets the history visibility for already stored events.
func UpSetHistoryVisibility(ctx context.Context, tx *sql.Tx) error {
// get the current room history visibilities
historyVisibilities, err := currentHistoryVisibilities(ctx, tx)
if err != nil {
return err
}
// update the history visibility
for roomID, hisVis := range historyVisibilities {
_, err = tx.ExecContext(ctx, `UPDATE syncapi_output_room_events SET history_visibility = $1
WHERE type IN ('m.room.message', 'm.room.encrypted') AND room_id = $2 AND history_visibility <> $1`, hisVis, roomID)
if err != nil {
return fmt.Errorf("failed to update history visibility: %w", err)
}
}
return nil
}
func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.Tx) error { func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.Tx) error {
// SQLite doesn't have "if exists", so check if the column exists. If the query doesn't return an error, it already exists. // SQLite doesn't have "if exists", so check if the column exists. If the query doesn't return an error, it already exists.
// Required for unit tests, as otherwise a duplicate column error will show up. // Required for unit tests, as otherwise a duplicate column error will show up.
@ -55,13 +75,19 @@ func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.T
return fmt.Errorf("failed to execute upgrade: %w", err) return fmt.Errorf("failed to execute upgrade: %w", err)
} }
// get the current room history visibility return nil
rows, err := tx.Query(`SELECT DISTINCT room_id, headered_event_json FROM syncapi_current_room_state }
// currentHistoryVisibilities returns a map from roomID to current history visibility.
// If the history visibility was changed after room creation, defaults to joined.
func currentHistoryVisibilities(ctx context.Context, tx *sql.Tx) (map[string]gomatrixserverlib.HistoryVisibility, error) {
rows, err := tx.QueryContext(ctx, `SELECT DISTINCT room_id, headered_event_json FROM syncapi_current_room_state
WHERE type = 'm.room.history_visibility' AND state_key = ''; WHERE type = 'm.room.history_visibility' AND state_key = '';
`) `)
if err != nil { if err != nil {
return fmt.Errorf("failed to query current room state: %w", err) return nil, fmt.Errorf("failed to query current room state: %w", err)
} }
defer rows.Close() // nolint: errcheck
var eventBytes []byte var eventBytes []byte
var roomID string var roomID string
var event gomatrixserverlib.HeaderedEvent var event gomatrixserverlib.HeaderedEvent
@ -69,27 +95,17 @@ func UpAddHistoryVisibilityColumnCurrentRoomState(ctx context.Context, tx *sql.T
historyVisibilities := make(map[string]gomatrixserverlib.HistoryVisibility) historyVisibilities := make(map[string]gomatrixserverlib.HistoryVisibility)
for rows.Next() { for rows.Next() {
if err = rows.Scan(&roomID, &eventBytes); err != nil { if err = rows.Scan(&roomID, &eventBytes); err != nil {
return fmt.Errorf("failed to scan row: %w", err) return nil, fmt.Errorf("failed to scan row: %w", err)
} }
if err = json.Unmarshal(eventBytes, &event); err != nil { if err = json.Unmarshal(eventBytes, &event); err != nil {
return fmt.Errorf("failed to unmarshal event: %w", err) return nil, fmt.Errorf("failed to unmarshal event: %w", err)
} }
historyVisibilities[roomID] = gomatrixserverlib.HistoryVisibilityShared historyVisibilities[roomID] = gomatrixserverlib.HistoryVisibilityJoined
if hisVis, err = event.HistoryVisibility(); err == nil { if hisVis, err = event.HistoryVisibility(); err == nil && event.Depth() < 10 {
historyVisibilities[roomID] = hisVis historyVisibilities[roomID] = hisVis
} }
} }
return historyVisibilities, nil
// update the history visibility
for roomID, hisVis = range historyVisibilities {
_, err = tx.Exec(`UPDATE syncapi_output_room_events SET history_visibility = $1
WHERE type IN ('m.room.message', 'm.room.encrypted') AND room_id = $2`, hisVis, roomID)
if err != nil {
return fmt.Errorf("failed to update history visibility: %w", err)
}
}
return nil
} }
func DownAddHistoryVisibilityColumn(ctx context.Context, tx *sql.Tx) error { func DownAddHistoryVisibilityColumn(ctx context.Context, tx *sql.Tx) error {

View file

@ -139,10 +139,16 @@ func NewSqliteEventsTable(db *sql.DB, streamID *StreamIDStatements) (tables.Even
} }
m := sqlutil.NewMigrator(db) m := sqlutil.NewMigrator(db)
m.AddMigrations(sqlutil.Migration{ m.AddMigrations(
Version: "syncapi: add history visibility column (output_room_events)", sqlutil.Migration{
Up: deltas.UpAddHistoryVisibilityColumnOutputRoomEvents, Version: "syncapi: add history visibility column (output_room_events)",
}) Up: deltas.UpAddHistoryVisibilityColumnOutputRoomEvents,
},
sqlutil.Migration{
Version: "syncapi: set history visibility for existing events",
Up: deltas.UpSetHistoryVisibility,
},
)
err = m.Up(context.Background()) err = m.Up(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err