|
1767 | 1767 | /**
|
1768 | 1768 | * Check whether two access token objects represent the same permissions or not.
|
1769 | 1769 | *
|
1770 |
| - * @param other - Other access token which should be used in comparison. |
1771 |
| - * @returns `true` if received and another access token object represents the same permissions. |
| 1770 | + * @param other - Other access token that should be used in comparison. |
| 1771 | + * @param checkExpiration - Whether the token expiration date also should be compared or not. |
| 1772 | + * @returns `true` if received and another access token object represents the same permissions (and `expiration` if |
| 1773 | + * has been requested). |
1772 | 1774 | */
|
1773 |
| - equalTo(other) { |
1774 |
| - return this.asIdentifier === other.asIdentifier; |
| 1775 | + equalTo(other, checkExpiration = false) { |
| 1776 | + return this.asIdentifier === other.asIdentifier && (checkExpiration ? this.expiration === other.expiration : true); |
| 1777 | + } |
| 1778 | + /** |
| 1779 | + * Check whether the receiver is a newer auth token than another. |
| 1780 | + * |
| 1781 | + * @param other - Other access token that should be used in comparison. |
| 1782 | + * @returns `true` if received has a more distant expiration date than another token. |
| 1783 | + */ |
| 1784 | + isNewerThan(other) { |
| 1785 | + return this.simplifiedToken ? this.expiration > other.expiration : false; |
1775 | 1786 | }
|
1776 | 1787 | /**
|
1777 | 1788 | * Stringify object to actual access token / key value.
|
|
2196 | 2207 | // --------------------- Aggregation ----------------------
|
2197 | 2208 | // --------------------------------------------------------
|
2198 | 2209 | // region Aggregation
|
| 2210 | + /** |
| 2211 | + * Update access token for the client which should be used with next subscribe request. |
| 2212 | + * |
| 2213 | + * @param accessToken - Access token for next subscribe REST API call. |
| 2214 | + */ |
| 2215 | + updateClientAccessToken(accessToken) { |
| 2216 | + if (!this.accessToken || accessToken.isNewerThan(this.accessToken)) |
| 2217 | + this.accessToken = accessToken; |
| 2218 | + } |
2199 | 2219 | /**
|
2200 | 2220 | * Mark specific client as suitable for state invalidation when it will be appropriate.
|
2201 | 2221 | *
|
|
2286 | 2306 | const newInitialServiceRequests = [];
|
2287 | 2307 | const cancelledServiceRequests = [];
|
2288 | 2308 | let serviceLeaveRequest;
|
2289 |
| - [...continuationRequests]; |
2290 |
| - [...initialRequests]; |
2291 | 2309 | // Identify token override for initial requests.
|
2292 | 2310 | let timetokenOverrideRefreshTimestamp;
|
2293 | 2311 | let decidedTimetokenRegionOverride;
|
|
2460 | 2478 | // region Event handlers
|
2461 | 2479 | addListenersForRequestEvents(request) {
|
2462 | 2480 | const abortController = (this.requestListenersAbort[request.identifier] = new AbortController());
|
2463 |
| - const cleanUpCallback = (evt) => { |
| 2481 | + const cleanUpCallback = () => { |
2464 | 2482 | this.removeListenersFromRequestEvents(request);
|
2465 | 2483 | if (!request.isServiceRequest) {
|
2466 | 2484 | if (this.requests[request.client.identifier]) {
|
|
2872 | 2890 | }
|
2873 | 2891 | if (!identifier)
|
2874 | 2892 | return;
|
2875 |
| - // |
2876 | 2893 | if (request) {
|
2877 | 2894 | // Unset `service`-provided request because we can't receive a response with new `userId`.
|
2878 | 2895 | request.serviceRequest = undefined;
|
|
3039 | 3056 | // Keep track of the client's listener abort controller.
|
3040 | 3057 | const abortController = new AbortController();
|
3041 | 3058 | this.clientAbortControllers[client.identifier] = abortController;
|
3042 |
| - client.addEventListener(PubNubClientEvent.IdentityChange, () => this.moveClient(client), { |
| 3059 | + client.addEventListener(PubNubClientEvent.IdentityChange, (event) => { |
| 3060 | + if (!(event instanceof PubNubClientIdentityChangeEvent)) |
| 3061 | + return; |
| 3062 | + // Make changes into state only if `userId` actually changed. |
| 3063 | + if (!!event.oldUserId !== !!event.newUserId || |
| 3064 | + (event.oldUserId && event.newUserId && event.newUserId !== event.oldUserId)) |
| 3065 | + this.moveClient(client); |
| 3066 | + }, { |
3043 | 3067 | signal: abortController.signal,
|
3044 | 3068 | });
|
3045 |
| - client.addEventListener(PubNubClientEvent.AuthChange, () => this.moveClient(client), { |
| 3069 | + client.addEventListener(PubNubClientEvent.AuthChange, (event) => { |
| 3070 | + var _a; |
| 3071 | + if (!(event instanceof PubNubClientAuthChangeEvent)) |
| 3072 | + return; |
| 3073 | + // Check whether the client should be moved to another state because of a permissions change or whether the |
| 3074 | + // same token with the same permissions should be used for the next requests. |
| 3075 | + if (!!event.oldAuth !== !!event.newAuth || |
| 3076 | + (event.oldAuth && event.newAuth && !event.oldAuth.equalTo(event.newAuth))) |
| 3077 | + this.moveClient(client); |
| 3078 | + else if (event.oldAuth && event.newAuth && event.oldAuth.equalTo(event.newAuth)) |
| 3079 | + (_a = this.subscriptionStateForClient(client)) === null || _a === void 0 ? void 0 : _a.updateClientAccessToken(event.newAuth); |
| 3080 | + }, { |
3046 | 3081 | signal: abortController.signal,
|
3047 | 3082 | });
|
3048 | 3083 | client.addEventListener(PubNubClientEvent.SendSubscribeRequest, (event) => {
|
|
3853 | 3888 | client.addEventListener(PubNubClientEvent.IdentityChange, (event) => {
|
3854 | 3889 | if (!(event instanceof PubNubClientIdentityChangeEvent))
|
3855 | 3890 | return;
|
3856 |
| - const state = this.heartbeatStateForClient(client); |
3857 |
| - const request = state ? state.requestForClient(client) : undefined; |
3858 |
| - if (request) |
3859 |
| - request.userId = event.newUserId; |
3860 |
| - this.moveClient(client); |
| 3891 | + // Make changes into state only if `userId` actually changed. |
| 3892 | + if (!!event.oldUserId !== !!event.newUserId || |
| 3893 | + (event.oldUserId && event.newUserId && event.newUserId !== event.oldUserId)) { |
| 3894 | + const state = this.heartbeatStateForClient(client); |
| 3895 | + const request = state ? state.requestForClient(client) : undefined; |
| 3896 | + if (request) |
| 3897 | + request.userId = event.newUserId; |
| 3898 | + this.moveClient(client); |
| 3899 | + } |
3861 | 3900 | }, {
|
3862 | 3901 | signal: abortController.signal,
|
3863 | 3902 | });
|
|
3868 | 3907 | const request = state ? state.requestForClient(client) : undefined;
|
3869 | 3908 | if (request)
|
3870 | 3909 | request.accessToken = event.newAuth;
|
3871 |
| - this.moveClient(client); |
| 3910 | + // Check whether the client should be moved to another state because of a permissions change or whether the |
| 3911 | + // same token with the same permissions should be used for the next requests. |
| 3912 | + if (!!event.oldAuth !== !!event.newAuth || |
| 3913 | + (event.oldAuth && event.newAuth && !event.newAuth.equalTo(event.oldAuth))) |
| 3914 | + this.moveClient(client); |
3872 | 3915 | }, {
|
3873 | 3916 | signal: abortController.signal,
|
3874 | 3917 | });
|
|
4252 | 4295 | const accessToken = authKey ? new AccessToken(authKey, (token !== null && token !== void 0 ? token : {}).token, (token !== null && token !== void 0 ? token : {}).expiration) : undefined;
|
4253 | 4296 | // Check whether the access token really changed or not.
|
4254 | 4297 | if (!!accessToken !== !!this.accessToken ||
|
4255 |
| - (!!accessToken && this.accessToken && !accessToken.equalTo(this.accessToken))) { |
| 4298 | + (!!accessToken && this.accessToken && !accessToken.equalTo(this.accessToken, true))) { |
4256 | 4299 | const oldValue = this._accessToken;
|
4257 | 4300 | this._accessToken = accessToken;
|
4258 | 4301 | // Make sure that all ongoing subscribe (usually should be only one at a time) requests use proper
|
|
4590 | 4633 | [...this.clientBySubscribeKey[subKey]].forEach((client) => {
|
4591 | 4634 | // Handle potential SharedWorker timers throttling and early eviction of the PubNub core client.
|
4592 | 4635 | // If timer fired later than specified interval - it has been throttled and shouldn't unregister client.
|
4593 |
| - if (client.lastPingRequest && Date.now() / 1000 - client.lastPingRequest > interval * 0.5) { |
| 4636 | + if (client.lastPingRequest && Date.now() / 1000 - client.lastPingRequest - 0.2 > interval * 0.5) { |
4594 | 4637 | client.logger.warn('PubNub clients timeout timer fired after throttling past due time.');
|
4595 | 4638 | client.lastPingRequest = undefined;
|
4596 | 4639 | }
|
4597 | 4640 | if (client.lastPingRequest &&
|
4598 |
| - (!client.lastPongEvent || Math.abs(client.lastPongEvent - client.lastPingRequest) > interval * 0.5)) { |
| 4641 | + (!client.lastPongEvent || Math.abs(client.lastPongEvent - client.lastPingRequest) > interval)) { |
4599 | 4642 | this.unregisterClient(client, this.timeouts[subKey].unsubscribeOffline);
|
4600 | 4643 | // Notify other clients with same subscription key that one of them became inactive.
|
4601 | 4644 | this.forEachClient(subKey, (subKeyClient) => {
|
|
0 commit comments