aboutsummaryrefslogtreecommitdiff
path: root/roomserver/api/perform.go
blob: 51cbcb1add399d701c85db22931d057a09794e70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package api

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/matrix-org/dendrite/clientapi/jsonerror"
	"github.com/matrix-org/gomatrixserverlib"
	"github.com/matrix-org/util"
)

type PerformErrorCode int

type PerformError struct {
	Msg        string
	RemoteCode int // remote HTTP status code, for PerformErrRemote
	Code       PerformErrorCode
}

func (p *PerformError) Error() string {
	return fmt.Sprintf("%d : %s", p.Code, p.Msg)
}

// JSONResponse maps error codes to suitable HTTP error codes, defaulting to 500.
func (p *PerformError) JSONResponse() util.JSONResponse {
	switch p.Code {
	case PerformErrorBadRequest:
		return util.JSONResponse{
			Code: http.StatusBadRequest,
			JSON: jsonerror.Unknown(p.Msg),
		}
	case PerformErrorNoRoom:
		return util.JSONResponse{
			Code: http.StatusNotFound,
			JSON: jsonerror.NotFound(p.Msg),
		}
	case PerformErrorNotAllowed:
		return util.JSONResponse{
			Code: http.StatusForbidden,
			JSON: jsonerror.Forbidden(p.Msg),
		}
	case PerformErrorNoOperation:
		return util.JSONResponse{
			Code: http.StatusForbidden,
			JSON: jsonerror.Forbidden(p.Msg),
		}
	case PerformErrRemote:
		// if the code is 0 then something bad happened and it isn't
		// a remote HTTP error being encapsulated, e.g network error to remote.
		if p.RemoteCode == 0 {
			return util.ErrorResponse(fmt.Errorf("%s", p.Msg))
		}
		return util.JSONResponse{
			Code: p.RemoteCode,
			// TODO: Should we assert this is in fact JSON? E.g gjson parse?
			JSON: json.RawMessage(p.Msg),
		}
	default:
		return util.ErrorResponse(p)
	}
}

const (
	// PerformErrorNotAllowed means the user is not allowed to invite/join/etc this room (e.g join_rule:invite or banned)
	PerformErrorNotAllowed PerformErrorCode = 1
	// PerformErrorBadRequest means the request was wrong in some way (invalid user ID, wrong server, etc)
	PerformErrorBadRequest PerformErrorCode = 2
	// PerformErrorNoRoom means that the room being joined doesn't exist.
	PerformErrorNoRoom PerformErrorCode = 3
	// PerformErrorNoOperation means that the request resulted in nothing happening e.g invite->invite or leave->leave.
	PerformErrorNoOperation PerformErrorCode = 4
	// PerformErrRemote means that the request failed and the PerformError.Msg is the raw remote JSON error response
	PerformErrRemote PerformErrorCode = 5
)

type PerformJoinRequest struct {
	RoomIDOrAlias string                         `json:"room_id_or_alias"`
	UserID        string                         `json:"user_id"`
	Content       map[string]interface{}         `json:"content"`
	ServerNames   []gomatrixserverlib.ServerName `json:"server_names"`
}

type PerformJoinResponse struct {
	// The room ID, populated on success.
	RoomID    string `json:"room_id"`
	JoinedVia gomatrixserverlib.ServerName
	// If non-nil, the join request failed. Contains more information why it failed.
	Error *PerformError
}

type PerformLeaveRequest struct {
	RoomID string `json:"room_id"`
	UserID string `json:"user_id"`
}

type PerformLeaveResponse struct {
}

type PerformInviteRequest struct {
	RoomVersion     gomatrixserverlib.RoomVersion             `json:"room_version"`
	Event           *gomatrixserverlib.HeaderedEvent          `json:"event"`
	InviteRoomState []gomatrixserverlib.InviteV2StrippedState `json:"invite_room_state"`
	SendAsServer    string                                    `json:"send_as_server"`
	TransactionID   *TransactionID                            `json:"transaction_id"`
}

type PerformInviteResponse struct {
	Error *PerformError
}

type PerformPeekRequest struct {
	RoomIDOrAlias string                         `json:"room_id_or_alias"`
	UserID        string                         `json:"user_id"`
	DeviceID      string                         `json:"device_id"`
	ServerNames   []gomatrixserverlib.ServerName `json:"server_names"`
}

type PerformPeekResponse struct {
	// The room ID, populated on success.
	RoomID string `json:"room_id"`
	// If non-nil, the join request failed. Contains more information why it failed.
	Error *PerformError
}

type PerformUnpeekRequest struct {
	RoomID   string `json:"room_id"`
	UserID   string `json:"user_id"`
	DeviceID string `json:"device_id"`
}

type PerformUnpeekResponse struct {
	// If non-nil, the join request failed. Contains more information why it failed.
	Error *PerformError
}

// PerformBackfillRequest is a request to PerformBackfill.
type PerformBackfillRequest struct {
	// The room to backfill
	RoomID string `json:"room_id"`
	// A map of backwards extremity event ID to a list of its prev_event IDs.
	BackwardsExtremities map[string][]string `json:"backwards_extremities"`
	// The maximum number of events to retrieve.
	Limit int `json:"limit"`
	// The server interested in the events.
	ServerName gomatrixserverlib.ServerName `json:"server_name"`
}

// PrevEventIDs returns the prev_event IDs of all backwards extremities, de-duplicated in a lexicographically sorted order.
func (r *PerformBackfillRequest) PrevEventIDs() []string {
	var prevEventIDs []string
	for _, pes := range r.BackwardsExtremities {
		prevEventIDs = append(prevEventIDs, pes...)
	}
	prevEventIDs = util.UniqueStrings(prevEventIDs)
	return prevEventIDs
}

// PerformBackfillResponse is a response to PerformBackfill.
type PerformBackfillResponse struct {
	// Missing events, arbritrary order.
	Events []*gomatrixserverlib.HeaderedEvent `json:"events"`
}

type PerformPublishRequest struct {
	RoomID     string
	Visibility string
}

type PerformPublishResponse struct {
	// If non-nil, the publish request failed. Contains more information why it failed.
	Error *PerformError
}

type PerformInboundPeekRequest struct {
	UserID          string                       `json:"user_id"`
	RoomID          string                       `json:"room_id"`
	PeekID          string                       `json:"peek_id"`
	ServerName      gomatrixserverlib.ServerName `json:"server_name"`
	RenewalInterval int64                        `json:"renewal_interval"`
}

type PerformInboundPeekResponse struct {
	// Does the room exist on this roomserver?
	// If the room doesn't exist this will be false and StateEvents will be empty.
	RoomExists bool `json:"room_exists"`
	// The room version of the room.
	RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
	// The current state and auth chain events.
	// The lists will be in an arbitrary order.
	StateEvents     []*gomatrixserverlib.HeaderedEvent `json:"state_events"`
	AuthChainEvents []*gomatrixserverlib.HeaderedEvent `json:"auth_chain_events"`
	// The event at which this state was captured
	LatestEvent *gomatrixserverlib.HeaderedEvent `json:"latest_event"`
}

// PerformForgetRequest is a request to PerformForget
type PerformForgetRequest struct {
	RoomID string `json:"room_id"`
	UserID string `json:"user_id"`
}

type PerformForgetResponse struct{}