From dab3b9dc61ce2ec9c8820c790573eb192e7cb005 Mon Sep 17 00:00:00 2001 From: harshithnrao Date: Sat, 29 Mar 2025 20:07:22 +0530 Subject: [PATCH] google-signin --- package-lock.json | 288 +++++++++++++----- package.json | 4 + src/app-config/app-config.service.ts | 4 + src/app-config/config.json | 6 + src/app-config/config.local.json | 6 + src/app.service.ts | 4 + src/auth/auth.controller.ts | 22 +- src/auth/auth.module.ts | 3 +- src/auth/auth.service.ts | 53 +++- src/booking-gateway/booking-gateway.module.ts | 8 +- src/booking-gateway/booking.gateway.ts | 8 + src/booking-gateway/booking.service.ts | 2 +- src/common/Utility.ts | 1 + src/common/common.service.ts | 1 + src/google-oauth/google-oauth.guard.ts | 12 + src/google-oauth/google.strategy.ts | 30 ++ src/jwt/refresh-token.entity.ts | 4 + src/main.ts | 1 + 18 files changed, 361 insertions(+), 96 deletions(-) create mode 100644 src/google-oauth/google-oauth.guard.ts create mode 100644 src/google-oauth/google.strategy.ts diff --git a/package-lock.json b/package-lock.json index ac9238a..80e7bca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@nestjs/jwt": "^11.0.0", "@nestjs/passport": "^11.0.5", "@nestjs/platform-express": "^10.0.0", + "@nestjs/platform-socket.io": "^10.4.15", "@nestjs/swagger": "^8.1.1", "@nestjs/typeorm": "^10.0.1", "@nestjs/websockets": "^10.4.15", @@ -25,6 +26,8 @@ "moment": "^2.30.1", "nodemailer": "^6.9.9", "otp-generator": "^4.0.1", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", "passport-jwt": "^4.0.1", "pg": "^8.14.1", "reflect-metadata": "^0.1.14", @@ -45,6 +48,7 @@ "@types/node": "^20.10.6", "@types/nodemailer": "^6.4.14", "@types/passport": "^1.0.17", + "@types/passport-google-oauth20": "^2.0.16", "@types/passport-jwt": "^4.0.1", "@types/supertest": "^2.0.12", "@types/validator": "^13.11.7", @@ -1797,12 +1801,6 @@ } } }, - "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/@nestjs/config": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.3.0.tgz", @@ -1856,12 +1854,6 @@ } } }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/@nestjs/jwt": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.0.tgz", @@ -1926,11 +1918,24 @@ "@nestjs/core": "^10.0.0" } }, - "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/@nestjs/platform-socket.io": { + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.15.tgz", + "integrity": "sha512-KZAxNEADPwoORixh3NJgGYWMVGORVPKeTqjD7hbF8TPDLKWWxru9yasBQwEz2/wXH/WgpkQbbaYwx4nUjCIVpw==", + "license": "MIT", + "dependencies": { + "socket.io": "4.8.1", + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "rxjs": "^7.1.0" + } }, "node_modules/@nestjs/schematics": { "version": "10.2.3", @@ -1983,12 +1988,13 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.3.0.tgz", - "integrity": "sha512-8DM+bw1qASCvaEnoHUQhypCOf54+G5R21MeFBMvnSk5DtKaWVZuzDP2GjLeYCpTH19WeP6LrrjHv3rX2LKU02A==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.15.tgz", + "integrity": "sha512-eGlWESkACMKti+iZk1hs6FUY/UqObmMaa8HAN9JLnaYkoLf1Jeh+EuHlGnfqo/Rq77oznNLIyaA3PFjrFDlNUg==", "dev": true, + "license": "MIT", "dependencies": { - "tslib": "2.6.2" + "tslib": "2.8.1" }, "funding": { "type": "opencollective", @@ -2010,16 +2016,17 @@ } }, "node_modules/@nestjs/typeorm": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.1.tgz", - "integrity": "sha512-YVFYL7D25VAVp5/G+KLXIgsRfYomA+VaFZBpm2rtwrrBOmkXNrxr7kuI2bBBO/Xy4kKBDe6wbvIVVFeEA7/ngA==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", + "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", + "license": "MIT", "dependencies": { "uuid": "9.0.1" }, "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13", + "reflect-metadata": "^0.1.13 || ^0.2.0", "rxjs": "^7.2.0", "typeorm": "^0.3.0" } @@ -2047,12 +2054,6 @@ } } }, - "node_modules/@nestjs/websockets/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2434,6 +2435,16 @@ "@types/node": "*" } }, + "node_modules/@types/oauth": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.6.tgz", + "integrity": "sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/passport": { "version": "1.0.17", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", @@ -2444,6 +2455,18 @@ "@types/express": "*" } }, + "node_modules/@types/passport-google-oauth20": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", + "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, "node_modules/@types/passport-jwt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", @@ -2455,6 +2478,18 @@ "@types/passport-strategy": "*" } }, + "node_modules/@types/passport-oauth2": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", + "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, "node_modules/@types/passport-strategy": { "version": "0.2.38", "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", @@ -3381,6 +3416,15 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -7579,6 +7623,12 @@ "node": ">=8" } }, + "node_modules/oauth": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.2.tgz", + "integrity": "sha512-JtFnB+8nxDEXgNyniwz573xxbKSOu3R8D40xQKqcjwJ2CDkYqUDI53o6IuzDJBx60Z8VKCm271+t8iFjakrl8Q==", + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7808,7 +7858,6 @@ "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", "license": "MIT", - "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -7822,6 +7871,18 @@ "url": "https://github.com/sponsors/jaredhanson" } }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "license": "MIT", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/passport-jwt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", @@ -7832,6 +7893,26 @@ "passport-strategy": "^1.0.0" } }, + "node_modules/passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "license": "MIT", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, "node_modules/passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", @@ -7914,8 +7995,7 @@ "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "peer": true + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "node_modules/pg": { "version": "8.14.1", @@ -9849,9 +9929,10 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", @@ -10111,6 +10192,12 @@ "node": ">=8" } }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==", + "license": "MIT" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -11943,13 +12030,6 @@ "iterare": "1.2.1", "tslib": "2.8.1", "uid": "2.0.2" - }, - "dependencies": { - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - } } }, "@nestjs/config": { @@ -11973,13 +12053,6 @@ "path-to-regexp": "3.3.0", "tslib": "2.8.1", "uid": "2.0.2" - }, - "dependencies": { - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - } } }, "@nestjs/jwt": { @@ -12013,13 +12086,15 @@ "express": "4.21.2", "multer": "1.4.4-lts.1", "tslib": "2.8.1" - }, - "dependencies": { - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - } + } + }, + "@nestjs/platform-socket.io": { + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.15.tgz", + "integrity": "sha512-KZAxNEADPwoORixh3NJgGYWMVGORVPKeTqjD7hbF8TPDLKWWxru9yasBQwEz2/wXH/WgpkQbbaYwx4nUjCIVpw==", + "requires": { + "socket.io": "4.8.1", + "tslib": "2.8.1" } }, "@nestjs/schematics": { @@ -12049,18 +12124,18 @@ } }, "@nestjs/testing": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.3.0.tgz", - "integrity": "sha512-8DM+bw1qASCvaEnoHUQhypCOf54+G5R21MeFBMvnSk5DtKaWVZuzDP2GjLeYCpTH19WeP6LrrjHv3rX2LKU02A==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.15.tgz", + "integrity": "sha512-eGlWESkACMKti+iZk1hs6FUY/UqObmMaa8HAN9JLnaYkoLf1Jeh+EuHlGnfqo/Rq77oznNLIyaA3PFjrFDlNUg==", "dev": true, "requires": { - "tslib": "2.6.2" + "tslib": "2.8.1" } }, "@nestjs/typeorm": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.1.tgz", - "integrity": "sha512-YVFYL7D25VAVp5/G+KLXIgsRfYomA+VaFZBpm2rtwrrBOmkXNrxr7kuI2bBBO/Xy4kKBDe6wbvIVVFeEA7/ngA==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", + "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", "requires": { "uuid": "9.0.1" } @@ -12073,13 +12148,6 @@ "iterare": "1.2.1", "object-hash": "3.0.0", "tslib": "2.8.1" - }, - "dependencies": { - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - } } }, "@nodelib/fs.scandir": { @@ -12432,6 +12500,15 @@ "@types/node": "*" } }, + "@types/oauth": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.6.tgz", + "integrity": "sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/passport": { "version": "1.0.17", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", @@ -12441,6 +12518,17 @@ "@types/express": "*" } }, + "@types/passport-google-oauth20": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", + "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, "@types/passport-jwt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", @@ -12451,6 +12539,17 @@ "@types/passport-strategy": "*" } }, + "@types/passport-oauth2": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", + "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, "@types/passport-strategy": { "version": "0.2.38", "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", @@ -13129,6 +13228,11 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -16169,6 +16273,11 @@ "path-key": "^3.0.0" } }, + "oauth": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.2.tgz", + "integrity": "sha512-JtFnB+8nxDEXgNyniwz573xxbKSOu3R8D40xQKqcjwJ2CDkYqUDI53o6IuzDJBx60Z8VKCm271+t8iFjakrl8Q==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -16331,13 +16440,20 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", - "peer": true, "requires": { "passport-strategy": "1.x.x", "pause": "0.0.1", "utils-merge": "^1.0.1" } }, + "passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, "passport-jwt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", @@ -16347,6 +16463,18 @@ "passport-strategy": "^1.0.0" } }, + "passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, "passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", @@ -16407,8 +16535,7 @@ "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "peer": true + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "pg": { "version": "8.14.1", @@ -17749,9 +17876,9 @@ } }, "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "type-check": { "version": "0.4.0", @@ -17866,6 +17993,11 @@ "@lukeed/csprng": "^1.0.0" } }, + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index abb3aeb..650667d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@nestjs/jwt": "^11.0.0", "@nestjs/passport": "^11.0.5", "@nestjs/platform-express": "^10.0.0", + "@nestjs/platform-socket.io": "^10.4.15", "@nestjs/swagger": "^8.1.1", "@nestjs/typeorm": "^10.0.1", "@nestjs/websockets": "^10.4.15", @@ -39,6 +40,8 @@ "moment": "^2.30.1", "nodemailer": "^6.9.9", "otp-generator": "^4.0.1", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", "passport-jwt": "^4.0.1", "pg": "^8.14.1", "reflect-metadata": "^0.1.14", @@ -59,6 +62,7 @@ "@types/node": "^20.10.6", "@types/nodemailer": "^6.4.14", "@types/passport": "^1.0.17", + "@types/passport-google-oauth20": "^2.0.16", "@types/passport-jwt": "^4.0.1", "@types/supertest": "^2.0.12", "@types/validator": "^13.11.7", diff --git a/src/app-config/app-config.service.ts b/src/app-config/app-config.service.ts index aee2120..092a91e 100644 --- a/src/app-config/app-config.service.ts +++ b/src/app-config/app-config.service.ts @@ -57,4 +57,8 @@ export class AppConfigService { getSwaggerConfig(){ return configMaster[this.defaultEnv].swaggerConfig; } + + getGoogleOauthConfig(){ + return configMaster[this.defaultEnv].googleOauthConfig; + } } diff --git a/src/app-config/config.json b/src/app-config/config.json index acc632d..c98a89f 100644 --- a/src/app-config/config.json +++ b/src/app-config/config.json @@ -60,6 +60,12 @@ "host":"localhost", "port":6379, "db":0 + }, + "googleOauthConfig": { + "clientId":"361418022886-4d4p2v7n9tq8t4tq8t4tq8tq8tq8tq8t.apps.googleusercontent.com", + "clientSecret":"GOCSPX-2Vt7b5Oo4t4t4t4t4t4t4t4t4t4", + "callbackURL":"http://localhost:3000/auth/google-redirect", + "scope":["email","profile"] } } } \ No newline at end of file diff --git a/src/app-config/config.local.json b/src/app-config/config.local.json index acc632d..c98a89f 100644 --- a/src/app-config/config.local.json +++ b/src/app-config/config.local.json @@ -60,6 +60,12 @@ "host":"localhost", "port":6379, "db":0 + }, + "googleOauthConfig": { + "clientId":"361418022886-4d4p2v7n9tq8t4tq8t4tq8tq8tq8tq8t.apps.googleusercontent.com", + "clientSecret":"GOCSPX-2Vt7b5Oo4t4t4t4t4t4t4t4t4t4", + "callbackURL":"http://localhost:3000/auth/google-redirect", + "scope":["email","profile"] } } } \ No newline at end of file diff --git a/src/app.service.ts b/src/app.service.ts index 08142f6..13b261b 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -57,6 +57,10 @@ export class AppService { const redisConfig = this.configService.getRedisConfig(); this.commonService.redisConfig = redisConfig; Utility.redisConfig = redisConfig; + + const googleOauthConfig = this.configService.getGoogleOauthConfig(); + this.commonService.googleOauthConfig = googleOauthConfig; + Utility.googleOauthConfig = googleOauthConfig; } getModels() { diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index e4bed98..d4da566 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -1,8 +1,9 @@ -import { Body, Controller, Delete, Post, Res } from '@nestjs/common'; +import { Body, Controller, Delete, Get, Post, Req, Res, UseGuards } from '@nestjs/common'; import { GenericResponse } from 'src/common/GenericResponse.model'; import { AuthService } from './auth.service'; -import { Response } from 'express'; +import { Request, Response } from 'express'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { GoogleOauthGuard } from 'src/google-oauth/google-oauth.guard'; @ApiTags('Auth') @Controller('auth') export class AuthController { @@ -100,4 +101,21 @@ export class AuthController { } } + //google oauth implementation + + @Get() + @UseGuards(GoogleOauthGuard) + async googleLogin(@Res() res: Response) { + console.log("inside google login"); + } //basically this is used to call googleLogin for login credentials + + @Get('google-redirect') + @UseGuards(GoogleOauthGuard) + async googleOauthRedirect(@Req() req: Request, @Res() res: Response) { + console.log("inside google redirect"); + const httpResponse = await this.authService.googleOauthRedirect(req.user); + return res.status(httpResponse.statusCode).send(httpResponse); + } + + } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 3ed4668..f017b11 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -7,6 +7,7 @@ import { UserModule } from 'src/user/user.module'; import { JwtStrategy } from 'src/jwt/jwt.strategy'; import { Utility } from 'src/common/Utility'; import { ConfigModule, ConfigService } from '@nestjs/config'; +import { GoogleStrategy } from 'src/google-oauth/google.strategy'; @Module({ imports: [ @@ -26,7 +27,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config'; UserModule, ], controllers: [AuthController], - providers: [AuthService, JwtStrategy], + providers: [AuthService, JwtStrategy,GoogleStrategy], exports: [AuthService], }) export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 146cf73..ca8e817 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,18 +1,20 @@ import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; +import { Response } from 'express'; import { Utility } from 'src/common/Utility'; import JwtPayload from 'src/jwt/jwt-payload.dto'; import RefreshToken from 'src/jwt/refresh-token.entity'; +import { User } from 'src/user/user.entity'; import { UserService } from 'src/user/user.service'; +import { Request } from 'express'; @Injectable() export class AuthService { + constructor(private userService: UserService, private jwtService: JwtService) { } - private signToken(payload: any, type: 'accessToken' | 'refreshToken'): string { - console.log("yav type andre", type) + private async signToken(payload: any, type: 'accessToken' | 'refreshToken') { const config = Utility.jwtConfig[type]; - console.log("yav expiry andre", config.expiresIn) return this.jwtService.sign(payload, { secret: config.secretOrKey, expiresIn: config.expiresIn, @@ -26,7 +28,7 @@ export class AuthService { secret: config.secretOrKey, }); } catch (error) { - console.log(`${type} token is invalid`, error); + // console.log(`${type} token is invalid`, error); return null; } } @@ -37,13 +39,11 @@ export class AuthService { async login(user: any) { const payload: JwtPayload = { email: user.email, password: user.password }; - console.log("illig bandu nilthu", payload) const accessToken = this.signToken(payload, 'accessToken'); - console.log("illig bandu nilthu", accessToken) const refreshToken = this.signToken(payload, 'refreshToken'); - await RefreshToken.create({ email: user.email, token: refreshToken }); + await RefreshToken.create({ email: user.email, token: refreshToken, type: 'jwt' }); return { access_token: accessToken, @@ -57,17 +57,17 @@ export class AuthService { throw new Error('Invalid refresh token'); } - console.log(refreshToken); - console.log(payload); + // console.log(refreshToken); + // console.log(payload); const user = await this.userService.findByEmail(payload.email); if (!user) { throw new Error('User not found'); } - console.log(user) + // console.log(user) const accessToken = this.signToken({ email: payload.email }, 'accessToken'); - console.log(accessToken) + // console.log(accessToken) return { access_token: accessToken }; } @@ -90,4 +90,35 @@ export class AuthService { async logout(refreshToken: string) { return RefreshToken.destroy({ where: { token: refreshToken } }); } + + + //google services + + async googleOauthRedirect(user) { + console.log("user in service is",user); + if(!user.email) { + return { + statusCode: 400, + message: 'User not found' + } + } + console.log("user.email in service is",user.email); + let existingUser = await User.findOne({ where: { email: user.email } }); + if(!existingUser) { + existingUser = await User.create({ + email: user.email, + name: user.name,}); + + } + + const payload = existingUser.get(); + const accessToken = await this.signToken(payload, 'accessToken'); + const refreshToken = await this.signToken(payload, 'refreshToken'); + await RefreshToken.create({ email: payload.email, token: refreshToken, type: 'jwt' }); + return { + statusCode: 200, + access_token: accessToken, + refresh_token: refreshToken + } + } } diff --git a/src/booking-gateway/booking-gateway.module.ts b/src/booking-gateway/booking-gateway.module.ts index 5e3105f..1dafb3b 100644 --- a/src/booking-gateway/booking-gateway.module.ts +++ b/src/booking-gateway/booking-gateway.module.ts @@ -2,10 +2,12 @@ import { Module } from '@nestjs/common'; import { BookingGateway } from './booking.gateway'; import { BookingService } from './booking.service'; import { SeatService } from 'src/seat/seat.service'; +import { TicketService } from 'src/ticket/ticket.service'; +import { HttpModule, HttpService } from '@nestjs/axios'; @Module({ - providers: [BookingGateway, BookingService], - exports: [BookingService], - imports: [SeatService] + imports: [HttpModule], + providers: [BookingService, BookingGateway, SeatService, TicketService], + exports: [BookingService, BookingGateway], }) export class BookingGatewayModule { } diff --git a/src/booking-gateway/booking.gateway.ts b/src/booking-gateway/booking.gateway.ts index 0d5b538..0bfaa2f 100644 --- a/src/booking-gateway/booking.gateway.ts +++ b/src/booking-gateway/booking.gateway.ts @@ -28,6 +28,7 @@ export class BookingGateway implements OnGatewayConnection, OnGatewayDisconnect @SubscribeMessage('bookTciket') async handleBookTicket(@MessageBody() ticket: Ticket) { const response = await this.bookingService.bookTicket(ticket); + this.server.to(ticket.eventId.toString() ).emit('ticketBooked', response); this.server.emit('ticketBooked', response); } @SubscribeMessage('checkSeatAvailability') @@ -37,6 +38,13 @@ export class BookingGateway implements OnGatewayConnection, OnGatewayDisconnect this.server.emit('seatAvailability', { isAvailable }); } + @SubscribeMessage('joinRoom') + async handleJoinEvent(client: Socket,@MessageBody() data: { roomId: string }) { + client.join(data.roomId); + console.log(`Client joined room: ${data.roomId}`); + this.server.to(data.roomId).emit('clientJoinedRoom'); + } + @SubscribeMessage('getBookedSeats') async handleGetBookedSeats(@MessageBody() movieId: string) { const bookedSeats = await this.bookingService.getBookedSeats(movieId); diff --git a/src/booking-gateway/booking.service.ts b/src/booking-gateway/booking.service.ts index dbd0cc6..a12adeb 100644 --- a/src/booking-gateway/booking.service.ts +++ b/src/booking-gateway/booking.service.ts @@ -8,7 +8,7 @@ import Seat from 'src/seat/seat.entity'; @Injectable() export class BookingService { constructor( - @Inject('BookingGateway') private readonly bookingGateway: BookingGateway, + // @Inject('BookingGateway') private readonly bookingGateway: BookingGateway, private readonly seatService: SeatService, private readonly ticketService: TicketService ) { } diff --git a/src/common/Utility.ts b/src/common/Utility.ts index 7748da7..6e4e4bc 100644 --- a/src/common/Utility.ts +++ b/src/common/Utility.ts @@ -24,4 +24,5 @@ export class Utility { static urlConfig:any; static vapidConfig: any; static redisConfig: any; + static googleOauthConfig: any; } \ No newline at end of file diff --git a/src/common/common.service.ts b/src/common/common.service.ts index 6c73b19..4c444e1 100644 --- a/src/common/common.service.ts +++ b/src/common/common.service.ts @@ -12,6 +12,7 @@ export class CommonService { vapidConfig:any; redisConfig:any; swaggerConfig:any; + googleOauthConfig:any; constructor() { } diff --git a/src/google-oauth/google-oauth.guard.ts b/src/google-oauth/google-oauth.guard.ts new file mode 100644 index 0000000..65d73c7 --- /dev/null +++ b/src/google-oauth/google-oauth.guard.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { AuthGuard } from "@nestjs/passport"; + +@Injectable() +export class GoogleOauthGuard extends AuthGuard('google') { + constructor() { + super({ + // accessType: 'offline', + }); + } +} \ No newline at end of file diff --git a/src/google-oauth/google.strategy.ts b/src/google-oauth/google.strategy.ts new file mode 100644 index 0000000..4533b4b --- /dev/null +++ b/src/google-oauth/google.strategy.ts @@ -0,0 +1,30 @@ +import { Injectable } from "@nestjs/common"; +import { PassportStrategy } from "@nestjs/passport"; +import { Strategy, VerifyCallback } from "passport-google-oauth20"; +import { Utility } from "src/common/Utility"; + +@Injectable() +export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { + + constructor() { + super({ + clientID: Utility.googleOauthConfig.clientId, + clientSecret: Utility.googleOauthConfig.clientSecret, + callbackURL: Utility.googleOauthConfig.callbackUrl, + scope: Utility.googleOauthConfig.scope, + }); + } + + async validate(accessToken: string, refreshToken: string, profile: any, done: VerifyCallback) { + + const { name, emails } = profile; + const user = { + email: emails[0].value, + name: name.givenName, + accessToken, + refreshToken, + }; + console.log("user object in validate is", user) + done(null, user); + } +} \ No newline at end of file diff --git a/src/jwt/refresh-token.entity.ts b/src/jwt/refresh-token.entity.ts index 152e35b..d26348c 100644 --- a/src/jwt/refresh-token.entity.ts +++ b/src/jwt/refresh-token.entity.ts @@ -11,4 +11,8 @@ export default class RefreshToken extends Model { @ApiProperty({ type: String }) @Column({ type: DataType.TEXT }) token: string; + + @ApiProperty({ type: String }) + @Column({ type: DataType.TEXT }) + type: string; } diff --git a/src/main.ts b/src/main.ts index 9bbea93..b883223 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,7 @@ async function bootstrap() { Utility.swaggerConfig = configMaster.local.swaggerConfig; Utility.vapidConfig = configMaster.local.vapidConfig; Utility.redisConfig = configMaster.local.redisConfig; + Utility.googleOauthConfig = configMaster.local.googleOauthConfig; const app = await NestFactory.create(AppModule, { cors: true });