1// Copyright 2017 Vector Creations Ltd
2// Copyright 2018 New Vector Ltd
3// Copyright 2019-2020 The Matrix.org Foundation C.I.C.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package api
18
19import (
20	"encoding/json"
21	"fmt"
22	"strings"
23
24	"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
25	"github.com/matrix-org/gomatrixserverlib"
26)
27
28// QueryLatestEventsAndStateRequest is a request to QueryLatestEventsAndState
29type QueryLatestEventsAndStateRequest struct {
30	// The room ID to query the latest events for.
31	RoomID string `json:"room_id"`
32	// The state key tuples to fetch from the room current state.
33	// If this list is empty or nil then *ALL* current state events are returned.
34	StateToFetch []gomatrixserverlib.StateKeyTuple `json:"state_to_fetch"`
35}
36
37// QueryLatestEventsAndStateResponse is a response to QueryLatestEventsAndState
38// This is used when sending events to set the prev_events, auth_events and depth.
39// It is also used to tell whether the event is allowed by the event auth rules.
40type QueryLatestEventsAndStateResponse struct {
41	// Does the room exist?
42	// If the room doesn't exist this will be false and LatestEvents will be empty.
43	RoomExists bool `json:"room_exists"`
44	// The room version of the room.
45	RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
46	// The latest events in the room.
47	// These are used to set the prev_events when sending an event.
48	LatestEvents []gomatrixserverlib.EventReference `json:"latest_events"`
49	// The state events requested.
50	// This list will be in an arbitrary order.
51	// These are used to set the auth_events when sending an event.
52	// These are used to check whether the event is allowed.
53	StateEvents []*gomatrixserverlib.HeaderedEvent `json:"state_events"`
54	// The depth of the latest events.
55	// This is one greater than the maximum depth of the latest events.
56	// This is used to set the depth when sending an event.
57	Depth int64 `json:"depth"`
58}
59
60// QueryStateAfterEventsRequest is a request to QueryStateAfterEvents
61type QueryStateAfterEventsRequest struct {
62	// The room ID to query the state in.
63	RoomID string `json:"room_id"`
64	// The list of previous events to return the events after.
65	PrevEventIDs []string `json:"prev_event_ids"`
66	// The state key tuples to fetch from the state. If none are specified then
67	// the entire resolved room state will be returned.
68	StateToFetch []gomatrixserverlib.StateKeyTuple `json:"state_to_fetch"`
69}
70
71// QueryStateAfterEventsResponse is a response to QueryStateAfterEvents
72type QueryStateAfterEventsResponse struct {
73	// Does the room exist on this roomserver?
74	// If the room doesn't exist this will be false and StateEvents will be empty.
75	RoomExists bool `json:"room_exists"`
76	// The room version of the room.
77	RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
78	// Do all the previous events exist on this roomserver?
79	// If some of previous events do not exist this will be false and StateEvents will be empty.
80	PrevEventsExist bool `json:"prev_events_exist"`
81	// The state events requested.
82	// This list will be in an arbitrary order.
83	StateEvents []*gomatrixserverlib.HeaderedEvent `json:"state_events"`
84}
85
86type QueryMissingAuthPrevEventsRequest struct {
87	// The room ID to query the state in.
88	RoomID string `json:"room_id"`
89	// The list of auth events to check the existence of.
90	AuthEventIDs []string `json:"auth_event_ids"`
91	// The list of previous events to check the existence of.
92	PrevEventIDs []string `json:"prev_event_ids"`
93}
94
95type QueryMissingAuthPrevEventsResponse struct {
96	// Does the room exist on this roomserver?
97	// If the room doesn't exist all other fields will be empty.
98	RoomExists bool `json:"room_exists"`
99	// The room version of the room.
100	RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
101	// The event IDs of the auth events that we don't know locally.
102	MissingAuthEventIDs []string `json:"missing_auth_event_ids"`
103	// The event IDs of the previous events that we don't know locally.
104	MissingPrevEventIDs []string `json:"missing_prev_event_ids"`
105}
106
107// QueryEventsByIDRequest is a request to QueryEventsByID
108type QueryEventsByIDRequest struct {
109	// The event IDs to look up.
110	EventIDs []string `json:"event_ids"`
111}
112
113// QueryEventsByIDResponse is a response to QueryEventsByID
114type QueryEventsByIDResponse struct {
115	// A list of events with the requested IDs.
116	// If the roomserver does not have a copy of a requested event
117	// then it will omit that event from the list.
118	// If the roomserver thinks it has a copy of the event, but
119	// fails to read it from the database then it will fail
120	// the entire request.
121	// This list will be in an arbitrary order.
122	Events []*gomatrixserverlib.HeaderedEvent `json:"events"`
123}
124
125// QueryMembershipForUserRequest is a request to QueryMembership
126type QueryMembershipForUserRequest struct {
127	// ID of the room to fetch membership from
128	RoomID string `json:"room_id"`
129	// ID of the user for whom membership is requested
130	UserID string `json:"user_id"`
131}
132
133// QueryMembershipForUserResponse is a response to QueryMembership
134type QueryMembershipForUserResponse struct {
135	// The EventID of the latest "m.room.member" event for the sender,
136	// if HasBeenInRoom is true.
137	EventID string `json:"event_id"`
138	// True if the user has been in room before and has either stayed in it or left it.
139	HasBeenInRoom bool `json:"has_been_in_room"`
140	// True if the user is in room.
141	IsInRoom bool `json:"is_in_room"`
142	// The current membership
143	Membership string `json:"membership"`
144	// True if the user asked to forget this room.
145	IsRoomForgotten bool `json:"is_room_forgotten"`
146}
147
148// QueryMembershipsForRoomRequest is a request to QueryMembershipsForRoom
149type QueryMembershipsForRoomRequest struct {
150	// If true, only returns the membership events of "join" membership
151	JoinedOnly bool `json:"joined_only"`
152	// ID of the room to fetch memberships from
153	RoomID string `json:"room_id"`
154	// Optional - ID of the user sending the request, for checking if the
155	// user is allowed to see the memberships. If not specified then all
156	// room memberships will be returned.
157	Sender string `json:"sender"`
158}
159
160// QueryMembershipsForRoomResponse is a response to QueryMembershipsForRoom
161type QueryMembershipsForRoomResponse struct {
162	// The "m.room.member" events (of "join" membership) in the client format
163	JoinEvents []gomatrixserverlib.ClientEvent `json:"join_events"`
164	// True if the user has been in room before and has either stayed in it or
165	// left it.
166	HasBeenInRoom bool `json:"has_been_in_room"`
167	// True if the user asked to forget this room.
168	IsRoomForgotten bool `json:"is_room_forgotten"`
169}
170
171// QueryServerJoinedToRoomRequest is a request to QueryServerJoinedToRoom
172type QueryServerJoinedToRoomRequest struct {
173	// Server name of the server to find. If not specified, we will
174	// default to checking if the local server is joined.
175	ServerName gomatrixserverlib.ServerName `json:"server_name"`
176	// ID of the room to see if we are still joined to
177	RoomID string `json:"room_id"`
178}
179
180// QueryMembershipsForRoomResponse is a response to QueryServerJoinedToRoom
181type QueryServerJoinedToRoomResponse struct {
182	// True if the room exists on the server
183	RoomExists bool `json:"room_exists"`
184	// True if we still believe that the server is participating in the room
185	IsInRoom bool `json:"is_in_room"`
186}
187
188// QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent
189type QueryServerAllowedToSeeEventRequest struct {
190	// The event ID to look up invites in.
191	EventID string `json:"event_id"`
192	// The server interested in the event
193	ServerName gomatrixserverlib.ServerName `json:"server_name"`
194}
195
196// QueryServerAllowedToSeeEventResponse is a response to QueryServerAllowedToSeeEvent
197type QueryServerAllowedToSeeEventResponse struct {
198	// Wether the server in question is allowed to see the event
199	AllowedToSeeEvent bool `json:"can_see_event"`
200}
201
202// QueryMissingEventsRequest is a request to QueryMissingEvents
203type QueryMissingEventsRequest struct {
204	// Events which are known previous to the gap in the timeline.
205	EarliestEvents []string `json:"earliest_events"`
206	// Latest known events.
207	LatestEvents []string `json:"latest_events"`
208	// Limit the number of events this query returns.
209	Limit int `json:"limit"`
210	// The server interested in the event
211	ServerName gomatrixserverlib.ServerName `json:"server_name"`
212}
213
214// QueryMissingEventsResponse is a response to QueryMissingEvents
215type QueryMissingEventsResponse struct {
216	// Missing events, arbritrary order.
217	Events []*gomatrixserverlib.HeaderedEvent `json:"events"`
218}
219
220// QueryStateAndAuthChainRequest is a request to QueryStateAndAuthChain
221type QueryStateAndAuthChainRequest struct {
222	// The room ID to query the state in.
223	RoomID string `json:"room_id"`
224	// The list of prev events for the event. Used to calculate the state at
225	// the event.
226	PrevEventIDs []string `json:"prev_event_ids"`
227	// The list of auth events for the event. Used to calculate the auth chain
228	AuthEventIDs []string `json:"auth_event_ids"`
229	// Should state resolution be ran on the result events?
230	// TODO: check call sites and remove if we always want to do state res
231	ResolveState bool `json:"resolve_state"`
232}
233
234// QueryStateAndAuthChainResponse is a response to QueryStateAndAuthChain
235type QueryStateAndAuthChainResponse struct {
236	// Does the room exist on this roomserver?
237	// If the room doesn't exist this will be false and StateEvents will be empty.
238	RoomExists bool `json:"room_exists"`
239	// The room version of the room.
240	RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
241	// Do all the previous events exist on this roomserver?
242	// If some of previous events do not exist this will be false and StateEvents will be empty.
243	PrevEventsExist bool `json:"prev_events_exist"`
244	// The state and auth chain events that were requested.
245	// The lists will be in an arbitrary order.
246	StateEvents     []*gomatrixserverlib.HeaderedEvent `json:"state_events"`
247	AuthChainEvents []*gomatrixserverlib.HeaderedEvent `json:"auth_chain_events"`
248}
249
250// QueryRoomVersionCapabilitiesRequest asks for the default room version
251type QueryRoomVersionCapabilitiesRequest struct{}
252
253// QueryRoomVersionCapabilitiesResponse is a response to QueryRoomVersionCapabilitiesRequest
254type QueryRoomVersionCapabilitiesResponse struct {
255	DefaultRoomVersion    gomatrixserverlib.RoomVersion            `json:"default"`
256	AvailableRoomVersions map[gomatrixserverlib.RoomVersion]string `json:"available"`
257}
258
259// QueryRoomVersionForRoomRequest asks for the room version for a given room.
260type QueryRoomVersionForRoomRequest struct {
261	RoomID string `json:"room_id"`
262}
263
264// QueryRoomVersionForRoomResponse is a response to QueryRoomVersionForRoomRequest
265type QueryRoomVersionForRoomResponse struct {
266	RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
267}
268
269type QueryPublishedRoomsRequest struct {
270	// Optional. If specified, returns whether this room is published or not.
271	RoomID string
272}
273
274type QueryPublishedRoomsResponse struct {
275	// The list of published rooms.
276	RoomIDs []string
277}
278
279type QueryAuthChainRequest struct {
280	EventIDs []string
281}
282
283type QueryAuthChainResponse struct {
284	AuthChain []*gomatrixserverlib.HeaderedEvent
285}
286
287type QuerySharedUsersRequest struct {
288	UserID         string
289	ExcludeRoomIDs []string
290	IncludeRoomIDs []string
291}
292
293type QuerySharedUsersResponse struct {
294	UserIDsToCount map[string]int
295}
296
297type QueryRoomsForUserRequest struct {
298	UserID string
299	// The desired membership of the user. If this is the empty string then no rooms are returned.
300	WantMembership string
301}
302
303type QueryRoomsForUserResponse struct {
304	RoomIDs []string
305}
306
307type QueryBulkStateContentRequest struct {
308	// Returns state events in these rooms
309	RoomIDs []string
310	// If true, treats the '*' StateKey as "all state events of this type" rather than a literal value of '*'
311	AllowWildcards bool
312	// The state events to return. Only a small subset of tuples are allowed in this request as only certain events
313	// have their content fields extracted. Specifically, the tuple Type must be one of:
314	//   m.room.avatar
315	//   m.room.create
316	//   m.room.canonical_alias
317	//   m.room.guest_access
318	//   m.room.history_visibility
319	//   m.room.join_rules
320	//   m.room.member
321	//   m.room.name
322	//   m.room.topic
323	// Any other tuple type will result in the query failing.
324	StateTuples []gomatrixserverlib.StateKeyTuple
325}
326type QueryBulkStateContentResponse struct {
327	// map of room ID -> tuple -> content_value
328	Rooms map[string]map[gomatrixserverlib.StateKeyTuple]string
329}
330
331type QueryCurrentStateRequest struct {
332	RoomID      string
333	StateTuples []gomatrixserverlib.StateKeyTuple
334}
335
336type QueryCurrentStateResponse struct {
337	StateEvents map[gomatrixserverlib.StateKeyTuple]*gomatrixserverlib.HeaderedEvent
338}
339
340type QueryKnownUsersRequest struct {
341	UserID       string `json:"user_id"`
342	SearchString string `json:"search_string"`
343	Limit        int    `json:"limit"`
344}
345
346type QueryKnownUsersResponse struct {
347	Users []authtypes.FullyQualifiedProfile `json:"profiles"`
348}
349
350type QueryServerBannedFromRoomRequest struct {
351	ServerName gomatrixserverlib.ServerName `json:"server_name"`
352	RoomID     string                       `json:"room_id"`
353}
354
355type QueryServerBannedFromRoomResponse struct {
356	Banned bool `json:"banned"`
357}
358
359// MarshalJSON stringifies the room ID and StateKeyTuple keys so they can be sent over the wire in HTTP API mode.
360func (r *QueryBulkStateContentResponse) MarshalJSON() ([]byte, error) {
361	se := make(map[string]string)
362	for roomID, tupleToEvent := range r.Rooms {
363		for tuple, event := range tupleToEvent {
364			// use 0x1F (unit separator) as the delimiter between room ID/type/state key,
365			se[fmt.Sprintf("%s\x1F%s\x1F%s", roomID, tuple.EventType, tuple.StateKey)] = event
366		}
367	}
368	return json.Marshal(se)
369}
370
371func (r *QueryBulkStateContentResponse) UnmarshalJSON(data []byte) error {
372	wireFormat := make(map[string]string)
373	err := json.Unmarshal(data, &wireFormat)
374	if err != nil {
375		return err
376	}
377	r.Rooms = make(map[string]map[gomatrixserverlib.StateKeyTuple]string)
378	for roomTuple, value := range wireFormat {
379		fields := strings.Split(roomTuple, "\x1F")
380		roomID := fields[0]
381		if r.Rooms[roomID] == nil {
382			r.Rooms[roomID] = make(map[gomatrixserverlib.StateKeyTuple]string)
383		}
384		r.Rooms[roomID][gomatrixserverlib.StateKeyTuple{
385			EventType: fields[1],
386			StateKey:  fields[2],
387		}] = value
388	}
389	return nil
390}
391
392// MarshalJSON stringifies the StateKeyTuple keys so they can be sent over the wire in HTTP API mode.
393func (r *QueryCurrentStateResponse) MarshalJSON() ([]byte, error) {
394	se := make(map[string]*gomatrixserverlib.HeaderedEvent, len(r.StateEvents))
395	for k, v := range r.StateEvents {
396		// use 0x1F (unit separator) as the delimiter between type/state key,
397		se[fmt.Sprintf("%s\x1F%s", k.EventType, k.StateKey)] = v
398	}
399	return json.Marshal(se)
400}
401
402func (r *QueryCurrentStateResponse) UnmarshalJSON(data []byte) error {
403	res := make(map[string]*gomatrixserverlib.HeaderedEvent)
404	err := json.Unmarshal(data, &res)
405	if err != nil {
406		return err
407	}
408	r.StateEvents = make(map[gomatrixserverlib.StateKeyTuple]*gomatrixserverlib.HeaderedEvent, len(res))
409	for k, v := range res {
410		fields := strings.Split(k, "\x1F")
411		r.StateEvents[gomatrixserverlib.StateKeyTuple{
412			EventType: fields[0],
413			StateKey:  fields[1],
414		}] = v
415	}
416	return nil
417}
418