matrix-nodejs-homeserver 0.2.0 → 0.3.2
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 +89 -11
- package/dist/adapters/cluster.d.ts +1 -26
- package/dist/adapters/cluster.js +50 -103
- package/dist/api/account.js +407 -354
- package/dist/api/admin.js +82 -61
- 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 +71 -55
- package/dist/api/misc.js +46 -37
- package/dist/api/preview.js +37 -73
- 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 +325 -135
- 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/cluster.d.ts +12 -5
- package/dist/core/cluster.js +46 -29
- package/dist/core/delayed.js +2 -1
- package/dist/core/events.js +11 -10
- package/dist/core/html.js +13 -0
- package/dist/core/identity.js +1 -1
- package/dist/core/invitefilter.js +2 -1
- package/dist/core/json.js +10 -1
- package/dist/core/keys.d.ts +10 -1
- package/dist/core/keys.js +62 -42
- package/dist/core/m.d.ts +209 -0
- package/dist/core/m.js +182 -0
- package/dist/core/outbound.d.ts +16 -0
- package/dist/core/outbound.js +172 -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 +41 -28
- package/dist/core/pushrules.js +36 -35
- package/dist/core/ratelimit.d.ts +1 -1
- package/dist/core/rooms.d.ts +10 -1
- package/dist/core/rooms.js +101 -74
- package/dist/core/semaphore.js +23 -0
- package/dist/core/sso.d.ts +15 -1
- package/dist/core/sso.js +38 -2
- package/dist/core/stateres.js +7 -6
- package/dist/core/threepid.js +1 -9
- package/dist/federation/client.js +9 -1
- package/dist/federation/index.d.ts +2 -2
- package/dist/federation/index.js +43 -35
- package/dist/homeserver.d.ts +23 -4
- package/dist/homeserver.js +12 -3
- 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 +4 -3
- package/dist/index.js +3 -2
- package/dist/storage/batch.js +11 -0
- package/dist/storage/memory.js +1 -0
- package/dist/storage/schema.js +1 -1
- package/dist/storage/sql.js +20 -1
- package/dist/storage/types.d.ts +16 -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 +8 -6
- package/dist/core/pushrules.d.ts +0 -1
package/dist/core/m.d.ts
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
//#region src/core/m.d.ts
|
|
2
|
+
export declare const M: {
|
|
3
|
+
readonly BEACON_INFO: "m.beacon_info";
|
|
4
|
+
readonly CALL: {
|
|
5
|
+
readonly INVITE: "m.call.invite";
|
|
6
|
+
};
|
|
7
|
+
readonly CHANGE_PASSWORD: "m.change_password";
|
|
8
|
+
readonly DEVICE_LIST_UPDATE: "m.device_list_update";
|
|
9
|
+
readonly DIRECT: "m.direct";
|
|
10
|
+
readonly DIRECT_TO_DEVICE: "m.direct_to_device";
|
|
11
|
+
readonly FEDERATE: "m.federate";
|
|
12
|
+
readonly FULLY_READ: "m.fully_read";
|
|
13
|
+
readonly GET_LOGIN_TOKEN: "m.get_login_token";
|
|
14
|
+
readonly HEROES: "m.heroes";
|
|
15
|
+
readonly HOMESERVER: "m.homeserver";
|
|
16
|
+
readonly ID: {
|
|
17
|
+
readonly PHONE: "m.id.phone";
|
|
18
|
+
readonly THIRDPARTY: "m.id.thirdparty";
|
|
19
|
+
readonly USER: "m.id.user";
|
|
20
|
+
};
|
|
21
|
+
readonly IGNORED_USER_LIST: "m.ignored_user_list";
|
|
22
|
+
readonly IN_REPLY_TO: "m.in_reply_to";
|
|
23
|
+
readonly INVITED_MEMBER_COUNT: "m.invited_member_count";
|
|
24
|
+
readonly JOINED_MEMBER_COUNT: "m.joined_member_count";
|
|
25
|
+
readonly LOGIN: {
|
|
26
|
+
readonly APPLICATION_SERVICE: "m.login.application_service";
|
|
27
|
+
readonly DUMMY: "m.login.dummy";
|
|
28
|
+
readonly EMAIL: {
|
|
29
|
+
readonly IDENTITY: "m.login.email.identity";
|
|
30
|
+
};
|
|
31
|
+
readonly MSISDN: "m.login.msisdn";
|
|
32
|
+
readonly PASSWORD: "m.login.password";
|
|
33
|
+
readonly REGISTRATION_TOKEN: "m.login.registration_token";
|
|
34
|
+
readonly SSO: "m.login.sso";
|
|
35
|
+
readonly TOKEN: "m.login.token";
|
|
36
|
+
};
|
|
37
|
+
readonly NOTICE: "m.notice";
|
|
38
|
+
readonly OAUTH: "m.oauth";
|
|
39
|
+
readonly POLL: {
|
|
40
|
+
readonly START: "m.poll.start";
|
|
41
|
+
};
|
|
42
|
+
readonly PRESENCE: "m.presence";
|
|
43
|
+
readonly PROFILE_FIELDS: "m.profile_fields";
|
|
44
|
+
readonly PUSH_RULES: "m.push_rules";
|
|
45
|
+
readonly REACTION: "m.reaction";
|
|
46
|
+
readonly READ: {
|
|
47
|
+
readonly _: "m.read";
|
|
48
|
+
readonly PRIVATE: "m.read.private";
|
|
49
|
+
};
|
|
50
|
+
readonly RECEIPT: "m.receipt";
|
|
51
|
+
readonly RELATES_TO: "m.relates_to";
|
|
52
|
+
readonly RELATIONS: "m.relations";
|
|
53
|
+
readonly RELATIONSHIP: "m.relationship";
|
|
54
|
+
readonly REPLACE: "m.replace";
|
|
55
|
+
readonly ROLE: {
|
|
56
|
+
readonly ADMIN: "m.role.admin";
|
|
57
|
+
readonly SECURITY: "m.role.security";
|
|
58
|
+
};
|
|
59
|
+
readonly ROOM: {
|
|
60
|
+
readonly ALIASES: "m.room.aliases";
|
|
61
|
+
readonly AVATAR: "m.room.avatar";
|
|
62
|
+
readonly CANONICAL_ALIAS: "m.room.canonical_alias";
|
|
63
|
+
readonly CREATE: "m.room.create";
|
|
64
|
+
readonly ENCRYPTED: "m.room.encrypted";
|
|
65
|
+
readonly ENCRYPTION: "m.room.encryption";
|
|
66
|
+
readonly GUEST_ACCESS: "m.room.guest_access";
|
|
67
|
+
readonly HISTORY_VISIBILITY: "m.room.history_visibility";
|
|
68
|
+
readonly JOIN_RULES: "m.room.join_rules";
|
|
69
|
+
readonly MEMBER: "m.room.member";
|
|
70
|
+
readonly MESSAGE: "m.room.message";
|
|
71
|
+
readonly NAME: "m.room.name";
|
|
72
|
+
readonly POLICY: "m.room.policy";
|
|
73
|
+
readonly POWER_LEVELS: "m.room.power_levels";
|
|
74
|
+
readonly REDACTION: "m.room.redaction";
|
|
75
|
+
readonly SERVER_ACL: "m.room.server_acl";
|
|
76
|
+
readonly THIRD_PARTY_INVITE: "m.room.third_party_invite";
|
|
77
|
+
readonly TOMBSTONE: "m.room.tombstone";
|
|
78
|
+
readonly TOPIC: "m.room.topic";
|
|
79
|
+
};
|
|
80
|
+
readonly ROOM_MEMBERSHIP: "m.room_membership";
|
|
81
|
+
readonly ROOM_VERSIONS: "m.room_versions";
|
|
82
|
+
readonly RULE: {
|
|
83
|
+
readonly CALL: ".m.rule.call";
|
|
84
|
+
readonly CONTAINS_DISPLAY_NAME: ".m.rule.contains_display_name";
|
|
85
|
+
readonly CONTAINS_USER_NAME: ".m.rule.contains_user_name";
|
|
86
|
+
readonly ENCRYPTED: ".m.rule.encrypted";
|
|
87
|
+
readonly ENCRYPTED_ROOM_ONE_TO_ONE: ".m.rule.encrypted_room_one_to_one";
|
|
88
|
+
readonly INVITE_FOR_ME: ".m.rule.invite_for_me";
|
|
89
|
+
readonly IS_ROOM_MENTION: ".m.rule.is_room_mention";
|
|
90
|
+
readonly IS_USER_MENTION: ".m.rule.is_user_mention";
|
|
91
|
+
readonly MASTER: ".m.rule.master";
|
|
92
|
+
readonly MEMBER_EVENT: ".m.rule.member_event";
|
|
93
|
+
readonly MESSAGE: ".m.rule.message";
|
|
94
|
+
readonly REACTION: ".m.rule.reaction";
|
|
95
|
+
readonly ROOM: {
|
|
96
|
+
readonly SERVER_ACL: ".m.rule.room.server_acl";
|
|
97
|
+
};
|
|
98
|
+
readonly ROOM_ONE_TO_ONE: ".m.rule.room_one_to_one";
|
|
99
|
+
readonly ROOMNOTIF: ".m.rule.roomnotif";
|
|
100
|
+
readonly SUPPRESS_EDITS: ".m.rule.suppress_edits";
|
|
101
|
+
readonly SUPPRESS_NOTICES: ".m.rule.suppress_notices";
|
|
102
|
+
readonly TOMBSTONE: ".m.rule.tombstone";
|
|
103
|
+
};
|
|
104
|
+
readonly SERVER: "m.server";
|
|
105
|
+
readonly SERVER_NOTICE: "m.server_notice";
|
|
106
|
+
readonly SET_AVATAR_URL: "m.set_avatar_url";
|
|
107
|
+
readonly SET_DISPLAYNAME: "m.set_displayname";
|
|
108
|
+
readonly SIGNING_KEY_UPDATE: "m.signing_key_update";
|
|
109
|
+
readonly SPACE: {
|
|
110
|
+
readonly _: "m.space";
|
|
111
|
+
readonly CHILD: "m.space.child";
|
|
112
|
+
};
|
|
113
|
+
readonly STICKER: "m.sticker";
|
|
114
|
+
readonly TAG: "m.tag";
|
|
115
|
+
readonly TEXT: "m.text";
|
|
116
|
+
readonly THREAD: "m.thread";
|
|
117
|
+
readonly THREEPID_CHANGES: "m.3pid_changes";
|
|
118
|
+
readonly TOPIC: "m.topic";
|
|
119
|
+
readonly TYPING: "m.typing";
|
|
120
|
+
readonly UPLOAD: {
|
|
121
|
+
readonly SIZE: "m.upload.size";
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
export declare const UNSTABLE: {
|
|
125
|
+
readonly DE: {
|
|
126
|
+
readonly SORUNOME: {
|
|
127
|
+
readonly MSC2409: {
|
|
128
|
+
readonly EPHEMERAL: "de.sorunome.msc2409.ephemeral";
|
|
129
|
+
readonly PUSH_EPHEMERAL: "de.sorunome.msc2409.push_ephemeral";
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
readonly IO: {
|
|
134
|
+
readonly ELEMENT: {
|
|
135
|
+
readonly MSC4306: {
|
|
136
|
+
readonly RULE: {
|
|
137
|
+
readonly SUBSCRIBED_THREAD: ".io.element.msc4306.rule.subscribed_thread";
|
|
138
|
+
readonly UNSUBSCRIBED_THREAD: ".io.element.msc4306.rule.unsubscribed_thread";
|
|
139
|
+
};
|
|
140
|
+
readonly THREAD_SUBSCRIPTION: "io.element.msc4306.thread_subscription";
|
|
141
|
+
};
|
|
142
|
+
readonly MSC4308: {
|
|
143
|
+
readonly THREAD_SUBSCRIPTIONS: "io.element.msc4308.thread_subscriptions";
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
readonly ORG: {
|
|
148
|
+
readonly MATRIX: {
|
|
149
|
+
readonly CROSS_SIGNING_RESET: "org.matrix.cross_signing_reset";
|
|
150
|
+
readonly CUSTOM: {
|
|
151
|
+
readonly HTML: "org.matrix.custom.html";
|
|
152
|
+
};
|
|
153
|
+
readonly MSC2732: {
|
|
154
|
+
readonly FALLBACK_KEYS: "org.matrix.msc2732.fallback_keys";
|
|
155
|
+
};
|
|
156
|
+
readonly MSC3202: {
|
|
157
|
+
readonly DEVICE_ID: "org.matrix.msc3202.device_id";
|
|
158
|
+
};
|
|
159
|
+
readonly MSC3381: {
|
|
160
|
+
readonly POLL: {
|
|
161
|
+
readonly END: "org.matrix.msc3381.poll.end";
|
|
162
|
+
readonly RESPONSE: "org.matrix.msc3381.poll.response";
|
|
163
|
+
readonly START: "org.matrix.msc3381.poll.start";
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
readonly MSC3874: {
|
|
167
|
+
readonly NOT_REL_TYPES: "org.matrix.msc3874.not_rel_types";
|
|
168
|
+
readonly REL_TYPES: "org.matrix.msc3874.rel_types";
|
|
169
|
+
};
|
|
170
|
+
readonly MSC3916: {
|
|
171
|
+
readonly STABLE: "org.matrix.msc3916.stable";
|
|
172
|
+
};
|
|
173
|
+
readonly MSC3930: {
|
|
174
|
+
readonly RULE: {
|
|
175
|
+
readonly POLL_END: ".org.matrix.msc3930.rule.poll_end";
|
|
176
|
+
readonly POLL_END_ONE_TO_ONE: ".org.matrix.msc3930.rule.poll_end_one_to_one";
|
|
177
|
+
readonly POLL_RESPONSE: ".org.matrix.msc3930.rule.poll_response";
|
|
178
|
+
readonly POLL_START: ".org.matrix.msc3930.rule.poll_start";
|
|
179
|
+
readonly POLL_START_ONE_TO_ONE: ".org.matrix.msc3930.rule.poll_start_one_to_one";
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
readonly MSC4140: {
|
|
183
|
+
readonly _: "org.matrix.msc4140";
|
|
184
|
+
readonly DELAY: "org.matrix.msc4140.delay";
|
|
185
|
+
readonly MAX_DELAY: "org.matrix.msc4140.max_delay";
|
|
186
|
+
};
|
|
187
|
+
readonly MSC4143: {
|
|
188
|
+
readonly _: "org.matrix.msc4143";
|
|
189
|
+
readonly RTC_FOCI: "org.matrix.msc4143.rtc_foci";
|
|
190
|
+
};
|
|
191
|
+
readonly MSC4155: {
|
|
192
|
+
readonly ERRCODE: "org.matrix.msc4155.errcode";
|
|
193
|
+
readonly INVITE_PERMISSION_CONFIG: "org.matrix.msc4155.invite_permission_config";
|
|
194
|
+
};
|
|
195
|
+
readonly MSC4222: {
|
|
196
|
+
readonly _: "org.matrix.msc4222";
|
|
197
|
+
readonly STATE_AFTER: "org.matrix.msc4222.state_after";
|
|
198
|
+
readonly USE_STATE_AFTER: "org.matrix.msc4222.use_state_after";
|
|
199
|
+
};
|
|
200
|
+
readonly MSC4306: "org.matrix.msc4306";
|
|
201
|
+
readonly MSC4429: {
|
|
202
|
+
readonly PROFILE_FIELDS: "org.matrix.msc4429.profile_fields";
|
|
203
|
+
readonly USERS: "org.matrix.msc4429.users";
|
|
204
|
+
};
|
|
205
|
+
readonly SIMPLIFIED_MSC3575: "org.matrix.simplified_msc3575";
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
//#endregion
|
package/dist/core/m.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
//#region src/core/m.ts
|
|
2
|
+
function deepFreeze(o) {
|
|
3
|
+
for (const v of Object.values(o)) if (typeof v === "object" && v !== null) deepFreeze(v);
|
|
4
|
+
return Object.freeze(o);
|
|
5
|
+
}
|
|
6
|
+
const M = deepFreeze({
|
|
7
|
+
BEACON_INFO: "m.beacon_info",
|
|
8
|
+
CALL: { INVITE: "m.call.invite" },
|
|
9
|
+
CHANGE_PASSWORD: "m.change_password",
|
|
10
|
+
DEVICE_LIST_UPDATE: "m.device_list_update",
|
|
11
|
+
DIRECT: "m.direct",
|
|
12
|
+
DIRECT_TO_DEVICE: "m.direct_to_device",
|
|
13
|
+
FEDERATE: "m.federate",
|
|
14
|
+
FULLY_READ: "m.fully_read",
|
|
15
|
+
GET_LOGIN_TOKEN: "m.get_login_token",
|
|
16
|
+
HEROES: "m.heroes",
|
|
17
|
+
HOMESERVER: "m.homeserver",
|
|
18
|
+
ID: {
|
|
19
|
+
PHONE: "m.id.phone",
|
|
20
|
+
THIRDPARTY: "m.id.thirdparty",
|
|
21
|
+
USER: "m.id.user"
|
|
22
|
+
},
|
|
23
|
+
IGNORED_USER_LIST: "m.ignored_user_list",
|
|
24
|
+
IN_REPLY_TO: "m.in_reply_to",
|
|
25
|
+
INVITED_MEMBER_COUNT: "m.invited_member_count",
|
|
26
|
+
JOINED_MEMBER_COUNT: "m.joined_member_count",
|
|
27
|
+
LOGIN: {
|
|
28
|
+
APPLICATION_SERVICE: "m.login.application_service",
|
|
29
|
+
DUMMY: "m.login.dummy",
|
|
30
|
+
EMAIL: { IDENTITY: "m.login.email.identity" },
|
|
31
|
+
MSISDN: "m.login.msisdn",
|
|
32
|
+
PASSWORD: "m.login.password",
|
|
33
|
+
REGISTRATION_TOKEN: "m.login.registration_token",
|
|
34
|
+
SSO: "m.login.sso",
|
|
35
|
+
TOKEN: "m.login.token"
|
|
36
|
+
},
|
|
37
|
+
NOTICE: "m.notice",
|
|
38
|
+
OAUTH: "m.oauth",
|
|
39
|
+
POLL: { START: "m.poll.start" },
|
|
40
|
+
PRESENCE: "m.presence",
|
|
41
|
+
PROFILE_FIELDS: "m.profile_fields",
|
|
42
|
+
PUSH_RULES: "m.push_rules",
|
|
43
|
+
REACTION: "m.reaction",
|
|
44
|
+
READ: {
|
|
45
|
+
_: "m.read",
|
|
46
|
+
PRIVATE: "m.read.private"
|
|
47
|
+
},
|
|
48
|
+
RECEIPT: "m.receipt",
|
|
49
|
+
RELATES_TO: "m.relates_to",
|
|
50
|
+
RELATIONS: "m.relations",
|
|
51
|
+
RELATIONSHIP: "m.relationship",
|
|
52
|
+
REPLACE: "m.replace",
|
|
53
|
+
ROLE: {
|
|
54
|
+
ADMIN: "m.role.admin",
|
|
55
|
+
SECURITY: "m.role.security"
|
|
56
|
+
},
|
|
57
|
+
ROOM: {
|
|
58
|
+
ALIASES: "m.room.aliases",
|
|
59
|
+
AVATAR: "m.room.avatar",
|
|
60
|
+
CANONICAL_ALIAS: "m.room.canonical_alias",
|
|
61
|
+
CREATE: "m.room.create",
|
|
62
|
+
ENCRYPTED: "m.room.encrypted",
|
|
63
|
+
ENCRYPTION: "m.room.encryption",
|
|
64
|
+
GUEST_ACCESS: "m.room.guest_access",
|
|
65
|
+
HISTORY_VISIBILITY: "m.room.history_visibility",
|
|
66
|
+
JOIN_RULES: "m.room.join_rules",
|
|
67
|
+
MEMBER: "m.room.member",
|
|
68
|
+
MESSAGE: "m.room.message",
|
|
69
|
+
NAME: "m.room.name",
|
|
70
|
+
POLICY: "m.room.policy",
|
|
71
|
+
POWER_LEVELS: "m.room.power_levels",
|
|
72
|
+
REDACTION: "m.room.redaction",
|
|
73
|
+
SERVER_ACL: "m.room.server_acl",
|
|
74
|
+
THIRD_PARTY_INVITE: "m.room.third_party_invite",
|
|
75
|
+
TOMBSTONE: "m.room.tombstone",
|
|
76
|
+
TOPIC: "m.room.topic"
|
|
77
|
+
},
|
|
78
|
+
ROOM_MEMBERSHIP: "m.room_membership",
|
|
79
|
+
ROOM_VERSIONS: "m.room_versions",
|
|
80
|
+
RULE: {
|
|
81
|
+
CALL: ".m.rule.call",
|
|
82
|
+
CONTAINS_DISPLAY_NAME: ".m.rule.contains_display_name",
|
|
83
|
+
CONTAINS_USER_NAME: ".m.rule.contains_user_name",
|
|
84
|
+
ENCRYPTED: ".m.rule.encrypted",
|
|
85
|
+
ENCRYPTED_ROOM_ONE_TO_ONE: ".m.rule.encrypted_room_one_to_one",
|
|
86
|
+
INVITE_FOR_ME: ".m.rule.invite_for_me",
|
|
87
|
+
IS_ROOM_MENTION: ".m.rule.is_room_mention",
|
|
88
|
+
IS_USER_MENTION: ".m.rule.is_user_mention",
|
|
89
|
+
MASTER: ".m.rule.master",
|
|
90
|
+
MEMBER_EVENT: ".m.rule.member_event",
|
|
91
|
+
MESSAGE: ".m.rule.message",
|
|
92
|
+
REACTION: ".m.rule.reaction",
|
|
93
|
+
ROOM: { SERVER_ACL: ".m.rule.room.server_acl" },
|
|
94
|
+
ROOM_ONE_TO_ONE: ".m.rule.room_one_to_one",
|
|
95
|
+
ROOMNOTIF: ".m.rule.roomnotif",
|
|
96
|
+
SUPPRESS_EDITS: ".m.rule.suppress_edits",
|
|
97
|
+
SUPPRESS_NOTICES: ".m.rule.suppress_notices",
|
|
98
|
+
TOMBSTONE: ".m.rule.tombstone"
|
|
99
|
+
},
|
|
100
|
+
SERVER: "m.server",
|
|
101
|
+
SERVER_NOTICE: "m.server_notice",
|
|
102
|
+
SET_AVATAR_URL: "m.set_avatar_url",
|
|
103
|
+
SET_DISPLAYNAME: "m.set_displayname",
|
|
104
|
+
SIGNING_KEY_UPDATE: "m.signing_key_update",
|
|
105
|
+
SPACE: {
|
|
106
|
+
_: "m.space",
|
|
107
|
+
CHILD: "m.space.child"
|
|
108
|
+
},
|
|
109
|
+
STICKER: "m.sticker",
|
|
110
|
+
TAG: "m.tag",
|
|
111
|
+
TEXT: "m.text",
|
|
112
|
+
THREAD: "m.thread",
|
|
113
|
+
THREEPID_CHANGES: "m.3pid_changes",
|
|
114
|
+
TOPIC: "m.topic",
|
|
115
|
+
TYPING: "m.typing",
|
|
116
|
+
UPLOAD: { SIZE: "m.upload.size" }
|
|
117
|
+
});
|
|
118
|
+
const UNSTABLE = deepFreeze({
|
|
119
|
+
DE: { SORUNOME: { MSC2409: {
|
|
120
|
+
EPHEMERAL: "de.sorunome.msc2409.ephemeral",
|
|
121
|
+
PUSH_EPHEMERAL: "de.sorunome.msc2409.push_ephemeral"
|
|
122
|
+
} } },
|
|
123
|
+
IO: { ELEMENT: {
|
|
124
|
+
MSC4306: {
|
|
125
|
+
RULE: {
|
|
126
|
+
SUBSCRIBED_THREAD: ".io.element.msc4306.rule.subscribed_thread",
|
|
127
|
+
UNSUBSCRIBED_THREAD: ".io.element.msc4306.rule.unsubscribed_thread"
|
|
128
|
+
},
|
|
129
|
+
THREAD_SUBSCRIPTION: "io.element.msc4306.thread_subscription"
|
|
130
|
+
},
|
|
131
|
+
MSC4308: { THREAD_SUBSCRIPTIONS: "io.element.msc4308.thread_subscriptions" }
|
|
132
|
+
} },
|
|
133
|
+
ORG: { MATRIX: {
|
|
134
|
+
CROSS_SIGNING_RESET: "org.matrix.cross_signing_reset",
|
|
135
|
+
CUSTOM: { HTML: "org.matrix.custom.html" },
|
|
136
|
+
MSC2732: { FALLBACK_KEYS: "org.matrix.msc2732.fallback_keys" },
|
|
137
|
+
MSC3202: { DEVICE_ID: "org.matrix.msc3202.device_id" },
|
|
138
|
+
MSC3381: { POLL: {
|
|
139
|
+
END: "org.matrix.msc3381.poll.end",
|
|
140
|
+
RESPONSE: "org.matrix.msc3381.poll.response",
|
|
141
|
+
START: "org.matrix.msc3381.poll.start"
|
|
142
|
+
} },
|
|
143
|
+
MSC3874: {
|
|
144
|
+
NOT_REL_TYPES: "org.matrix.msc3874.not_rel_types",
|
|
145
|
+
REL_TYPES: "org.matrix.msc3874.rel_types"
|
|
146
|
+
},
|
|
147
|
+
MSC3916: { STABLE: "org.matrix.msc3916.stable" },
|
|
148
|
+
MSC3930: { RULE: {
|
|
149
|
+
POLL_END: ".org.matrix.msc3930.rule.poll_end",
|
|
150
|
+
POLL_END_ONE_TO_ONE: ".org.matrix.msc3930.rule.poll_end_one_to_one",
|
|
151
|
+
POLL_RESPONSE: ".org.matrix.msc3930.rule.poll_response",
|
|
152
|
+
POLL_START: ".org.matrix.msc3930.rule.poll_start",
|
|
153
|
+
POLL_START_ONE_TO_ONE: ".org.matrix.msc3930.rule.poll_start_one_to_one"
|
|
154
|
+
} },
|
|
155
|
+
MSC4140: {
|
|
156
|
+
_: "org.matrix.msc4140",
|
|
157
|
+
DELAY: "org.matrix.msc4140.delay",
|
|
158
|
+
MAX_DELAY: "org.matrix.msc4140.max_delay"
|
|
159
|
+
},
|
|
160
|
+
MSC4143: {
|
|
161
|
+
_: "org.matrix.msc4143",
|
|
162
|
+
RTC_FOCI: "org.matrix.msc4143.rtc_foci"
|
|
163
|
+
},
|
|
164
|
+
MSC4155: {
|
|
165
|
+
ERRCODE: "org.matrix.msc4155.errcode",
|
|
166
|
+
INVITE_PERMISSION_CONFIG: "org.matrix.msc4155.invite_permission_config"
|
|
167
|
+
},
|
|
168
|
+
MSC4222: {
|
|
169
|
+
_: "org.matrix.msc4222",
|
|
170
|
+
STATE_AFTER: "org.matrix.msc4222.state_after",
|
|
171
|
+
USE_STATE_AFTER: "org.matrix.msc4222.use_state_after"
|
|
172
|
+
},
|
|
173
|
+
MSC4306: "org.matrix.msc4306",
|
|
174
|
+
MSC4429: {
|
|
175
|
+
PROFILE_FIELDS: "org.matrix.msc4429.profile_fields",
|
|
176
|
+
USERS: "org.matrix.msc4429.users"
|
|
177
|
+
},
|
|
178
|
+
SIMPLIFIED_MSC3575: "org.matrix.simplified_msc3575"
|
|
179
|
+
} }
|
|
180
|
+
});
|
|
181
|
+
//#endregion
|
|
182
|
+
export { M, UNSTABLE };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LookupAddress, LookupOptions } from "node:dns";
|
|
2
|
+
//#region src/core/outbound.d.ts
|
|
3
|
+
type LookupCallback = (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family?: number) => void;
|
|
4
|
+
/** Which addresses outbound requests to user- or remote-chosen destinations may connect to. */
|
|
5
|
+
export interface AddressPolicy {
|
|
6
|
+
allows(address: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A `dns.lookup` for http(s) requests that refuses disallowed addresses. It runs when the
|
|
9
|
+
* connection is made, so the address checked is the one connected to: a name cannot resolve to
|
|
10
|
+
* a public address for a check and to a private one for the request (DNS rebinding).
|
|
11
|
+
* Undefined when every address is allowed.
|
|
12
|
+
*/
|
|
13
|
+
lookup?: (hostname: string, options: LookupOptions, callback: LookupCallback) => void;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { errors } from "./errors.js";
|
|
2
|
+
import { lookup } from "node:dns/promises";
|
|
3
|
+
import { request } from "node:https";
|
|
4
|
+
import { BlockList, isIP } from "node:net";
|
|
5
|
+
import { lookup as lookup$1 } from "node:dns";
|
|
6
|
+
import { request as request$1 } from "node:http";
|
|
7
|
+
import { Readable } from "node:stream";
|
|
8
|
+
//#region src/core/outbound.ts
|
|
9
|
+
const privateRanges = new BlockList();
|
|
10
|
+
for (const [net, prefix] of [
|
|
11
|
+
["0.0.0.0", 8],
|
|
12
|
+
["10.0.0.0", 8],
|
|
13
|
+
["100.64.0.0", 10],
|
|
14
|
+
["127.0.0.0", 8],
|
|
15
|
+
["169.254.0.0", 16],
|
|
16
|
+
["172.16.0.0", 12],
|
|
17
|
+
["192.0.0.0", 24],
|
|
18
|
+
["192.168.0.0", 16],
|
|
19
|
+
["198.18.0.0", 15],
|
|
20
|
+
["224.0.0.0", 4],
|
|
21
|
+
["240.0.0.0", 4]
|
|
22
|
+
]) privateRanges.addSubnet(net, prefix, "ipv4");
|
|
23
|
+
for (const [net, prefix] of [
|
|
24
|
+
["::", 128],
|
|
25
|
+
["::1", 128],
|
|
26
|
+
["fc00::", 7],
|
|
27
|
+
["fe80::", 10],
|
|
28
|
+
["ff00::", 8]
|
|
29
|
+
]) privateRanges.addSubnet(net, prefix, "ipv6");
|
|
30
|
+
/** Whether an IP address is loopback, private, link-local, multicast or otherwise not public. */
|
|
31
|
+
function isPrivateAddress(address) {
|
|
32
|
+
const family = isIP(address);
|
|
33
|
+
return family !== 0 && privateRanges.check(address, family === 6 ? "ipv6" : "ipv4");
|
|
34
|
+
}
|
|
35
|
+
/** The policy for the `allowPrivateAddresses` option. */
|
|
36
|
+
function addressPolicy(allowPrivate) {
|
|
37
|
+
if (allowPrivate === true) return { allows: () => true };
|
|
38
|
+
const allowed = new BlockList();
|
|
39
|
+
for (const entry of Array.isArray(allowPrivate) ? allowPrivate : []) {
|
|
40
|
+
const [address, prefix] = entry.split("/");
|
|
41
|
+
const family = isIP(address);
|
|
42
|
+
if (family === 0) throw new Error(`allowPrivateAddresses: not an IP address or range: ${entry}`);
|
|
43
|
+
allowed.addSubnet(address, prefix === void 0 ? family === 6 ? 128 : 32 : Number(prefix), family === 6 ? "ipv6" : "ipv4");
|
|
44
|
+
}
|
|
45
|
+
const allows = (address) => !isPrivateAddress(address) || allowed.check(address, isIP(address) === 6 ? "ipv6" : "ipv4");
|
|
46
|
+
return {
|
|
47
|
+
allows,
|
|
48
|
+
lookup: (hostname, options, callback) => {
|
|
49
|
+
lookup$1(hostname, {
|
|
50
|
+
...options,
|
|
51
|
+
all: true
|
|
52
|
+
}, (err, addresses) => {
|
|
53
|
+
if (err) return callback(err, []);
|
|
54
|
+
if (addresses.length === 0 || !addresses.every((a) => allows(a.address))) return callback(privateAddressError(hostname), []);
|
|
55
|
+
if (options.all) callback(null, addresses);
|
|
56
|
+
else callback(null, addresses[0].address, addresses[0].family);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function privateAddressError(host) {
|
|
62
|
+
return Object.assign(/* @__PURE__ */ new Error(`${host} resolves to a private address`), { code: "EPRIVATE" });
|
|
63
|
+
}
|
|
64
|
+
/** Refuse an IP literal the policy does not allow (literals are connected to without a lookup). */
|
|
65
|
+
function checkLiteral(policy, host) {
|
|
66
|
+
const literal = host.replace(/^\[|\]$/g, "");
|
|
67
|
+
if (isIP(literal) && !policy.allows(literal)) throw errors.forbidden("Address is private");
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A `fetch` for user- or remote-chosen URLs that connects only to addresses `policy` allows.
|
|
71
|
+
* Redirects are never followed: callers that follow them send the next request through this
|
|
72
|
+
* function again, so each target is checked. Only http(s) URLs are accepted.
|
|
73
|
+
*
|
|
74
|
+
* With a custom `fetch` (the `fetch` option, e.g. for a proxy), the host is resolved and checked
|
|
75
|
+
* before the request instead. That leaves the DNS-rebinding window open; the custom client is the
|
|
76
|
+
* operator's to secure.
|
|
77
|
+
*/
|
|
78
|
+
function policyFetch(policy, custom) {
|
|
79
|
+
return async (input, init = {}) => {
|
|
80
|
+
const url = new URL(input instanceof Request ? input.url : String(input));
|
|
81
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") throw errors.forbidden("Only http and https URLs can be fetched");
|
|
82
|
+
checkLiteral(policy, url.hostname);
|
|
83
|
+
if (custom) {
|
|
84
|
+
if (policy.lookup && !isIP(url.hostname.replace(/^\[|\]$/g, ""))) {
|
|
85
|
+
if (!(await lookup(url.hostname, { all: true })).every((a) => policy.allows(a.address))) throw errors.forbidden("Address is private");
|
|
86
|
+
}
|
|
87
|
+
return custom(input, {
|
|
88
|
+
...init,
|
|
89
|
+
redirect: "manual"
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return nodeFetch(url, init, policy);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const NULL_BODY = /* @__PURE__ */ new Set([
|
|
96
|
+
101,
|
|
97
|
+
103,
|
|
98
|
+
204,
|
|
99
|
+
205,
|
|
100
|
+
304
|
|
101
|
+
]);
|
|
102
|
+
function nodeFetch(url, init, policy) {
|
|
103
|
+
const method = (init.method ?? "GET").toUpperCase();
|
|
104
|
+
const headers = new Headers(init.headers);
|
|
105
|
+
const body = init.body === void 0 || init.body === null ? void 0 : typeof init.body === "string" || init.body instanceof URLSearchParams ? Buffer.from(String(init.body)) : Buffer.from(init.body);
|
|
106
|
+
if (body && init.body instanceof URLSearchParams && !headers.has("content-type")) headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8");
|
|
107
|
+
const request$2 = url.protocol === "https:" ? request : request$1;
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const req = request$2(url, {
|
|
110
|
+
method,
|
|
111
|
+
headers: Object.fromEntries(headers),
|
|
112
|
+
lookup: policy.lookup,
|
|
113
|
+
signal: init.signal ?? void 0
|
|
114
|
+
}, (res) => {
|
|
115
|
+
const out = new Headers();
|
|
116
|
+
for (let i = 0; i < res.rawHeaders.length; i += 2) out.append(res.rawHeaders[i], res.rawHeaders[i + 1]);
|
|
117
|
+
const status = res.statusCode ?? 502;
|
|
118
|
+
const nullBody = NULL_BODY.has(status) || method === "HEAD";
|
|
119
|
+
if (nullBody) res.resume();
|
|
120
|
+
resolve(new Response(nullBody ? null : Readable.toWeb(res), {
|
|
121
|
+
status,
|
|
122
|
+
statusText: res.statusMessage,
|
|
123
|
+
headers: out
|
|
124
|
+
}));
|
|
125
|
+
});
|
|
126
|
+
req.on("error", (err) => reject(err.code === "EPRIVATE" ? errors.forbidden("Address is private") : err));
|
|
127
|
+
req.end(body);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** GET a URL through a `policyFetch`, following redirects (each one checked again) and capping the body. */
|
|
131
|
+
async function publicGet(fetchFn, rawUrl, options) {
|
|
132
|
+
let url = new URL(rawUrl);
|
|
133
|
+
const signal = AbortSignal.timeout(options.timeoutMs ?? 3e4);
|
|
134
|
+
for (let redirects = 0;; redirects++) {
|
|
135
|
+
const res = await fetchFn(url, {
|
|
136
|
+
redirect: "manual",
|
|
137
|
+
signal,
|
|
138
|
+
headers: options.headers
|
|
139
|
+
});
|
|
140
|
+
const location = res.headers.get("location");
|
|
141
|
+
if (res.status >= 300 && res.status < 400 && location) {
|
|
142
|
+
await res.body?.cancel();
|
|
143
|
+
if (redirects >= (options.maxRedirects ?? 5)) throw errors.notFound("Too many redirects");
|
|
144
|
+
url = new URL(location, url);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (Number(res.headers.get("content-length")) > options.maxBytes && !options.truncate) {
|
|
148
|
+
await res.body?.cancel();
|
|
149
|
+
throw errors.tooLarge("Remote response is too large");
|
|
150
|
+
}
|
|
151
|
+
const chunks = [];
|
|
152
|
+
let size = 0;
|
|
153
|
+
for await (const chunk of res.body ?? []) {
|
|
154
|
+
size += chunk.length;
|
|
155
|
+
if (size > options.maxBytes) {
|
|
156
|
+
await res.body?.cancel().catch(() => {});
|
|
157
|
+
if (!options.truncate) throw errors.tooLarge("Remote response is too large");
|
|
158
|
+
chunks.push(chunk.subarray(0, chunk.length - (size - options.maxBytes)));
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
chunks.push(chunk);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
status: res.status,
|
|
165
|
+
headers: res.headers,
|
|
166
|
+
body: Buffer.concat(chunks),
|
|
167
|
+
url
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
export { addressPolicy, checkLiteral, isPrivateAddress, policyFetch, publicGet };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { M } from "./m.js";
|
|
1
2
|
import { eventIdOf, roomVersionFeatures, stateKey } from "./events.js";
|
|
2
3
|
import { EventEmitter } from "node:events";
|
|
3
4
|
//#region src/core/partialstate.ts
|
|
@@ -162,7 +163,7 @@ var PartialStateService = class {
|
|
|
162
163
|
try {
|
|
163
164
|
const fullBefore = await this.hs.federation.stateFromPrevs(server, roomId, version, prevIds, { remote: true });
|
|
164
165
|
if (this.stopped || this.hs.isClosed) return true;
|
|
165
|
-
if (!fullBefore[stateKey(
|
|
166
|
+
if (!fullBefore[stateKey(M.ROOM.CREATE, "")] && !roomVersionFeatures(version).v12) throw new Error("Resynced state lacks the create event");
|
|
166
167
|
const notified = /* @__PURE__ */ new Set([...row.servers ?? [], ...this.hs.federation.serversInRoom(await this.hs.rooms.currentState(roomId), false)]);
|
|
167
168
|
const missed = await this.hs.rooms.withLock(roomId, () => this.hs.rooms.completePartialState(roomId, version, row.join_event_id, fullBefore, notified));
|
|
168
169
|
await this.finish(roomId);
|
package/dist/core/policy.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { publicKeyFromBase64, verifyJsonSignature } from "./crypto.js";
|
|
2
|
+
import { M } from "./m.js";
|
|
2
3
|
import { redact } from "./events.js";
|
|
3
4
|
import { MatrixError } from "./errors.js";
|
|
4
5
|
import { getState } from "./authrules.js";
|
|
@@ -13,7 +14,7 @@ var PolicyServers = class {
|
|
|
13
14
|
/** The room's policy server, if the room uses one (valid `m.room.policy` and a joined user on `via`). */
|
|
14
15
|
async policyOf(roomId) {
|
|
15
16
|
const state = await this.hs.rooms.currentState(roomId);
|
|
16
|
-
const content = getState(state,
|
|
17
|
+
const content = getState(state, M.ROOM.POLICY, "")?.content;
|
|
17
18
|
const via = content?.via;
|
|
18
19
|
const ed25519 = content?.public_keys?.ed25519;
|
|
19
20
|
if (typeof via !== "string" || typeof ed25519 !== "string") return null;
|
|
@@ -23,7 +24,7 @@ var PolicyServers = class {
|
|
|
23
24
|
} catch {
|
|
24
25
|
return null;
|
|
25
26
|
}
|
|
26
|
-
for (const ev of state.values()) if (ev.type ===
|
|
27
|
+
for (const ev of state.values()) if (ev.type === M.ROOM.MEMBER && ev.content?.membership === "join" && typeof ev.state_key === "string" && domainOf(ev.state_key) === via) return {
|
|
27
28
|
via,
|
|
28
29
|
key
|
|
29
30
|
};
|
|
@@ -31,7 +32,7 @@ var PolicyServers = class {
|
|
|
31
32
|
}
|
|
32
33
|
/** The policy state event itself is never sent to the policy server. */
|
|
33
34
|
exempt(pdu) {
|
|
34
|
-
return pdu.type ===
|
|
35
|
+
return pdu.type === M.ROOM.POLICY && pdu.state_key === "";
|
|
35
36
|
}
|
|
36
37
|
validSignature(pdu, version, policy) {
|
|
37
38
|
const wire = this.hs.federation.toFederationPdu(pdu, version);
|
package/dist/core/push.d.ts
CHANGED