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 ( )
db , err := syncDB . NewDatabaseTransaction ( ctx )
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-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-08-15 11:37:04 +00:00
senderUserID , err := rsAPI . QueryUserIDForSender ( req . Context ( ) , * roomID , events [ 0 ] . SenderID ( ) )
if err != nil || senderUserID == nil {
util . GetLogger ( req . Context ( ) ) . WithError ( err ) . WithField ( "senderID" , events [ 0 ] . SenderID ( ) ) . WithField ( "roomID" , * roomID ) . Error ( "QueryUserIDForSender errored or returned nil-user ID when user should be part of a room" )
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
sk := events [ 0 ] . StateKey ( )
if sk != nil && * sk != "" {
2023-09-15 14:39:06 +00:00
skUserID , err := rsAPI . QueryUserIDForSender ( ctx , events [ 0 ] . RoomID ( ) , spec . SenderID ( * events [ 0 ] . StateKey ( ) ) )
2023-06-12 11:19:25 +00:00
if err == nil && skUserID != nil {
skString := skUserID . String ( )
sk = & skString
}
}
2022-10-10 10:19:16 +00:00
return util . JSONResponse {
Code : http . StatusOK ,
2023-08-31 15:33:38 +00:00
JSON : synctypes . ToClientEvent ( events [ 0 ] , synctypes . FormatAll , senderUserID . String ( ) , sk , events [ 0 ] . Unsigned ( ) ) ,
2022-10-10 10:19:16 +00:00
}
}