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}`
This commit is contained in:
parent
81f73c9f8d
commit
ad0a7d09e8
12 changed files with 380 additions and 1 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue