diff --git a/examples/secured-room-namespace/LICENSE b/examples/secured-room-namespace/LICENSE new file mode 100644 index 0000000000..a1b765967f --- /dev/null +++ b/examples/secured-room-namespace/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ahsan Aasim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/examples/secured-room-namespace/README.md b/examples/secured-room-namespace/README.md new file mode 100644 index 0000000000..40d6d6ead1 --- /dev/null +++ b/examples/secured-room-namespace/README.md @@ -0,0 +1,15 @@ +
+
+
+ +[](https://app.codacy.com/gh/ahsanaasim/boiled-socket.io/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) + +
+ +## Socket.IO Secured Room & Namespace Example + +This is a Socket.IO boilerplate code in TypeScript that includes an example of authentication for securing the socket server, as well as examples of room and namespace usage. + +You can check out [this blog on Medium](https://medium.com/@ahsan.aasim/building-a-secured-socket-server-with-express-and-socket-io-in-typescript-eaa8eac54889) to gain a better understanding of the concept and codes used in building a secured socket server with Express and Socket.IO in TypeScript." \ No newline at end of file diff --git a/examples/secured-room-namespace/index.html b/examples/secured-room-namespace/index.html new file mode 100644 index 0000000000..004975c276 --- /dev/null +++ b/examples/secured-room-namespace/index.html @@ -0,0 +1,34 @@ + + + + + + \ No newline at end of file diff --git a/examples/secured-room-namespace/index.ts b/examples/secured-room-namespace/index.ts new file mode 100644 index 0000000000..909310ef0e --- /dev/null +++ b/examples/secured-room-namespace/index.ts @@ -0,0 +1,22 @@ +import express, { Express, Request, Response } from 'express'; +import { createServer } from 'http'; +import { Socket } from './src/socket'; + +const app: Express = express(); + +app.get('/', (req: Request, res: Response) => { + res.sendFile('index.html', { root: __dirname }); +}); + +const httpServer = createServer(app); + +const socket = new Socket(httpServer); +const space = socket.createNamespace('sessions'); + +socket.onConnect(space, (s) => { + const room = 'room_' + s.handshake.auth.room; + socket.joinRoom(room, s); + socket.emitToRoomInSpace('connect_msg', space, room, { test: 'test', room: s.handshake.auth.room }); +}); + +httpServer.listen(3000); diff --git a/examples/secured-room-namespace/package.json b/examples/secured-room-namespace/package.json new file mode 100644 index 0000000000..5c24f98c9b --- /dev/null +++ b/examples/secured-room-namespace/package.json @@ -0,0 +1,55 @@ +{ + "name": "boiled-socket.io", + "version": "1.0.1", + "description": "", + "main": "index.ts", + "scripts": { + "start:dev": "npx nodemon", + "build": "tsc", + "prepare": "npm run build", + "preversion": "npm run lint", + "version": "npm run format && git add -A src", + "postversion": "git push && git push --tags", + "format": "prettier --config .prettierrc 'src/**/*.ts' --write", + "lint": "tslint -p tsconfig.json", + "test": "mocha --timeout 10000 -r ts-node/register src/**/*.test.ts", + "test-single": "mocha --timeout 10000 -r ts-node/register", + "coverage": "nyc -r lcov -e .ts -x \"*.test.ts\" npm run test" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ahsanaasim/boiled-socket.io.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/ahsanaasim/boiled-socket.io/issues" + }, + "homepage": "https://github.com/ahsanaasim/boiled-socket.io#readme", + "dependencies": { + "@types/uuid": "^9.0.1", + "express": "^4.18.2", + "socket.io": "^4.6.1", + "socket.io-client": "^4.6.1", + "uuid": "^9.0.0" + }, + "optionalDependencies": { + "bufferutil": "^4.0.7", + "utf-8-validate": "^5.0.10" + }, + "devDependencies": { + "@types/chai": "^4.3.4", + "@types/express": "^4.17.17", + "@types/mocha": "^10.0.1", + "@types/node": "^18.15.6", + "chai": "^4.3.7", + "mocha": "^10.2.0", + "nodemon": "^2.0.22", + "nyc": "^15.1.0", + "prettier": "^2.8.7", + "ts-node": "^10.9.1", + "tslint": "^6.1.3", + "tslint-config-prettier": "^1.18.0", + "typescript": "^5.0.2" + } +} diff --git a/examples/secured-room-namespace/socketio.png b/examples/secured-room-namespace/socketio.png new file mode 100644 index 0000000000..4d1760f9b0 Binary files /dev/null and b/examples/secured-room-namespace/socketio.png differ diff --git a/examples/secured-room-namespace/src/socket.ts b/examples/secured-room-namespace/src/socket.ts new file mode 100644 index 0000000000..2c72907fc6 --- /dev/null +++ b/examples/secured-room-namespace/src/socket.ts @@ -0,0 +1,50 @@ +import { Namespace, Server, Socket as IOSocket } from 'socket.io'; + +export class Socket { + io: Server; + + constructor(httpServer: any) { + this.io = new Server(httpServer, { + /* options */ + }); + + this.init(); + } + + private init = () => { + this.io.use(async (socket, next) => { + try { + if (socket.handshake.auth.token === 'aa') { + next(); + } else { + const err = new Error('unauthorized'); + next(err); + } + } catch (e) { + next(new Error('unauthorized')); + } + }); + }; + + public createNamespace = (spaceName: string): Namespace => { + return this.io.of('/' + spaceName); + }; + + public onConnect = (space: Namespace, cb: (socket: IOSocket) => void) => { + space.on('connection', (socket: IOSocket) => { + cb(socket); + }); + }; + + public joinRoom = (room: string, socket: IOSocket) => { + socket.join(room); + }; + + public emitToRoomInSpace = (name: string, space: Namespace, room: string, data: any) => { + space.to(room).emit(name, data); + }; + + public emitToSpace = (name: string, space: Namespace, data: any) => { + space.emit(name, data); + }; +} diff --git a/examples/secured-room-namespace/tsconfig.json b/examples/secured-room-namespace/tsconfig.json new file mode 100644 index 0000000000..34f4d1702b --- /dev/null +++ b/examples/secured-room-namespace/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "target": "es5", + "module": "commonjs", + "declaration": true, + "outDir": "./lib", + "strict": true, + "rootDir": "./src", + "baseUrl": "./" + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "**/__tests__/*" + ] +} \ No newline at end of file diff --git a/examples/secured-room-namespace/tslint.json b/examples/secured-room-namespace/tslint.json new file mode 100644 index 0000000000..71287e59b5 --- /dev/null +++ b/examples/secured-room-namespace/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": [ + "tslint:recommended", + "tslint-config-prettier" + ] +} \ No newline at end of file