2022-10-10 10:19:16 +00:00
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package routing
import (
"net/http"
"github.com/matrix-org/util"
"github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/syncapi/internal"
"github.com/matrix-org/dendrite/syncapi/storage"
2023-04-04 17:16:53 +00:00
"github.com/matrix-org/dendrite/syncapi/synctypes"
2022-10-10 10:19:16 +00:00
userapi "github.com/matrix-org/dendrite/userapi/api"
2023-05-09 22:46:49 +00:00
"github.com/matrix-org/gomatrixserverlib/spec"
2022-10-10 10:19:16 +00:00
)
// GetEvent implements
//
// GET /_matrix/client/r0/rooms/{roomId}/event/{eventId}
//
// https://spec.matrix.org/v1.4/client-server-api/#get_matrixclientv3roomsroomideventeventid
func GetEvent (
req * http . Request ,
device * userapi . Device ,
2023-08-15 11:37:04 +00:00
rawRoomID string ,
2022-10-10 10:19:16 +00:00
eventID string ,
cfg * config . SyncAPI ,
syncDB storage . Database ,
rsAPI api . SyncRoomserverAPI ,
) util . JSONResponse {
ctx := req . Context ( )
2023-11-08 13:22:20 +00:00
db , err := syncDB . NewDatabaseSnapshot ( ctx )
2022-10-10 10:19:16 +00:00
logger := util . GetLogger ( ctx ) . WithFields ( logrus . Fields {
"event_id" : eventID ,
2023-08-15 11:37:04 +00:00
"room_id" : rawRoomID ,
2022-10-10 10:19:16 +00:00
} )
if err != nil {
logger . WithError ( err ) . Error ( "GetEvent: syncDB.NewDatabaseTransaction failed" )
2023-05-17 00:33:27 +00:00
return util . JSONResponse {
Code : http . StatusInternalServerError ,
JSON : spec . InternalServerError { } ,
}
2022-10-10 10:19:16 +00:00
}
2023-11-08 13:22:20 +00:00
defer db . Rollback ( ) // nolint: errcheck
2022-10-10 10:19:16 +00:00
2023-08-15 11:37:04 +00:00
roomID , err := spec . NewRoomID ( rawRoomID )
if err != nil {
return util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : spec . InvalidParam ( "invalid room ID" ) ,
}
}
2022-10-10 10:19:16 +00:00
events , err := db . Events ( ctx , [ ] string { eventID } )
if err != nil {
logger . WithError ( err ) . Error ( "GetEvent: syncDB.Events failed" )
2023-05-17 00:33:27 +00:00
return util . JSONResponse {
Code : http . StatusInternalServerError ,
JSON : spec . InternalServerError { } ,
}
2022-10-10 10:19:16 +00:00
}
// The requested event does not exist in our database
if len ( events ) == 0 {
logger . Debugf ( "GetEvent: requested event doesn't exist locally" )
return util . JSONResponse {
Code : http . StatusNotFound ,
2023-05-09 22:46:49 +00:00
JSON : spec . NotFound ( "The event was not found or you do not have permission to read this event" ) ,
2022-10-10 10:19:16 +00:00
}
}
// If the request is coming from an appservice, get the user from the request
2023-08-15 11:37:04 +00:00
rawUserID := device . UserID
2022-10-10 10:19:16 +00:00
if asUserID := req . FormValue ( "user_id" ) ; device . AppserviceID != "" && asUserID != "" {
2023-08-15 11:37:04 +00:00
rawUserID = asUserID
}
userID , err := spec . NewUserID ( rawUserID , true )
if err != nil {
util . GetLogger ( req . Context ( ) ) . WithError ( err ) . Error ( "invalid device.UserID" )
return util . JSONResponse {
Code : http . StatusInternalServerError ,
JSON : spec . Unknown ( "internal server error" ) ,
}
2022-10-10 10:19:16 +00:00
}
// Apply history visibility to determine if the user is allowed to view the event
2023-08-15 11:37:04 +00:00
events , err = internal . ApplyHistoryVisibilityFilter ( ctx , db , rsAPI , events , nil , * userID , "event" )
2022-10-10 10:19:16 +00:00
if err != nil {
logger . WithError ( err ) . Error ( "GetEvent: internal.ApplyHistoryVisibilityFilter failed" )
return util . JSONResponse {
Code : http . StatusInternalServerError ,
2023-05-17 00:33:27 +00:00
JSON : spec . InternalServerError { } ,
2022-10-10 10:19:16 +00:00
}
}
// We only ever expect there to be one event
if len ( events ) != 1 {
// 0 events -> not allowed to view event; > 1 events -> something that shouldn't happen
logger . WithField ( "event_count" , len ( events ) ) . Debug ( "GetEvent: can't return the requested event" )
return util . JSONResponse {
Code : http . StatusNotFound ,
2023-05-09 22:46:49 +00:00
JSON : spec . NotFound ( "The event was not found or you do not have permission to read this event" ) ,
2022-10-10 10:19:16 +00:00
}
}
2023-09-15 15:25:09 +00:00
clientEvent , err := synctypes . ToClientEvent ( events [ 0 ] , synctypes . FormatAll , func ( roomID spec . RoomID , senderID spec . SenderID ) ( * spec . UserID , error ) {
return rsAPI . QueryUserIDForSender ( ctx , roomID , senderID )
} )
if err != nil {
util . GetLogger ( req . Context ( ) ) . WithError ( err ) . WithField ( "senderID" , events [ 0 ] . SenderID ( ) ) . WithField ( "roomID" , * roomID ) . Error ( "Failed converting to ClientEvent" )
2023-06-14 14:23:46 +00:00
return util . JSONResponse {
2023-08-15 11:37:04 +00:00
Code : http . StatusInternalServerError ,
JSON : spec . Unknown ( "internal server error" ) ,
2023-06-14 14:23:46 +00:00
}
}
2023-06-12 11:19:25 +00:00
2022-10-10 10:19:16 +00:00
return util . JSONResponse {
Code : http . StatusOK ,
2023-09-15 15:25:09 +00:00
JSON : * clientEvent ,
2022-10-10 10:19:16 +00:00
}
}