diff options
author | Till <2353100+S7evinK@users.noreply.github.com> | 2024-03-22 22:54:29 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-22 21:54:29 +0000 |
commit | ad0a7d09e89fe18c9e2b08f23f5817a5231c6074 (patch) | |
tree | 01ae155c112ac01dce299724790a9db8d999994d /roomserver | |
parent | 81f73c9f8df6dd3078a93b6ca978ecbb9c95df16 (diff) |
Add getting/deleting single event report (#3344)
Based on https://github.com/matrix-org/dendrite/pull/3342
Adds `GET /_synapse/admin/v1/event_reports/{reportID}` and `DELETE
/_synapse/admin/v1/event_reports/{reportID}`
Diffstat (limited to 'roomserver')
-rw-r--r-- | roomserver/api/api.go | 2 | ||||
-rw-r--r-- | roomserver/api/query.go | 5 | ||||
-rw-r--r-- | roomserver/internal/perform/perform_admin.go | 4 | ||||
-rw-r--r-- | roomserver/internal/query/query.go | 5 | ||||
-rw-r--r-- | roomserver/storage/interface.go | 2 | ||||
-rw-r--r-- | roomserver/storage/postgres/reported_events_table.go | 41 | ||||
-rw-r--r-- | roomserver/storage/shared/storage.go | 68 | ||||
-rw-r--r-- | roomserver/storage/sqlite3/reported_events_table.go | 41 | ||||
-rw-r--r-- | roomserver/storage/tables/interface.go | 6 |
9 files changed, 174 insertions, 0 deletions
diff --git a/roomserver/api/api.go b/roomserver/api/api.go index ac4ea5ba..dffb6d47 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -272,6 +272,8 @@ type ClientRoomserverAPI interface { score int64, ) (int64, error) QueryAdminEventReports(ctx context.Context, from, limit uint64, backwards bool, userID, roomID string) ([]QueryAdminEventReportsResponse, int64, error) + QueryAdminEventReport(ctx context.Context, reportID uint64) (QueryAdminEventReportResponse, error) + PerformAdminDeleteEventReport(ctx context.Context, reportID uint64) error } type UserRoomserverAPI interface { diff --git a/roomserver/api/query.go b/roomserver/api/query.go index 9a7acab9..c4c019f9 100644 --- a/roomserver/api/query.go +++ b/roomserver/api/query.go @@ -363,6 +363,11 @@ type QueryAdminEventReportsResponse struct { ReceivedTS spec.Timestamp `json:"received_ts"` } +type QueryAdminEventReportResponse struct { + QueryAdminEventReportsResponse + EventJSON json.RawMessage `json:"event_json"` +} + // MarshalJSON stringifies the room ID and StateKeyTuple keys so they can be sent over the wire in HTTP API mode. func (r *QueryBulkStateContentResponse) MarshalJSON() ([]byte, error) { se := make(map[string]string) diff --git a/roomserver/internal/perform/perform_admin.go b/roomserver/internal/perform/perform_admin.go index ae203854..1b881723 100644 --- a/roomserver/internal/perform/perform_admin.go +++ b/roomserver/internal/perform/perform_admin.go @@ -354,3 +354,7 @@ func (r *Admin) PerformAdminDownloadState( return nil } + +func (r *Admin) PerformAdminDeleteEventReport(ctx context.Context, reportID uint64) error { + return r.DB.AdminDeleteEventReport(ctx, reportID) +} diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index b1b11df3..886d0049 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -1109,3 +1109,8 @@ func (r *Queryer) RoomsWithACLs(ctx context.Context) ([]string, error) { func (r *Queryer) QueryAdminEventReports(ctx context.Context, from uint64, limit uint64, backwards bool, userID, roomID string) ([]api.QueryAdminEventReportsResponse, int64, error) { return r.DB.QueryAdminEventReports(ctx, from, limit, backwards, userID, roomID) } + +// QueryAdminEventReport returns a single event report. +func (r *Queryer) QueryAdminEventReport(ctx context.Context, reportID uint64) (api.QueryAdminEventReportResponse, error) { + return r.DB.QueryAdminEventReport(ctx, reportID) +} diff --git a/roomserver/storage/interface.go b/roomserver/storage/interface.go index eb169cbb..ab105e6f 100644 --- a/roomserver/storage/interface.go +++ b/roomserver/storage/interface.go @@ -196,6 +196,8 @@ type Database interface { // RoomsWithACLs returns all room IDs for rooms with ACLs RoomsWithACLs(ctx context.Context) ([]string, error) QueryAdminEventReports(ctx context.Context, from uint64, limit uint64, backwards bool, userID string, roomID string) ([]api.QueryAdminEventReportsResponse, int64, error) + QueryAdminEventReport(ctx context.Context, reportID uint64) (api.QueryAdminEventReportResponse, error) + AdminDeleteEventReport(ctx context.Context, reportID uint64) error } type UserRoomKeys interface { diff --git a/roomserver/storage/postgres/reported_events_table.go b/roomserver/storage/postgres/reported_events_table.go index 70393833..c46f47b3 100644 --- a/roomserver/storage/postgres/reported_events_table.go +++ b/roomserver/storage/postgres/reported_events_table.go @@ -75,10 +75,20 @@ OFFSET $3 LIMIT $4 ` +const selectReportedEventSQL = ` +SELECT id, room_nid, event_nid, reporting_user_nid, event_sender_nid, reason, score, received_ts +FROM roomserver_reported_events +WHERE id = $1 +` + +const deleteReportedEventSQL = `DELETE FROM roomserver_reported_events WHERE id = $1` + type reportedEventsStatements struct { insertReportedEventsStmt *sql.Stmt selectReportedEventsDescStmt *sql.Stmt selectReportedEventsAscStmt *sql.Stmt + selectReportedEventStmt *sql.Stmt + deleteReportedEventStmt *sql.Stmt } func CreateReportedEventsTable(db *sql.DB) error { @@ -93,6 +103,8 @@ func PrepareReportedEventsTable(db *sql.DB) (tables.ReportedEvents, error) { {&s.insertReportedEventsStmt, insertReportedEventSQL}, {&s.selectReportedEventsDescStmt, selectReportedEventsDescSQL}, {&s.selectReportedEventsAscStmt, selectReportedEventsAscSQL}, + {&s.selectReportedEventStmt, selectReportedEventSQL}, + {&s.deleteReportedEventStmt, deleteReportedEventSQL}, }.Prepare(db) } @@ -178,3 +190,32 @@ func (r *reportedEventsStatements) SelectReportedEvents( return result, count, rows.Err() } + +func (r *reportedEventsStatements) SelectReportedEvent( + ctx context.Context, + txn *sql.Tx, + reportID uint64, +) (api.QueryAdminEventReportResponse, error) { + stmt := sqlutil.TxStmt(txn, r.selectReportedEventStmt) + + var row api.QueryAdminEventReportResponse + if err := stmt.QueryRowContext(ctx, reportID).Scan( + &row.ID, + &row.RoomNID, + &row.EventNID, + &row.ReportingUserNID, + &row.SenderNID, + &row.Reason, + &row.Score, + &row.ReceivedTS, + ); err != nil { + return api.QueryAdminEventReportResponse{}, err + } + return row, nil +} + +func (r *reportedEventsStatements) DeleteReportedEvent(ctx context.Context, txn *sql.Tx, reportID uint64) error { + stmt := sqlutil.TxStmt(txn, r.deleteReportedEventStmt) + _, err := stmt.ExecContext(ctx, reportID) + return err +} diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index c8c34907..7b04641b 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -2040,6 +2040,74 @@ func (d *Database) QueryAdminEventReports(ctx context.Context, from uint64, limi return reports, count, nil } +func (d *Database) QueryAdminEventReport(ctx context.Context, reportID uint64) (api.QueryAdminEventReportResponse, error) { + + report, err := d.ReportedEventsTable.SelectReportedEvent(ctx, nil, reportID) + if err != nil { + return api.QueryAdminEventReportResponse{}, err + } + + // Get a map from EventStateKeyNID to userID + userNIDMap, err := d.EventStateKeys(ctx, []types.EventStateKeyNID{report.ReportingUserNID, report.SenderNID}) + if err != nil { + logrus.WithError(err).Error("unable to map userNIDs to userIDs") + return report, err + } + + roomIDs, err := d.RoomsTable.BulkSelectRoomIDs(ctx, nil, []types.RoomNID{report.RoomNID}) + if err != nil { + return report, err + } + + if len(roomIDs) != 1 { + return report, fmt.Errorf("expected one roomID, got %d", len(roomIDs)) + } + + // TODO: replace this with something more efficient, as it loads the entire state snapshot. + stateContent, err := d.GetBulkStateContent(ctx, roomIDs, []gomatrixserverlib.StateKeyTuple{ + {EventType: spec.MRoomName, StateKey: ""}, + {EventType: spec.MRoomCanonicalAlias, StateKey: ""}, + }, false) + if err != nil { + return report, err + } + + eventIDMap, err := d.EventIDs(ctx, []types.EventNID{report.EventNID}) + if err != nil { + logrus.WithError(err).Error("unable to map eventNIDs to eventIDs") + return report, err + } + if len(eventIDMap) != 1 { + return report, fmt.Errorf("expected %d eventIDs, got %d", 1, len(eventIDMap)) + } + + eventJSONs, err := d.EventJSONTable.BulkSelectEventJSON(ctx, nil, []types.EventNID{report.EventNID}) + if err != nil { + return report, err + } + if len(eventJSONs) != 1 { + return report, fmt.Errorf("expected %d eventJSONs, got %d", 1, len(eventJSONs)) + } + + roomName, canonicalAlias := findRoomNameAndCanonicalAlias(stateContent, roomIDs[0]) + + report.Sender = userNIDMap[report.SenderNID] + report.UserID = userNIDMap[report.ReportingUserNID] + report.RoomID = roomIDs[0] + report.RoomName = roomName + report.CanonicalAlias = canonicalAlias + report.EventID = eventIDMap[report.EventNID] + report.EventJSON = eventJSONs[0].EventJSON + + return report, nil +} + +func (d *Database) AdminDeleteEventReport(ctx context.Context, reportID uint64) error { + return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { + return d.ReportedEventsTable.DeleteReportedEvent(ctx, txn, reportID) + }) +} + // findRoomNameAndCanonicalAlias loops over events to find the corresponding room name and canonicalAlias // for a given roomID. func findRoomNameAndCanonicalAlias(events []tables.StrippedEvent, roomID string) (name, canonicalAlias string) { diff --git a/roomserver/storage/sqlite3/reported_events_table.go b/roomserver/storage/sqlite3/reported_events_table.go index 65584f4c..b72cb068 100644 --- a/roomserver/storage/sqlite3/reported_events_table.go +++ b/roomserver/storage/sqlite3/reported_events_table.go @@ -74,10 +74,20 @@ LIMIT $3 OFFSET $4 ` +const selectReportedEventSQL = ` +SELECT id, room_nid, event_nid, reporting_user_nid, event_sender_nid, reason, score, received_ts +FROM roomserver_reported_events +WHERE id = $1 +` + +const deleteReportedEventSQL = `DELETE FROM roomserver_reported_events WHERE id = $1` + type reportedEventsStatements struct { insertReportedEventsStmt *sql.Stmt selectReportedEventsDescStmt *sql.Stmt selectReportedEventsAscStmt *sql.Stmt + selectReportedEventStmt *sql.Stmt + deleteReportedEventStmt *sql.Stmt } func CreateReportedEventsTable(db *sql.DB) error { @@ -92,6 +102,8 @@ func PrepareReportedEventsTable(db *sql.DB) (tables.ReportedEvents, error) { {&s.insertReportedEventsStmt, insertReportedEventSQL}, {&s.selectReportedEventsDescStmt, selectReportedEventsDescSQL}, {&s.selectReportedEventsAscStmt, selectReportedEventsAscSQL}, + {&s.selectReportedEventStmt, selectReportedEventSQL}, + {&s.deleteReportedEventStmt, deleteReportedEventSQL}, }.Prepare(db) } @@ -178,3 +190,32 @@ func (r *reportedEventsStatements) SelectReportedEvents( return result, count, rows.Err() } + +func (r *reportedEventsStatements) SelectReportedEvent( + ctx context.Context, + txn *sql.Tx, + reportID uint64, +) (api.QueryAdminEventReportResponse, error) { + stmt := sqlutil.TxStmt(txn, r.selectReportedEventStmt) + + var row api.QueryAdminEventReportResponse + if err := stmt.QueryRowContext(ctx, reportID).Scan( + &row.ID, + &row.RoomNID, + &row.EventNID, + &row.ReportingUserNID, + &row.SenderNID, + &row.Reason, + &row.Score, + &row.ReceivedTS, + ); err != nil { + return api.QueryAdminEventReportResponse{}, err + } + return row, nil +} + +func (r *reportedEventsStatements) DeleteReportedEvent(ctx context.Context, txn *sql.Tx, reportID uint64) error { + stmt := sqlutil.TxStmt(txn, r.deleteReportedEventStmt) + _, err := stmt.ExecContext(ctx, reportID) + return err +} diff --git a/roomserver/storage/tables/interface.go b/roomserver/storage/tables/interface.go index d41b5032..02f6992c 100644 --- a/roomserver/storage/tables/interface.go +++ b/roomserver/storage/tables/interface.go @@ -147,6 +147,12 @@ type ReportedEvents interface { reportingUserID types.EventStateKeyNID, roomNID types.RoomNID, ) ([]api.QueryAdminEventReportsResponse, int64, error) + SelectReportedEvent( + ctx context.Context, + txn *sql.Tx, + reportID uint64, + ) (api.QueryAdminEventReportResponse, error) + DeleteReportedEvent(ctx context.Context, txn *sql.Tx, reportID uint64) error } type MembershipState int64 |