-
Notifications
You must be signed in to change notification settings - Fork 0
/
endpoints.rs
541 lines (460 loc) · 18.6 KB
/
endpoints.rs
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
// MIT License
// Copyright (c) 2020 Florian Jacob
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Threepid {
pub medium: ruma::thirdparty::Medium,
pub address: String,
}
pub mod version {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "version endpoint",
method: GET,
name: "version",
path: "/_synapse/admin/v1/server_version",
rate_limited: false,
authentication: None,
}
request: {}
response: {
pub server_version: String,
pub python_version: String,
}
// TODO: What kind of error is needed here?
// This is probably not a general matrix status error with json body, however, some http
// error code is highly likely and a semantical result of “no valid identity server here”
}
impl Request {
pub fn new() -> Self {
Self { }
}
}
}
// TODO: isn't this covered by ruma's identity-service-api?
// -> not yet, as that crate is still empty, could send a PR. Is there a deprecation flag for the metadata?
// also: might send a PR to matrix-spec first to switch to the /_matrix/identity/v2 endpoint for identity service autodiscovery
// That MSC already exists: https://github.com/matrix-org/matrix-doc/pull/2499
pub mod identity_status {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "identity status endpoint",
method: GET,
name: "version",
path: "/_matrix/identity/api/v1",
rate_limited: false,
authentication: None,
}
request: {}
response: {}
// TODO: What kind of error is needed here?
// This is probably not a general matrix status error with json body, however, some http
// error code is highly likely and a semantical result of “no valid identity server here”
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst#list-accounts
pub mod list_accounts {
use ruma::api::ruma_api;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct UserDetails {
pub name: ruma::UserId,
// TODO: this isn't named as optional in the spec, but missing from the responses
pub password_hash: Option<String>,
// TODO: why not bool?
pub is_guest: js_int::UInt,
// TODO: why not bool?
pub admin: js_int::UInt,
// TODO: what is this field? It's null in the examples
pub user_type: Option<String>,
// TODO: why not bool?
pub deactivated: js_int::UInt,
pub displayname: Option<String>,
pub avatar_url: Option<String>,
}
ruma_api! {
metadata: {
description: "list accounts endpoint",
method: GET,
name: "list_accounts",
path: "/_synapse/admin/v2/users",
rate_limited: false,
authentication: AccessToken,
}
#[derive(Default)]
request: {
/// TODO: this should be treated as opaque, i.e. a newtype, so that only values returned from responses can be used here
/// Offset in the returned list. Defaults to 0.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub from: Option<js_int::UInt>,
/// Maximum amount of users to return. Defaults to 100.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub limit: Option<js_int::UInt>,
/// user_id is optional and filters to only return users with user IDs that contain this value. This parameter is ignored when using the name parameter.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub user_id: Option<String>,
/// name is optional and filters to only return users with user ID localparts or displaynames that contain this value.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub name: Option<String>,
/// The parameter guests is optional and if false will exclude guest users. Defaults to true to include guest users.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub guests: Option<bool>,
/// The parameter deactivated is optional and if true will include deactivated users. Defaults to false to exclude deactivated users.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub deactivated: Option<bool>,
}
response: {
pub users: Vec<UserDetails>,
/// To paginate, check for next_token and if present, call the endpoint again with from set to the value of next_token. This will return a new page.
/// If the endpoint does not return a next_token then there are no more users to paginate through.
pub next_token: Option<String>,
pub total: js_int::UInt,
}
error: ruma::api::client::Error
}
impl Request {
pub fn new() -> Self {
Default::default()
}
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/rooms.md#list-room-api
pub mod list_rooms {
use ruma::api::ruma_api;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RoomDetails {
pub room_id: ruma::RoomId,
pub name: Option<String>,
pub canonical_alias: Option<ruma::RoomAliasId>,
pub joined_members: js_int::UInt,
pub joined_local_members: js_int::UInt,
pub version: String,
#[serde(deserialize_with = "ruma::serde::empty_string_as_none")]
pub creator: Option<ruma::UserId>,
pub encryption: Option<String>,
pub federatable: bool,
pub public: bool,
// TODO: make enum
pub join_rules: Option<String>,
// TODO: make enum
pub guest_access: Option<String>,
// TODO: make enum
pub history_visibility: Option<String>,
pub state_events: js_int::UInt,
}
ruma_api! {
metadata: {
description: "list rooms endpoint",
method: GET,
name: "list_rooms",
path: "/_synapse/admin/v1/rooms",
rate_limited: false,
authentication: AccessToken,
}
#[derive(Default)]
request: {
/// Offset in the returned list. Defaults to 0.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub from: Option<js_int::UInt>,
/// Maximum amount of rooms to return. Defaults to 100.
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub limit: Option<js_int::UInt>,
// TODO: enum
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub order_by: Option<String>,
// TODO: enum
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub dir: Option<String>,
/// Filter rooms by their room name. Search term can be contained in any part of the room name. Defaults to no filtering.
// TODO: enum
#[serde(skip_serializing_if="Option::is_none")]
#[ruma_api(query)]
pub search_term: Option<String>,
}
response: {
pub rooms: Vec<RoomDetails>,
pub offset: js_int::UInt,
pub total_rooms: js_int::UInt,
pub next_batch: Option<js_int::UInt>,
pub prev_batch: Option<js_int::UInt>,
}
error: ruma::api::client::Error
}
impl Request {
pub fn new() -> Self {
Default::default()
}
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst#query-user-account
pub mod query_user {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "query user endpoint",
method: GET,
name: "query_user",
path: "/_synapse/admin/v2/users/:user_id",
rate_limited: false,
authentication: AccessToken,
}
request: {
#[ruma_api(path)]
pub user_id: ruma::UserId,
}
response: {
pub displayname: Option<String>,
pub threepids: Option<Vec<super::Threepid>>,
pub avatar_url: Option<String>,
// TODO: this is returned as int, while the doc shows a bool
// I could convert, or investigate further whether there are other values, or fix it upstream
pub admin: js_int::UInt,
// TODO: this is returned as int, while the doc shows a bool
// I could convert, or investigate further whether there are other values, or fix it upstream
pub deactivated: js_int::UInt,
}
error: ruma::api::client::Error
}
impl Request {
pub fn new(user_id: ruma::UserId) -> Self {
Self { user_id }
}
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst#list-room-memberships-of-an-user
pub mod list_joined_rooms {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "list room memberships of a user",
method: GET,
name: "query_user",
path: "/_synapse/admin/v1/users/:user_id/joined_rooms",
rate_limited: false,
authentication: AccessToken,
}
request: {
#[ruma_api(path)]
pub user_id: ruma::UserId,
}
response: {
pub joined_rooms: Vec<ruma::RoomId>,
/// number of rooms
pub total: js_int::UInt,
}
error: ruma::api::client::Error
}
impl Request {
pub fn new(user_id: ruma::UserId) -> Self {
Self { user_id }
}
}
}
// TODO: This endpoint is deprecated:
// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/purge_room.md
pub mod purge_room {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "purge room endpoint",
method: POST,
name: "purge_room",
path: "/_synapse/admin/v1/purge_room",
rate_limited: false,
authentication: AccessToken,
}
request: {
pub room_id: ruma::RoomId,
}
response: {}
error: ruma::api::client::Error
}
impl Request {
pub fn new(room_id: ruma::RoomId) -> Self {
Self { room_id }
}
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst#create-or-modify-account
pub mod create_modify_account {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "create or modify account endpoint",
method: PUT,
name: "create_modify_account",
path: "/_synapse/admin/v2/users/:user_id",
rate_limited: false,
authentication: AccessToken,
}
request: {
#[ruma_api(path)]
pub user_id: ruma::UserId,
// TODO: password should also be optional for modify user account,
// but that's not written in the docs. Don't care for now, I mainly want to create users.
// -> it is, and especially when changing passwords, it has the "all device logout" semantics
pub password: String,
// NOTE: Server explodes if attributes are not omitted but specified as null, like the default
// Serde case.
// defaults to user_id, or the current value if user already exists
// Some("") is treated as setting it to null.
#[serde(skip_serializing_if="Option::is_none")]
pub displayname: Option<String>,
// defaults to empty, or the current value if user already exists
#[serde(skip_serializing_if="Option::is_none")]
pub threepids: Option<Vec<super::Threepid>>,
#[serde(skip_serializing_if="Option::is_none")]
pub avatar_url: Option<String>,
// defaults to false, or the current value if user already exists
#[serde(skip_serializing_if="Option::is_none")]
pub admin: Option<bool>,
// defaults to false, or the current value if user already exists
#[serde(skip_serializing_if="Option::is_none")]
pub deactivated: Option<bool>,
}
// TODO: this response reverse-engineered and not documented, should all of those be required?
// Alternative: https://serde.rs/attr-flatten.html
response: {
pub name: ruma::UserId,
pub password_hash: String,
// TODO: this is not returned as bool…?
pub is_guest: js_int::UInt,
// TODO: this is not returned as bool…?
pub admin: js_int::UInt,
// TODO: not sure if this should be Option<js::UInt>
// this is present but can be null, therefore optional
pub consent_version: Option<String>,
// TODO: not sure if this should be Option<js::UInt> or whatever
// this is present but can be null, therefore optional
pub consent_server_notice_sent: Option<String>,
// TODO: not sure if this should be Option<js::UInt>
// this is present but can be null, therefore optional
pub appservice_id: Option<String>,
pub creation_ts: js_int::UInt,
// this is present but can be null, therefore optional
pub user_type: Option<String>,
// TODO: this is not returned as bool…?
pub deactivated: js_int::UInt,
pub displayname: Option<String>,
// this is present but can be null, therefore optional
pub avatar_url: Option<String>,
pub threepids: Option<Vec<super::Threepid>>,
// TODO: das hier sind Extrafelder bei der Threepid nebendran
// pub validated_at: js_int::UInt,
// pub added_at: js_int::UInt,
}
error: ruma::api::client::Error
// TODO: returns 200 if account-exist-and-was-updated,
// but 201 CREATED if a new account was created.
// However, ruma does throw away this information.
// TODO: Was genau hat es mit den EndpointErrors auf sich?
// -> Ich kann da custom code mitgeben, der die Conversion von http::Response in einen in ruma
// error eingepackten Fehlertyp baut
// Ich brauch den error allein schon deswegen mindestens bei allen authentifizierten
// Requests, weil ein ungültiger Login eben solch ein Error im Matrix-Standardformat ist.
// TODO: Müsste ich hier wo auch nen tatsächlichen Error eintragen wie ruma client api
// error, oder reicht hier überall der Void-Default?
// TODO: ruma api serialisiert als Ok wenn status code < 400, sonst als error. Das halte ich
// für nicht unfragwürdig, da auch den 300-Umleitungsblock mitzunehmen und zwischen z.B. 200 Ok
// und 201 Created nicht zu unterscheiden.
}
impl Request {
pub fn new(user_id: ruma::UserId, password: String) -> Self {
Self {
user_id,
password,
displayname: None,
threepids: None,
avatar_url: None,
admin: None,
deactivated: None,
}
}
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst#reset-password
pub mod reset_password {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "password reset endpoint",
method: POST,
name: "reset_password",
path: "/_synapse/admin/v1/reset_password/:user_id",
rate_limited: false,
authentication: AccessToken,
}
request: {
#[ruma_api(path)]
pub user_id: ruma::UserId,
pub new_password: String,
// whether to invalidate all access tokens, i.e. whether the password was just forgotten
// or whether the password got compromised potentially.
// defaults to true if not set
#[serde(skip_serializing_if="Option::is_none")]
pub logout_devices: Option<bool>,
}
response: {}
error: ruma::api::client::Error
}
impl Request {
pub fn new(user_id: ruma::UserId, new_password: String, logout_devices: Option<bool>) -> Self {
Self { user_id, new_password, logout_devices }
}
}
}
/// https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst
pub mod user_is_admin {
use ruma::api::ruma_api;
ruma_api! {
metadata: {
description: "is admin endpoint",
method: GET,
name: "user_is_admin",
path: "/_synapse/admin/v1/users/:user_id/admin",
rate_limited: false,
authentication: AccessToken,
}
request: {
#[ruma_api(path)]
pub user_id: ruma::UserId,
}
response: {
pub admin: bool,
}
error: ruma::api::client::Error
}
impl Request {
pub fn new(user_id: ruma::UserId) -> Self {
Self { user_id }
}
}
}