1// Copyright 2017 New Vector Ltd
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package routing
16
17import (
18	"context"
19	"encoding/json"
20	"net/http"
21	"time"
22
23	"github.com/matrix-org/dendrite/roomserver/api"
24	"github.com/matrix-org/gomatrixserverlib"
25	"github.com/matrix-org/util"
26)
27
28// GetEvent returns the requested event
29func GetEvent(
30	ctx context.Context,
31	request *gomatrixserverlib.FederationRequest,
32	rsAPI api.RoomserverInternalAPI,
33	eventID string,
34	origin gomatrixserverlib.ServerName,
35) util.JSONResponse {
36	err := allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID)
37	if err != nil {
38		return *err
39	}
40	event, err := fetchEvent(ctx, rsAPI, eventID)
41	if err != nil {
42		return *err
43	}
44
45	return util.JSONResponse{Code: http.StatusOK, JSON: gomatrixserverlib.Transaction{
46		Origin:         origin,
47		OriginServerTS: gomatrixserverlib.AsTimestamp(time.Now()),
48		PDUs: []json.RawMessage{
49			event.JSON(),
50		},
51	}}
52}
53
54// allowedToSeeEvent returns no error if the server is allowed to see this event,
55// otherwise it returns an error response which can be sent to the client.
56func allowedToSeeEvent(
57	ctx context.Context,
58	origin gomatrixserverlib.ServerName,
59	rsAPI api.RoomserverInternalAPI,
60	eventID string,
61) *util.JSONResponse {
62	var authResponse api.QueryServerAllowedToSeeEventResponse
63	err := rsAPI.QueryServerAllowedToSeeEvent(
64		ctx,
65		&api.QueryServerAllowedToSeeEventRequest{
66			EventID:    eventID,
67			ServerName: origin,
68		},
69		&authResponse,
70	)
71	if err != nil {
72		resErr := util.ErrorResponse(err)
73		return &resErr
74	}
75
76	if !authResponse.AllowedToSeeEvent {
77		resErr := util.MessageResponse(http.StatusForbidden, "server not allowed to see event")
78		return &resErr
79	}
80
81	return nil
82}
83
84// fetchEvent fetches the event without auth checks. Returns an error if the event cannot be found.
85func fetchEvent(ctx context.Context, rsAPI api.RoomserverInternalAPI, eventID string) (*gomatrixserverlib.Event, *util.JSONResponse) {
86	var eventsResponse api.QueryEventsByIDResponse
87	err := rsAPI.QueryEventsByID(
88		ctx,
89		&api.QueryEventsByIDRequest{EventIDs: []string{eventID}},
90		&eventsResponse,
91	)
92	if err != nil {
93		resErr := util.ErrorResponse(err)
94		return nil, &resErr
95	}
96
97	if len(eventsResponse.Events) == 0 {
98		return nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil}
99	}
100
101	return eventsResponse.Events[0].Event, nil
102}
103