matrix-nodejs-homeserver 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -7
- package/dist/api/account.js +385 -351
- package/dist/api/admin.js +76 -60
- package/dist/api/appservice.js +37 -25
- package/dist/api/backup.js +73 -62
- package/dist/api/federation.js +172 -138
- package/dist/api/filters.js +4 -3
- package/dist/api/legacy.js +91 -78
- package/dist/api/media.js +70 -54
- package/dist/api/misc.js +46 -37
- package/dist/api/preview.js +4 -3
- package/dist/api/profile.js +108 -97
- package/dist/api/push.js +114 -99
- package/dist/api/relationships.js +64 -58
- package/dist/api/rooms.js +703 -580
- package/dist/api/rtc.d.ts +0 -1
- package/dist/api/rtc.js +48 -34
- package/dist/api/search.js +133 -127
- package/dist/api/slidingsync.js +41 -31
- package/dist/api/spaces.js +82 -77
- package/dist/api/sync.js +59 -50
- package/dist/api/threadsubs.js +72 -61
- package/dist/api/threepid.js +99 -66
- package/dist/api/uia.js +17 -16
- package/dist/api/user.js +221 -178
- package/dist/core/admin.d.ts +0 -1
- package/dist/core/admin.js +6 -5
- package/dist/core/adminroom.js +9 -8
- package/dist/core/appservices.d.ts +2 -1
- package/dist/core/appservices.js +5 -4
- package/dist/core/audit.d.ts +0 -1
- package/dist/core/authrules.js +26 -25
- package/dist/core/delayed.js +2 -1
- package/dist/core/events.js +11 -10
- package/dist/core/invitefilter.js +2 -1
- package/dist/core/keys.js +2 -1
- package/dist/core/m.d.ts +209 -0
- package/dist/core/m.js +182 -0
- package/dist/core/partialstate.js +2 -1
- package/dist/core/policy.js +4 -3
- package/dist/core/push.d.ts +0 -1
- package/dist/core/push.js +12 -11
- package/dist/core/pushrules.js +36 -35
- package/dist/core/rooms.js +76 -74
- package/dist/core/stateres.js +7 -6
- package/dist/federation/client.js +2 -1
- package/dist/federation/index.d.ts +1 -1
- package/dist/federation/index.js +30 -29
- package/dist/homeserver.d.ts +2 -1
- package/dist/homeserver.js +1 -0
- package/dist/http/handler.js +2 -23
- package/dist/http/input.js +2 -2
- package/dist/http/procedure.js +25 -0
- package/dist/http/router.d.ts +9 -26
- package/dist/http/router.js +10 -30
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/vendor/zod/LICENSE +21 -0
- package/dist/vendor/zod/v4/classic/errors.js +54 -0
- package/dist/vendor/zod/v4/classic/parse.js +17 -0
- package/dist/vendor/zod/v4/classic/schemas.js +865 -0
- package/dist/vendor/zod/v4/core/api.js +512 -0
- package/dist/vendor/zod/v4/core/checks.js +300 -0
- package/dist/vendor/zod/v4/core/core.js +109 -0
- package/dist/vendor/zod/v4/core/doc.js +35 -0
- package/dist/vendor/zod/v4/core/errors.js +118 -0
- package/dist/vendor/zod/v4/core/json-schema-processors.js +428 -0
- package/dist/vendor/zod/v4/core/memoizer.js +255 -0
- package/dist/vendor/zod/v4/core/parse.js +206 -0
- package/dist/vendor/zod/v4/core/regexes.js +73 -0
- package/dist/vendor/zod/v4/core/registries.js +48 -0
- package/dist/vendor/zod/v4/core/schemas.js +1378 -0
- package/dist/vendor/zod/v4/core/to-json-schema.js +448 -0
- package/dist/vendor/zod/v4/core/util.js +537 -0
- package/dist/vendor/zod/v4/core/versions.js +8 -0
- package/dist/vendor/zod/v4/locales/en.js +110 -0
- package/package.json +3 -5
- package/dist/core/pushrules.d.ts +0 -1
package/dist/api/admin.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { errors } from "../core/errors.js";
|
|
2
|
+
import { boolean, looseObject, number, string } from "../vendor/zod/v4/classic/schemas.js";
|
|
2
3
|
import { body, fail, lenient } from "../http/input.js";
|
|
3
|
-
import {
|
|
4
|
+
import { procedure } from "../http/procedure.js";
|
|
4
5
|
//#region src/api/admin.ts
|
|
5
6
|
const required = fail("M_BAD_JSON", "user_id and content are required");
|
|
6
7
|
const noticeBody = body({
|
|
7
|
-
user_id:
|
|
8
|
-
content:
|
|
9
|
-
type: lenient(
|
|
8
|
+
user_id: string(required),
|
|
9
|
+
content: looseObject({}, required),
|
|
10
|
+
type: lenient(string())
|
|
10
11
|
});
|
|
11
|
-
const optionalInt = (name) =>
|
|
12
|
+
const optionalInt = (name) => number(fail("M_INVALID_PARAM", `${name} must be an integer`)).int(`M_INVALID_PARAM: ${name} must be an integer`);
|
|
12
13
|
const registrationTokenBody = body({
|
|
13
|
-
token:
|
|
14
|
+
token: string(fail("M_INVALID_PARAM", "Invalid token")).optional(),
|
|
14
15
|
uses_allowed: optionalInt("uses_allowed").nullable().optional(),
|
|
15
16
|
expiry_time: optionalInt("expiry_time").nullable().optional(),
|
|
16
17
|
length: optionalInt("length").optional()
|
|
@@ -65,13 +66,19 @@ function registerAdminRoutes(r) {
|
|
|
65
66
|
};
|
|
66
67
|
};
|
|
67
68
|
const lock = moderation("locked"), suspend = moderation("suspended");
|
|
68
|
-
r.get("/_matrix/client/v1/admin/lock/:userId", lock.get);
|
|
69
|
-
r.put("/_matrix/client/v1/admin/lock/:userId", lock.put);
|
|
70
|
-
r.get("/_matrix/client/v1/admin/suspend/:userId", suspend.get);
|
|
71
|
-
r.put("/_matrix/client/v1/admin/suspend/:userId", suspend.put);
|
|
72
|
-
r.post("/_synapse/admin/v1/send_server_notice", {
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
r.get("/_matrix/client/v1/admin/lock/:userId", procedure({ handler: lock.get }));
|
|
70
|
+
r.put("/_matrix/client/v1/admin/lock/:userId", procedure({ handler: lock.put }));
|
|
71
|
+
r.get("/_matrix/client/v1/admin/suspend/:userId", procedure({ handler: suspend.get }));
|
|
72
|
+
r.put("/_matrix/client/v1/admin/suspend/:userId", procedure({ handler: suspend.put }));
|
|
73
|
+
r.post("/_synapse/admin/v1/send_server_notice", procedure({
|
|
74
|
+
input: noticeBody,
|
|
75
|
+
handler: notice
|
|
76
|
+
}));
|
|
77
|
+
r.put("/_synapse/admin/v1/send_server_notice/:txnId", procedure({
|
|
78
|
+
input: noticeBody,
|
|
79
|
+
handler: notice
|
|
80
|
+
}));
|
|
81
|
+
r.get("/_synapse/admin/v2/users", procedure({ handler: async (ctx) => {
|
|
75
82
|
await requireAdmin(ctx);
|
|
76
83
|
const from = Number(ctx.query.get("from") ?? 0) || 0;
|
|
77
84
|
const res = await ctx.hs.admin.listUsers({
|
|
@@ -85,14 +92,14 @@ function registerAdminRoutes(r) {
|
|
|
85
92
|
total: res.total,
|
|
86
93
|
...res.next !== null ? { next_token: String(res.next) } : {}
|
|
87
94
|
};
|
|
88
|
-
});
|
|
89
|
-
r.get("/_synapse/admin/v2/users/:userId", async (ctx) => {
|
|
95
|
+
} }));
|
|
96
|
+
r.get("/_synapse/admin/v2/users/:userId", procedure({ handler: async (ctx) => {
|
|
90
97
|
await requireAdmin(ctx);
|
|
91
98
|
const user = await ctx.hs.admin.getUser(ctx.params.userId);
|
|
92
99
|
if (!user) throw errors.notFound("Unknown user");
|
|
93
100
|
return user;
|
|
94
|
-
});
|
|
95
|
-
r.put("/_synapse/admin/v2/users/:userId", async (ctx) => {
|
|
101
|
+
} }));
|
|
102
|
+
r.put("/_synapse/admin/v2/users/:userId", procedure({ handler: async (ctx) => {
|
|
96
103
|
await requireAdmin(ctx);
|
|
97
104
|
const body = await ctx.json();
|
|
98
105
|
const userId = ctx.params.userId;
|
|
@@ -119,43 +126,52 @@ function registerAdminRoutes(r) {
|
|
|
119
126
|
}
|
|
120
127
|
if (body.deactivated === true) await ctx.hs.admin.deactivateUser(userId);
|
|
121
128
|
return ctx.hs.admin.getUser(userId);
|
|
122
|
-
});
|
|
123
|
-
r.post("/_synapse/admin/v1/deactivate/:userId",
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
} }));
|
|
130
|
+
r.post("/_synapse/admin/v1/deactivate/:userId", procedure({
|
|
131
|
+
input: body({ erase: lenient(boolean()) }),
|
|
132
|
+
handler: async (ctx) => {
|
|
133
|
+
await requireAdmin(ctx);
|
|
134
|
+
const body = ctx.input;
|
|
135
|
+
await ctx.hs.admin.deactivateUser(ctx.params.userId, { erase: body.erase === true });
|
|
136
|
+
return { id_server_unbind_result: "no-support" };
|
|
137
|
+
}
|
|
138
|
+
}));
|
|
129
139
|
const resetPasswordBody = body({
|
|
130
|
-
new_password:
|
|
131
|
-
logout_devices: lenient(
|
|
140
|
+
new_password: string(fail("M_MISSING_PARAM", "Missing new_password")),
|
|
141
|
+
logout_devices: lenient(boolean())
|
|
132
142
|
});
|
|
133
|
-
r.post("/_synapse/admin/v1/reset_password/:userId",
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
r.post("/_synapse/admin/v1/reset_password/:userId", procedure({
|
|
144
|
+
input: resetPasswordBody,
|
|
145
|
+
handler: async (ctx) => {
|
|
146
|
+
await requireAdmin(ctx);
|
|
147
|
+
const body = ctx.input;
|
|
148
|
+
await ctx.hs.admin.resetPassword(ctx.params.userId, body.new_password, body.logout_devices !== false);
|
|
149
|
+
return {};
|
|
150
|
+
}
|
|
151
|
+
}));
|
|
152
|
+
r.get("/_synapse/admin/v1/registration_tokens", procedure({ handler: async (ctx) => {
|
|
140
153
|
await requireAdmin(ctx);
|
|
141
154
|
return { registration_tokens: await ctx.hs.admin.listRegistrationTokens() };
|
|
142
|
-
});
|
|
143
|
-
r.post("/_synapse/admin/v1/registration_tokens/new",
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
155
|
+
} }));
|
|
156
|
+
r.post("/_synapse/admin/v1/registration_tokens/new", procedure({
|
|
157
|
+
input: registrationTokenBody,
|
|
158
|
+
handler: async (ctx) => {
|
|
159
|
+
await requireAdmin(ctx);
|
|
160
|
+
const body = ctx.input;
|
|
161
|
+
return ctx.hs.admin.createRegistrationToken({
|
|
162
|
+
token: body.token,
|
|
163
|
+
usesAllowed: body.uses_allowed,
|
|
164
|
+
expiryTime: body.expiry_time,
|
|
165
|
+
length: body.length
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}));
|
|
169
|
+
r.delete("/_synapse/admin/v1/registration_tokens/:token", procedure({ handler: async (ctx) => {
|
|
154
170
|
await requireAdmin(ctx);
|
|
155
171
|
await ctx.hs.admin.deleteRegistrationToken(ctx.params.token);
|
|
156
172
|
return {};
|
|
157
|
-
});
|
|
158
|
-
r.get("/_synapse/admin/v1/audit_log", async (ctx) => {
|
|
173
|
+
} }));
|
|
174
|
+
r.get("/_synapse/admin/v1/audit_log", procedure({ handler: async (ctx) => {
|
|
159
175
|
await requireAdmin(ctx);
|
|
160
176
|
if (!ctx.hs.audit.enabled) throw errors.unrecognized("The audit log is disabled");
|
|
161
177
|
const rows = await ctx.hs.audit.query({
|
|
@@ -169,8 +185,8 @@ function registerAdminRoutes(r) {
|
|
|
169
185
|
const out = { entries: rows };
|
|
170
186
|
if (rows.length) out.next_token = String(rows[rows.length - 1].id);
|
|
171
187
|
return out;
|
|
172
|
-
});
|
|
173
|
-
r.get("/_synapse/admin/v1/event_reports", async (ctx) => {
|
|
188
|
+
} }));
|
|
189
|
+
r.get("/_synapse/admin/v1/event_reports", procedure({ handler: async (ctx) => {
|
|
174
190
|
await requireAdmin(ctx);
|
|
175
191
|
const rows = await ctx.hs.db.findMany("event_reports", {
|
|
176
192
|
sortBy: {
|
|
@@ -192,16 +208,16 @@ function registerAdminRoutes(r) {
|
|
|
192
208
|
})),
|
|
193
209
|
total: rows.length
|
|
194
210
|
};
|
|
195
|
-
});
|
|
196
|
-
r.post("/_synapse/admin/v1/event_reports/:id/resolve", async (ctx) => {
|
|
211
|
+
} }));
|
|
212
|
+
r.post("/_synapse/admin/v1/event_reports/:id/resolve", procedure({ handler: async (ctx) => {
|
|
197
213
|
await requireAdmin(ctx);
|
|
198
214
|
if (!await ctx.hs.db.update("event_reports", [{
|
|
199
215
|
field: "id",
|
|
200
216
|
value: Number(ctx.params.id)
|
|
201
217
|
}], { resolved: true })) throw errors.notFound("Unknown report");
|
|
202
218
|
return {};
|
|
203
|
-
});
|
|
204
|
-
r.get("/_synapse/admin/v1/rooms", async (ctx) => {
|
|
219
|
+
} }));
|
|
220
|
+
r.get("/_synapse/admin/v1/rooms", procedure({ handler: async (ctx) => {
|
|
205
221
|
await requireAdmin(ctx);
|
|
206
222
|
const res = await ctx.hs.admin.listRooms({
|
|
207
223
|
from: Number(ctx.query.get("from") ?? 0) || 0,
|
|
@@ -211,8 +227,8 @@ function registerAdminRoutes(r) {
|
|
|
211
227
|
rooms: res.rooms,
|
|
212
228
|
total_rooms: res.total
|
|
213
229
|
};
|
|
214
|
-
});
|
|
215
|
-
r.delete("/_synapse/admin/v1/rooms/:roomId", async (ctx) => {
|
|
230
|
+
} }));
|
|
231
|
+
r.delete("/_synapse/admin/v1/rooms/:roomId", procedure({ handler: async (ctx) => {
|
|
216
232
|
const s = await requireAdmin(ctx);
|
|
217
233
|
const body = await ctx.json();
|
|
218
234
|
const { kicked } = await ctx.hs.admin.deleteRoom(ctx.params.roomId, {
|
|
@@ -226,8 +242,8 @@ function registerAdminRoutes(r) {
|
|
|
226
242
|
local_aliases: [],
|
|
227
243
|
new_room_id: null
|
|
228
244
|
};
|
|
229
|
-
});
|
|
230
|
-
r.delete("/_synapse/admin/v1/media/:serverName/:mediaId", async (ctx) => {
|
|
245
|
+
} }));
|
|
246
|
+
r.delete("/_synapse/admin/v1/media/:serverName/:mediaId", procedure({ handler: async (ctx) => {
|
|
231
247
|
await requireAdmin(ctx);
|
|
232
248
|
if (ctx.params.serverName !== ctx.hs.serverName) throw errors.notFound("Remote media");
|
|
233
249
|
await ctx.hs.admin.deleteMedia(ctx.params.mediaId);
|
|
@@ -235,8 +251,8 @@ function registerAdminRoutes(r) {
|
|
|
235
251
|
deleted_media: [ctx.params.mediaId],
|
|
236
252
|
total: 1
|
|
237
253
|
};
|
|
238
|
-
});
|
|
239
|
-
r.post("/_synapse/admin/v1/media/delete", async (ctx) => {
|
|
254
|
+
} }));
|
|
255
|
+
r.post("/_synapse/admin/v1/media/delete", procedure({ handler: async (ctx) => {
|
|
240
256
|
await requireAdmin(ctx);
|
|
241
257
|
const before = Number(ctx.query.get("before_ts"));
|
|
242
258
|
if (!Number.isFinite(before)) throw errors.missingParam("Missing before_ts");
|
|
@@ -245,7 +261,7 @@ function registerAdminRoutes(r) {
|
|
|
245
261
|
deleted_media: deleted,
|
|
246
262
|
total: deleted.length
|
|
247
263
|
};
|
|
248
|
-
});
|
|
264
|
+
} }));
|
|
249
265
|
}
|
|
250
266
|
//#endregion
|
|
251
267
|
export { registerAdminRoutes };
|
package/dist/api/appservice.js
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
1
|
import { errors } from "../core/errors.js";
|
|
2
|
+
import { procedure } from "../http/procedure.js";
|
|
2
3
|
//#region src/api/appservice.ts
|
|
3
4
|
function registerAppServiceRoutes(r) {
|
|
4
|
-
r.client("POST", "/appservice/:appserviceId/ping",
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
r.client("POST", "/appservice/:appserviceId/ping", procedure({
|
|
6
|
+
auth: "user",
|
|
7
|
+
handler: async (ctx) => {
|
|
8
|
+
const s = ctx.session;
|
|
9
|
+
if (!s.appservice) throw errors.forbidden("An application service token is required");
|
|
10
|
+
if (s.appservice.id !== ctx.params.appserviceId) throw errors.forbidden("Token does not belong to this application service");
|
|
11
|
+
const body = await ctx.json();
|
|
12
|
+
return { duration_ms: await ctx.hs.appservices.ping(s.appservice, typeof body.transaction_id === "string" ? body.transaction_id : void 0) };
|
|
13
|
+
}
|
|
14
|
+
}), ["v1"]);
|
|
15
|
+
r.client("GET", "/thirdparty/protocols", procedure({
|
|
16
|
+
auth: "user",
|
|
17
|
+
handler: async (ctx) => {
|
|
18
|
+
return ctx.hs.appservices.protocols();
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
r.client("GET", "/thirdparty/protocol/:protocol", procedure({
|
|
22
|
+
auth: "user",
|
|
23
|
+
handler: async (ctx) => {
|
|
24
|
+
const p = (await ctx.hs.appservices.protocols())[ctx.params.protocol];
|
|
25
|
+
if (!p) throw errors.notFound("Unknown protocol");
|
|
26
|
+
return p;
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
21
29
|
for (const kind of ["location", "user"]) {
|
|
22
|
-
r.client("GET", `/thirdparty/${kind}/:protocol`,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
r.client("GET", `/thirdparty/${kind}/:protocol`, procedure({
|
|
31
|
+
auth: "user",
|
|
32
|
+
handler: async (ctx) => {
|
|
33
|
+
return ctx.hs.appservices.thirdParty(`${kind}/${encodeURIComponent(ctx.params.protocol)}`, ctx.query);
|
|
34
|
+
}
|
|
35
|
+
}));
|
|
36
|
+
r.client("GET", `/thirdparty/${kind}`, procedure({
|
|
37
|
+
auth: "user",
|
|
38
|
+
handler: async (ctx) => {
|
|
39
|
+
return ctx.hs.appservices.thirdParty(kind, ctx.query);
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
30
42
|
}
|
|
31
43
|
}
|
|
32
44
|
//#endregion
|
package/dist/api/backup.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { isObject } from "../core/json.js";
|
|
2
2
|
import { MatrixError, errors } from "../core/errors.js";
|
|
3
|
+
import { looseObject, string } from "../vendor/zod/v4/classic/schemas.js";
|
|
3
4
|
import { body, fail } from "../http/input.js";
|
|
4
|
-
import {
|
|
5
|
+
import { procedure } from "../http/procedure.js";
|
|
5
6
|
//#region src/api/backup.ts
|
|
6
7
|
const required = fail("M_BAD_JSON", "algorithm and auth_data are required");
|
|
7
8
|
const createVersionBody = body({
|
|
8
|
-
algorithm:
|
|
9
|
-
auth_data:
|
|
9
|
+
algorithm: string(required),
|
|
10
|
+
auth_data: looseObject({}, required)
|
|
10
11
|
});
|
|
11
12
|
/** Server-side room key backups (`/room_keys`). */
|
|
12
13
|
async function latestVersion(hs, userId) {
|
|
@@ -74,68 +75,78 @@ async function requireCurrentVersion(ctx, userId) {
|
|
|
74
75
|
};
|
|
75
76
|
}
|
|
76
77
|
function registerBackupRoutes(r) {
|
|
77
|
-
r.client("POST", "/room_keys/version",
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
r.client("POST", "/room_keys/version", procedure({
|
|
79
|
+
auth: "user",
|
|
80
|
+
input: createVersionBody,
|
|
81
|
+
handler: async (ctx) => {
|
|
82
|
+
const s = ctx.session;
|
|
83
|
+
const body = ctx.input;
|
|
84
|
+
const max = (await ctx.hs.db.findMany("backup_versions", { where: [{
|
|
85
|
+
field: "user_id",
|
|
86
|
+
value: s.userId
|
|
87
|
+
}] })).reduce((m, v) => Math.max(m, v.version), 0);
|
|
88
|
+
await ctx.hs.db.create("backup_versions", {
|
|
89
|
+
user_id: s.userId,
|
|
90
|
+
version: max + 1,
|
|
91
|
+
algorithm: body.algorithm,
|
|
92
|
+
auth_data: body.auth_data,
|
|
93
|
+
etag: 0,
|
|
94
|
+
deleted: false
|
|
95
|
+
});
|
|
96
|
+
return { version: String(max + 1) };
|
|
97
|
+
}
|
|
98
|
+
}));
|
|
94
99
|
const getVersionHandler = async (ctx) => {
|
|
95
100
|
const s = await ctx.auth();
|
|
96
101
|
const row = await getVersion(ctx.hs, s.userId, ctx.params.version ?? null);
|
|
97
102
|
if (!row) throw errors.notFound("No backup found");
|
|
98
103
|
return describe(ctx.hs, row);
|
|
99
104
|
};
|
|
100
|
-
r.client("GET", "/room_keys/version", getVersionHandler);
|
|
101
|
-
r.client("GET", "/room_keys/version/:version", getVersionHandler);
|
|
102
|
-
r.client("PUT", "/room_keys/version/:version",
|
|
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
|
-
|
|
105
|
+
r.client("GET", "/room_keys/version", procedure({ handler: getVersionHandler }));
|
|
106
|
+
r.client("GET", "/room_keys/version/:version", procedure({ handler: getVersionHandler }));
|
|
107
|
+
r.client("PUT", "/room_keys/version/:version", procedure({
|
|
108
|
+
auth: "user",
|
|
109
|
+
handler: async (ctx) => {
|
|
110
|
+
const s = ctx.session;
|
|
111
|
+
const body = await ctx.json();
|
|
112
|
+
const row = await getVersion(ctx.hs, s.userId, ctx.params.version);
|
|
113
|
+
if (!row) throw errors.notFound("Unknown backup version");
|
|
114
|
+
if (body.version !== void 0 && String(body.version) !== ctx.params.version) throw errors.invalidParam("Version mismatch");
|
|
115
|
+
if (body.algorithm !== row.algorithm) throw errors.invalidParam("Algorithm cannot be changed");
|
|
116
|
+
if (!isObject(body.auth_data)) throw errors.badJson("auth_data is required");
|
|
117
|
+
await ctx.hs.db.update("backup_versions", [{
|
|
118
|
+
field: "user_id",
|
|
119
|
+
value: s.userId
|
|
120
|
+
}, {
|
|
121
|
+
field: "version",
|
|
122
|
+
value: row.version
|
|
123
|
+
}], { auth_data: body.auth_data });
|
|
124
|
+
return {};
|
|
125
|
+
}
|
|
126
|
+
}));
|
|
127
|
+
r.client("DELETE", "/room_keys/version/:version", procedure({
|
|
128
|
+
auth: "user",
|
|
129
|
+
handler: async (ctx) => {
|
|
130
|
+
const s = ctx.session;
|
|
131
|
+
const row = await getVersion(ctx.hs, s.userId, ctx.params.version);
|
|
132
|
+
if (!row) throw errors.notFound("Unknown backup version");
|
|
133
|
+
await ctx.hs.db.update("backup_versions", [{
|
|
134
|
+
field: "user_id",
|
|
135
|
+
value: s.userId
|
|
136
|
+
}, {
|
|
137
|
+
field: "version",
|
|
138
|
+
value: row.version
|
|
139
|
+
}], { deleted: true });
|
|
140
|
+
await ctx.hs.db.delete("backup_keys", [{
|
|
141
|
+
field: "user_id",
|
|
142
|
+
value: s.userId
|
|
143
|
+
}, {
|
|
144
|
+
field: "version",
|
|
145
|
+
value: row.version
|
|
146
|
+
}]);
|
|
147
|
+
return {};
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
139
150
|
const putKeys = async (ctx) => {
|
|
140
151
|
const s = await ctx.auth();
|
|
141
152
|
const hs = ctx.hs;
|
|
@@ -260,9 +271,9 @@ function registerBackupRoutes(r) {
|
|
|
260
271
|
"/room_keys/keys/:roomId",
|
|
261
272
|
"/room_keys/keys/:roomId/:sessionId"
|
|
262
273
|
]) {
|
|
263
|
-
r.client("PUT", path, putKeys);
|
|
264
|
-
r.client("GET", path, getKeys);
|
|
265
|
-
r.client("DELETE", path, deleteKeys);
|
|
274
|
+
r.client("PUT", path, procedure({ handler: putKeys }));
|
|
275
|
+
r.client("GET", path, procedure({ handler: getKeys }));
|
|
276
|
+
r.client("DELETE", path, procedure({ handler: deleteKeys }));
|
|
266
277
|
}
|
|
267
278
|
}
|
|
268
279
|
//#endregion
|