matrix-js-sdk 42.1.0 → 42.2.0

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.
Files changed (154) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/lib/@types/beacon.d.ts +1 -1
  3. package/lib/@types/beacon.js +1 -1
  4. package/lib/@types/beacon.js.map +1 -1
  5. package/lib/@types/extensible_events.d.ts.map +1 -1
  6. package/lib/@types/extensible_events.js.map +1 -1
  7. package/lib/autodiscovery.js.map +1 -1
  8. package/lib/browser-index.js.map +1 -1
  9. package/lib/client.d.ts +12 -5
  10. package/lib/client.d.ts.map +1 -1
  11. package/lib/client.js +23 -26
  12. package/lib/client.js.map +1 -1
  13. package/lib/common-crypto/key-passphrase.js +1 -1
  14. package/lib/common-crypto/key-passphrase.js.map +1 -1
  15. package/lib/crypto/store/indexeddb-crypto-store-backend.js +2 -1
  16. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
  17. package/lib/crypto/store/indexeddb-crypto-store.d.ts.map +1 -1
  18. package/lib/crypto/store/indexeddb-crypto-store.js +1 -1
  19. package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
  20. package/lib/crypto/store/memory-crypto-store.js.map +1 -1
  21. package/lib/embedded.d.ts +16 -0
  22. package/lib/embedded.d.ts.map +1 -1
  23. package/lib/embedded.js +19 -6
  24. package/lib/embedded.js.map +1 -1
  25. package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
  26. package/lib/matrixrtc/MembershipManager.js.map +1 -1
  27. package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
  28. package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
  29. package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
  30. package/lib/matrixrtc/membershipData/rtc.js.map +1 -1
  31. package/lib/matrixrtc/utils.d.ts +0 -1
  32. package/lib/matrixrtc/utils.d.ts.map +1 -1
  33. package/lib/matrixrtc/utils.js +0 -1
  34. package/lib/matrixrtc/utils.js.map +1 -1
  35. package/lib/models/event-timeline-set.js +3 -3
  36. package/lib/models/event-timeline-set.js.map +1 -1
  37. package/lib/models/event.d.ts.map +1 -1
  38. package/lib/models/event.js.map +1 -1
  39. package/lib/models/invites-ignorer.js.map +1 -1
  40. package/lib/models/poll.js.map +1 -1
  41. package/lib/models/read-receipt.js.map +1 -1
  42. package/lib/models/relations-container.d.ts +10 -0
  43. package/lib/models/relations-container.d.ts.map +1 -1
  44. package/lib/models/relations-container.js +39 -17
  45. package/lib/models/relations-container.js.map +1 -1
  46. package/lib/models/relations.js +1 -1
  47. package/lib/models/relations.js.map +1 -1
  48. package/lib/models/room.js +3 -3
  49. package/lib/models/room.js.map +1 -1
  50. package/lib/models/thread.d.ts +3 -0
  51. package/lib/models/thread.d.ts.map +1 -1
  52. package/lib/models/thread.js +36 -3
  53. package/lib/models/thread.js.map +1 -1
  54. package/lib/oauth/authorize.js +1 -1
  55. package/lib/oauth/authorize.js.map +1 -1
  56. package/lib/oauth/index.js +4 -2
  57. package/lib/oauth/index.js.map +1 -1
  58. package/lib/pollingCachedValue.d.ts +77 -0
  59. package/lib/pollingCachedValue.d.ts.map +1 -0
  60. package/lib/pollingCachedValue.js +160 -0
  61. package/lib/pollingCachedValue.js.map +1 -0
  62. package/lib/pushprocessor.js.map +1 -1
  63. package/lib/receipt-accumulator.d.ts.map +1 -1
  64. package/lib/receipt-accumulator.js.map +1 -1
  65. package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +1 -1
  66. package/lib/rendezvous/MSC4108SignInWithQR.js +2 -3
  67. package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
  68. package/lib/rtcTransportsCachedValue.d.ts +9 -0
  69. package/lib/rtcTransportsCachedValue.d.ts.map +1 -0
  70. package/lib/rtcTransportsCachedValue.js +38 -0
  71. package/lib/rtcTransportsCachedValue.js.map +1 -0
  72. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
  73. package/lib/rust-crypto/backup.d.ts +2 -3
  74. package/lib/rust-crypto/backup.d.ts.map +1 -1
  75. package/lib/rust-crypto/backup.js.map +1 -1
  76. package/lib/rust-crypto/index.d.ts +10 -4
  77. package/lib/rust-crypto/index.d.ts.map +1 -1
  78. package/lib/rust-crypto/index.js +20 -3
  79. package/lib/rust-crypto/index.js.map +1 -1
  80. package/lib/rust-crypto/libolm_migration.js.map +1 -1
  81. package/lib/rust-crypto/rust-crypto.js.map +1 -1
  82. package/lib/sliding-sync-sdk.js.map +1 -1
  83. package/lib/sliding-sync.js.map +1 -1
  84. package/lib/store/indexeddb-local-backend.js +1 -1
  85. package/lib/store/indexeddb-local-backend.js.map +1 -1
  86. package/lib/store/indexeddb-store-worker.d.ts.map +1 -1
  87. package/lib/store/indexeddb-store-worker.js +1 -0
  88. package/lib/store/indexeddb-store-worker.js.map +1 -1
  89. package/lib/sync.d.ts.map +1 -1
  90. package/lib/sync.js.map +1 -1
  91. package/lib/utils.d.ts +1 -1
  92. package/lib/utils.d.ts.map +1 -1
  93. package/lib/utils.js +1 -0
  94. package/lib/utils.js.map +1 -1
  95. package/lib/webrtc/call.js.map +1 -1
  96. package/lib/webrtc/groupCall.js.map +1 -1
  97. package/lib/webrtc/mediaHandler.js.map +1 -1
  98. package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
  99. package/lib/webrtc/stats/transportStatsBuilder.js.map +1 -1
  100. package/lib/wellKnownCachedValue.d.ts +8 -0
  101. package/lib/wellKnownCachedValue.d.ts.map +1 -0
  102. package/lib/wellKnownCachedValue.js +34 -0
  103. package/lib/wellKnownCachedValue.js.map +1 -0
  104. package/package.json +4 -4
  105. package/src/@types/beacon.ts +1 -1
  106. package/src/@types/extensible_events.ts +3 -4
  107. package/src/autodiscovery.ts +2 -2
  108. package/src/browser-index.ts +1 -1
  109. package/src/client.ts +48 -40
  110. package/src/common-crypto/key-passphrase.ts +1 -1
  111. package/src/crypto/store/indexeddb-crypto-store-backend.ts +2 -1
  112. package/src/crypto/store/indexeddb-crypto-store.ts +1 -3
  113. package/src/crypto/store/memory-crypto-store.ts +1 -1
  114. package/src/embedded.ts +34 -11
  115. package/src/matrixrtc/MatrixRTCSession.ts +3 -3
  116. package/src/matrixrtc/MembershipManager.ts +1 -1
  117. package/src/matrixrtc/MembershipManagerActionScheduler.ts +1 -1
  118. package/src/matrixrtc/RTCEncryptionManager.ts +2 -2
  119. package/src/matrixrtc/ToDeviceKeyTransport.ts +3 -3
  120. package/src/matrixrtc/membershipData/rtc.ts +1 -1
  121. package/src/matrixrtc/utils.ts +0 -2
  122. package/src/models/event-timeline-set.ts +3 -3
  123. package/src/models/event.ts +7 -10
  124. package/src/models/invites-ignorer.ts +1 -1
  125. package/src/models/poll.ts +1 -1
  126. package/src/models/read-receipt.ts +1 -1
  127. package/src/models/relations-container.ts +55 -19
  128. package/src/models/relations.ts +1 -1
  129. package/src/models/room.ts +9 -9
  130. package/src/models/thread.ts +49 -4
  131. package/src/oauth/authorize.ts +1 -1
  132. package/src/oauth/index.ts +2 -2
  133. package/src/pollingCachedValue.ts +184 -0
  134. package/src/pushprocessor.ts +3 -3
  135. package/src/receipt-accumulator.ts +1 -2
  136. package/src/rendezvous/MSC4108SignInWithQR.ts +3 -4
  137. package/src/rtcTransportsCachedValue.ts +40 -0
  138. package/src/rust-crypto/PerSessionKeyBackupDownloader.ts +1 -1
  139. package/src/rust-crypto/backup.ts +1 -5
  140. package/src/rust-crypto/index.ts +23 -25
  141. package/src/rust-crypto/libolm_migration.ts +1 -1
  142. package/src/rust-crypto/rust-crypto.ts +3 -3
  143. package/src/sliding-sync-sdk.ts +1 -1
  144. package/src/sliding-sync.ts +1 -1
  145. package/src/store/indexeddb-local-backend.ts +1 -1
  146. package/src/store/indexeddb-store-worker.ts +1 -0
  147. package/src/sync.ts +4 -3
  148. package/src/utils.ts +3 -2
  149. package/src/webrtc/call.ts +6 -6
  150. package/src/webrtc/groupCall.ts +7 -7
  151. package/src/webrtc/mediaHandler.ts +1 -1
  152. package/src/webrtc/stats/callStatsReportGatherer.ts +2 -2
  153. package/src/webrtc/stats/transportStatsBuilder.ts +1 -1
  154. package/src/wellKnownCachedValue.ts +34 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/oauth/index.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport {\n type BearerTokenResponse,\n type DeviceAccessTokenError,\n type DeviceAccessTokenResponse,\n type DeviceAuthorizationResponse,\n generateScope,\n normalizeBearerTokenResponseTokenType,\n startDeviceAuthorization,\n validateBearerTokenResponse,\n waitForDeviceAuthorization,\n} from \"./authorize.ts\";\nimport type { ValidatedAuthMetadata } from \"./discover.ts\";\nimport {\n OAuthGrantType,\n type OAuthRegistrationRequest,\n urlHasCommonBase,\n validateRegistrationResponse,\n} from \"./register.ts\";\nimport { encodeUnpaddedBase64Url } from \"../base64.ts\";\nimport { sha256 } from \"../digest.ts\";\nimport { HTTPError, Method } from \"../http-api\";\nimport { logger } from \"../logger.ts\";\nimport { OAuth2Error } from \"./error.ts\";\nimport { secureRandomString } from \"../randomstring.ts\";\nimport { type NonEmptyArray } from \"../@types/common.ts\";\n\nexport * from \"./authorize.ts\";\nexport * from \"./error.ts\";\nexport * from \"./register.ts\";\nexport * from \"./tokenRefresher.ts\";\nexport * from \"./discover.ts\";\n\n/**\n * Type representing the persistent context needed for typical OAuth flows\n */\ntype Context = {\n /** The OAuth client ID */\n clientId: string;\n /** The desired device ID */\n deviceId?: string;\n /** The seed used to generate the challenge code */\n codeVerifier?: string;\n /** The URI to redirect the user to with credentials after auth */\n redirectUri: string;\n};\n\nexport class OAuth2 {\n /**\n * Attempts dynamic registration against the configured registration endpoint.\n * Will ignore any URIs that do not use client_uri as a common base as per the spec.\n * @param authMetadata - Auth config from {@link MatrixClient.getAuthMetadata}\n * @param clientMetadata - The metadata for the client which to register,\n * grant_types & response_types & token_endpoint_auth_method will be sanely calculated if omitted.\n * @returns Promise<string> resolved with registered clientId\n * @throws when registration is not supported, on failed request or invalid response\n */\n public static async registerClient(\n authMetadata: ValidatedAuthMetadata,\n clientMetadata: OAuthRegistrationRequest,\n ): Promise<string> {\n const defaultGrantTypes: NonEmptyArray<string> = [\n OAuthGrantType.AuthorizationCode,\n OAuthGrantType.RefreshToken,\n ];\n // ask for device authorization grant if supported\n if (authMetadata.grant_types_supported.includes(OAuthGrantType.DeviceAuthorization)) {\n defaultGrantTypes.push(OAuthGrantType.DeviceAuthorization);\n }\n\n const grantTypes = clientMetadata.grant_types ?? defaultGrantTypes;\n if (grantTypes.some((scope) => !authMetadata.grant_types_supported.includes(scope))) {\n throw new Error(OAuth2Error.DynamicRegistrationNotSupported);\n }\n\n const commonBase = new URL(clientMetadata.client_uri);\n\n const request: OAuthRegistrationRequest = {\n // Apply some defaults\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n ...clientMetadata,\n grant_types: grantTypes,\n logo_uri: urlHasCommonBase(commonBase, clientMetadata.logo_uri) ? clientMetadata.logo_uri : undefined,\n policy_uri: urlHasCommonBase(commonBase, clientMetadata.policy_uri) ? clientMetadata.policy_uri : undefined,\n tos_uri: urlHasCommonBase(commonBase, clientMetadata.tos_uri) ? clientMetadata.tos_uri : undefined,\n };\n\n try {\n const response = await fetch(authMetadata.registration_endpoint, {\n method: Method.Post,\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (response.status >= 400) {\n throw new Error(OAuth2Error.DynamicRegistrationFailed);\n }\n\n const registrationResponse = await response.json();\n if (validateRegistrationResponse(registrationResponse)) {\n return registrationResponse.client_id;\n }\n\n throw new Error(OAuth2Error.DynamicRegistrationInvalid);\n } catch (error) {\n if (Object.values(OAuth2Error).includes((error as Error).message as OAuth2Error)) {\n throw error;\n } else {\n logger.error(\"Dynamic registration request failed\", error);\n throw new Error(OAuth2Error.DynamicRegistrationFailed);\n }\n }\n }\n\n public readonly context: Required<Context>;\n\n public constructor(\n public readonly metadata: ValidatedAuthMetadata,\n context: Context,\n ) {\n this.context = {\n clientId: context.clientId,\n redirectUri: context.redirectUri,\n deviceId: context.deviceId ?? secureRandomString(10),\n codeVerifier: context.codeVerifier ?? secureRandomString(96),\n };\n }\n\n /**\n * Generate a URL to attempt authorization with the OP\n * See https://spec.matrix.org/v1.18/client-server-api/#authorization-code-flow\n * @param state - A unique opaque identifier, like a transaction ID,\n * that will allow the client to maintain state between the authorization request and the callback.\n * The app should use this to key the storage for where the rest of the auth context is saved.\n * @param responseMode - The manner in which the IdP should send the secrets back to the app. Defaults to `fragment` for privacy.\n * @param prompt - Optional prompt parameter to pass to the IdP to signal intent, e.g. `create` for User registration.\n * @param scope - The OAuth2 scope to request, will be generated based on the device ID if omitted.\n * @returns a Promise with the url as a string\n */\n public async generateAuthorizationCodeGrantUrl(\n state: string,\n responseMode: \"fragment\" | \"query\" = \"fragment\",\n prompt?: string,\n scope?: string,\n ): Promise<string> {\n const challenge = encodeUnpaddedBase64Url(await sha256(this.context.codeVerifier));\n\n const url = new URL(this.metadata.authorization_endpoint);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"response_mode\", responseMode);\n url.searchParams.set(\"client_id\", this.context.clientId);\n url.searchParams.set(\"redirect_uri\", this.context.redirectUri);\n url.searchParams.set(\"scope\", scope ?? generateScope(this.context.deviceId));\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"code_challenge\", challenge);\n\n if (prompt) {\n url.searchParams.set(\"prompt\", prompt);\n }\n\n return url.toString();\n }\n\n /**\n * Attempt to exchange authorization code for bearer token.\n *\n * Takes the authorization code returned by the OAuth2 Provider via the authorization URL, and makes a\n * request to the Token Endpoint, to obtain the access token, refresh token, etc.\n *\n * @param code - authorization code as returned by IdP during authorization\n * @returns a validated bearer token response\n * @throws An `Error` with `message` set to an entry in {@link OAuth2Error},\n * when the request fails, or the returned token response is invalid.\n */\n public async completeAuthorizationCodeGrant(code: string): Promise<BearerTokenResponse> {\n const params = new URLSearchParams();\n params.append(\"grant_type\", \"authorization_code\");\n params.append(\"client_id\", this.context.clientId);\n params.append(\"code_verifier\", this.context.codeVerifier);\n params.append(\"redirect_uri\", this.context.redirectUri);\n params.append(\"code\", code);\n\n const tokenResponse = await this.fetch(\"token\", params, OAuth2Error.CodeExchangeFailed);\n\n // throws when response is invalid\n validateBearerTokenResponse(tokenResponse);\n return normalizeBearerTokenResponseTokenType(tokenResponse);\n }\n\n /**\n * Refresh the access token using the given refresh token and the refresh token grant\n * @param refreshToken - the token to use to refresh the access token\n */\n public async performRefreshTokenGrant(refreshToken: string): Promise<BearerTokenResponse> {\n const params = new URLSearchParams();\n params.append(\"grant_type\", \"refresh_token\");\n params.append(\"client_id\", this.context.clientId);\n params.append(\"refresh_token\", refreshToken);\n\n const tokenResponse = await this.fetch(\"token\", params, OAuth2Error.RefreshTokenFailed);\n\n // throws when response is invalid\n validateBearerTokenResponse(tokenResponse);\n return normalizeBearerTokenResponseTokenType(tokenResponse);\n }\n\n /**\n * Revokes the given token\n * @param token - the token to remove\n * @param type - the type of token, acts as a hint to the IdP\n */\n public async revokeToken(token: string, type?: \"access_token\" | \"refresh_token\"): Promise<void> {\n const params = new URLSearchParams();\n params.append(\"token\", token);\n params.append(\"client_id\", this.context.clientId);\n if (type) {\n params.append(\"token_type_hint\", type);\n }\n\n await this.fetch(\"revocation\", params, OAuth2Error.RevokeTokenFailed);\n\n const headers = new Headers();\n headers.set(\"Content-Type\", \"application/x-www-form-urlencoded\");\n }\n\n /**\n * Begin OAuth2 device authorization flow.\n * @param scope - the scope to request for authorization.\n * @returns a promise that resolves to a device access token response,\n * or an error response if the user denies authorization or the device code expires.\n */\n public async startDeviceAuthorizationGrant(scope?: string): Promise<DeviceAuthorizationResponse> {\n return startDeviceAuthorization({\n scope: scope ?? generateScope(this.context.deviceId),\n metadata: this.metadata,\n clientId: this.context.clientId,\n });\n }\n\n /**\n * Polls the OAuth2 token endpoint until we get a device access token response, or encounter an unrecoverable error.\n * @param session - The session returned from a previous call to {@link OAuth2.startDeviceAuthorizationGrant}.\n * @returns a promise that resolves to a device access token response,\n * or an error response if the user denies authorization or the device code expires.\n */\n public async waitForDeviceAuthorizationGrant(\n session: DeviceAuthorizationResponse,\n ): Promise<DeviceAccessTokenResponse | DeviceAccessTokenError> {\n return waitForDeviceAuthorization({\n session,\n metadata: this.metadata,\n clientId: this.context.clientId,\n });\n }\n\n private async fetch(\n target: \"token\" | \"registration\" | \"revocation\",\n params: URLSearchParams,\n error: OAuth2Error,\n ): Promise<unknown> {\n const url = this.metadata[`${target}_endpoint`];\n const res = await fetch(url, {\n method: Method.Post,\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n \"Accept\": \"application/json\",\n },\n body: params,\n });\n\n if (res.status >= 400) {\n throw new HTTPError(error, res.status, res.headers);\n }\n\n return await res.json();\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/oauth/index.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport {\n type BearerTokenResponse,\n type DeviceAccessTokenError,\n type DeviceAccessTokenResponse,\n type DeviceAuthorizationResponse,\n generateScope,\n normalizeBearerTokenResponseTokenType,\n startDeviceAuthorization,\n validateBearerTokenResponse,\n waitForDeviceAuthorization,\n} from \"./authorize.ts\";\nimport type { ValidatedAuthMetadata } from \"./discover.ts\";\nimport {\n OAuthGrantType,\n type OAuthRegistrationRequest,\n urlHasCommonBase,\n validateRegistrationResponse,\n} from \"./register.ts\";\nimport { encodeUnpaddedBase64Url } from \"../base64.ts\";\nimport { sha256 } from \"../digest.ts\";\nimport { HTTPError, Method } from \"../http-api/index.ts\";\nimport { logger } from \"../logger.ts\";\nimport { OAuth2Error } from \"./error.ts\";\nimport { secureRandomString } from \"../randomstring.ts\";\nimport { type NonEmptyArray } from \"../@types/common.ts\";\n\nexport * from \"./authorize.ts\";\nexport * from \"./error.ts\";\nexport * from \"./register.ts\";\nexport * from \"./tokenRefresher.ts\";\nexport * from \"./discover.ts\";\n\n/**\n * Type representing the persistent context needed for typical OAuth flows\n */\ntype Context = {\n /** The OAuth client ID */\n clientId: string;\n /** The desired device ID */\n deviceId?: string;\n /** The seed used to generate the challenge code */\n codeVerifier?: string;\n /** The URI to redirect the user to with credentials after auth */\n redirectUri: string;\n};\n\nexport class OAuth2 {\n /**\n * Attempts dynamic registration against the configured registration endpoint.\n * Will ignore any URIs that do not use client_uri as a common base as per the spec.\n * @param authMetadata - Auth config from {@link MatrixClient.getAuthMetadata}\n * @param clientMetadata - The metadata for the client which to register,\n * grant_types & response_types & token_endpoint_auth_method will be sanely calculated if omitted.\n * @returns Promise<string> resolved with registered clientId\n * @throws when registration is not supported, on failed request or invalid response\n */\n public static async registerClient(\n authMetadata: ValidatedAuthMetadata,\n clientMetadata: OAuthRegistrationRequest,\n ): Promise<string> {\n const defaultGrantTypes: NonEmptyArray<string> = [\n OAuthGrantType.AuthorizationCode,\n OAuthGrantType.RefreshToken,\n ];\n // ask for device authorization grant if supported\n if (authMetadata.grant_types_supported.includes(OAuthGrantType.DeviceAuthorization)) {\n defaultGrantTypes.push(OAuthGrantType.DeviceAuthorization);\n }\n\n const grantTypes = clientMetadata.grant_types ?? defaultGrantTypes;\n if (grantTypes.some((scope) => !authMetadata.grant_types_supported.includes(scope))) {\n throw new Error(OAuth2Error.DynamicRegistrationNotSupported);\n }\n\n const commonBase = new URL(clientMetadata.client_uri);\n\n const request: OAuthRegistrationRequest = {\n // Apply some defaults\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n ...clientMetadata,\n grant_types: grantTypes,\n logo_uri: urlHasCommonBase(commonBase, clientMetadata.logo_uri) ? clientMetadata.logo_uri : undefined,\n policy_uri: urlHasCommonBase(commonBase, clientMetadata.policy_uri) ? clientMetadata.policy_uri : undefined,\n tos_uri: urlHasCommonBase(commonBase, clientMetadata.tos_uri) ? clientMetadata.tos_uri : undefined,\n };\n\n try {\n const response = await fetch(authMetadata.registration_endpoint, {\n method: Method.Post,\n headers: {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (response.status >= 400) {\n throw new Error(OAuth2Error.DynamicRegistrationFailed);\n }\n\n const registrationResponse = await response.json();\n if (validateRegistrationResponse(registrationResponse)) {\n return registrationResponse.client_id;\n }\n\n throw new Error(OAuth2Error.DynamicRegistrationInvalid);\n } catch (error) {\n if (Object.values(OAuth2Error).includes((error as Error).message as OAuth2Error)) {\n throw error;\n } else {\n logger.error(\"Dynamic registration request failed\", error);\n throw new Error(OAuth2Error.DynamicRegistrationFailed, { cause: error });\n }\n }\n }\n\n public readonly context: Required<Context>;\n\n public constructor(\n public readonly metadata: ValidatedAuthMetadata,\n context: Context,\n ) {\n this.context = {\n clientId: context.clientId,\n redirectUri: context.redirectUri,\n deviceId: context.deviceId ?? secureRandomString(10),\n codeVerifier: context.codeVerifier ?? secureRandomString(96),\n };\n }\n\n /**\n * Generate a URL to attempt authorization with the OP\n * See https://spec.matrix.org/v1.18/client-server-api/#authorization-code-flow\n * @param state - A unique opaque identifier, like a transaction ID,\n * that will allow the client to maintain state between the authorization request and the callback.\n * The app should use this to key the storage for where the rest of the auth context is saved.\n * @param responseMode - The manner in which the IdP should send the secrets back to the app. Defaults to `fragment` for privacy.\n * @param prompt - Optional prompt parameter to pass to the IdP to signal intent, e.g. `create` for User registration.\n * @param scope - The OAuth2 scope to request, will be generated based on the device ID if omitted.\n * @returns a Promise with the url as a string\n */\n public async generateAuthorizationCodeGrantUrl(\n state: string,\n responseMode: \"fragment\" | \"query\" = \"fragment\",\n prompt?: string,\n scope?: string,\n ): Promise<string> {\n const challenge = encodeUnpaddedBase64Url(await sha256(this.context.codeVerifier));\n\n const url = new URL(this.metadata.authorization_endpoint);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"response_mode\", responseMode);\n url.searchParams.set(\"client_id\", this.context.clientId);\n url.searchParams.set(\"redirect_uri\", this.context.redirectUri);\n url.searchParams.set(\"scope\", scope ?? generateScope(this.context.deviceId));\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"code_challenge\", challenge);\n\n if (prompt) {\n url.searchParams.set(\"prompt\", prompt);\n }\n\n return url.toString();\n }\n\n /**\n * Attempt to exchange authorization code for bearer token.\n *\n * Takes the authorization code returned by the OAuth2 Provider via the authorization URL, and makes a\n * request to the Token Endpoint, to obtain the access token, refresh token, etc.\n *\n * @param code - authorization code as returned by IdP during authorization\n * @returns a validated bearer token response\n * @throws An `Error` with `message` set to an entry in {@link OAuth2Error},\n * when the request fails, or the returned token response is invalid.\n */\n public async completeAuthorizationCodeGrant(code: string): Promise<BearerTokenResponse> {\n const params = new URLSearchParams();\n params.append(\"grant_type\", \"authorization_code\");\n params.append(\"client_id\", this.context.clientId);\n params.append(\"code_verifier\", this.context.codeVerifier);\n params.append(\"redirect_uri\", this.context.redirectUri);\n params.append(\"code\", code);\n\n const tokenResponse = await this.fetch(\"token\", params, OAuth2Error.CodeExchangeFailed);\n\n // throws when response is invalid\n validateBearerTokenResponse(tokenResponse);\n return normalizeBearerTokenResponseTokenType(tokenResponse);\n }\n\n /**\n * Refresh the access token using the given refresh token and the refresh token grant\n * @param refreshToken - the token to use to refresh the access token\n */\n public async performRefreshTokenGrant(refreshToken: string): Promise<BearerTokenResponse> {\n const params = new URLSearchParams();\n params.append(\"grant_type\", \"refresh_token\");\n params.append(\"client_id\", this.context.clientId);\n params.append(\"refresh_token\", refreshToken);\n\n const tokenResponse = await this.fetch(\"token\", params, OAuth2Error.RefreshTokenFailed);\n\n // throws when response is invalid\n validateBearerTokenResponse(tokenResponse);\n return normalizeBearerTokenResponseTokenType(tokenResponse);\n }\n\n /**\n * Revokes the given token\n * @param token - the token to remove\n * @param type - the type of token, acts as a hint to the IdP\n */\n public async revokeToken(token: string, type?: \"access_token\" | \"refresh_token\"): Promise<void> {\n const params = new URLSearchParams();\n params.append(\"token\", token);\n params.append(\"client_id\", this.context.clientId);\n if (type) {\n params.append(\"token_type_hint\", type);\n }\n\n await this.fetch(\"revocation\", params, OAuth2Error.RevokeTokenFailed);\n\n const headers = new Headers();\n headers.set(\"Content-Type\", \"application/x-www-form-urlencoded\");\n }\n\n /**\n * Begin OAuth2 device authorization flow.\n * @param scope - the scope to request for authorization.\n * @returns a promise that resolves to a device access token response,\n * or an error response if the user denies authorization or the device code expires.\n */\n public async startDeviceAuthorizationGrant(scope?: string): Promise<DeviceAuthorizationResponse> {\n return startDeviceAuthorization({\n scope: scope ?? generateScope(this.context.deviceId),\n metadata: this.metadata,\n clientId: this.context.clientId,\n });\n }\n\n /**\n * Polls the OAuth2 token endpoint until we get a device access token response, or encounter an unrecoverable error.\n * @param session - The session returned from a previous call to {@link OAuth2.startDeviceAuthorizationGrant}.\n * @returns a promise that resolves to a device access token response,\n * or an error response if the user denies authorization or the device code expires.\n */\n public async waitForDeviceAuthorizationGrant(\n session: DeviceAuthorizationResponse,\n ): Promise<DeviceAccessTokenResponse | DeviceAccessTokenError> {\n return waitForDeviceAuthorization({\n session,\n metadata: this.metadata,\n clientId: this.context.clientId,\n });\n }\n\n private async fetch(\n target: \"token\" | \"registration\" | \"revocation\",\n params: URLSearchParams,\n error: OAuth2Error,\n ): Promise<unknown> {\n const url = this.metadata[`${target}_endpoint`];\n const res = await fetch(url, {\n method: Method.Post,\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n \"Accept\": \"application/json\",\n },\n body: params,\n });\n\n if (res.status >= 400) {\n throw new HTTPError(error, res.status, res.headers);\n }\n\n return await res.json();\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,77 @@
1
+ import { type Logger } from "./logger.ts";
2
+ /**
3
+ * How to fetch and cache a given value, as passed to {@link PollingCachedValue}.
4
+ */
5
+ export interface PollingCachedValueOptions<ValueType> {
6
+ /** The name of the cached value (for tracing/logs). */
7
+ name: string;
8
+ /** The logger to derive this value's child logger from. */
9
+ logger: Logger;
10
+ /** Fetches a fresh value. Rejections are retried according to the retry policy. */
11
+ fetch: () => Promise<ValueType>;
12
+ /**
13
+ * The default time-to-live before the value gets refreshed, overridable per run
14
+ * via {@link PollingCachedValue.start}.
15
+ * If undefined the value never expires; use {@link PollingCachedValue.refresh} to clear the cache.
16
+ */
17
+ ttlMillis?: number;
18
+ /** Called when a new value is cached. Use to emit changes if needed. */
19
+ onValueCached?: (value: ValueType) => void;
20
+ /**
21
+ * Determines whether a non-transient error should be cached.
22
+ * By default errors are not cached, i.e. the next attempt retries the fetch.
23
+ */
24
+ shouldCacheError?: (error: unknown) => boolean;
25
+ }
26
+ /**
27
+ * Defines a generic mechanism to fetch and cache a value, refreshing it periodically.
28
+ */
29
+ export declare class PollingCachedValue<ValueType> {
30
+ private readonly opts;
31
+ private cached?;
32
+ private fetchPromise?;
33
+ private ttlTimeoutHandle?;
34
+ private isStopped;
35
+ private ttlMillis?;
36
+ private readonly logger;
37
+ /**
38
+ * Build a generic mechanism allowing to fetch and cache a given value.
39
+ * @param opts - Describes what to fetch and how to cache it, see {@link PollingCachedValueOptions}.
40
+ */
41
+ constructor(opts: PollingCachedValueOptions<ValueType>);
42
+ /**
43
+ * Gets the cached value if any.
44
+ */
45
+ get(): ValueType | undefined;
46
+ /**
47
+ * Ensures that the value was fetched once before getting the actual cached value.
48
+ */
49
+ wait(): Promise<ValueType | undefined>;
50
+ /**
51
+ * Call this as early as possible and when the value can already be fetched.
52
+ * @param ttlMillis - The time-to-live before the value gets refreshed, overriding the one
53
+ * given at construction. If omitted the configured default is kept.
54
+ */
55
+ start(ttlMillis?: number): void;
56
+ /**
57
+ * Call when the client is stopped, or when the cached value is no longer needed.
58
+ */
59
+ stop(): void;
60
+ /**
61
+ * Force to refresh.
62
+ * @throws
63
+ */
64
+ refresh(): Promise<ValueType | undefined>;
65
+ /**
66
+ * Internal fetch method
67
+ * @param force - if set to true will force a fetch of the value even if a fetch is already in progress.
68
+ * @private
69
+ */
70
+ private doFetch;
71
+ /**
72
+ * Gracefully handle transient error retries, respect retry_after_millis for rate limits.
73
+ * @private
74
+ */
75
+ private fetchWithRetryPolicy;
76
+ }
77
+ //# sourceMappingURL=pollingCachedValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pollingCachedValue.d.ts","sourceRoot":"","sources":["../src/pollingCachedValue.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,SAAS;IAChD,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,KAAK,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC3C;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CAClD;AAED;;GAEG;AACH,qBAAa,kBAAkB,CAAC,SAAS;IAclB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAbxC,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,YAAY,CAAC,CAAqB;IAC1C,OAAO,CAAC,gBAAgB,CAAC,CAAgC;IAEzD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAC,CAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;OAGG;IACH,YAAoC,IAAI,EAAE,yBAAyB,CAAC,SAAS,CAAC,EAG7E;IAED;;OAEG;IACI,GAAG,IAAI,SAAS,GAAG,SAAS,CAElC;IAED;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAGlD;IAED;;;;OAIG;IACI,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CASrC;IACD;;OAEG;IACI,IAAI,IAAI,IAAI,CAKlB;IAED;;;OAGG;IACU,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAGrD;IAED;;;;OAIG;YACW,OAAO;IAqCrB;;;OAGG;YACW,oBAAoB;CAqBrC"}
@@ -0,0 +1,160 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ /*
3
+ Copyright 2026 The Matrix.org Foundation C.I.C.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+
18
+ import { calculateRetryBackoff } from "./http-api/index.js";
19
+ import { sleep } from "./utils.js";
20
+
21
+ /**
22
+ * How to fetch and cache a given value, as passed to {@link PollingCachedValue}.
23
+ */
24
+
25
+ /**
26
+ * Defines a generic mechanism to fetch and cache a value, refreshing it periodically.
27
+ */
28
+ export class PollingCachedValue {
29
+ /**
30
+ * Build a generic mechanism allowing to fetch and cache a given value.
31
+ * @param opts - Describes what to fetch and how to cache it, see {@link PollingCachedValueOptions}.
32
+ */
33
+ constructor(opts) {
34
+ _defineProperty(this, "cached", void 0);
35
+ _defineProperty(this, "fetchPromise", void 0);
36
+ _defineProperty(this, "ttlTimeoutHandle", void 0);
37
+ _defineProperty(this, "isStopped", false);
38
+ _defineProperty(this, "ttlMillis", void 0);
39
+ _defineProperty(this, "logger", void 0);
40
+ this.opts = opts;
41
+ this.ttlMillis = opts.ttlMillis;
42
+ this.logger = opts.logger.getChild(`PollingCachedValue<${opts.name}>`);
43
+ }
44
+
45
+ /**
46
+ * Gets the cached value if any.
47
+ */
48
+ get() {
49
+ return this.cached;
50
+ }
51
+
52
+ /**
53
+ * Ensures that the value was fetched once before getting the actual cached value.
54
+ */
55
+ async wait() {
56
+ await this.doFetch();
57
+ return this.cached;
58
+ }
59
+
60
+ /**
61
+ * Call this as early as possible and when the value can already be fetched.
62
+ * @param ttlMillis - The time-to-live before the value gets refreshed, overriding the one
63
+ * given at construction. If omitted the configured default is kept.
64
+ */
65
+ start(ttlMillis) {
66
+ if (ttlMillis !== undefined) {
67
+ this.ttlMillis = ttlMillis;
68
+ }
69
+ this.isStopped = false;
70
+ // Request a fetch as soon as possible
71
+ this.doFetch().catch(err => {
72
+ this.logger.debug("Cached value fetch on start did fail", err);
73
+ });
74
+ }
75
+ /**
76
+ * Call when the client is stopped, or when the cached value is no longer needed.
77
+ */
78
+ stop() {
79
+ if (this.ttlTimeoutHandle) {
80
+ clearTimeout(this.ttlTimeoutHandle);
81
+ }
82
+ this.isStopped = true;
83
+ }
84
+
85
+ /**
86
+ * Force to refresh.
87
+ * @throws
88
+ */
89
+ async refresh() {
90
+ await this.doFetch(true);
91
+ return this.cached;
92
+ }
93
+
94
+ /**
95
+ * Internal fetch method
96
+ * @param force - if set to true will force a fetch of the value even if a fetch is already in progress.
97
+ * @private
98
+ */
99
+ async doFetch(force = false) {
100
+ if (this.fetchPromise && !force) {
101
+ await this.fetchPromise;
102
+ return;
103
+ }
104
+ this.fetchPromise = this.fetchWithRetryPolicy();
105
+ try {
106
+ this.cached = await this.fetchPromise;
107
+ if (this.isStopped) {
108
+ this.fetchPromise = undefined;
109
+ return;
110
+ }
111
+ this.logger.trace(`New cachedValue: ${this.cached}`);
112
+ this.opts.onValueCached?.(this.cached);
113
+ // The value is cached only for a given time.
114
+ if (this.ttlMillis) {
115
+ this.ttlTimeoutHandle = setTimeout(() => {
116
+ this.fetchPromise = undefined;
117
+ void this.doFetch();
118
+ }, this.ttlMillis);
119
+ }
120
+ } catch (error) {
121
+ this.logger.debug(`Error fetching server value for ${error}`);
122
+ if (this.isStopped) {
123
+ this.fetchPromise = undefined;
124
+ return;
125
+ }
126
+ if (!this.opts.shouldCacheError?.(error)) {
127
+ // clear the promise, i.e next tentative will retry to fetch
128
+ this.fetchPromise = undefined;
129
+ }
130
+ throw error;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Gracefully handle transient error retries, respect retry_after_millis for rate limits.
136
+ * @private
137
+ */
138
+ async fetchWithRetryPolicy() {
139
+ let currentRetryCount = 0;
140
+ while (true) {
141
+ try {
142
+ return await this.opts.fetch();
143
+ } catch (e) {
144
+ this.logger.trace(`Failed to fetch retry: ${e}`);
145
+ if (this.isStopped) {
146
+ throw e;
147
+ }
148
+ currentRetryCount++;
149
+ const backoff = calculateRetryBackoff(e, currentRetryCount, true);
150
+ if (backoff < 0) {
151
+ // Max number of retries reached, or error is not retryable. rethrow the error
152
+ throw e;
153
+ }
154
+ // wait for the specified time and then retry the request
155
+ await sleep(backoff);
156
+ }
157
+ }
158
+ }
159
+ }
160
+ //# sourceMappingURL=pollingCachedValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pollingCachedValue.js","names":[],"sources":["../src/pollingCachedValue.ts"],"sourcesContent":["/*\nCopyright 2026 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { calculateRetryBackoff } from \"./http-api/index.ts\";\nimport { type Logger } from \"./logger.ts\";\nimport { sleep } from \"./utils.ts\";\n\n/**\n * How to fetch and cache a given value, as passed to {@link PollingCachedValue}.\n */\nexport interface PollingCachedValueOptions<ValueType> {\n /** The name of the cached value (for tracing/logs). */\n name: string;\n /** The logger to derive this value's child logger from. */\n logger: Logger;\n /** Fetches a fresh value. Rejections are retried according to the retry policy. */\n fetch: () => Promise<ValueType>;\n /**\n * The default time-to-live before the value gets refreshed, overridable per run\n * via {@link PollingCachedValue.start}.\n * If undefined the value never expires; use {@link PollingCachedValue.refresh} to clear the cache.\n */\n ttlMillis?: number;\n /** Called when a new value is cached. Use to emit changes if needed. */\n onValueCached?: (value: ValueType) => void;\n /**\n * Determines whether a non-transient error should be cached.\n * By default errors are not cached, i.e. the next attempt retries the fetch.\n */\n shouldCacheError?: (error: unknown) => boolean;\n}\n\n/**\n * Defines a generic mechanism to fetch and cache a value, refreshing it periodically.\n */\nexport class PollingCachedValue<ValueType> {\n private cached?: ValueType;\n private fetchPromise?: Promise<ValueType>;\n private ttlTimeoutHandle?: ReturnType<typeof setTimeout>;\n\n private isStopped = false;\n private ttlMillis?: number;\n\n private readonly logger: Logger;\n\n /**\n * Build a generic mechanism allowing to fetch and cache a given value.\n * @param opts - Describes what to fetch and how to cache it, see {@link PollingCachedValueOptions}.\n */\n public constructor(private readonly opts: PollingCachedValueOptions<ValueType>) {\n this.ttlMillis = opts.ttlMillis;\n this.logger = opts.logger.getChild(`PollingCachedValue<${opts.name}>`);\n }\n\n /**\n * Gets the cached value if any.\n */\n public get(): ValueType | undefined {\n return this.cached;\n }\n\n /**\n * Ensures that the value was fetched once before getting the actual cached value.\n */\n public async wait(): Promise<ValueType | undefined> {\n await this.doFetch();\n return this.cached;\n }\n\n /**\n * Call this as early as possible and when the value can already be fetched.\n * @param ttlMillis - The time-to-live before the value gets refreshed, overriding the one\n * given at construction. If omitted the configured default is kept.\n */\n public start(ttlMillis?: number): void {\n if (ttlMillis !== undefined) {\n this.ttlMillis = ttlMillis;\n }\n this.isStopped = false;\n // Request a fetch as soon as possible\n this.doFetch().catch((err) => {\n this.logger.debug(\"Cached value fetch on start did fail\", err);\n });\n }\n /**\n * Call when the client is stopped, or when the cached value is no longer needed.\n */\n public stop(): void {\n if (this.ttlTimeoutHandle) {\n clearTimeout(this.ttlTimeoutHandle);\n }\n this.isStopped = true;\n }\n\n /**\n * Force to refresh.\n * @throws\n */\n public async refresh(): Promise<ValueType | undefined> {\n await this.doFetch(true);\n return this.cached;\n }\n\n /**\n * Internal fetch method\n * @param force - if set to true will force a fetch of the value even if a fetch is already in progress.\n * @private\n */\n private async doFetch(force: boolean = false): Promise<void> {\n if (this.fetchPromise && !force) {\n await this.fetchPromise;\n return;\n }\n\n this.fetchPromise = this.fetchWithRetryPolicy();\n\n try {\n this.cached = await this.fetchPromise;\n if (this.isStopped) {\n this.fetchPromise = undefined;\n return;\n }\n this.logger.trace(`New cachedValue: ${this.cached}`);\n this.opts.onValueCached?.(this.cached);\n // The value is cached only for a given time.\n if (this.ttlMillis) {\n this.ttlTimeoutHandle = setTimeout(() => {\n this.fetchPromise = undefined;\n void this.doFetch();\n }, this.ttlMillis);\n }\n } catch (error) {\n this.logger.debug(`Error fetching server value for ${error}`);\n if (this.isStopped) {\n this.fetchPromise = undefined;\n return;\n }\n if (!this.opts.shouldCacheError?.(error)) {\n // clear the promise, i.e next tentative will retry to fetch\n this.fetchPromise = undefined;\n }\n throw error;\n }\n }\n\n /**\n * Gracefully handle transient error retries, respect retry_after_millis for rate limits.\n * @private\n */\n private async fetchWithRetryPolicy(): Promise<ValueType> {\n let currentRetryCount = 0;\n while (true) {\n try {\n return await this.opts.fetch();\n } catch (e) {\n this.logger.trace(`Failed to fetch retry: ${e}`);\n if (this.isStopped) {\n throw e;\n }\n currentRetryCount++;\n const backoff = calculateRetryBackoff(e, currentRetryCount, true);\n if (backoff < 0) {\n // Max number of retries reached, or error is not retryable. rethrow the error\n throw e;\n }\n // wait for the specified time and then retry the request\n await sleep(backoff);\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"pushprocessor.js","names":[],"sources":["../src/pushprocessor.ts"],"sourcesContent":["/*\nCopyright 2015 - 2021 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { deepCompare, escapeRegExp, globToRegexp, isNullOrUndefined } from \"./utils.ts\";\nimport { type Logger } from \"./logger.ts\";\nimport { type MatrixClient } from \"./client.ts\";\nimport { type MatrixEvent } from \"./models/event.ts\";\nimport {\n ConditionKind,\n type IAnnotatedPushRule,\n type ICallStartedCondition,\n type ICallStartedPrefixCondition,\n type IContainsDisplayNameCondition,\n type IEventMatchCondition,\n type IEventPropertyContainsCondition,\n type IEventPropertyIsCondition,\n type IPushRule,\n type IPushRules,\n type IRoomMemberCountCondition,\n type ISenderNotificationPermissionCondition,\n type PushRuleAction,\n PushRuleActionName,\n type PushRuleCondition,\n PushRuleKind,\n type PushRuleSet,\n RuleId,\n TweakName,\n} from \"./@types/PushRules.ts\";\nimport { EventType } from \"./@types/event.ts\";\n\nconst RULEKINDS_IN_ORDER = [\n PushRuleKind.Override,\n PushRuleKind.ContentSpecific,\n PushRuleKind.RoomSpecific,\n PushRuleKind.SenderSpecific,\n PushRuleKind.Underride,\n];\n\n// The default override rules to apply to the push rules that arrive from the server.\n// We do this for two reasons:\n// 1. Synapse is unlikely to send us the push rule in an incremental sync - see\n// https://github.com/matrix-org/synapse/pull/4867#issuecomment-481446072 for\n// more details.\n// 2. We often want to start using push rules ahead of the server supporting them,\n// and so we can put them here.\nconst DEFAULT_OVERRIDE_RULES: Record<string, IPushRule> = {\n \".m.rule.is_room_mention\": {\n // Matrix v1.7\n rule_id: \".m.rule.is_room_mention\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventPropertyIs,\n key: \"content.m\\\\.mentions.room\",\n value: true,\n },\n {\n kind: ConditionKind.SenderNotificationPermission,\n key: \"room\",\n },\n ],\n actions: [\n PushRuleActionName.Notify,\n {\n set_tweak: TweakName.Highlight,\n },\n ],\n },\n \".m.rule.reaction\": {\n // For homeservers which don't support MSC2153 yet\n rule_id: \".m.rule.reaction\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: \"m.reaction\",\n },\n ],\n actions: [PushRuleActionName.DontNotify],\n },\n \".org.matrix.msc3786.rule.room.server_acl\": {\n // For homeservers which don't support MSC3786 yet\n rule_id: \".org.matrix.msc3786.rule.room.server_acl\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: EventType.RoomServerAcl,\n },\n {\n kind: ConditionKind.EventMatch,\n key: \"state_key\",\n pattern: \"\",\n },\n ],\n actions: [],\n },\n};\n\n// A special rule id for `EXPECTED_DEFAULT_OVERRIDE_RULE_IDS` and friends which denotes where user-defined rules live in the order.\nconst UserDefinedRules = Symbol(\"UserDefinedRules\");\n\ntype OrderedRules = Array<string | typeof UserDefinedRules>;\n\nconst EXPECTED_DEFAULT_OVERRIDE_RULE_IDS: OrderedRules = [\n RuleId.Master,\n UserDefinedRules,\n RuleId.SuppressNotices,\n RuleId.InviteToSelf,\n RuleId.MemberEvent,\n RuleId.IsUserMention,\n RuleId.ContainsDisplayName,\n RuleId.IsRoomMention,\n RuleId.AtRoomNotification,\n RuleId.Tombstone,\n \".m.rule.reaction\",\n \".m.rule.room.server_acl\",\n \".org.matrix.msc3786.rule.room.server_acl\",\n \".m.rule.suppress_edits\",\n];\n\nconst DEFAULT_UNDERRIDE_RULES: Record<string, IPushRule> = {\n \".org.matrix.msc3914.rule.room.call\": {\n // For homeservers which don't support MSC3914 yet\n rule_id: \".org.matrix.msc3914.rule.room.call\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: \"org.matrix.msc3401.call\",\n },\n {\n kind: ConditionKind.CallStarted,\n },\n ],\n actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: \"default\" }],\n },\n};\n\nconst EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS: OrderedRules = [\n UserDefinedRules,\n RuleId.IncomingCall,\n \".org.matrix.msc3914.rule.room.call\",\n RuleId.EncryptedDM,\n RuleId.DM,\n RuleId.Message,\n RuleId.EncryptedMessage,\n];\n\n/**\n * Make sure that each of the rules listed in `defaultRuleIds` is listed in the given set of push rules.\n *\n * @param logger - A `Logger` to write log messages to.\n * @param kind - the kind of push rule set being merged.\n * @param incomingRules - the existing set of known push rules for the user.\n * @param defaultRules - a lookup table for the default definitions of push rules.\n * @param orderedRuleIds - the IDs of the expected push rules, in order.\n *\n * @returns A copy of `incomingRules`, with any missing default rules inserted in the right place.\n */\nfunction mergeRulesWithDefaults(\n logger: Logger,\n kind: PushRuleKind,\n incomingRules: IPushRule[],\n defaultRules: Record<string, IPushRule>,\n orderedRuleIds: OrderedRules,\n): IPushRule[] {\n // Split the incomingRules into defaults and custom\n const incomingDefaultRules = incomingRules.filter((rule) => rule.default);\n const incomingCustomRules = incomingRules.filter((rule) => !rule.default);\n\n function insertDefaultPushRule(ruleId: OrderedRules[number]): void {\n if (ruleId === UserDefinedRules) {\n // Re-insert any user-defined rules that were in `incomingRules`\n newRules.push(...incomingCustomRules);\n } else if (ruleId in defaultRules) {\n logger.warn(`Adding default global ${kind} push rule ${ruleId}`);\n newRules.push(defaultRules[ruleId]);\n } else {\n logger.warn(`Missing default global ${kind} push rule ${ruleId}`);\n }\n }\n\n let nextExpectedRuleIdIndex = 0;\n const newRules: IPushRule[] = [];\n // Merge our expected rules (including the incoming custom rules) into the incoming default rules.\n for (const rule of incomingDefaultRules) {\n const ruleIndex = orderedRuleIds.indexOf(rule.rule_id);\n if (ruleIndex === -1) {\n // an unrecognised rule; copy it over\n newRules.push(rule);\n continue;\n }\n while (ruleIndex > nextExpectedRuleIdIndex) {\n // insert new rules\n const defaultRuleId = orderedRuleIds[nextExpectedRuleIdIndex];\n insertDefaultPushRule(defaultRuleId);\n nextExpectedRuleIdIndex += 1;\n }\n // copy over the existing rule\n newRules.push(rule);\n nextExpectedRuleIdIndex += 1;\n }\n\n // Now copy over any remaining default rules\n for (const ruleId of orderedRuleIds.slice(nextExpectedRuleIdIndex)) {\n insertDefaultPushRule(ruleId);\n }\n\n return newRules;\n}\n\nexport interface IActionsObject {\n /** Whether this event should notify the user or not. */\n notify: boolean;\n /** How this event should be notified. */\n tweaks: Partial<Record<TweakName, any>>;\n}\n\nexport class PushProcessor {\n /**\n * Construct a Push Processor.\n * @param client - The Matrix client object to use\n */\n public constructor(private readonly client: MatrixClient) {}\n\n /**\n * Maps the original key from the push rules to a list of property names\n * after unescaping.\n */\n private readonly parsedKeys = new Map<string, string[]>();\n\n /**\n * Convert a list of actions into a object with the actions as keys and their values\n * @example\n * eg. `[ 'notify', { set_tweak: 'sound', value: 'default' } ]`\n * becomes `{ notify: true, tweaks: { sound: 'default' } }`\n * @param actionList - The actions list\n *\n * @returns A object with key 'notify' (true or false) and an object of actions\n */\n public static actionListToActionsObject(actionList: PushRuleAction[]): IActionsObject {\n const actionObj: IActionsObject = { notify: false, tweaks: {} };\n for (const action of actionList) {\n if (action === PushRuleActionName.Notify) {\n actionObj.notify = true;\n } else if (typeof action === \"object\") {\n if (action.value === undefined) {\n action.value = true;\n }\n actionObj.tweaks[action.set_tweak] = action.value;\n }\n }\n return actionObj;\n }\n\n /**\n * Rewrites conditions on a client's push rules to match the defaults\n * where applicable. Useful for upgrading push rules to more strict\n * conditions when the server is falling behind on defaults.\n *\n * @param logger - A `Logger` to write log messages to.\n * @param incomingRules - The client's existing push rules\n * @param userId - The Matrix ID of the client.\n * @returns The rewritten rules\n */\n public static rewriteDefaultRules(\n logger: Logger,\n incomingRules: IPushRules,\n userId: string | undefined = undefined,\n ): IPushRules {\n let newRules: IPushRules = JSON.parse(JSON.stringify(incomingRules)); // deep clone\n\n // These lines are mostly to make the tests happy. We shouldn't run into these\n // properties missing in practice.\n if (!newRules) newRules = {} as IPushRules;\n if (!newRules.global) newRules.global = {} as PushRuleSet;\n if (!newRules.global.override) newRules.global.override = [];\n if (!newRules.global.underride) newRules.global.underride = [];\n\n // Merge the client-level defaults with the ones from the server\n newRules.global.override = mergeRulesWithDefaults(\n logger,\n PushRuleKind.Override,\n newRules.global.override,\n DEFAULT_OVERRIDE_RULES,\n EXPECTED_DEFAULT_OVERRIDE_RULE_IDS,\n );\n\n newRules.global.underride = mergeRulesWithDefaults(\n logger,\n PushRuleKind.Underride,\n newRules.global.underride,\n DEFAULT_UNDERRIDE_RULES,\n EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS,\n );\n\n return newRules;\n }\n\n /**\n * Create a RegExp object for the given glob pattern with a single capture group around the pattern itself, caching the result.\n * No cache invalidation is present currently,\n * as this will be inherently bounded to the size of the user's own push rules.\n * @param pattern - the glob pattern to convert to a RegExp\n * @param alignToWordBoundary - whether to align the pattern to word boundaries,\n * as specified for `content.body` matches, will use lookaround assertions to ensure the match only includes the pattern\n * @param flags - the flags to pass to the RegExp constructor, defaults to case-insensitive\n */\n public static getPushRuleGlobRegex(pattern: string, alignToWordBoundary = false, flags = \"i\"): RegExp {\n const [prefix, suffix] = alignToWordBoundary ? [\"(?<=^|\\\\W)\", \"(?=\\\\W|$)\"] : [\"^\", \"$\"];\n const cacheKey = `${alignToWordBoundary}-${flags}-${pattern}`;\n\n if (!PushProcessor.cachedGlobToRegex[cacheKey]) {\n PushProcessor.cachedGlobToRegex[cacheKey] = new RegExp(\n prefix + \"(\" + globToRegexp(pattern) + \")\" + suffix,\n flags,\n );\n }\n return PushProcessor.cachedGlobToRegex[cacheKey];\n }\n\n /**\n * Pre-caches the parsed keys for push rules and cleans out any obsolete cache\n * entries. Should be called after push rules are updated.\n * @param newRules - The new push rules.\n */\n public updateCachedPushRuleKeys(newRules: IPushRules): void {\n // These lines are mostly to make the tests happy. We shouldn't run into these\n // properties missing in practice.\n if (!newRules) newRules = {} as IPushRules;\n if (!newRules.global) newRules.global = {} as PushRuleSet;\n if (!newRules.global.override) newRules.global.override = [];\n if (!newRules.global.room) newRules.global.room = [];\n if (!newRules.global.sender) newRules.global.sender = [];\n if (!newRules.global.underride) newRules.global.underride = [];\n\n // Process the 'key' property on event_match conditions pre-cache the\n // values and clean-out any unused values.\n const toRemoveKeys = new Set(this.parsedKeys.keys());\n for (const ruleset of [\n newRules.global.override,\n newRules.global.room,\n newRules.global.sender,\n newRules.global.underride,\n ]) {\n for (const rule of ruleset) {\n if (!rule.conditions) {\n continue;\n }\n\n for (const condition of rule.conditions) {\n if (condition.kind !== ConditionKind.EventMatch) {\n continue;\n }\n\n // Ensure we keep this key.\n toRemoveKeys.delete(condition.key);\n\n // Pre-process the key.\n this.parsedKeys.set(condition.key, PushProcessor.partsForDottedKey(condition.key));\n }\n }\n }\n // Any keys that were previously cached, but are no longer needed should\n // be removed.\n toRemoveKeys.forEach((k) => this.parsedKeys.delete(k));\n }\n\n private static cachedGlobToRegex: Record<string, RegExp> = {}; // $glob: RegExp\n\n private matchingRuleFromKindSet(ev: MatrixEvent, kindset: PushRuleSet): IAnnotatedPushRule | null {\n for (const kind of RULEKINDS_IN_ORDER) {\n const ruleset = kindset[kind];\n if (!ruleset) {\n continue;\n }\n\n for (const rule of ruleset) {\n if (!rule.enabled) {\n continue;\n }\n\n const rawrule = this.templateRuleToRaw(kind, rule);\n if (!rawrule) {\n continue;\n }\n\n if (this.ruleMatchesEvent(rawrule, ev)) {\n return {\n ...rule,\n kind,\n };\n }\n }\n }\n return null;\n }\n\n private templateRuleToRaw(\n kind: PushRuleKind,\n tprule: IPushRule,\n ): Pick<IPushRule, \"rule_id\" | \"actions\" | \"conditions\"> | null {\n const rawrule: Pick<IPushRule, \"rule_id\" | \"actions\" | \"conditions\"> = {\n rule_id: tprule.rule_id,\n actions: tprule.actions,\n conditions: [],\n };\n switch (kind) {\n case PushRuleKind.Underride:\n case PushRuleKind.Override:\n rawrule.conditions = tprule.conditions;\n break;\n case PushRuleKind.RoomSpecific:\n if (!tprule.rule_id) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"room_id\",\n value: tprule.rule_id,\n });\n break;\n case PushRuleKind.SenderSpecific:\n if (!tprule.rule_id) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"user_id\",\n value: tprule.rule_id,\n });\n break;\n case PushRuleKind.ContentSpecific:\n if (!tprule.pattern) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"content.body\",\n pattern: tprule.pattern,\n });\n break;\n }\n return rawrule;\n }\n\n private eventFulfillsCondition(cond: PushRuleCondition, ev: MatrixEvent): boolean {\n switch (cond.kind) {\n case ConditionKind.EventMatch:\n return this.eventFulfillsEventMatchCondition(cond, ev);\n case ConditionKind.EventPropertyIs:\n return this.eventFulfillsEventPropertyIsCondition(cond, ev);\n case ConditionKind.EventPropertyContains:\n return this.eventFulfillsEventPropertyContains(cond, ev);\n case ConditionKind.ContainsDisplayName:\n return this.eventFulfillsDisplayNameCondition(cond, ev);\n case ConditionKind.RoomMemberCount:\n return this.eventFulfillsRoomMemberCountCondition(cond, ev);\n case ConditionKind.SenderNotificationPermission:\n return this.eventFulfillsSenderNotifPermCondition(cond, ev);\n case ConditionKind.CallStarted:\n case ConditionKind.CallStartedPrefix:\n return this.eventFulfillsCallStartedCondition(cond, ev);\n }\n\n // unknown conditions: we previously matched all unknown conditions,\n // but given that rules can be added to the base rules on a server,\n // it's probably better to not match unknown conditions.\n return false;\n }\n\n private eventFulfillsSenderNotifPermCondition(\n cond: ISenderNotificationPermissionCondition,\n ev: MatrixEvent,\n ): boolean {\n const notifLevelKey = cond[\"key\"];\n if (!notifLevelKey) {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n if (!room?.currentState) {\n return false;\n }\n\n // Note that this should not be the current state of the room but the state at\n // the point the event is in the DAG. Unfortunately the js-sdk does not store\n // this.\n return room.currentState.mayTriggerNotifOfType(notifLevelKey, ev.getSender()!);\n }\n\n private eventFulfillsRoomMemberCountCondition(cond: IRoomMemberCountCondition, ev: MatrixEvent): boolean {\n if (!cond.is) {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n if (!room || !room.currentState || !room.currentState.members) {\n return false;\n }\n\n const memberCount = room.currentState.getJoinedMemberCount();\n\n const m = cond.is.match(/^([=<>]*)(\\d*)$/);\n if (!m) {\n return false;\n }\n const ineq = m[1];\n const rhs = parseInt(m[2]);\n if (isNaN(rhs)) {\n return false;\n }\n switch (ineq) {\n case \"\":\n case \"==\":\n return memberCount == rhs;\n case \"<\":\n return memberCount < rhs;\n case \">\":\n return memberCount > rhs;\n case \"<=\":\n return memberCount <= rhs;\n case \">=\":\n return memberCount >= rhs;\n default:\n return false;\n }\n }\n\n private eventFulfillsDisplayNameCondition(cond: IContainsDisplayNameCondition, ev: MatrixEvent): boolean {\n let content = ev.getContent();\n if (ev.isEncrypted() && ev.getClearContent()) {\n content = ev.getClearContent()!;\n }\n if (!content || !content.body || typeof content.body != \"string\") {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n const member = room?.currentState?.getMember(this.client.credentials.userId!);\n if (!member) {\n return false;\n }\n\n const displayName = member.name;\n\n // N.B. we can't use \\b as it chokes on unicode. however \\W seems to be okay\n // as shorthand for [^0-9A-Za-z_].\n const pat = new RegExp(\"(^|\\\\W)\" + escapeRegExp(displayName) + \"(\\\\W|$)\", \"i\");\n return content.body.search(pat) > -1;\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing against the condition's glob-based\n * pattern.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventMatchCondition(cond: IEventMatchCondition, ev: MatrixEvent): boolean {\n if (!cond.key) {\n return false;\n }\n\n const val = this.valueForDottedKey(cond.key, ev);\n if (typeof val !== \"string\") {\n return false;\n }\n\n // XXX This does not match in a case-insensitive manner.\n //\n // See https://spec.matrix.org/v1.5/client-server-api/#conditions-1\n if (cond.value) {\n return cond.value === val;\n }\n\n if (typeof cond.pattern !== \"string\") {\n return false;\n }\n\n // Align to word boundary on `content.body` matches, whole string otherwise\n // https://spec.matrix.org/v1.13/client-server-api/#conditions-1\n const regex = PushProcessor.getPushRuleGlobRegex(cond.pattern, cond.key === \"content.body\");\n return !!val.match(regex);\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing exactly against the condition's\n * value.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventPropertyIsCondition(cond: IEventPropertyIsCondition, ev: MatrixEvent): boolean {\n if (!cond.key || cond.value === undefined) {\n return false;\n }\n return cond.value === this.valueForDottedKey(cond.key, ev);\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing exactly against the condition's\n * value.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventPropertyContains(cond: IEventPropertyContainsCondition, ev: MatrixEvent): boolean {\n if (!cond.key || cond.value === undefined) {\n return false;\n }\n const val = this.valueForDottedKey(cond.key, ev);\n if (!Array.isArray(val)) {\n return false;\n }\n return val.includes(cond.value);\n }\n\n private eventFulfillsCallStartedCondition(\n _cond: ICallStartedCondition | ICallStartedPrefixCondition,\n ev: MatrixEvent,\n ): boolean {\n // Since servers don't support properly sending push notification\n // about MSC3401 call events, we do the handling ourselves\n return (\n [\"m.ring\", \"m.prompt\"].includes(ev.getContent()[\"m.intent\"]) &&\n !(\"m.terminated\" in ev.getContent()) &&\n (ev.getPrevContent()[\"m.terminated\"] !== ev.getContent()[\"m.terminated\"] ||\n deepCompare(ev.getPrevContent(), {}))\n );\n }\n\n /**\n * Parse the key into the separate fields to search by splitting on\n * unescaped \".\", and then removing any escape characters.\n *\n * @param str - The key of the push rule condition: a dotted field.\n * @returns The unescaped parts to fetch.\n * @internal\n */\n public static partsForDottedKey(str: string): string[] {\n const result: string[] = [];\n\n // The current field and whether the previous character was the escape\n // character (a backslash).\n let part = \"\";\n let escaped = false;\n\n // Iterate over each character, and decide whether to append to the current\n // part (following the escape rules) or to start a new part (based on the\n // field separator).\n for (const c of str) {\n // If the previous character was the escape character (a backslash)\n // then decide what to append to the current part.\n if (escaped) {\n if (c === \"\\\\\" || c === \".\") {\n // An escaped backslash or dot just gets added.\n part += c;\n } else {\n // A character that shouldn't be escaped gets the backslash prepended.\n part += \"\\\\\" + c;\n }\n // This always resets being escaped.\n escaped = false;\n continue;\n }\n\n if (c == \".\") {\n // The field separator creates a new part.\n result.push(part);\n part = \"\";\n } else if (c == \"\\\\\") {\n // A backslash adds no characters, but starts an escape sequence.\n escaped = true;\n } else {\n // Otherwise, just add the current character.\n part += c;\n }\n }\n\n // Ensure the final part is included. If there's an open escape sequence\n // it should be included.\n if (escaped) {\n part += \"\\\\\";\n }\n result.push(part);\n\n return result;\n }\n\n /**\n * For a dotted field and event, fetch the value at that position, if one\n * exists.\n *\n * @param key - The key of the push rule condition: a dotted field to fetch.\n * @param ev - The matrix event to fetch the field from.\n * @returns The value at the dotted path given by key.\n */\n private valueForDottedKey(key: string, ev: MatrixEvent): any {\n // The key should already have been parsed via updateCachedPushRuleKeys,\n // but if it hasn't (maybe via an old consumer of the SDK which hasn't\n // been updated?) then lazily calculate it here.\n let parts = this.parsedKeys.get(key);\n if (parts === undefined) {\n parts = PushProcessor.partsForDottedKey(key);\n this.parsedKeys.set(key, parts);\n }\n let val: any;\n\n // special-case the first component to deal with encrypted messages\n const firstPart = parts[0];\n let currentIndex = 0;\n if (firstPart === \"content\") {\n val = ev.getContent();\n ++currentIndex;\n } else if (firstPart === \"type\") {\n val = ev.getType();\n ++currentIndex;\n } else {\n // use the raw event for any other fields\n val = ev.event;\n }\n\n for (; currentIndex < parts.length; ++currentIndex) {\n // The previous iteration resulted in null or undefined, bail (and\n // avoid the type error of attempting to retrieve a property).\n if (isNullOrUndefined(val)) {\n return undefined;\n }\n\n const thisPart = parts[currentIndex];\n val = val[thisPart];\n }\n return val;\n }\n\n private matchingRuleForEventWithRulesets(ev: MatrixEvent, rulesets?: IPushRules): IAnnotatedPushRule | null {\n if (!rulesets) {\n return null;\n }\n\n if (ev.getSender() === this.client.getSafeUserId()) {\n return null;\n }\n\n return this.matchingRuleFromKindSet(ev, rulesets.global);\n }\n\n private pushActionsForEventAndRulesets(\n ev: MatrixEvent,\n rulesets?: IPushRules,\n ): {\n actions?: IActionsObject;\n rule?: IAnnotatedPushRule;\n } {\n const rule = this.matchingRuleForEventWithRulesets(ev, rulesets);\n if (!rule) {\n return {};\n }\n\n const actionObj = PushProcessor.actionListToActionsObject(rule.actions);\n\n // Some actions are implicit in some situations: we add those here\n if (actionObj.tweaks.highlight === undefined) {\n // if it isn't specified, highlight if it's a content\n // rule but otherwise not\n actionObj.tweaks.highlight = rule.kind == PushRuleKind.ContentSpecific;\n }\n\n return { actions: actionObj, rule };\n }\n\n public ruleMatchesEvent(rule: Partial<IPushRule> & Pick<IPushRule, \"conditions\">, ev: MatrixEvent): boolean {\n // Disable the deprecated mentions push rules if the new mentions property exists.\n if (\n this.client.supportsIntentionalMentions() &&\n ev.getContent()[\"m.mentions\"] !== undefined &&\n (rule.rule_id === RuleId.ContainsUserName ||\n rule.rule_id === RuleId.ContainsDisplayName ||\n rule.rule_id === RuleId.AtRoomNotification)\n ) {\n return false;\n }\n\n return !rule.conditions?.some((cond) => !this.eventFulfillsCondition(cond, ev));\n }\n\n /**\n * Get the user's push actions for the given event\n */\n public actionsForEvent(ev: MatrixEvent): IActionsObject {\n const { actions } = this.pushActionsForEventAndRulesets(ev, this.client.pushRules);\n return actions || ({} as IActionsObject);\n }\n\n public actionsAndRuleForEvent(ev: MatrixEvent): {\n actions?: IActionsObject;\n rule?: IAnnotatedPushRule;\n } {\n return this.pushActionsForEventAndRulesets(ev, this.client.pushRules);\n }\n\n /**\n * Get one of the users push rules by its ID\n *\n * @param ruleId - The ID of the rule to search for\n * @returns The push rule, or null if no such rule was found\n */\n public getPushRuleById(ruleId: string): IPushRule | null {\n const result = this.getPushRuleAndKindById(ruleId);\n return result?.rule ?? null;\n }\n\n /**\n * Get one of the users push rules by its ID\n *\n * @param ruleId - The ID of the rule to search for\n * @returns rule The push rule, or null if no such rule was found\n * @returns kind - The PushRuleKind of the rule to search for\n */\n public getPushRuleAndKindById(ruleId: string): { rule: IPushRule; kind: PushRuleKind } | null {\n for (const scope of [\"global\"] as const) {\n if (this.client.pushRules?.[scope] === undefined) continue;\n\n for (const kind of RULEKINDS_IN_ORDER) {\n if (this.client.pushRules[scope][kind] === undefined) continue;\n\n for (const rule of this.client.pushRules[scope][kind]!) {\n if (rule.rule_id === ruleId) return { rule, kind };\n }\n }\n }\n return null;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"pushprocessor.js","names":[],"sources":["../src/pushprocessor.ts"],"sourcesContent":["/*\nCopyright 2015 - 2021 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { deepCompare, escapeRegExp, globToRegexp, isNullOrUndefined } from \"./utils.ts\";\nimport { type Logger } from \"./logger.ts\";\nimport { type MatrixClient } from \"./client.ts\";\nimport { type MatrixEvent } from \"./models/event.ts\";\nimport {\n ConditionKind,\n type IAnnotatedPushRule,\n type ICallStartedCondition,\n type ICallStartedPrefixCondition,\n type IContainsDisplayNameCondition,\n type IEventMatchCondition,\n type IEventPropertyContainsCondition,\n type IEventPropertyIsCondition,\n type IPushRule,\n type IPushRules,\n type IRoomMemberCountCondition,\n type ISenderNotificationPermissionCondition,\n type PushRuleAction,\n PushRuleActionName,\n type PushRuleCondition,\n PushRuleKind,\n type PushRuleSet,\n RuleId,\n TweakName,\n} from \"./@types/PushRules.ts\";\nimport { EventType } from \"./@types/event.ts\";\n\nconst RULEKINDS_IN_ORDER = [\n PushRuleKind.Override,\n PushRuleKind.ContentSpecific,\n PushRuleKind.RoomSpecific,\n PushRuleKind.SenderSpecific,\n PushRuleKind.Underride,\n];\n\n// The default override rules to apply to the push rules that arrive from the server.\n// We do this for two reasons:\n// 1. Synapse is unlikely to send us the push rule in an incremental sync - see\n// https://github.com/matrix-org/synapse/pull/4867#issuecomment-481446072 for\n// more details.\n// 2. We often want to start using push rules ahead of the server supporting them,\n// and so we can put them here.\nconst DEFAULT_OVERRIDE_RULES: Record<string, IPushRule> = {\n \".m.rule.is_room_mention\": {\n // Matrix v1.7\n rule_id: \".m.rule.is_room_mention\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventPropertyIs,\n key: \"content.m\\\\.mentions.room\",\n value: true,\n },\n {\n kind: ConditionKind.SenderNotificationPermission,\n key: \"room\",\n },\n ],\n actions: [\n PushRuleActionName.Notify,\n {\n set_tweak: TweakName.Highlight,\n },\n ],\n },\n \".m.rule.reaction\": {\n // For homeservers which don't support MSC2153 yet\n rule_id: \".m.rule.reaction\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: \"m.reaction\",\n },\n ],\n actions: [PushRuleActionName.DontNotify],\n },\n \".org.matrix.msc3786.rule.room.server_acl\": {\n // For homeservers which don't support MSC3786 yet\n rule_id: \".org.matrix.msc3786.rule.room.server_acl\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: EventType.RoomServerAcl,\n },\n {\n kind: ConditionKind.EventMatch,\n key: \"state_key\",\n pattern: \"\",\n },\n ],\n actions: [],\n },\n};\n\n// A special rule id for `EXPECTED_DEFAULT_OVERRIDE_RULE_IDS` and friends which denotes where user-defined rules live in the order.\nconst UserDefinedRules = Symbol(\"UserDefinedRules\");\n\ntype OrderedRules = Array<string | typeof UserDefinedRules>;\n\nconst EXPECTED_DEFAULT_OVERRIDE_RULE_IDS: OrderedRules = [\n RuleId.Master,\n UserDefinedRules,\n RuleId.SuppressNotices,\n RuleId.InviteToSelf,\n RuleId.MemberEvent,\n RuleId.IsUserMention,\n RuleId.ContainsDisplayName,\n RuleId.IsRoomMention,\n RuleId.AtRoomNotification,\n RuleId.Tombstone,\n \".m.rule.reaction\",\n \".m.rule.room.server_acl\",\n \".org.matrix.msc3786.rule.room.server_acl\",\n \".m.rule.suppress_edits\",\n];\n\nconst DEFAULT_UNDERRIDE_RULES: Record<string, IPushRule> = {\n \".org.matrix.msc3914.rule.room.call\": {\n // For homeservers which don't support MSC3914 yet\n rule_id: \".org.matrix.msc3914.rule.room.call\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: \"org.matrix.msc3401.call\",\n },\n {\n kind: ConditionKind.CallStarted,\n },\n ],\n actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: \"default\" }],\n },\n};\n\nconst EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS: OrderedRules = [\n UserDefinedRules,\n RuleId.IncomingCall,\n \".org.matrix.msc3914.rule.room.call\",\n RuleId.EncryptedDM,\n RuleId.DM,\n RuleId.Message,\n RuleId.EncryptedMessage,\n];\n\n/**\n * Make sure that each of the rules listed in `defaultRuleIds` is listed in the given set of push rules.\n *\n * @param logger - A `Logger` to write log messages to.\n * @param kind - the kind of push rule set being merged.\n * @param incomingRules - the existing set of known push rules for the user.\n * @param defaultRules - a lookup table for the default definitions of push rules.\n * @param orderedRuleIds - the IDs of the expected push rules, in order.\n *\n * @returns A copy of `incomingRules`, with any missing default rules inserted in the right place.\n */\nfunction mergeRulesWithDefaults(\n logger: Logger,\n kind: PushRuleKind,\n incomingRules: IPushRule[],\n defaultRules: Record<string, IPushRule>,\n orderedRuleIds: OrderedRules,\n): IPushRule[] {\n // Split the incomingRules into defaults and custom\n const incomingDefaultRules = incomingRules.filter((rule) => rule.default);\n const incomingCustomRules = incomingRules.filter((rule) => !rule.default);\n\n function insertDefaultPushRule(ruleId: OrderedRules[number]): void {\n if (ruleId === UserDefinedRules) {\n // Re-insert any user-defined rules that were in `incomingRules`\n newRules.push(...incomingCustomRules);\n } else if (ruleId in defaultRules) {\n logger.warn(`Adding default global ${kind} push rule ${ruleId}`);\n newRules.push(defaultRules[ruleId]);\n } else {\n logger.warn(`Missing default global ${kind} push rule ${ruleId}`);\n }\n }\n\n let nextExpectedRuleIdIndex = 0;\n const newRules: IPushRule[] = [];\n // Merge our expected rules (including the incoming custom rules) into the incoming default rules.\n for (const rule of incomingDefaultRules) {\n const ruleIndex = orderedRuleIds.indexOf(rule.rule_id);\n if (ruleIndex === -1) {\n // an unrecognised rule; copy it over\n newRules.push(rule);\n continue;\n }\n while (ruleIndex > nextExpectedRuleIdIndex) {\n // insert new rules\n const defaultRuleId = orderedRuleIds[nextExpectedRuleIdIndex];\n insertDefaultPushRule(defaultRuleId);\n nextExpectedRuleIdIndex += 1;\n }\n // copy over the existing rule\n newRules.push(rule);\n nextExpectedRuleIdIndex += 1;\n }\n\n // Now copy over any remaining default rules\n for (const ruleId of orderedRuleIds.slice(nextExpectedRuleIdIndex)) {\n insertDefaultPushRule(ruleId);\n }\n\n return newRules;\n}\n\nexport interface IActionsObject {\n /** Whether this event should notify the user or not. */\n notify: boolean;\n /** How this event should be notified. */\n tweaks: Partial<Record<TweakName, any>>;\n}\n\nexport class PushProcessor {\n /**\n * Construct a Push Processor.\n * @param client - The Matrix client object to use\n */\n public constructor(private readonly client: MatrixClient) {}\n\n /**\n * Maps the original key from the push rules to a list of property names\n * after unescaping.\n */\n private readonly parsedKeys = new Map<string, string[]>();\n\n /**\n * Convert a list of actions into a object with the actions as keys and their values\n * @example\n * eg. `[ 'notify', { set_tweak: 'sound', value: 'default' } ]`\n * becomes `{ notify: true, tweaks: { sound: 'default' } }`\n * @param actionList - The actions list\n *\n * @returns A object with key 'notify' (true or false) and an object of actions\n */\n public static actionListToActionsObject(actionList: PushRuleAction[]): IActionsObject {\n const actionObj: IActionsObject = { notify: false, tweaks: {} };\n for (const action of actionList) {\n if (action === PushRuleActionName.Notify) {\n actionObj.notify = true;\n } else if (typeof action === \"object\") {\n if (action.value === undefined) {\n action.value = true;\n }\n actionObj.tweaks[action.set_tweak] = action.value;\n }\n }\n return actionObj;\n }\n\n /**\n * Rewrites conditions on a client's push rules to match the defaults\n * where applicable. Useful for upgrading push rules to more strict\n * conditions when the server is falling behind on defaults.\n *\n * @param logger - A `Logger` to write log messages to.\n * @param incomingRules - The client's existing push rules\n * @param userId - The Matrix ID of the client.\n * @returns The rewritten rules\n */\n public static rewriteDefaultRules(\n logger: Logger,\n incomingRules: IPushRules,\n userId: string | undefined = undefined,\n ): IPushRules {\n let newRules: IPushRules = JSON.parse(JSON.stringify(incomingRules)); // deep clone\n\n // These lines are mostly to make the tests happy. We shouldn't run into these\n // properties missing in practice.\n if (!newRules) newRules = {} as IPushRules;\n if (!newRules.global) newRules.global = {};\n if (!newRules.global.override) newRules.global.override = [];\n if (!newRules.global.underride) newRules.global.underride = [];\n\n // Merge the client-level defaults with the ones from the server\n newRules.global.override = mergeRulesWithDefaults(\n logger,\n PushRuleKind.Override,\n newRules.global.override,\n DEFAULT_OVERRIDE_RULES,\n EXPECTED_DEFAULT_OVERRIDE_RULE_IDS,\n );\n\n newRules.global.underride = mergeRulesWithDefaults(\n logger,\n PushRuleKind.Underride,\n newRules.global.underride,\n DEFAULT_UNDERRIDE_RULES,\n EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS,\n );\n\n return newRules;\n }\n\n /**\n * Create a RegExp object for the given glob pattern with a single capture group around the pattern itself, caching the result.\n * No cache invalidation is present currently,\n * as this will be inherently bounded to the size of the user's own push rules.\n * @param pattern - the glob pattern to convert to a RegExp\n * @param alignToWordBoundary - whether to align the pattern to word boundaries,\n * as specified for `content.body` matches, will use lookaround assertions to ensure the match only includes the pattern\n * @param flags - the flags to pass to the RegExp constructor, defaults to case-insensitive\n */\n public static getPushRuleGlobRegex(pattern: string, alignToWordBoundary = false, flags = \"i\"): RegExp {\n const [prefix, suffix] = alignToWordBoundary ? [\"(?<=^|\\\\W)\", \"(?=\\\\W|$)\"] : [\"^\", \"$\"];\n const cacheKey = `${alignToWordBoundary}-${flags}-${pattern}`;\n\n if (!PushProcessor.cachedGlobToRegex[cacheKey]) {\n PushProcessor.cachedGlobToRegex[cacheKey] = new RegExp(\n prefix + \"(\" + globToRegexp(pattern) + \")\" + suffix,\n flags,\n );\n }\n return PushProcessor.cachedGlobToRegex[cacheKey];\n }\n\n /**\n * Pre-caches the parsed keys for push rules and cleans out any obsolete cache\n * entries. Should be called after push rules are updated.\n * @param newRules - The new push rules.\n */\n public updateCachedPushRuleKeys(newRules: IPushRules): void {\n // These lines are mostly to make the tests happy. We shouldn't run into these\n // properties missing in practice.\n if (!newRules) newRules = {} as IPushRules;\n if (!newRules.global) newRules.global = {};\n if (!newRules.global.override) newRules.global.override = [];\n if (!newRules.global.room) newRules.global.room = [];\n if (!newRules.global.sender) newRules.global.sender = [];\n if (!newRules.global.underride) newRules.global.underride = [];\n\n // Process the 'key' property on event_match conditions pre-cache the\n // values and clean-out any unused values.\n const toRemoveKeys = new Set(this.parsedKeys.keys());\n for (const ruleset of [\n newRules.global.override,\n newRules.global.room,\n newRules.global.sender,\n newRules.global.underride,\n ]) {\n for (const rule of ruleset) {\n if (!rule.conditions) {\n continue;\n }\n\n for (const condition of rule.conditions) {\n if (condition.kind !== ConditionKind.EventMatch) {\n continue;\n }\n\n // Ensure we keep this key.\n toRemoveKeys.delete(condition.key);\n\n // Pre-process the key.\n this.parsedKeys.set(condition.key, PushProcessor.partsForDottedKey(condition.key));\n }\n }\n }\n // Any keys that were previously cached, but are no longer needed should\n // be removed.\n toRemoveKeys.forEach((k) => this.parsedKeys.delete(k));\n }\n\n private static cachedGlobToRegex: Record<string, RegExp> = {}; // $glob: RegExp\n\n private matchingRuleFromKindSet(ev: MatrixEvent, kindset: PushRuleSet): IAnnotatedPushRule | null {\n for (const kind of RULEKINDS_IN_ORDER) {\n const ruleset = kindset[kind];\n if (!ruleset) {\n continue;\n }\n\n for (const rule of ruleset) {\n if (!rule.enabled) {\n continue;\n }\n\n const rawrule = this.templateRuleToRaw(kind, rule);\n if (!rawrule) {\n continue;\n }\n\n if (this.ruleMatchesEvent(rawrule, ev)) {\n return {\n ...rule,\n kind,\n };\n }\n }\n }\n return null;\n }\n\n private templateRuleToRaw(\n kind: PushRuleKind,\n tprule: IPushRule,\n ): Pick<IPushRule, \"rule_id\" | \"actions\" | \"conditions\"> | null {\n const rawrule: Pick<IPushRule, \"rule_id\" | \"actions\" | \"conditions\"> = {\n rule_id: tprule.rule_id,\n actions: tprule.actions,\n conditions: [],\n };\n switch (kind) {\n case PushRuleKind.Underride:\n case PushRuleKind.Override:\n rawrule.conditions = tprule.conditions;\n break;\n case PushRuleKind.RoomSpecific:\n if (!tprule.rule_id) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"room_id\",\n value: tprule.rule_id,\n });\n break;\n case PushRuleKind.SenderSpecific:\n if (!tprule.rule_id) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"user_id\",\n value: tprule.rule_id,\n });\n break;\n case PushRuleKind.ContentSpecific:\n if (!tprule.pattern) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"content.body\",\n pattern: tprule.pattern,\n });\n break;\n }\n return rawrule;\n }\n\n private eventFulfillsCondition(cond: PushRuleCondition, ev: MatrixEvent): boolean {\n switch (cond.kind) {\n case ConditionKind.EventMatch:\n return this.eventFulfillsEventMatchCondition(cond, ev);\n case ConditionKind.EventPropertyIs:\n return this.eventFulfillsEventPropertyIsCondition(cond, ev);\n case ConditionKind.EventPropertyContains:\n return this.eventFulfillsEventPropertyContains(cond, ev);\n case ConditionKind.ContainsDisplayName:\n return this.eventFulfillsDisplayNameCondition(cond, ev);\n case ConditionKind.RoomMemberCount:\n return this.eventFulfillsRoomMemberCountCondition(cond, ev);\n case ConditionKind.SenderNotificationPermission:\n return this.eventFulfillsSenderNotifPermCondition(cond, ev);\n case ConditionKind.CallStarted:\n case ConditionKind.CallStartedPrefix:\n return this.eventFulfillsCallStartedCondition(cond, ev);\n }\n\n // unknown conditions: we previously matched all unknown conditions,\n // but given that rules can be added to the base rules on a server,\n // it's probably better to not match unknown conditions.\n return false;\n }\n\n private eventFulfillsSenderNotifPermCondition(\n cond: ISenderNotificationPermissionCondition,\n ev: MatrixEvent,\n ): boolean {\n const notifLevelKey = cond[\"key\"];\n if (!notifLevelKey) {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n if (!room?.currentState) {\n return false;\n }\n\n // Note that this should not be the current state of the room but the state at\n // the point the event is in the DAG. Unfortunately the js-sdk does not store\n // this.\n return room.currentState.mayTriggerNotifOfType(notifLevelKey, ev.getSender()!);\n }\n\n private eventFulfillsRoomMemberCountCondition(cond: IRoomMemberCountCondition, ev: MatrixEvent): boolean {\n if (!cond.is) {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n if (!room || !room.currentState || !room.currentState.members) {\n return false;\n }\n\n const memberCount = room.currentState.getJoinedMemberCount();\n\n const m = cond.is.match(/^([=<>]*)(\\d*)$/);\n if (!m) {\n return false;\n }\n const ineq = m[1];\n const rhs = parseInt(m[2]);\n if (isNaN(rhs)) {\n return false;\n }\n switch (ineq) {\n case \"\":\n case \"==\":\n return memberCount == rhs;\n case \"<\":\n return memberCount < rhs;\n case \">\":\n return memberCount > rhs;\n case \"<=\":\n return memberCount <= rhs;\n case \">=\":\n return memberCount >= rhs;\n default:\n return false;\n }\n }\n\n private eventFulfillsDisplayNameCondition(cond: IContainsDisplayNameCondition, ev: MatrixEvent): boolean {\n let content = ev.getContent();\n if (ev.isEncrypted() && ev.getClearContent()) {\n content = ev.getClearContent()!;\n }\n if (!content || !content.body || typeof content.body != \"string\") {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n const member = room?.currentState?.getMember(this.client.credentials.userId!);\n if (!member) {\n return false;\n }\n\n const displayName = member.name;\n\n // N.B. we can't use \\b as it chokes on unicode. however \\W seems to be okay\n // as shorthand for [^0-9A-Za-z_].\n const pat = new RegExp(\"(^|\\\\W)\" + escapeRegExp(displayName) + \"(\\\\W|$)\", \"i\");\n return content.body.search(pat) > -1;\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing against the condition's glob-based\n * pattern.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventMatchCondition(cond: IEventMatchCondition, ev: MatrixEvent): boolean {\n if (!cond.key) {\n return false;\n }\n\n const val = this.valueForDottedKey(cond.key, ev);\n if (typeof val !== \"string\") {\n return false;\n }\n\n // XXX This does not match in a case-insensitive manner.\n //\n // See https://spec.matrix.org/v1.5/client-server-api/#conditions-1\n if (cond.value) {\n return cond.value === val;\n }\n\n if (typeof cond.pattern !== \"string\") {\n return false;\n }\n\n // Align to word boundary on `content.body` matches, whole string otherwise\n // https://spec.matrix.org/v1.13/client-server-api/#conditions-1\n const regex = PushProcessor.getPushRuleGlobRegex(cond.pattern, cond.key === \"content.body\");\n return !!val.match(regex);\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing exactly against the condition's\n * value.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventPropertyIsCondition(cond: IEventPropertyIsCondition, ev: MatrixEvent): boolean {\n if (!cond.key || cond.value === undefined) {\n return false;\n }\n return cond.value === this.valueForDottedKey(cond.key, ev);\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing exactly against the condition's\n * value.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventPropertyContains(cond: IEventPropertyContainsCondition, ev: MatrixEvent): boolean {\n if (!cond.key || cond.value === undefined) {\n return false;\n }\n const val = this.valueForDottedKey(cond.key, ev);\n if (!Array.isArray(val)) {\n return false;\n }\n return val.includes(cond.value);\n }\n\n private eventFulfillsCallStartedCondition(\n _cond: ICallStartedCondition | ICallStartedPrefixCondition,\n ev: MatrixEvent,\n ): boolean {\n // Since servers don't support properly sending push notification\n // about MSC3401 call events, we do the handling ourselves\n return (\n [\"m.ring\", \"m.prompt\"].includes(ev.getContent()[\"m.intent\"]) &&\n !(\"m.terminated\" in ev.getContent()) &&\n (ev.getPrevContent()[\"m.terminated\"] !== ev.getContent()[\"m.terminated\"] ||\n deepCompare(ev.getPrevContent(), {}))\n );\n }\n\n /**\n * Parse the key into the separate fields to search by splitting on\n * unescaped \".\", and then removing any escape characters.\n *\n * @param str - The key of the push rule condition: a dotted field.\n * @returns The unescaped parts to fetch.\n * @internal\n */\n public static partsForDottedKey(str: string): string[] {\n const result: string[] = [];\n\n // The current field and whether the previous character was the escape\n // character (a backslash).\n let part = \"\";\n let escaped = false;\n\n // Iterate over each character, and decide whether to append to the current\n // part (following the escape rules) or to start a new part (based on the\n // field separator).\n for (const c of str) {\n // If the previous character was the escape character (a backslash)\n // then decide what to append to the current part.\n if (escaped) {\n if (c === \"\\\\\" || c === \".\") {\n // An escaped backslash or dot just gets added.\n part += c;\n } else {\n // A character that shouldn't be escaped gets the backslash prepended.\n part += \"\\\\\" + c;\n }\n // This always resets being escaped.\n escaped = false;\n continue;\n }\n\n if (c == \".\") {\n // The field separator creates a new part.\n result.push(part);\n part = \"\";\n } else if (c == \"\\\\\") {\n // A backslash adds no characters, but starts an escape sequence.\n escaped = true;\n } else {\n // Otherwise, just add the current character.\n part += c;\n }\n }\n\n // Ensure the final part is included. If there's an open escape sequence\n // it should be included.\n if (escaped) {\n part += \"\\\\\";\n }\n result.push(part);\n\n return result;\n }\n\n /**\n * For a dotted field and event, fetch the value at that position, if one\n * exists.\n *\n * @param key - The key of the push rule condition: a dotted field to fetch.\n * @param ev - The matrix event to fetch the field from.\n * @returns The value at the dotted path given by key.\n */\n private valueForDottedKey(key: string, ev: MatrixEvent): any {\n // The key should already have been parsed via updateCachedPushRuleKeys,\n // but if it hasn't (maybe via an old consumer of the SDK which hasn't\n // been updated?) then lazily calculate it here.\n let parts = this.parsedKeys.get(key);\n if (parts === undefined) {\n parts = PushProcessor.partsForDottedKey(key);\n this.parsedKeys.set(key, parts);\n }\n let val: any;\n\n // special-case the first component to deal with encrypted messages\n const firstPart = parts[0];\n let currentIndex = 0;\n if (firstPart === \"content\") {\n val = ev.getContent();\n ++currentIndex;\n } else if (firstPart === \"type\") {\n val = ev.getType();\n ++currentIndex;\n } else {\n // use the raw event for any other fields\n val = ev.event;\n }\n\n for (; currentIndex < parts.length; ++currentIndex) {\n // The previous iteration resulted in null or undefined, bail (and\n // avoid the type error of attempting to retrieve a property).\n if (isNullOrUndefined(val)) {\n return undefined;\n }\n\n const thisPart = parts[currentIndex];\n val = val[thisPart];\n }\n return val;\n }\n\n private matchingRuleForEventWithRulesets(ev: MatrixEvent, rulesets?: IPushRules): IAnnotatedPushRule | null {\n if (!rulesets) {\n return null;\n }\n\n if (ev.getSender() === this.client.getSafeUserId()) {\n return null;\n }\n\n return this.matchingRuleFromKindSet(ev, rulesets.global);\n }\n\n private pushActionsForEventAndRulesets(\n ev: MatrixEvent,\n rulesets?: IPushRules,\n ): {\n actions?: IActionsObject;\n rule?: IAnnotatedPushRule;\n } {\n const rule = this.matchingRuleForEventWithRulesets(ev, rulesets);\n if (!rule) {\n return {};\n }\n\n const actionObj = PushProcessor.actionListToActionsObject(rule.actions);\n\n // Some actions are implicit in some situations: we add those here\n if (actionObj.tweaks.highlight === undefined) {\n // if it isn't specified, highlight if it's a content\n // rule but otherwise not\n actionObj.tweaks.highlight = rule.kind == PushRuleKind.ContentSpecific;\n }\n\n return { actions: actionObj, rule };\n }\n\n public ruleMatchesEvent(rule: Partial<IPushRule> & Pick<IPushRule, \"conditions\">, ev: MatrixEvent): boolean {\n // Disable the deprecated mentions push rules if the new mentions property exists.\n if (\n this.client.supportsIntentionalMentions() &&\n ev.getContent()[\"m.mentions\"] !== undefined &&\n (rule.rule_id === RuleId.ContainsUserName ||\n rule.rule_id === RuleId.ContainsDisplayName ||\n rule.rule_id === RuleId.AtRoomNotification)\n ) {\n return false;\n }\n\n return !rule.conditions?.some((cond) => !this.eventFulfillsCondition(cond, ev));\n }\n\n /**\n * Get the user's push actions for the given event\n */\n public actionsForEvent(ev: MatrixEvent): IActionsObject {\n const { actions } = this.pushActionsForEventAndRulesets(ev, this.client.pushRules);\n return actions || ({} as IActionsObject);\n }\n\n public actionsAndRuleForEvent(ev: MatrixEvent): {\n actions?: IActionsObject;\n rule?: IAnnotatedPushRule;\n } {\n return this.pushActionsForEventAndRulesets(ev, this.client.pushRules);\n }\n\n /**\n * Get one of the users push rules by its ID\n *\n * @param ruleId - The ID of the rule to search for\n * @returns The push rule, or null if no such rule was found\n */\n public getPushRuleById(ruleId: string): IPushRule | null {\n const result = this.getPushRuleAndKindById(ruleId);\n return result?.rule ?? null;\n }\n\n /**\n * Get one of the users push rules by its ID\n *\n * @param ruleId - The ID of the rule to search for\n * @returns rule The push rule, or null if no such rule was found\n * @returns kind - The PushRuleKind of the rule to search for\n */\n public getPushRuleAndKindById(ruleId: string): { rule: IPushRule; kind: PushRuleKind } | null {\n for (const scope of [\"global\"] as const) {\n if (this.client.pushRules?.[scope] === undefined) continue;\n\n for (const kind of RULEKINDS_IN_ORDER) {\n if (this.client.pushRules[scope][kind] === undefined) continue;\n\n for (const rule of this.client.pushRules[scope][kind]) {\n if (rule.rule_id === ruleId) return { rule, kind };\n }\n }\n }\n return null;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"receipt-accumulator.d.ts","sourceRoot":"","sources":["../src/receipt-accumulator.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAY3D;;;;;;;;;;GAUG;AACH,qBAAa,kBAAkB;IAC3B,4DAA4D;IAC5D,OAAO,CAAC,sBAAsB,CAA8C;IAE5E,+EAA+E;IAC/E,OAAO,CAAC,oBAAoB,CAE1B;IAEF;;;OAGG;IACH,OAAO,CAAC,aAAa;IAIrB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAInB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;OAKG;IACH,OAAO,CAAE,WAAW;IAQpB;;;OAGG;IACI,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,SAAS,GAAG,IAAI,CA4DvE;IAED;;;;OAIG;IACI,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA+BxE;CACJ"}
1
+ {"version":3,"file":"receipt-accumulator.d.ts","sourceRoot":"","sources":["../src/receipt-accumulator.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAW3D;;;;;;;;;;GAUG;AACH,qBAAa,kBAAkB;IAC3B,4DAA4D;IAC5D,OAAO,CAAC,sBAAsB,CAA8C;IAE5E,+EAA+E;IAC/E,OAAO,CAAC,oBAAoB,CAE1B;IAEF;;;OAGG;IACH,OAAO,CAAC,aAAa;IAIrB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAInB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;OAKG;IACH,OAAO,CAAE,WAAW;IAQpB;;;OAGG;IACI,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,SAAS,GAAG,IAAI,CA4DvE;IAED;;;;OAIG;IACI,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA+BxE;CACJ"}