diff --git a/README.md b/README.md index eb628ca..2d024de 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,9 @@ import { YSocketIO } from 'y-socket.io/dist/server' ```js configuration = { // Optionally, set here the authentication validation callback (by default server accepts all connections) - // (for example: if client sent a token, you can get token from auth object - authenticate: undefined, // Example: (auth) => auth.token === 'valid-token') + // For example: if client sent a token or other data, you can get it from auth object of + // socket.io handshake + authenticate: undefined, // Example: (handshake) => handshake.auth.token === 'valid-token') // Optionally, enable LevelDB persistence by setting the directory where you want to store the database (by default the LevelDB persistence is disabled) levelPersistenceDir: undefined, // Enable/Disable garbage collection (by default the garbage collection is enabled) diff --git a/examples/react-example/src/App.tsx b/examples/react-example/src/App.tsx index 276f340..ddf7ee1 100644 --- a/examples/react-example/src/App.tsx +++ b/examples/react-example/src/App.tsx @@ -5,7 +5,7 @@ import { SocketIOProvider } from 'y-socket.io'; function App() { const [doc, setDoc] = useState(null); const [provider, setProvider] = useState(null); - const [connected, setConnected] = useState(true); + const [status, setStatus] = useState('disconnected'); const [input, setInput] = useState(''); const [clients, setClients] = useState([]); @@ -37,10 +37,9 @@ function App() { }); socketIOProvider.awareness.on('change', () => setClients(Array.from(socketIOProvider.awareness.getStates().keys()).map(key => `${key}`))) socketIOProvider.awareness.setLocalState({ id: Math.random(), name: 'Perico' }); - socketIOProvider.on('sync', (status: boolean) => console.log('websocket sync', status)) - socketIOProvider.on('status', ({ status }: { status: string }) => { - if (status === 'connected') setConnected(true); - else setConnected(false); + socketIOProvider.on('sync', (isSync: boolean) => console.log('websocket sync', isSync)) + socketIOProvider.on('status', ({ status: _status }: { status: string }) => { + if (!!_status) setStatus(_status); }) setProvider(socketIOProvider); } @@ -58,9 +57,9 @@ function App() {
App
-

State: {connected ? 'Connected' : 'Disconneted'}

+

State: {status}

{ - !connected + !(status === 'connected') ? <> diff --git a/src/client/provider.ts b/src/client/provider.ts index c0ecfc4..2545bac 100644 --- a/src/client/provider.ts +++ b/src/client/provider.ts @@ -242,7 +242,7 @@ export class SocketIOProvider extends Observable { * Connect provider's socket * @type {() => void} */ - public connect (): void { + public connect(): void { if (!this.socket.connected) { this.emit('status', [{ status: 'connecting' }]) this.socket.connect() diff --git a/src/server/server.ts b/src/server/server.ts index 374a79a..2d5a800 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -21,7 +21,14 @@ const io = new Server(server) // for other logic, these do not match the regular expression, this could cause unwanted problems. // TIP: You can export a new instance from another file to manage as singleton and access documents from all app. const ysocketio = new YSocketIO(io, { - // authenticate: (auth) => auth.token === 'valid-token', + // authenticate: (handshake) => handshake.auth.token === 'valid-token', + // OR + // authenticate: (handshake) => { + // return new Promise(resolve => { + // setTimeout(() => resolve(handshake.auth.token === 'valid-token'), 2000) + // }) + // }, + // levelPersistenceDir: './storage-location', // gcEnabled: true, }) diff --git a/src/server/y-socket-io.ts b/src/server/y-socket-io.ts index 8c3591c..ab58876 100644 --- a/src/server/y-socket-io.ts +++ b/src/server/y-socket-io.ts @@ -32,10 +32,10 @@ export interface YSocketIOConfiguration { /** * Callback to authenticate the client connection. * - * If it returns true, the connection is allowed; otherwise, if it returns false, the connection is rejected. - * @param auth Provided from the auth attribute on the socket io handshake + * It can be a promise and if it returns true, the connection is allowed; otherwise, if it returns false, the connection is rejected. + * @param handshake Provided from the handshake attribute of the socket io */ - authenticate?: (auth: { [key: string]: any }) => boolean + authenticate?: (handshake: { [key: string]: any }) => Promise | boolean } /** @@ -92,9 +92,9 @@ export class YSocketIO extends Observable { public initialize (): void { const dynamicNamespace = this.io.of(/^\/yjs\|.*$/) - dynamicNamespace.use((socket, next) => { + dynamicNamespace.use(async (socket, next) => { if ((this.configuration?.authenticate) == null) return next() - if (this.configuration.authenticate(socket.handshake.auth)) return next() + if (await this.configuration.authenticate(socket.handshake)) return next() else return next(new Error('Unauthorized')) })