matrix-nodejs-homeserver 0.0.0-stage → 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/LICENSE +75 -0
- package/README.md +479 -2
- package/dist/adapters/auth.d.ts +50 -0
- package/dist/adapters/auth.js +18 -0
- package/dist/adapters/cluster.d.ts +55 -0
- package/dist/adapters/cluster.js +249 -0
- package/dist/adapters/media.d.ts +50 -0
- package/dist/adapters/media.js +63 -0
- package/dist/adapters/s3.d.ts +33 -0
- package/dist/adapters/s3.js +95 -0
- package/dist/api/account.js +594 -0
- package/dist/api/admin.js +267 -0
- package/dist/api/appservice.js +45 -0
- package/dist/api/backup.js +280 -0
- package/dist/api/federation.js +826 -0
- package/dist/api/filters.js +88 -0
- package/dist/api/index.js +47 -0
- package/dist/api/legacy.js +183 -0
- package/dist/api/media.js +271 -0
- package/dist/api/misc.js +95 -0
- package/dist/api/preview.js +201 -0
- package/dist/api/profile.js +176 -0
- package/dist/api/push.js +202 -0
- package/dist/api/relationships.js +270 -0
- package/dist/api/rooms.js +1487 -0
- package/dist/api/rtc.d.ts +23 -0
- package/dist/api/rtc.js +66 -0
- package/dist/api/search.js +161 -0
- package/dist/api/slidingsync.js +474 -0
- package/dist/api/spaces.js +177 -0
- package/dist/api/sync.js +609 -0
- package/dist/api/threadsubs.js +140 -0
- package/dist/api/threepid.js +155 -0
- package/dist/api/uia.js +127 -0
- package/dist/api/user.js +329 -0
- package/dist/core/admin.d.ts +84 -0
- package/dist/core/admin.js +308 -0
- package/dist/core/adminroom.d.ts +49 -0
- package/dist/core/adminroom.js +483 -0
- package/dist/core/appservices.d.ts +74 -0
- package/dist/core/appservices.js +369 -0
- package/dist/core/audit.d.ts +50 -0
- package/dist/core/audit.js +86 -0
- package/dist/core/auth.d.ts +48 -0
- package/dist/core/auth.js +237 -0
- package/dist/core/authrules.d.ts +4 -0
- package/dist/core/authrules.js +348 -0
- package/dist/core/cluster.d.ts +66 -0
- package/dist/core/cluster.js +191 -0
- package/dist/core/crypto.d.ts +10 -0
- package/dist/core/crypto.js +100 -0
- package/dist/core/delayed.d.ts +39 -0
- package/dist/core/delayed.js +160 -0
- package/dist/core/errors.d.ts +9 -0
- package/dist/core/errors.js +45 -0
- package/dist/core/events.d.ts +32 -0
- package/dist/core/events.js +186 -0
- package/dist/core/glob.js +66 -0
- package/dist/core/identity.d.ts +24 -0
- package/dist/core/identity.js +96 -0
- package/dist/core/ids.js +36 -0
- package/dist/core/invitefilter.js +36 -0
- package/dist/core/json.js +16 -0
- package/dist/core/keys.d.ts +36 -0
- package/dist/core/keys.js +450 -0
- package/dist/core/m.d.ts +209 -0
- package/dist/core/m.js +182 -0
- package/dist/core/notifier.d.ts +17 -0
- package/dist/core/notifier.js +54 -0
- package/dist/core/oauth.d.ts +38 -0
- package/dist/core/oauth.js +108 -0
- package/dist/core/partialstate.d.ts +32 -0
- package/dist/core/partialstate.js +198 -0
- package/dist/core/phone.js +268 -0
- package/dist/core/policy.d.ts +29 -0
- package/dist/core/policy.js +97 -0
- package/dist/core/profile.js +39 -0
- package/dist/core/push.d.ts +46 -0
- package/dist/core/push.js +307 -0
- package/dist/core/pushrules.js +229 -0
- package/dist/core/ratelimit.d.ts +23 -0
- package/dist/core/ratelimit.js +77 -0
- package/dist/core/rooms.d.ts +215 -0
- package/dist/core/rooms.js +1731 -0
- package/dist/core/settings.d.ts +11 -0
- package/dist/core/settings.js +29 -0
- package/dist/core/sso.d.ts +46 -0
- package/dist/core/sso.js +165 -0
- package/dist/core/stateres.d.ts +4 -0
- package/dist/core/stateres.js +209 -0
- package/dist/core/threepid.d.ts +80 -0
- package/dist/core/threepid.js +275 -0
- package/dist/core/typing.d.ts +16 -0
- package/dist/core/typing.js +60 -0
- package/dist/federation/client.d.ts +51 -0
- package/dist/federation/client.js +279 -0
- package/dist/federation/index.d.ts +153 -0
- package/dist/federation/index.js +1059 -0
- package/dist/federation/keyring.d.ts +26 -0
- package/dist/federation/keyring.js +122 -0
- package/dist/federation/sender.d.ts +26 -0
- package/dist/federation/sender.js +164 -0
- package/dist/homeserver.d.ts +224 -0
- package/dist/homeserver.js +302 -0
- package/dist/http/adapters.d.ts +40 -0
- package/dist/http/adapters.js +130 -0
- package/dist/http/handler.d.ts +8 -0
- package/dist/http/handler.js +181 -0
- package/dist/http/input.js +24 -0
- package/dist/http/procedure.js +25 -0
- package/dist/http/router.d.ts +43 -0
- package/dist/http/router.js +56 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +15 -0
- package/dist/storage/memory.d.ts +5 -0
- package/dist/storage/memory.js +122 -0
- package/dist/storage/schema.d.ts +4 -0
- package/dist/storage/schema.js +664 -0
- package/dist/storage/sql.d.ts +72 -0
- package/dist/storage/sql.js +274 -0
- package/dist/storage/types.d.ts +55 -0
- 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 +65 -4
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { randomString } from "./crypto.js";
|
|
2
|
+
import { M } from "./m.js";
|
|
3
|
+
import { errors } from "./errors.js";
|
|
4
|
+
import { LOCALPART_RE, isValidUserId } from "./ids.js";
|
|
5
|
+
import { createUser } from "../api/account.js";
|
|
6
|
+
//#region src/core/admin.ts
|
|
7
|
+
/** Programmatic administration, for embedding applications and the admin HTTP API. */
|
|
8
|
+
var AdminService = class {
|
|
9
|
+
hs;
|
|
10
|
+
constructor(hs) {
|
|
11
|
+
this.hs = hs;
|
|
12
|
+
}
|
|
13
|
+
async createUser(localpart, opts = {}) {
|
|
14
|
+
const lp = localpart.toLowerCase();
|
|
15
|
+
if (!LOCALPART_RE.test(lp)) throw errors.invalidUsername();
|
|
16
|
+
if (await this.getUser(`@${lp}:${this.hs.serverName}`)) throw errors.userInUse();
|
|
17
|
+
return createUser(this.hs, lp, opts);
|
|
18
|
+
}
|
|
19
|
+
async getUser(userId) {
|
|
20
|
+
const row = await this.hs.db.findOne("users", [{
|
|
21
|
+
field: "user_id",
|
|
22
|
+
value: userId
|
|
23
|
+
}]);
|
|
24
|
+
if (!row) return null;
|
|
25
|
+
const { password_hash, ...rest } = row;
|
|
26
|
+
return rest;
|
|
27
|
+
}
|
|
28
|
+
async listUsers(opts = {}) {
|
|
29
|
+
let rows = await this.hs.db.findMany("users", { sortBy: {
|
|
30
|
+
field: "created_ts",
|
|
31
|
+
direction: "asc"
|
|
32
|
+
} });
|
|
33
|
+
if (!opts.includeDeactivated) rows = rows.filter((r) => !r.deactivated);
|
|
34
|
+
if (opts.search) {
|
|
35
|
+
const term = opts.search.toLowerCase();
|
|
36
|
+
rows = rows.filter((r) => r.user_id.toLowerCase().includes(term) || (r.displayname ?? "").toLowerCase().includes(term));
|
|
37
|
+
}
|
|
38
|
+
const from = opts.from ?? 0;
|
|
39
|
+
const limit = opts.limit ?? 100;
|
|
40
|
+
return {
|
|
41
|
+
users: rows.slice(from, from + limit).map(({ password_hash, ...u }) => u),
|
|
42
|
+
total: rows.length,
|
|
43
|
+
next: from + limit < rows.length ? from + limit : null
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async setAdmin(userId, admin) {
|
|
47
|
+
if (!await this.hs.db.update("users", [{
|
|
48
|
+
field: "user_id",
|
|
49
|
+
value: userId
|
|
50
|
+
}], { is_admin: admin })) throw errors.notFound("Unknown user");
|
|
51
|
+
await this.hs.auth.invalidateUser(userId);
|
|
52
|
+
if (admin) await this.hs.adminRoom?.addAdmin(userId);
|
|
53
|
+
else await this.hs.adminRoom?.removeAdmin(userId);
|
|
54
|
+
}
|
|
55
|
+
/** Lock or unlock an account (reversible; sessions are kept but unusable while locked). */
|
|
56
|
+
async setLocked(userId, locked, actor = "server") {
|
|
57
|
+
if (!await this.hs.db.update("users", [{
|
|
58
|
+
field: "user_id",
|
|
59
|
+
value: userId
|
|
60
|
+
}], { locked })) throw errors.notFound("Unknown user");
|
|
61
|
+
await this.hs.auth.invalidateUser(userId);
|
|
62
|
+
await this.hs.audit.record({
|
|
63
|
+
action: locked ? "user_lock" : "user_unlock",
|
|
64
|
+
actor,
|
|
65
|
+
target: userId
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Suspend or unsuspend an account (reversible; the user can still read, leave and log out). */
|
|
69
|
+
async setSuspended(userId, suspended, actor = "server") {
|
|
70
|
+
if (!await this.hs.db.update("users", [{
|
|
71
|
+
field: "user_id",
|
|
72
|
+
value: userId
|
|
73
|
+
}], { suspended })) throw errors.notFound("Unknown user");
|
|
74
|
+
await this.hs.auth.invalidateUser(userId);
|
|
75
|
+
await this.hs.audit.record({
|
|
76
|
+
action: suspended ? "user_suspend" : "user_unsuspend",
|
|
77
|
+
actor,
|
|
78
|
+
target: userId
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async resetPassword(userId, password, logoutDevices = true) {
|
|
82
|
+
const hash = await this.hs.userAuth.hashPassword(password);
|
|
83
|
+
if (!await this.hs.db.update("users", [{
|
|
84
|
+
field: "user_id",
|
|
85
|
+
value: userId
|
|
86
|
+
}], { password_hash: hash })) throw errors.notFound("Unknown user");
|
|
87
|
+
if (logoutDevices) await this.hs.auth.deleteAllDevices(userId);
|
|
88
|
+
}
|
|
89
|
+
/** Deactivate an account: leave all rooms, log out everywhere and (optionally) erase the profile. */
|
|
90
|
+
async deactivateUser(userId, opts = {}) {
|
|
91
|
+
if (!await this.hs.db.findOne("users", [{
|
|
92
|
+
field: "user_id",
|
|
93
|
+
value: userId
|
|
94
|
+
}])) throw errors.notFound("Unknown user");
|
|
95
|
+
for (const membership of [
|
|
96
|
+
"join",
|
|
97
|
+
"invite",
|
|
98
|
+
"knock"
|
|
99
|
+
]) for (const roomId of await this.hs.rooms.roomsForUser(userId, membership)) try {
|
|
100
|
+
await this.hs.rooms.setMembership(roomId, userId, userId, "leave");
|
|
101
|
+
} catch {}
|
|
102
|
+
await this.hs.auth.deleteAllDevices(userId);
|
|
103
|
+
await this.hs.threepids.removeAll(userId);
|
|
104
|
+
await this.hs.db.delete("pushers", [{
|
|
105
|
+
field: "user_id",
|
|
106
|
+
value: userId
|
|
107
|
+
}]);
|
|
108
|
+
const update = {
|
|
109
|
+
deactivated: true,
|
|
110
|
+
password_hash: null
|
|
111
|
+
};
|
|
112
|
+
if (opts.erase !== false) Object.assign(update, {
|
|
113
|
+
displayname: null,
|
|
114
|
+
avatar_url: null
|
|
115
|
+
});
|
|
116
|
+
await this.hs.db.update("users", [{
|
|
117
|
+
field: "user_id",
|
|
118
|
+
value: userId
|
|
119
|
+
}], update);
|
|
120
|
+
await this.hs.auth.invalidateUser(userId);
|
|
121
|
+
}
|
|
122
|
+
async createRegistrationToken(opts = {}) {
|
|
123
|
+
const token = opts.token ?? randomString(opts.length ?? 16);
|
|
124
|
+
if (!/^[A-Za-z0-9._~-]{1,64}$/.test(token)) throw errors.invalidParam("Invalid token");
|
|
125
|
+
if (await this.hs.db.findOne("registration_tokens", [{
|
|
126
|
+
field: "token",
|
|
127
|
+
value: token
|
|
128
|
+
}])) throw errors.invalidParam("Token already exists");
|
|
129
|
+
const row = {
|
|
130
|
+
token,
|
|
131
|
+
uses_allowed: opts.usesAllowed ?? null,
|
|
132
|
+
pending: 0,
|
|
133
|
+
completed: 0,
|
|
134
|
+
expiry_time: opts.expiryTime ?? null
|
|
135
|
+
};
|
|
136
|
+
await this.hs.db.create("registration_tokens", row);
|
|
137
|
+
return row;
|
|
138
|
+
}
|
|
139
|
+
listRegistrationTokens() {
|
|
140
|
+
return this.hs.db.findMany("registration_tokens");
|
|
141
|
+
}
|
|
142
|
+
async deleteRegistrationToken(token) {
|
|
143
|
+
if (!await this.hs.db.delete("registration_tokens", [{
|
|
144
|
+
field: "token",
|
|
145
|
+
value: token
|
|
146
|
+
}])) throw errors.notFound("Unknown token");
|
|
147
|
+
}
|
|
148
|
+
async listRooms(opts = {}) {
|
|
149
|
+
const rows = await this.hs.db.findMany("rooms", { sortBy: {
|
|
150
|
+
field: "created_ts",
|
|
151
|
+
direction: "asc"
|
|
152
|
+
} });
|
|
153
|
+
const from = opts.from ?? 0;
|
|
154
|
+
const page = rows.slice(from, from + (opts.limit ?? 100));
|
|
155
|
+
return {
|
|
156
|
+
rooms: await Promise.all(page.map(async (r) => ({
|
|
157
|
+
...r,
|
|
158
|
+
joined_members: (await this.hs.rooms.joinedMembers(r.room_id)).length
|
|
159
|
+
}))),
|
|
160
|
+
total: rows.length
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** Remove everyone from a room, delist it and drop its aliases. With `purge`, also delete its history. */
|
|
164
|
+
async deleteRoom(roomId, opts = {}) {
|
|
165
|
+
if (!await this.hs.rooms.exists(roomId)) throw errors.notFound("Unknown room");
|
|
166
|
+
const kicked = [];
|
|
167
|
+
for (const membership of [
|
|
168
|
+
"join",
|
|
169
|
+
"invite",
|
|
170
|
+
"knock"
|
|
171
|
+
]) for (const row of await this.hs.db.findMany("memberships", { where: [{
|
|
172
|
+
field: "room_id",
|
|
173
|
+
value: roomId
|
|
174
|
+
}, {
|
|
175
|
+
field: "membership",
|
|
176
|
+
value: membership
|
|
177
|
+
}] })) {
|
|
178
|
+
if (!this.hs.isLocalUser(row.user_id)) continue;
|
|
179
|
+
try {
|
|
180
|
+
await this.hs.rooms.setMembership(roomId, row.user_id, row.user_id, "leave", opts.reason);
|
|
181
|
+
kicked.push(row.user_id);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
this.hs.logger.warn("Could not remove", row.user_id, "from", roomId, err);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
await this.hs.db.update("rooms", [{
|
|
187
|
+
field: "room_id",
|
|
188
|
+
value: roomId
|
|
189
|
+
}], { is_public: false });
|
|
190
|
+
await this.hs.db.delete("room_aliases", [{
|
|
191
|
+
field: "room_id",
|
|
192
|
+
value: roomId
|
|
193
|
+
}]);
|
|
194
|
+
if (opts.purge) {
|
|
195
|
+
const where = [{
|
|
196
|
+
field: "room_id",
|
|
197
|
+
value: roomId
|
|
198
|
+
}];
|
|
199
|
+
await this.hs.transaction(async (db) => {
|
|
200
|
+
for (const table of [
|
|
201
|
+
"events",
|
|
202
|
+
"state_snapshots",
|
|
203
|
+
"current_state",
|
|
204
|
+
"memberships",
|
|
205
|
+
"receipts",
|
|
206
|
+
"relations",
|
|
207
|
+
"notifications",
|
|
208
|
+
"rooms"
|
|
209
|
+
]) await db.delete(table, where);
|
|
210
|
+
});
|
|
211
|
+
this.hs.rooms.forgetRoom(roomId);
|
|
212
|
+
}
|
|
213
|
+
return { kicked };
|
|
214
|
+
}
|
|
215
|
+
async deleteMedia(mediaId) {
|
|
216
|
+
await this.hs.media.delete?.(mediaId);
|
|
217
|
+
await this.hs.db.delete("media", [{
|
|
218
|
+
field: "media_id",
|
|
219
|
+
value: mediaId
|
|
220
|
+
}]);
|
|
221
|
+
}
|
|
222
|
+
/** Delete local media uploaded before `beforeTs`. Returns the deleted media IDs. */
|
|
223
|
+
async purgeMediaBefore(beforeTs) {
|
|
224
|
+
const rows = await this.hs.db.findMany("media", { where: [{
|
|
225
|
+
field: "created_ts",
|
|
226
|
+
operator: "lt",
|
|
227
|
+
value: beforeTs
|
|
228
|
+
}] });
|
|
229
|
+
for (const r of rows) await this.deleteMedia(r.media_id);
|
|
230
|
+
return rows.map((r) => r.media_id);
|
|
231
|
+
}
|
|
232
|
+
get noticeUserId() {
|
|
233
|
+
return `@${this.hs.config.serverNotices.localpart}:${this.hs.serverName}`;
|
|
234
|
+
}
|
|
235
|
+
/** Whether `roomId` is a server notices room (members may not reject or leave its invites). */
|
|
236
|
+
async isNoticeRoom(roomId) {
|
|
237
|
+
return (await this.hs.db.findOne("rooms", [{
|
|
238
|
+
field: "room_id",
|
|
239
|
+
value: roomId
|
|
240
|
+
}]))?.creator === this.noticeUserId;
|
|
241
|
+
}
|
|
242
|
+
/** Send a message to a user in their server notices room, creating or re-inviting as needed. */
|
|
243
|
+
async sendServerNotice(userId, content, opts = {}) {
|
|
244
|
+
if (!isValidUserId(userId) || !this.hs.isLocalUser(userId)) throw errors.invalidParam("Server notices can only be sent to local users");
|
|
245
|
+
if (!await this.hs.db.findOne("users", [{
|
|
246
|
+
field: "user_id",
|
|
247
|
+
value: userId
|
|
248
|
+
}])) throw errors.notFound("Unknown user");
|
|
249
|
+
const txnKey = opts.txnId ? `notice-txn:${userId}|${opts.txnId}` : null;
|
|
250
|
+
if (txnKey) {
|
|
251
|
+
const existing = await this.hs.cluster.get(txnKey);
|
|
252
|
+
if (existing) return existing;
|
|
253
|
+
}
|
|
254
|
+
const noticeUser = this.noticeUserId;
|
|
255
|
+
if (!await this.hs.db.findOne("users", [{
|
|
256
|
+
field: "user_id",
|
|
257
|
+
value: noticeUser
|
|
258
|
+
}])) await createUser(this.hs, noticeUser.slice(1).split(":")[0], { displayname: this.hs.config.serverNotices.displayName });
|
|
259
|
+
const roomId = await this.noticeRoomFor(userId);
|
|
260
|
+
const membership = await this.hs.rooms.membership(roomId, userId);
|
|
261
|
+
if (membership !== "join" && membership !== "invite") await this.hs.rooms.invite(roomId, noticeUser, userId);
|
|
262
|
+
const eventId = await this.hs.rooms.sendEvent(roomId, noticeUser, {
|
|
263
|
+
type: opts.type ?? M.ROOM.MESSAGE,
|
|
264
|
+
content
|
|
265
|
+
});
|
|
266
|
+
if (txnKey) await this.hs.cluster.set(txnKey, eventId, 864e5);
|
|
267
|
+
return eventId;
|
|
268
|
+
}
|
|
269
|
+
async noticeRoomFor(userId) {
|
|
270
|
+
const noticeUser = this.noticeUserId;
|
|
271
|
+
const rooms = await this.hs.db.findMany("rooms", { where: [{
|
|
272
|
+
field: "creator",
|
|
273
|
+
value: noticeUser
|
|
274
|
+
}] });
|
|
275
|
+
for (const room of rooms) if ((await this.hs.db.findOne("account_data", [
|
|
276
|
+
{
|
|
277
|
+
field: "user_id",
|
|
278
|
+
value: userId
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
field: "room_id",
|
|
282
|
+
value: room.room_id
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
field: "type",
|
|
286
|
+
value: M.TAG
|
|
287
|
+
}
|
|
288
|
+
]))?.content?.tags?.[M.SERVER_NOTICE]) return room.room_id;
|
|
289
|
+
const { room_id } = await this.hs.rooms.createRoom(noticeUser, {
|
|
290
|
+
preset: "private_chat",
|
|
291
|
+
name: this.hs.config.serverNotices.roomName,
|
|
292
|
+
power_level_content_override: {
|
|
293
|
+
users: { [noticeUser]: 100 },
|
|
294
|
+
events_default: 100
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
await this.hs.streams.write((stream) => this.hs.db.upsert("account_data", {
|
|
298
|
+
user_id: userId,
|
|
299
|
+
room_id,
|
|
300
|
+
type: M.TAG,
|
|
301
|
+
content: { tags: { [M.SERVER_NOTICE]: { order: .5 } } },
|
|
302
|
+
stream
|
|
303
|
+
}));
|
|
304
|
+
return room_id;
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
//#endregion
|
|
308
|
+
export { AdminService };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PDU } from "./events.js";
|
|
2
|
+
import { Homeserver } from "../homeserver.js";
|
|
3
|
+
//#region src/core/adminroom.d.ts
|
|
4
|
+
export interface AdminRoomOptions {
|
|
5
|
+
/** Enable the admin room and admin bot. Default: true when the option object is given. */
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
/** The first account registered on the server becomes a server admin. Default: true. */
|
|
8
|
+
firstUserIsAdmin?: boolean;
|
|
9
|
+
/** Let the very first account register even when registration is closed. Default: true. */
|
|
10
|
+
firstUserCanRegister?: boolean;
|
|
11
|
+
/** Localpart of the admin bot. Default: "admin". */
|
|
12
|
+
botLocalpart?: string;
|
|
13
|
+
botDisplayName?: string;
|
|
14
|
+
roomName?: string;
|
|
15
|
+
/** Localpart of the admin room alias (#admins:server). Default: "admins". */
|
|
16
|
+
aliasLocalpart?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A tuwunel-style admin room: server admins chat with an admin bot to manage the
|
|
20
|
+
* server. The first registered account becomes an admin and is put in the room.
|
|
21
|
+
*/
|
|
22
|
+
export declare class AdminRoomService {
|
|
23
|
+
private hs;
|
|
24
|
+
readonly options: Required<AdminRoomOptions>;
|
|
25
|
+
private roomIdCache;
|
|
26
|
+
constructor(hs: Homeserver, options: AdminRoomOptions);
|
|
27
|
+
get botUserId(): string;
|
|
28
|
+
get alias(): string;
|
|
29
|
+
/** Whether no real (non-bot) account exists yet. */
|
|
30
|
+
noUsersYet(): Promise<boolean>;
|
|
31
|
+
roomId(): Promise<string | null>;
|
|
32
|
+
/** Create the admin bot and room if needed. */
|
|
33
|
+
ensureRoom(): Promise<string>;
|
|
34
|
+
/** Called after an account was created. */
|
|
35
|
+
onUserCreated(userId: string): Promise<void>;
|
|
36
|
+
/** Put an admin into the admin room. */
|
|
37
|
+
addAdmin(userId: string): Promise<void>;
|
|
38
|
+
/** Remove a former admin from the admin room. */
|
|
39
|
+
removeAdmin(userId: string): Promise<void>;
|
|
40
|
+
/** Post a message from the admin bot. */
|
|
41
|
+
say(text: string, replyTo?: string): Promise<void>;
|
|
42
|
+
/** Called for every new event; handles commands posted in the admin room. */
|
|
43
|
+
onEvent(event: PDU): Promise<void>;
|
|
44
|
+
private resolveUser;
|
|
45
|
+
private resolveRoom;
|
|
46
|
+
/** Run one admin command; returns the reply text. */
|
|
47
|
+
execute(actor: string, args: string[]): Promise<string>;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|