Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

pusher-js

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pusher-js - npm Package Compare versions

Comparing version 7.3.0 to 7.4.0

spec/javascripts/helpers/timers/promises.js

4

CHANGELOG.md
# Changelog
## 7.4.0
* [FIXED] Allow presence channel authorization to depend on user authentication
## 7.3.0

@@ -4,0 +8,0 @@

9

package.json
{
"name": "pusher-js",
"version": "7.3.0",
"version": "7.4.0",
"description": "Pusher Channels JavaScript library for browsers, React Native, NodeJS and web workers",

@@ -41,3 +41,3 @@ "main": "dist/node/pusher.js",

"isomorphic-fetch": "^3.0.0",
"jasmine": "^3.8.0",
"jasmine": "^3.99.0",
"jasmine-spec-reporter": "^7.0.0",

@@ -58,3 +58,3 @@ "karma": "^6.4.0",

"ts-loader": "^6.0.4",
"typescript": "^3.4.5",
"typescript": "^3.9.0",
"uglify-js": "^2.6.2",

@@ -68,4 +68,5 @@ "webpack": "^4.46.0",

"dependencies": {
"tweetnacl": "^1.0.3"
"tweetnacl": "^1.0.3",
"@types/node": "^14.14.31"
}
}

@@ -5,4 +5,3 @@ # Pusher Channels Javascript Client

This Pusher Channels client library supports web browsers, web workers, Node.js
and React Native.
This Pusher Channels client library supports web browsers, web workers and Node.js

@@ -149,26 +148,8 @@ If you're looking for the Pusher Channels server library for Node.js, use

**Warning it's now necessary to install
[@react-native-community/netinfo](https://github.com/react-native-community/react-native-netinfo)
in order to use pusher-js with react-native.** pusher-js depends on NetInfo.
NetInfo. NetInfo was included within react-native core until v0.60, when it was
moved to the
[@react-native-community/netinfo](https://github.com/react-native-community/react-native-netinfo)
library. Please follow the [install
instructions](https://github.com/react-native-community/react-native-netinfo#getting-started)
for the
[@react-native-community/netinfo](https://github.com/react-native-community/react-native-netinfo)
library before trying to use pusher-js in your react-native project.
> **⚠️ Important notice**
>
> React Native support has been **deprecated** and soon will be removed from this repository.
>
> Please, use our official [React Native SDK](https://github.com/pusher/pusher-websocket-react-native) instead.
Use a package manager like Yarn or NPM to install `pusher-js` and then import
it as follows:
```javascript
import Pusher from 'pusher-js/react-native';
```
Notes:
* The fallbacks available for this runtime are HTTP streaming and polling.
* This build uses React Native's NetInfo API to detect changes on connectivity state. It will use this to automatically reconnect.
### Web Workers

@@ -259,3 +240,3 @@ (`pusher-js`'s Web Workers implementation is currently not compatible with Internet Explorer)

For more information see [authenticating users](https://pusher.com/docs/channels/server_api/authenticating-users/).
For more information see [authenticating users](https://pusher.com/docs/channels/server_api/authenticating-users/).

@@ -280,3 +261,3 @@

For more information see [authorizing users](https://pusher.com/docs/channels/server_api/authorizing-users).
For more information see [authorizing users](https://pusher.com/docs/channels/server_api/authorizing-users).

@@ -650,3 +631,3 @@

New to pusher-js 3.1 is the ability for the library to produce builds for different runtimes: classic web, React Native, NodeJS and
New to pusher-js 3.1 is the ability for the library to produce builds for different runtimes: classic web, NodeJS and
Web Workers.

@@ -690,3 +671,2 @@

```bash
make react-native # for the React Native build
make node # for the NodeJS build

@@ -705,3 +685,3 @@ make worker # for the worker build

There are 3 different testing environments: one for web, one for NodeJS and one for workers. We may consider adding another one for React Native in the future.
There are 3 different testing environments: one for web, one for NodeJS and one for workers.

@@ -708,0 +688,0 @@ The web and worker tests use [Karma](https://github.com/karma-runner/karma) to execute specs in real browsers. The NodeJS tests use [jasmine-node](https://github.com/mhevery/jasmine-node).

@@ -7,2 +7,4 @@ var PresenceChannel = require('core/channels/presence_channel').default;

var Mocks = require("mocks");
var flatPromise = require("core/utils/flat_promise").default;
var { setTimeout } = require("../../../helpers/timers/promises").default;

@@ -51,3 +53,3 @@ describe("PresenceChannel", function() {

describe("#authorize", function() {
it("should call channelAuthorizer", function() {

@@ -61,3 +63,3 @@ const callback = function(){}

it("should call the callback if an authorizaiton error is encountered", function() {
it("should call the callback if an authorization error is encountered", function() {
const callback = jasmine.createSpy("callback")

@@ -69,3 +71,3 @@ channel.authorize("1.23", callback);

const presenceChannelCallback = channelAuthorizer.calls.mostRecent().args[1];
presenceChannelCallback("error", {})

@@ -75,14 +77,81 @@ expect(callback).toHaveBeenCalledWith("error", {})

it("should call the callback with error if auth data doesn't have channel_data", function() {
const callback = jasmine.createSpy("callback")
channel.authorize("1.23", callback);
expect(channelAuthorizer.calls.count()).toEqual(1);
expect(channelAuthorizer).toHaveBeenCalledWith(
{ socketId: "1.23", channelName: "presence-test" }, jasmine.any(Function));
const presenceChannelCallback = channelAuthorizer.calls.mostRecent().args[1];
presenceChannelCallback(null, {
foo: 'bar'
})
expect(callback).toHaveBeenCalledWith("Invalid auth response")
describe("when channel_data isn't present", function() {
let callback;
let presenceChannelCallback;
const authWithoutChannelData = {foo: 'bar'}
beforeEach(function() {
pusher.user = jasmine.createSpy("user");
callback = jasmine.createSpy("callback")
channel.authorize("1.23", callback);
expect(channelAuthorizer.calls.count()).toEqual(1);
expect(channelAuthorizer).toHaveBeenCalledWith(
{ socketId: "1.23", channelName: "presence-test" }, jasmine.any(Function));
presenceChannelCallback = channelAuthorizer.calls.mostRecent().args[1];
});
it("should call the callback with an error if no signin is in progress", async function() {
pusher.user.signinDonePromise = null;
presenceChannelCallback(null, authWithoutChannelData);
await setTimeout(10);
expect(callback).toHaveBeenCalledWith("Invalid auth response");
});
it("should wait for the in-progress sign in and call the callback with an error if signin failed", async function() {
const {promise, resolve} = flatPromise();
pusher.user.signinDonePromise = promise
// signin is in progress
presenceChannelCallback(null, authWithoutChannelData)
await setTimeout(10);
expect(callback).not.toHaveBeenCalled()
// Signin failed
pusher.user.user_data = null
resolve()
await setTimeout(10);
expect(callback).toHaveBeenCalledWith("Invalid auth response")
});
it("should wait for the in-progress sign in and call the callback if signin succeeded", async function() {
const {promise, resolve} = flatPromise();
pusher.user.signinDonePromise = promise
// signin is in progress
presenceChannelCallback(null, authWithoutChannelData)
await setTimeout(10);
expect(callback).not.toHaveBeenCalled()
// Signin succeeded
pusher.user.user_data = {id: '123'}
resolve()
await setTimeout(10);
expect(callback).toHaveBeenCalledWith(null, authWithoutChannelData)
});
it("should call the callback if the user is already signed in", async function() {
const {promise, resolve} = flatPromise();
pusher.user.signinDonePromise = promise
resolve()
pusher.user.user_data = {id: '123'}
// signin is in progress
presenceChannelCallback(null, authWithoutChannelData)
await setTimeout(10);
expect(callback).toHaveBeenCalledWith(null, authWithoutChannelData)
});
it("should call the callback with an error if the user signin already failed", async function() {
const {promise, resolve} = flatPromise();
pusher.user.signinDonePromise = promise
resolve()
pusher.user.user_data = null
// signin is in progress
presenceChannelCallback(null, authWithoutChannelData)
await setTimeout(10);
expect(callback).toHaveBeenCalledWith("Invalid auth response")
});
});

@@ -97,3 +166,3 @@

const presenceChannelCallback = channelAuthorizer.calls.mostRecent().args[1];
const authdata = {

@@ -100,0 +169,0 @@ channel_data: "{\"user_id\":\"123\"}",

@@ -85,3 +85,3 @@ var TestEnv = require("testenv");

pusher.connection.state = "connected";
pusher.connection.emit('connected');
pusher.connection.emit('state_change', {previous:'connecting', current:'connected'});

@@ -120,7 +120,7 @@ expect(pusher.config.userAuthenticator).toHaveBeenCalledWith(

pusher.connection.state == "disconnected";
pusher.connection.emit("disconnected");
pusher.connection.emit('state_change', {previous:'connected', current:'disconnected'});
pusher.connection.state == "connecting";
pusher.connection.emit("connecting");
pusher.connection.emit('state_change', {previous:'disconnected', current:'connecting'});
pusher.connection.state == "connected";
pusher.connection.emit("connected");
pusher.connection.emit('state_change', {previous:'connecting', current:'connected'});

@@ -139,3 +139,3 @@ expect(pusher.config.userAuthenticator).toHaveBeenCalledWith(

pusher.connection.state = "connected";
pusher.connection.emit('connected');
pusher.connection.emit('state_change', {previous:'connecting', current:'connected'});
expect(pusher.config.userAuthenticator).not.toHaveBeenCalled();

@@ -178,2 +178,3 @@ })

it('should process pusher:signin_success', async function () {
pusher.user._signinDoneResolve = jasmine.createSpy('signinDoneResolve');
transport.emit('message', {

@@ -190,2 +191,3 @@ data: JSON.stringify({

expect(pusher.user.serverToUserChannel.subscriptionPending).toBe(true);
expect(pusher.user._signinDoneResolve).toHaveBeenCalled();
});

@@ -228,2 +230,3 @@

// Sign in successfully
pusher.user._signinDoneResolve = jasmine.createSpy('signinDoneResolve');
transport.emit('message', {

@@ -251,2 +254,3 @@ data: JSON.stringify({

);
expect(pusher.user._signinDoneResolve).toHaveBeenCalled();

@@ -269,2 +273,3 @@ // Send events on channel

// Sign in successfully
pusher.user._signinDoneResolve = jasmine.createSpy('signinDoneResolve');
transport.emit('message', {

@@ -292,2 +297,4 @@ data: JSON.stringify({

);
expect(pusher.user._signinDoneResolve).toHaveBeenCalled();
expect(pusher.user.user_data).toEqual({ id: '1', name: 'test' });

@@ -297,3 +304,3 @@ expect(pusher.user.serverToUserChannel.subscribed).toBe(true);

// Disconnect
pusher.connection.emit('disconnected');
pusher.connection.emit('state_change', {previous:'connected', current:'disconnected'});

@@ -300,0 +307,0 @@ expect(pusher.user.user_data).toEqual(null);

@@ -23,3 +23,3 @@ import PrivateChannel from './private_channel';

/** Authenticates the connection as a member of the channel.
/** Authorizes the connection as a member of the channel.
*

@@ -30,16 +30,25 @@ * @param {String} socketId

authorize(socketId: string, callback: Function) {
super.authorize(socketId, (error, authData) => {
super.authorize(socketId, async (error, authData) => {
if (!error) {
authData = authData as ChannelAuthorizationData;
if (authData.channel_data === undefined) {
let suffix = UrlStore.buildLogSuffix('authenticationEndpoint');
Logger.error(
`Invalid auth response for channel '${this.name}',` +
`expected 'channel_data' field. ${suffix}`
);
callback('Invalid auth response');
return;
if (authData.channel_data != null) {
var channelData = JSON.parse(authData.channel_data);
this.members.setMyID(channelData.user_id);
} else {
await this.pusher.user.signinDonePromise;
if (this.pusher.user.user_data != null) {
// If the user is signed in, get the id of the authenticated user
// and allow the presence authorization to continue.
this.members.setMyID(this.pusher.user.user_data.id);
} else {
let suffix = UrlStore.buildLogSuffix('authorizationEndpoint');
Logger.error(
`Invalid auth response for channel '${this.name}', ` +
`expected 'channel_data' field. ${suffix}, ` +
`or the user should be signed in.`
);
callback('Invalid auth response');
return;
}
}
var channelData = JSON.parse(authData.channel_data);
this.members.setMyID(channelData.user_id);
}

@@ -46,0 +55,0 @@ callback(error, authData);

@@ -207,3 +207,3 @@ import URLLocation from './url_location';

function randomNumber(max: number): number {
return Math.floor(Math.random() * max);
return Runtime.randomInt(max);
}

@@ -213,5 +213,7 @@

var result = [];
for (var i = 0; i < length; i++) {
result.push(randomNumber(32).toString(32));
}
return result.join('');

@@ -218,0 +220,0 @@ }

@@ -86,3 +86,3 @@ import AbstractRuntime from '../runtimes/interface';

this.global_emitter = new EventsDispatcher();
this.sessionID = Math.floor(Math.random() * 1000000000);
this.sessionID = Runtime.randomInt(1000000000);

@@ -89,0 +89,0 @@ this.timeline = new Timeline(this.key, this.sessionID, {

@@ -9,2 +9,3 @@ import Pusher from './pusher';

import EventsDispatcher from './events/dispatcher';
import flatPromise from './utils/flat_promise';

@@ -16,2 +17,4 @@ export default class UserFacade extends EventsDispatcher {

serverToUserChannel: Channel = null;
signinDonePromise: Promise<any> = null;
private _signinDoneResolve: Function = null;

@@ -23,11 +26,11 @@ public constructor(pusher: Pusher) {

this.pusher = pusher;
this.pusher.connection.bind('connected', () => {
this._signin();
this.pusher.connection.bind('state_change', ({ previous, current }) => {
if (previous !== 'connected' && current === 'connected') {
this._signin();
}
if (previous === 'connected' && current !== 'connected') {
this._cleanup();
this._newSigninPromiseIfNeeded();
}
});
this.pusher.connection.bind('connecting', () => {
this._disconnect();
});
this.pusher.connection.bind('disconnected', () => {
this._disconnect();
});
this.pusher.connection.bind('message', event => {

@@ -61,2 +64,4 @@ var eventName = event.event;

this._newSigninPromiseIfNeeded();
if (this.pusher.connection.state !== 'connected') {

@@ -67,19 +72,2 @@ // Signin will be attempted when the connection is connected

const onAuthorize: UserAuthenticationCallback = (
err,
authData: UserAuthenticationData
) => {
if (err) {
Logger.warn(`Error during signin: ${err}`);
return;
}
this.pusher.send_event('pusher:signin', {
auth: authData.auth,
user_data: authData.user_data
});
// Later when we get pusher:singin_success event, the user will be marked as signed in
};
this.pusher.config.userAuthenticator(

@@ -89,6 +77,24 @@ {

},
onAuthorize
this._onAuthorize
);
}
private _onAuthorize: UserAuthenticationCallback = (
err,
authData: UserAuthenticationData
) => {
if (err) {
Logger.warn(`Error during signin: ${err}`);
this._cleanup();
return;
}
this.pusher.send_event('pusher:signin', {
auth: authData.auth,
user_data: authData.user_data
});
// Later when we get pusher:singin_success event, the user will be marked as signed in
};
private _onSigninSuccess(data: any) {

@@ -99,2 +105,3 @@ try {

Logger.error(`Failed parsing user data after signin: ${data.user_data}`);
this._cleanup();
return;

@@ -107,5 +114,8 @@ }

);
this._cleanup();
return;
}
// Signin succeeded
this._signinDoneResolve();
this._subscribeChannels();

@@ -143,3 +153,3 @@ }

private _disconnect() {
private _cleanup() {
this.user_data = null;

@@ -151,3 +161,31 @@ if (this.serverToUserChannel) {

}
if (this.signin_requested) {
// If signin is in progress and cleanup is called,
// Mark the current signin process as done.
this._signinDoneResolve();
}
}
private _newSigninPromiseIfNeeded() {
if (!this.signin_requested) {
return;
}
// If there is a promise and it is not resolved, return without creating a new one.
if (this.signinDonePromise && !(this.signinDonePromise as any).done) {
return;
}
// This promise is never rejected.
// It gets resolved when the signin process is done whether it failed or succeeded
const { promise, resolve, reject: _ } = flatPromise();
(promise as any).done = false;
const setDone = () => {
(promise as any).done = true;
};
promise.then(setDone).catch(setDone);
this.signinDonePromise = promise;
this._signinDoneResolve = resolve;
}
}

@@ -49,2 +49,3 @@ import { AuthTransports } from '../core/auth/auth_transports';

createSocketRequest(method: string, url: string): HTTPRequest;
randomInt(max: number): number;

@@ -51,0 +52,0 @@ // these methods/types are only implemented in the web Runtime, so they're

@@ -9,2 +9,3 @@ import Isomorphic from 'isomorphic/runtime';

import xhrTimeline from 'isomorphic/timeline/xhr_timeline';
import { randomInt } from 'crypto';

@@ -61,2 +62,6 @@ // Very verbose but until unavoidable until

return Network;
},
randomInt(max: number): number {
return randomInt(max);
}

@@ -63,0 +68,0 @@ };

@@ -7,2 +7,3 @@ import Isomorphic from 'isomorphic/runtime';

import xhrTimeline from 'isomorphic/timeline/xhr_timeline';
import { randomInt } from 'crypto';

@@ -59,2 +60,6 @@ // Very verbose but until unavoidable until

return Network;
},
randomInt(max: number): number {
return randomInt(max);
}

@@ -61,0 +66,0 @@ };

@@ -157,2 +157,16 @@ import Browser from './browser';

}
},
randomInt(max: number): number {
/**
* Return values in the range of [0, 1[
*/
const random = function() {
const crypto = window.crypto || window['msCrypto'];
const random = crypto.getRandomValues(new Uint32Array(1))[0];
return random / 2 ** 32;
};
return Math.floor(random() * max);
}

@@ -159,0 +173,0 @@ };

@@ -58,2 +58,16 @@ import Isomorphic from 'isomorphic/runtime';

return Network;
},
randomInt(max: number): number {
/**
* Return values in the range of [0, 1[
*/
const random = function() {
const crypto = window.crypto || window['msCrypto'];
const random = crypto.getRandomValues(new Uint32Array(1))[0];
return random / 2 ** 32;
};
return Math.floor(random() * max);
}

@@ -60,0 +74,0 @@ };

@@ -13,4 +13,7 @@ import Strategy from './strategy';

abort: () => void;
forceMinPriority: () => void;
} | {
abort: () => void;
forceMinPriority: (p: any) => void;
};
}

@@ -9,8 +9,12 @@ import Pusher from './pusher';

serverToUserChannel: Channel;
signinDonePromise: Promise<any>;
private _signinDoneResolve;
constructor(pusher: Pusher);
signin(): void;
private _signin;
private _onAuthorize;
private _onSigninSuccess;
private _subscribeChannels;
private _disconnect;
private _cleanup;
private _newSigninPromiseIfNeeded;
}

@@ -36,2 +36,3 @@ import { AuthTransports } from '../core/auth/auth_transports';

createSocketRequest(method: string, url: string): HTTPRequest;
randomInt(max: number): number;
getDocument?(): Document;

@@ -38,0 +39,0 @@ createScriptRequest?(url: string): any;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc