From 94432d2bb81945577a6fa3dfbc1bdc90ff26faab Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Thu, 26 Sep 2024 22:54:18 +0530 Subject: [PATCH 01/41] Baisc setup --- week-7/server/.env.example | 2 -- week-7/server/server.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 week-7/server/.env.example diff --git a/week-7/server/.env.example b/week-7/server/.env.example deleted file mode 100644 index 6c797aa9..00000000 --- a/week-7/server/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -JWT_SECRET="" -PORT= \ No newline at end of file diff --git a/week-7/server/server.js b/week-7/server/server.js index de3d9f63..06692440 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -34,7 +34,7 @@ const authMiddleware = (req, res, next) => { }; // Connect to MongoDB -mongoose.connect(''); +mongoose.connect("mongodb://localhost:27017/mongo").then(() => console.log("Database connected successfully")) // Admin routes From 987be571b32d775b5cf99b88df13a60140f75df8 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Thu, 26 Sep 2024 23:26:27 +0530 Subject: [PATCH 02/41] Fixed: User Singup Functionality --- week-7/server/server.js | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index 06692440..2c5d8ed0 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -8,12 +8,14 @@ const app = express(); app.use(express.json()); -const secret = process.env.JWT_SECRERT; // This should be in an environment variable in a real application +const secret = process.env.JWT_SECRET; // This should be in an environment variable in a real application const port = process.env.PORT; // Define mongoose schemas const userSchema = new mongoose.Schema({ // userSchema here + username: {type: String, unique: true}, + password: String }); const adminSchema = new mongoose.Schema({ @@ -59,10 +61,33 @@ app.get('/admin/courses', (req, res) => { }); // User routes -app.post('/users/signup', (req, res) => { - // logic to sign up user +app.post('/users/signup', async (req, res) => { + try { + const { username, password } = req.body; + + const existUser = await User.findOne({ username }); + if (existUser) { + return res.status(400).json({ message: "Username already taken, please choose another username" }); + } + + const newUser = await User.create({ + username, + password + }); + + // Generate a JWT token + const token = jwt.sign({ id: newUser._id }, secret); + + res.status(201).json({ + message: "User Created Successfully", + token + }); + } catch (error) { + res.status(500).json({ message: "An error occurred." }); + } }); + app.post('/users/login', (req, res) => { // logic to log in user }); From fc83ea027dc55cd1dabb1059d838592ee0b13517 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Thu, 26 Sep 2024 23:41:41 +0530 Subject: [PATCH 03/41] Fixed: User Login Functionality --- week-7/server/package-lock.json | 603 ++++++++++++++++++++++++++++++++ week-7/server/package.json | 1 + week-7/server/server.js | 33 +- 3 files changed, 634 insertions(+), 3 deletions(-) diff --git a/week-7/server/package-lock.json b/week-7/server/package-lock.json index 5f1a5b87..ae7c9b06 100644 --- a/week-7/server/package-lock.json +++ b/week-7/server/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcrypt": "^5.1.1", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.0", @@ -16,6 +17,26 @@ "mongoose": "^8.6.2" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", @@ -40,6 +61,12 @@ "@types/webidl-conversions": "*" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -53,12 +80,96 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -83,6 +194,16 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/bson": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", @@ -126,6 +247,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -201,6 +352,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -220,6 +377,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -247,6 +413,12 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -370,6 +542,36 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -379,6 +581,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -398,6 +621,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -446,6 +690,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -474,6 +724,42 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -486,6 +772,17 @@ "node": ">=0.10.0" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -501,6 +798,15 @@ "node": ">= 0.10" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -601,6 +907,30 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -667,6 +997,64 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mongodb": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", @@ -810,6 +1198,82 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -843,6 +1307,15 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -852,6 +1325,15 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", @@ -919,6 +1401,36 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1011,6 +1523,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -1058,6 +1576,12 @@ "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", "license": "MIT" }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -1076,6 +1600,58 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1119,6 +1695,12 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1158,6 +1740,27 @@ "engines": { "node": ">=16" } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" } } } diff --git a/week-7/server/package.json b/week-7/server/package.json index ed08190c..d8b5ac6f 100644 --- a/week-7/server/package.json +++ b/week-7/server/package.json @@ -10,6 +10,7 @@ "license": "ISC", "description": "", "dependencies": { + "bcrypt": "^5.1.1", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.0", diff --git a/week-7/server/server.js b/week-7/server/server.js index 2c5d8ed0..1c9aea92 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -3,6 +3,7 @@ const express = require('express'); const jwt = require('jsonwebtoken'); const mongoose = require('mongoose'); const dotenv = require("dotenv"); +const bcrypt = require("bcrypt") dotenv.config(); const app = express(); @@ -70,12 +71,14 @@ app.post('/users/signup', async (req, res) => { return res.status(400).json({ message: "Username already taken, please choose another username" }); } + const hashedpassword = await bcrypt.hash(password, 10) + const newUser = await User.create({ username, - password + password: hashedpassword, }); - // Generate a JWT token + // Generating a JWT token const token = jwt.sign({ id: newUser._id }, secret); res.status(201).json({ @@ -88,8 +91,32 @@ app.post('/users/signup', async (req, res) => { }); -app.post('/users/login', (req, res) => { +app.post('/users/login', async (req, res) => { // logic to log in user + try { + const {username, password} = req.body; + const user = await User.findOne({ username }); + if(!user) { + return res.status(404).json("User not Found") + } + const passwordMatch = await bcrypt.compare(password, user.password) + if(!passwordMatch) { + return res.json({ + message: "Invalid credientails" + }) + } + + const token = jwt.sign({ id: user._id}, secret) + + res.status(200).json({ + message: "Logged in successfully", + token + }) + } catch (error) { + console.log(error); + res.status(500).json({ message: "An error occurred." }); + } + }); app.get('/users/courses', (req, res) => { From 0ee9b2cce8a7a2c75490ef1d63923ffc0bf742b5 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 18:01:54 +0530 Subject: [PATCH 04/41] Created: Course Schema --- week-7/server/server.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index 1c9aea92..5ccd15df 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -14,17 +14,22 @@ const port = process.env.PORT; // Define mongoose schemas const userSchema = new mongoose.Schema({ - // userSchema here - username: {type: String, unique: true}, - password: String + // userSchema here + username: { type: String, unique: true }, + password: String }); const adminSchema = new mongoose.Schema({ -// adminSchema here + // adminSchema here }); const courseSchema = new mongoose.Schema({ -// courseSchema here + // courseSchema here + title: String, + description: String, + price: Number, + imageLink: String, + published: Boolean }); // Define mongoose models @@ -33,11 +38,11 @@ const Admin = mongoose.model('Admin', adminSchema); const Course = mongoose.model('Course', courseSchema); const authMiddleware = (req, res, next) => { -// authMiddleware logic here + // authMiddleware logic here }; // Connect to MongoDB -mongoose.connect("mongodb://localhost:27017/mongo").then(() => console.log("Database connected successfully")) +mongoose.connect(process.env.MONGO_URL).then(() => console.log("Database connected successfully")) // Admin routes @@ -79,7 +84,7 @@ app.post('/users/signup', async (req, res) => { }); // Generating a JWT token - const token = jwt.sign({ id: newUser._id }, secret); + const token = jwt.sign({ id: newUser._id }, secret); res.status(201).json({ message: "User Created Successfully", @@ -94,19 +99,19 @@ app.post('/users/signup', async (req, res) => { app.post('/users/login', async (req, res) => { // logic to log in user try { - const {username, password} = req.body; + const { username, password } = req.body; const user = await User.findOne({ username }); - if(!user) { + if (!user) { return res.status(404).json("User not Found") } const passwordMatch = await bcrypt.compare(password, user.password) - if(!passwordMatch) { + if (!passwordMatch) { return res.json({ message: "Invalid credientails" }) } - const token = jwt.sign({ id: user._id}, secret) + const token = jwt.sign({ id: user._id }, secret) res.status(200).json({ message: "Logged in successfully", From ebd9b10ab856f9bd91bd900410dff9469aa80641 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 18:39:27 +0530 Subject: [PATCH 05/41] SetUp: Admin signup and login Functionality --- week-7/server/server.js | 59 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index 5ccd15df..fb034610 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -21,6 +21,8 @@ const userSchema = new mongoose.Schema({ const adminSchema = new mongoose.Schema({ // adminSchema here + username: { type: String, unique: true }, + password: String }); const courseSchema = new mongoose.Schema({ @@ -46,12 +48,65 @@ mongoose.connect(process.env.MONGO_URL).then(() => console.log("Database connect // Admin routes -app.post('/admin/signup', (req, res) => { +app.post('/admin/signup', async (req, res) => { // logic to sign up admin + try { + const { username, password } = req.body; + + const existAdmin = await Admin.findOne({ username }); + if (existAdmin) { + return res.status(400).json({ message: "Username already exists, Please try another username" }); + } + + const hashedpassword = await bcrypt.hash(password, 10) + + const newAdmin = await Admin.create({ + username, + password: hashedpassword, + }); + + // Generating a JWT token + const token = jwt.sign({ id: newAdmin._id }, secret); + + res.status(201).json({ + message: "Admin Created Successfully", + token + }); + } catch (error) { + res.status(500).json({ message: "An error occurred." }); + } + }); -app.post('/admin/login', (req, res) => { +app.post('/admin/login', async (req, res) => { // logic to log in admin + try { + const { username, password} = req.body; + const admin = await Admin.findOne({username}); // here getting error as findone only accept object with key-value pairs + if(!admin) { + res.status(404).json({ + message: "Admin not found" + }) + } + const isMatched = await bcrypt.compare(password, admin.password); + if(!isMatched) { + res.status(402).json({ + message: "Invalid credentials" + }) + } + + const token = jwt.sign({id: Admin._id}, secret) + res.status(200).json({ + message: "Logged in successfully", + token + }) + } catch (error) { + console.log("Error:", error); + res.status(500).json({ + Error: "Error Occured.." + }) + + } }); app.post('/admin/courses', (req, res) => { From f790564b907ef84d8428dfb928b7979f6b785230 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 19:00:53 +0530 Subject: [PATCH 06/41] Implemented: Authorization Functionality --- week-7/server/server.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index fb034610..a9e2453e 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -41,6 +41,18 @@ const Course = mongoose.model('Course', courseSchema); const authMiddleware = (req, res, next) => { // authMiddleware logic here + const token = req.header.authorization; + const response = jwt.verify(token, secret) + + if(response) { + req.userId = response.id; + next(); + } else { + res.json({ + message: "Invalid Token" + }) + } + }; // Connect to MongoDB @@ -90,7 +102,7 @@ app.post('/admin/login', async (req, res) => { } const isMatched = await bcrypt.compare(password, admin.password); if(!isMatched) { - res.status(402).json({ + res.status(401).json({ message: "Invalid credentials" }) } From d0aed44ba7adf1fcd4af62085fca6aa98b90d9e0 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 19:19:59 +0530 Subject: [PATCH 07/41] Implemented: Course creation for Admin --- week-7/server/package-lock.json | 325 ++++++++++++++++++++++++++++++++ week-7/server/package.json | 3 + week-7/server/server.js | 35 +++- 3 files changed, 361 insertions(+), 2 deletions(-) diff --git a/week-7/server/package-lock.json b/week-7/server/package-lock.json index ae7c9b06..8bd0c3e9 100644 --- a/week-7/server/package-lock.json +++ b/week-7/server/package-lock.json @@ -15,6 +15,9 @@ "express": "^4.21.0", "jsonwebtoken": "^9.0.2", "mongoose": "^8.6.2" + }, + "devDependencies": { + "nodemon": "^3.1.7" } }, "node_modules/@mapbox/node-pre-gyp": { @@ -124,6 +127,20 @@ "node": ">=8" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -170,6 +187,19 @@ "node": ">= 10.0.0" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -204,6 +234,19 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/bson": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", @@ -247,6 +290,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -506,6 +574,19 @@ "node": ">= 0.10.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -572,6 +653,21 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -642,6 +738,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -654,6 +763,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -772,6 +891,13 @@ "node": ">=0.10.0" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -798,6 +924,29 @@ "node": ">= 0.10" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -807,6 +956,29 @@ "node": ">=8" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -1246,6 +1418,60 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/nodemon": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", + "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -1261,6 +1487,16 @@ "node": ">=6" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -1340,6 +1576,19 @@ "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "license": "MIT" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1353,6 +1602,13 @@ "node": ">= 0.10" } }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -1415,6 +1671,19 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1582,6 +1851,19 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -1635,6 +1917,19 @@ "node": ">=8" } }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -1652,6 +1947,19 @@ "node": ">=10" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1661,6 +1969,16 @@ "node": ">=0.6" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tr46": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", @@ -1686,6 +2004,13 @@ "node": ">= 0.6" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/week-7/server/package.json b/week-7/server/package.json index d8b5ac6f..d008bf09 100644 --- a/week-7/server/package.json +++ b/week-7/server/package.json @@ -16,5 +16,8 @@ "express": "^4.21.0", "jsonwebtoken": "^9.0.2", "mongoose": "^8.6.2" + }, + "devDependencies": { + "nodemon": "^3.1.7" } } diff --git a/week-7/server/server.js b/week-7/server/server.js index a9e2453e..3643d4f4 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -27,7 +27,7 @@ const adminSchema = new mongoose.Schema({ const courseSchema = new mongoose.Schema({ // courseSchema here - title: String, + title: {type: String, unique: true}, description: String, price: Number, imageLink: String, @@ -121,8 +121,39 @@ app.post('/admin/login', async (req, res) => { } }); -app.post('/admin/courses', (req, res) => { +app.post('/admin/courses', async (req, res) => { // logic to create a course + try { + const { title , description, price, imageLink, published } = req.body; + + const existCourse = await Course.findOne({ title }) + if(existCourse) { + return res.status(400).json({ + message: "Title can't be same, Please choose another One" + }) + } + if (!title || !description || !price || !imageLink) { + return res.status(400).json({ + message: "All fields are required: title, description, price, imageLink and published" + }); + } + const newCourse = await Course.create({ + title, + description, + price, + imageLink, + published + }) + return res.status(201).json({ + message: "Course Created Successfully", + course: newCourse + }) + } catch (error) { + console.log("Error:", error); + res.status(500).json({ + message: "Error Occured.." + }) + } }); app.put('/admin/courses/:courseId', (req, res) => { From 1a3a49ab5e0ac9452f1b8b4b362c1d43bf128e3c Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 19:22:21 +0530 Subject: [PATCH 08/41] Added: Timestamps for specific dates --- week-7/server/server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index 3643d4f4..ae4cf158 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -17,13 +17,13 @@ const userSchema = new mongoose.Schema({ // userSchema here username: { type: String, unique: true }, password: String -}); +}, {timestamps: true}); const adminSchema = new mongoose.Schema({ // adminSchema here username: { type: String, unique: true }, password: String -}); +}, {timestamps: true}); const courseSchema = new mongoose.Schema({ // courseSchema here @@ -32,7 +32,7 @@ const courseSchema = new mongoose.Schema({ price: Number, imageLink: String, published: Boolean -}); +}, {timestamps: true}); // Define mongoose models const User = mongoose.model('User', userSchema); From ca2d7bdf20c8e2e95ca8ca4798b5bb5ffb7d5b1e Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 22:14:37 +0530 Subject: [PATCH 09/41] Fixed: admin posting using middleware --- week-7/server/server.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index ae4cf158..5a07ad1a 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -41,7 +41,7 @@ const Course = mongoose.model('Course', courseSchema); const authMiddleware = (req, res, next) => { // authMiddleware logic here - const token = req.header.authorization; + const token = req.headers.authorization; const response = jwt.verify(token, secret) if(response) { @@ -96,19 +96,19 @@ app.post('/admin/login', async (req, res) => { const { username, password} = req.body; const admin = await Admin.findOne({username}); // here getting error as findone only accept object with key-value pairs if(!admin) { - res.status(404).json({ + return res.status(404).json({ message: "Admin not found" }) } const isMatched = await bcrypt.compare(password, admin.password); if(!isMatched) { - res.status(401).json({ + return res.status(401).json({ message: "Invalid credentials" }) } const token = jwt.sign({id: Admin._id}, secret) - res.status(200).json({ + return res.status(200).json({ message: "Logged in successfully", token }) @@ -121,7 +121,7 @@ app.post('/admin/login', async (req, res) => { } }); -app.post('/admin/courses', async (req, res) => { +app.post('/admin/courses', authMiddleware, async (req, res) => { // logic to create a course try { const { title , description, price, imageLink, published } = req.body; From 9a0b30f7539f76d8033556701e73cd7c290fa7a0 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 23:08:05 +0530 Subject: [PATCH 10/41] Implemented: Updating course functionality --- week-7/server/server.js | 64 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index 5a07ad1a..cb19f1e7 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -17,22 +17,22 @@ const userSchema = new mongoose.Schema({ // userSchema here username: { type: String, unique: true }, password: String -}, {timestamps: true}); +}, { timestamps: true }); const adminSchema = new mongoose.Schema({ // adminSchema here username: { type: String, unique: true }, password: String -}, {timestamps: true}); +}, { timestamps: true }); const courseSchema = new mongoose.Schema({ // courseSchema here - title: {type: String, unique: true}, + title: { type: String, unique: true }, description: String, price: Number, imageLink: String, published: Boolean -}, {timestamps: true}); +}, { timestamps: true }); // Define mongoose models const User = mongoose.model('User', userSchema); @@ -44,7 +44,7 @@ const authMiddleware = (req, res, next) => { const token = req.headers.authorization; const response = jwt.verify(token, secret) - if(response) { + if (response) { req.userId = response.id; next(); } else { @@ -93,21 +93,21 @@ app.post('/admin/signup', async (req, res) => { app.post('/admin/login', async (req, res) => { // logic to log in admin try { - const { username, password} = req.body; - const admin = await Admin.findOne({username}); // here getting error as findone only accept object with key-value pairs - if(!admin) { + const { username, password } = req.body; + const admin = await Admin.findOne({ username }); // here getting error as findone only accept object with key-value pairs + if (!admin) { return res.status(404).json({ message: "Admin not found" }) } const isMatched = await bcrypt.compare(password, admin.password); - if(!isMatched) { + if (!isMatched) { return res.status(401).json({ message: "Invalid credentials" }) } - - const token = jwt.sign({id: Admin._id}, secret) + + const token = jwt.sign({ id: Admin._id }, secret) return res.status(200).json({ message: "Logged in successfully", token @@ -117,17 +117,17 @@ app.post('/admin/login', async (req, res) => { res.status(500).json({ Error: "Error Occured.." }) - + } }); app.post('/admin/courses', authMiddleware, async (req, res) => { // logic to create a course try { - const { title , description, price, imageLink, published } = req.body; + const { title, description, price, imageLink, published } = req.body; const existCourse = await Course.findOne({ title }) - if(existCourse) { + if (existCourse) { return res.status(400).json({ message: "Title can't be same, Please choose another One" }) @@ -138,9 +138,9 @@ app.post('/admin/courses', authMiddleware, async (req, res) => { }); } const newCourse = await Course.create({ - title, + title, description, - price, + price, imageLink, published }) @@ -156,10 +156,40 @@ app.post('/admin/courses', authMiddleware, async (req, res) => { } }); -app.put('/admin/courses/:courseId', (req, res) => { +app.put('/admin/courses/:courseId', async (req, res) => { // logic to edit a course + try { + const {courseId} = req.params; + const { title, description, price, imageLink, published } = req.body; + + const course = await Course.findById(courseId); + if (!course) { + return res.status(404).json({ + message: "Course not found" + }) + } + + if (title) course.title = title; + if (description) course.description = description; + if (price) course.price = price; + if (imageLink) course.imageLink = imageLink; + if (published !== undefined) course.published = published; + + const updatedCourse = await course.save(); + + return res.status(200).json({ + message: "Course updated Successfully", + updatedCourse + }) + } catch (error) { + console.log("Error:", error); + res.status(500).json({ + message: "Error Occured.." + }) + } }); + app.get('/admin/courses', (req, res) => { // logic to get all courses }); From 19e5a999f63972cc90256322a6086e6328fe6676 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 23:14:39 +0530 Subject: [PATCH 11/41] Implemented: get all courses functionality --- week-7/server/server.js | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index cb19f1e7..b5f08c50 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -159,24 +159,24 @@ app.post('/admin/courses', authMiddleware, async (req, res) => { app.put('/admin/courses/:courseId', async (req, res) => { // logic to edit a course try { - const {courseId} = req.params; + const { courseId } = req.params; const { title, description, price, imageLink, published } = req.body; - + const course = await Course.findById(courseId); if (!course) { return res.status(404).json({ message: "Course not found" }) } - + if (title) course.title = title; if (description) course.description = description; if (price) course.price = price; if (imageLink) course.imageLink = imageLink; if (published !== undefined) course.published = published; - + const updatedCourse = await course.save(); - + return res.status(200).json({ message: "Course updated Successfully", updatedCourse @@ -190,8 +190,25 @@ app.put('/admin/courses/:courseId', async (req, res) => { }); -app.get('/admin/courses', (req, res) => { +app.get('/admin/courses', async (req, res) => { // logic to get all courses + try { + const courses = await Course.find(); + if(courses.length < 1) { + return res.status(400).json({ + message: "No Courses Available" + }) + } + return res.status(200).json({ + message: "Courses Retrived Successfully", + courses + }) + } catch (error) { + res.status(500).json({ + message: "Error Occured.." + }) + } + }); // User routes From ddbc895648b86bae38bfb013c7c380695e88e3cf Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 23:32:32 +0530 Subject: [PATCH 12/41] Implemented: User purchasing courses --- week-7/server/server.js | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index b5f08c50..28168183 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -16,7 +16,8 @@ const port = process.env.PORT; const userSchema = new mongoose.Schema({ // userSchema here username: { type: String, unique: true }, - password: String + password: String, + purchasedCourses: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Course' }] // for course purchasing }, { timestamps: true }); const adminSchema = new mongoose.Schema({ @@ -273,8 +274,42 @@ app.get('/users/courses', (req, res) => { // logic to list all courses }); -app.post('/users/courses/:courseId', (req, res) => { +app.post('/users/courses/:courseId', authMiddleware, async (req, res) => { // logic to purchase a course + try { + const { courseId} = req.params; + const userId = req.userId; + + const course = await Course.findById(courseId); + if(!course) { + return res.status(404).json({ + message: "Course not Found" + }) + } + + const user = await User.findById(userId); + if(!user) { + res.status(404).json({ + message: "User not Found" + }) + } + + if(user.purchasedCourses && user.purchasedCourses.includes(courseId)) { + return res.status(200).json({ + message: "Course already Purchased" + }) + } + + user.purchasedCourses = user.purchasedCourses || []; + user.purchasedCourses.push(courseId) + + await user.save(); + } catch (error) { + console.log("Error:", error); + res.status(500).json({ + message: "Error Occured.." + }) + } }); app.get('/users/purchasedCourses', (req, res) => { From 11b39c7b3ce053badc9c51cd693157c92b39d388 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Fri, 27 Sep 2024 23:50:15 +0530 Subject: [PATCH 13/41] Updated: Necessary codes --- week-7/server/server.js | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index 28168183..f930b43a 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -42,16 +42,16 @@ const Course = mongoose.model('Course', courseSchema); const authMiddleware = (req, res, next) => { // authMiddleware logic here - const token = req.headers.authorization; - const response = jwt.verify(token, secret) - - if (response) { - req.userId = response.id; + const token = req.header('Authorization')?.replace('Bearer ', ''); + if (!token) { + return res.status(401).json({ message: "Access denied. No token provided." }); + } + try { + const decoded = jwt.verify(token, secret); + req.user = decoded; next(); - } else { - res.json({ - message: "Invalid Token" - }) + } catch (ex) { + return res.status(400).json({ message: "Invalid token." }); } }; @@ -157,7 +157,7 @@ app.post('/admin/courses', authMiddleware, async (req, res) => { } }); -app.put('/admin/courses/:courseId', async (req, res) => { +app.put('/admin/courses/:courseId', authMiddleware, async (req, res) => { // logic to edit a course try { const { courseId } = req.params; @@ -191,7 +191,7 @@ app.put('/admin/courses/:courseId', async (req, res) => { }); -app.get('/admin/courses', async (req, res) => { +app.get('/admin/courses', authMiddleware, async (req, res) => { // logic to get all courses try { const courses = await Course.find(); @@ -270,8 +270,24 @@ app.post('/users/login', async (req, res) => { }); -app.get('/users/courses', (req, res) => { +app.get('/users/courses', authMiddleware, async (req, res) => { // logic to list all courses + try { + const courses = await Course.find(); + if(courses.length < 1) { + return res.status(400).json({ + message: "No Courses Available" + }) + } + return res.status(200).json({ + message: "Courses Retrived Successfully", + courses + }) + } catch (error) { + res.status(500).json({ + message: "Error Occured.." + }) + } }); app.post('/users/courses/:courseId', authMiddleware, async (req, res) => { From b96f6f4abbbd9625f6e752692a669705208b3378 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 16:40:51 +0530 Subject: [PATCH 14/41] Done: Backend code --- week-7/server/server.js | 50 ++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/week-7/server/server.js b/week-7/server/server.js index f930b43a..6cf8e9ff 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -47,8 +47,8 @@ const authMiddleware = (req, res, next) => { return res.status(401).json({ message: "Access denied. No token provided." }); } try { - const decoded = jwt.verify(token, secret); - req.user = decoded; + const decoded = jwt.verify(token, secret); + req.user = decoded.id; // simply an id is stored in this req.user next(); } catch (ex) { return res.status(400).json({ message: "Invalid token." }); @@ -195,7 +195,7 @@ app.get('/admin/courses', authMiddleware, async (req, res) => { // logic to get all courses try { const courses = await Course.find(); - if(courses.length < 1) { + if (courses.length < 1) { return res.status(400).json({ message: "No Courses Available" }) @@ -274,7 +274,7 @@ app.get('/users/courses', authMiddleware, async (req, res) => { // logic to list all courses try { const courses = await Course.find(); - if(courses.length < 1) { + if (courses.length < 1) { return res.status(400).json({ message: "No Courses Available" }) @@ -293,33 +293,36 @@ app.get('/users/courses', authMiddleware, async (req, res) => { app.post('/users/courses/:courseId', authMiddleware, async (req, res) => { // logic to purchase a course try { - const { courseId} = req.params; - const userId = req.userId; - + const { courseId } = req.params; + const userId = req.user; + const course = await Course.findById(courseId); - if(!course) { + if (!course) { return res.status(404).json({ message: "Course not Found" }) } - + const user = await User.findById(userId); - if(!user) { + if (!user) { res.status(404).json({ message: "User not Found" }) } - - if(user.purchasedCourses && user.purchasedCourses.includes(courseId)) { + + if (user.purchasedCourses && user.purchasedCourses.includes(courseId)) { return res.status(200).json({ message: "Course already Purchased" }) } - + user.purchasedCourses = user.purchasedCourses || []; user.purchasedCourses.push(courseId) - + await user.save(); + return res.status(200).json({ + message: "Course puchased Successfully" + }) } catch (error) { console.log("Error:", error); res.status(500).json({ @@ -328,8 +331,25 @@ app.post('/users/courses/:courseId', authMiddleware, async (req, res) => { } }); -app.get('/users/purchasedCourses', (req, res) => { +app.get('/users/purchasedCourses', authMiddleware, async (req, res) => { // logic to view purchased courses + try { + const userId = req.user; + const user = await User.findById(userId).populate("purchasedCourses") + if (!user || !user.purchasedCourses || !user.purchasedCourses.length < 1) { + res.status(404).json({ + message: "No Coureses Available" + }) + } + res.status(200).json({ + purchasedCourses: user.purchasedCourses + }) + } catch (error) { + console.log("Error retriving puchasedCourses:", error); + res.status(500).json({ + message: "Error Occured.." + }) + } }); app.listen(port, () => { From 8859cf58bfdb0f144daffb6f98b7c09769acb976 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 17:09:22 +0530 Subject: [PATCH 15/41] Setup: Basic Frontend --- week-7/client/src/components/Login.jsx | 1 - week-7/client/src/components/Register.jsx | 21 ++++++++++++++++++--- week-7/client/src/pages/Home.jsx | 5 ++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/week-7/client/src/components/Login.jsx b/week-7/client/src/components/Login.jsx index 0948cf6e..f4a4b855 100644 --- a/week-7/client/src/components/Login.jsx +++ b/week-7/client/src/components/Login.jsx @@ -1,6 +1,5 @@ // login code here import axios from 'axios'; -import React from 'react' const Login = () => { // call the functions onClick of button. diff --git a/week-7/client/src/components/Register.jsx b/week-7/client/src/components/Register.jsx index c143c3f6..e59e328e 100644 --- a/week-7/client/src/components/Register.jsx +++ b/week-7/client/src/components/Register.jsx @@ -1,15 +1,30 @@ // register code here -import React from 'react' +import { useState } from 'react' import axios from "axios" const Register = () => { + + const [userName, setUserName] = useState("") + const [password, setPassword] = useState("") + // call the functions onClick of button. async function handleRegister() { - const resposne = await axios.post(); // if you don't know about axios, give it a read https://axios-http.com/docs/intro + try { + const resposne = await axios.post("http://localhost:3000/admin/signup", { userName, password}); + alert(resposne.data.message) + } catch (error) { + console.log("Error", error); + } } + return ( -
Register
+
+

Register Here

+ setUserName(e.target.value) } /> + setPassword(e.target.value) } /> + +
) } diff --git a/week-7/client/src/pages/Home.jsx b/week-7/client/src/pages/Home.jsx index 94691be9..973afabd 100644 --- a/week-7/client/src/pages/Home.jsx +++ b/week-7/client/src/pages/Home.jsx @@ -9,7 +9,10 @@ import Courses from '../components/Courses' const Home = () => { return ( // write home page UI code here -
Home
+
+

Home

+ +
) } From 1b58c6347567c05bea7682a10d87d93e49cf63e4 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 17:23:14 +0530 Subject: [PATCH 16/41] Fixed: Register Page --- week-7/client/src/components/Register.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/week-7/client/src/components/Register.jsx b/week-7/client/src/components/Register.jsx index e59e328e..7b083c52 100644 --- a/week-7/client/src/components/Register.jsx +++ b/week-7/client/src/components/Register.jsx @@ -5,14 +5,15 @@ import axios from "axios" const Register = () => { - const [userName, setUserName] = useState("") + const [username, setUsername] = useState("") const [password, setPassword] = useState("") // call the functions onClick of button. async function handleRegister() { try { - const resposne = await axios.post("http://localhost:3000/admin/signup", { userName, password}); + const resposne = await axios.post("http://localhost:3000/admin/signup", { username, password}); alert(resposne.data.message) + console.log(resposne.data); } catch (error) { console.log("Error", error); } @@ -21,8 +22,8 @@ const Register = () => { return (

Register Here

- setUserName(e.target.value) } /> - setPassword(e.target.value) } /> + setUsername(e.target.value) } /> + setPassword(e.target.value) } />
) From 31a3b3a586d0a7f404ce90b7b9dd62bc9ba279d9 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 17:30:03 +0530 Subject: [PATCH 17/41] Implemented: Cors for client-server commnuication --- week-7/server/server.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/week-7/server/server.js b/week-7/server/server.js index 6cf8e9ff..9913e7d0 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -4,10 +4,12 @@ const jwt = require('jsonwebtoken'); const mongoose = require('mongoose'); const dotenv = require("dotenv"); const bcrypt = require("bcrypt") +const cors = require("cors") dotenv.config(); const app = express(); app.use(express.json()); +app.use(cors()) // Note: This wil accept all const secret = process.env.JWT_SECRET; // This should be in an environment variable in a real application const port = process.env.PORT; From df61fb32fe3ad63463849b8673e75bd7a75fba98 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 18:10:41 +0530 Subject: [PATCH 18/41] Fixed: Login-Course functioality --- week-7/client/src/components/Courses.jsx | 36 ++++++++++++++++++++++-- week-7/client/src/components/Login.jsx | 22 +++++++++++++-- week-7/client/src/pages/Home.jsx | 11 ++++---- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/week-7/client/src/components/Courses.jsx b/week-7/client/src/components/Courses.jsx index cfbbaee9..2357e132 100644 --- a/week-7/client/src/components/Courses.jsx +++ b/week-7/client/src/components/Courses.jsx @@ -1,10 +1,40 @@ -// courses code here -import React from 'react' +import axios from "axios"; +import { useEffect, useState } from "react" // use axios here, similar to register and login const Courses = () => { + const [courses, setCourses] = useState([]) + + useEffect(() => { + const fetchCourses = async () => { + const response = await axios.get('http://localhost:3000/users/courses', { + headers: { + Authorization: `Bearer ${localStorage.getItem('adminToken')}` + } + }); + setCourses(response.data.courses); + console.log(courses); + }; + + fetchCourses(); + }, []); return ( -
Courses
+
+

All Courses

+ { + courses.map((item, index) => ( +
+
+ Image +
+

{item.title}

+

{item.description}

+

Rs.{item.price}

+

{item.published}

+
+ )) + } +
) } diff --git a/week-7/client/src/components/Login.jsx b/week-7/client/src/components/Login.jsx index f4a4b855..0f52ca0f 100644 --- a/week-7/client/src/components/Login.jsx +++ b/week-7/client/src/components/Login.jsx @@ -1,13 +1,31 @@ // login code here import axios from 'axios'; +import { useState } from 'react'; const Login = () => { + + const [username, setUsername] = useState("") + const [password, setPassword] = useState("") + // call the functions onClick of button. async function handleLogin() { - const resposne = await axios.post(); // // if you don't know about axios, give it a read https://axios-http.com/docs/intro + try { + const resposne = await axios.post("http://localhost:3000/admin/login", {username, password}); + alert(resposne.data.message) + console.log(resposne.data); + localStorage.setItem("adminToken", resposne.data.token) + } catch (error) { + console.log("Error", error); + } + } return ( -
Login
+
+

Login

+ setUsername(e.target.value)} /> + setPassword(e.target.value)} /> + +
) } diff --git a/week-7/client/src/pages/Home.jsx b/week-7/client/src/pages/Home.jsx index 973afabd..f03c5ee7 100644 --- a/week-7/client/src/pages/Home.jsx +++ b/week-7/client/src/pages/Home.jsx @@ -1,9 +1,6 @@ -// implement the home page UI here. -import React from 'react' - // compoents imports -import Login from '../components/Login' -import Register from '../components/Register' +// import Login from '../components/Login' +// import Register from '../components/Register' import Courses from '../components/Courses' const Home = () => { @@ -11,7 +8,9 @@ const Home = () => { // write home page UI code here

Home

- + {/* + */} +
) } From eedc459003e80d05107b6c194044b58e1b2fdb65 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 18:20:48 +0530 Subject: [PATCH 19/41] SetUp: Routing using reacr-router-dom --- week-7/client/package-lock.json | 44 +++++++++++++++++++++++++++++++- week-7/client/package.json | 3 ++- week-7/client/src/App.jsx | 12 +++++++-- week-7/client/src/pages/Home.jsx | 21 +++++++++------ 4 files changed, 68 insertions(+), 12 deletions(-) diff --git a/week-7/client/package-lock.json b/week-7/client/package-lock.json index 30066a67..9f411116 100644 --- a/week-7/client/package-lock.json +++ b/week-7/client/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "axios": "^1.7.7", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-router-dom": "^6.26.2" }, "devDependencies": { "@eslint/js": "^9.9.0", @@ -985,6 +986,15 @@ "node": ">= 8" } }, + "node_modules/@remix-run/router": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz", + "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.21.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", @@ -3782,6 +3792,38 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.2.tgz", + "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.19.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz", + "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.19.2", + "react-router": "6.26.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", diff --git a/week-7/client/package.json b/week-7/client/package.json index b98ecdd1..2b482ff4 100644 --- a/week-7/client/package.json +++ b/week-7/client/package.json @@ -12,7 +12,8 @@ "dependencies": { "axios": "^1.7.7", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-router-dom": "^6.26.2" }, "devDependencies": { "@eslint/js": "^9.9.0", diff --git a/week-7/client/src/App.jsx b/week-7/client/src/App.jsx index 8cc38704..1a57c1d5 100644 --- a/week-7/client/src/App.jsx +++ b/week-7/client/src/App.jsx @@ -1,11 +1,19 @@ // firstly, Don't get overwhelmed and if you are then go with client-easy. +import { BrowserRouter, Route, Routes} from "react-router-dom" import Home from "./pages/Home" +import Register from "./components/Register" +import Login from "./components/Login" function App() { return ( <> - {/* start writing from here */} - + + + } /> + } /> + } /> + + ) } diff --git a/week-7/client/src/pages/Home.jsx b/week-7/client/src/pages/Home.jsx index f03c5ee7..d45e8f43 100644 --- a/week-7/client/src/pages/Home.jsx +++ b/week-7/client/src/pages/Home.jsx @@ -1,16 +1,21 @@ -// compoents imports -// import Login from '../components/Login' -// import Register from '../components/Register' -import Courses from '../components/Courses' +import { Link } from "react-router-dom" const Home = () => { return ( // write home page UI code here
-

Home

- {/* - */} - +

Welcome to Coursifiy

+
+ +
+

Admin

+
+ + {/* will work on this later */} + {/*
+

User

+
*/} +
) } From 345965fa001e012dd578bc962898683c85da1bf7 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 21:28:50 +0530 Subject: [PATCH 20/41] Fixed: Admin dashboard --- week-7/client/src/App.jsx | 2 + week-7/client/src/components/Courses.jsx | 2 +- week-7/client/src/components/Dashboard.jsx | 90 ++++++++++++++++++++++ week-7/client/src/components/Login.jsx | 1 - 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 week-7/client/src/components/Dashboard.jsx diff --git a/week-7/client/src/App.jsx b/week-7/client/src/App.jsx index 1a57c1d5..82c7ae18 100644 --- a/week-7/client/src/App.jsx +++ b/week-7/client/src/App.jsx @@ -3,6 +3,7 @@ import { BrowserRouter, Route, Routes} from "react-router-dom" import Home from "./pages/Home" import Register from "./components/Register" import Login from "./components/Login" +import Dashboard from "./components/Dashboard" function App() { return ( @@ -12,6 +13,7 @@ function App() { } /> } /> } /> + } /> diff --git a/week-7/client/src/components/Courses.jsx b/week-7/client/src/components/Courses.jsx index 2357e132..7853d615 100644 --- a/week-7/client/src/components/Courses.jsx +++ b/week-7/client/src/components/Courses.jsx @@ -30,7 +30,7 @@ const Courses = () => {

{item.title}

{item.description}

Rs.{item.price}

-

{item.published}

+

{item.published ? 'Published' : 'Not Published'}

)) } diff --git a/week-7/client/src/components/Dashboard.jsx b/week-7/client/src/components/Dashboard.jsx new file mode 100644 index 00000000..b5237b4c --- /dev/null +++ b/week-7/client/src/components/Dashboard.jsx @@ -0,0 +1,90 @@ +import { useState } from 'react'; +import axios from 'axios'; +import Courses from "./Courses" + +const CreateCourse = () => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [price, setPrice] = useState(''); + const [imageLink, setImageLink] = useState(''); + const [published, setPublished] = useState(false); + + const handleSubmit = async (e) => { + e.preventDefault(); + + try { + await axios.post( + 'http://localhost:3000/admin/courses', + { + title, + description, + price, + imageLink, + published + }, + { + headers: { + Authorization: `Bearer ${localStorage.getItem('adminToken')}` + } + } + ); + + setTitle(''); + setDescription(''); + setPrice(''); + setImageLink(''); + setPublished(false); + // window.location.reload() + } catch (error) { + console.log("Error", error); + } + }; + + return ( +
+ +

Create New Course

+
+ + setTitle(e.target.value)} + required + /> + setDescription(e.target.value)} + required + /> + setPrice(e.target.value)} + required + /> + setImageLink(e.target.value)} + required + /> + + +
+
+ ); +}; + +export default CreateCourse; diff --git a/week-7/client/src/components/Login.jsx b/week-7/client/src/components/Login.jsx index 0f52ca0f..07deb4c9 100644 --- a/week-7/client/src/components/Login.jsx +++ b/week-7/client/src/components/Login.jsx @@ -17,7 +17,6 @@ const Login = () => { } catch (error) { console.log("Error", error); } - } return (
From a3aca696eaf085c1c8b96722a84cc3444f304c0c Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 22:26:15 +0530 Subject: [PATCH 21/41] Added: Get method for a specific course --- week-7/server/server.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/week-7/server/server.js b/week-7/server/server.js index 9913e7d0..14faea84 100644 --- a/week-7/server/server.js +++ b/week-7/server/server.js @@ -159,6 +159,27 @@ app.post('/admin/courses', authMiddleware, async (req, res) => { } }); + +// This is for getting the course from the database +app.get('/admin/courses/:courseId', authMiddleware, async (req, res) => { + try { + const {courseId} = req.params; + + // Find the course by its ID + const course = await Course.findById(courseId); + + if (!course) { + return res.status(404).json({ message: 'Course not found' }); + } + + // Send course data in the response + res.json({ course }); + } catch (error) { + console.error('Error fetching course:', error); + res.status(500).json({ message: 'Server error. Failed to retrieve course.' }); + } + }); + app.put('/admin/courses/:courseId', authMiddleware, async (req, res) => { // logic to edit a course try { From 0400392490f4e65e001bbaaa7cc0c4e9e8c26c16 Mon Sep 17 00:00:00 2001 From: Vikash Thakur Date: Sat, 28 Sep 2024 23:42:56 +0530 Subject: [PATCH 22/41] Fixed: Updating and Creating of course for Admin: --- week-7/client/src/App.jsx | 2 + week-7/client/src/components/Courses.jsx | 21 +- week-7/client/src/components/Dashboard.jsx | 98 +++------ week-7/client/src/components/UpdateCourse.jsx | 187 ++++++++++++++++++ 4 files changed, 231 insertions(+), 77 deletions(-) create mode 100644 week-7/client/src/components/UpdateCourse.jsx diff --git a/week-7/client/src/App.jsx b/week-7/client/src/App.jsx index 82c7ae18..8cfd9edf 100644 --- a/week-7/client/src/App.jsx +++ b/week-7/client/src/App.jsx @@ -4,6 +4,7 @@ import Home from "./pages/Home" import Register from "./components/Register" import Login from "./components/Login" import Dashboard from "./components/Dashboard" +import UpdateCourse from "./components/UpdateCourse" function App() { return ( @@ -14,6 +15,7 @@ function App() { } /> } /> } /> + } /> diff --git a/week-7/client/src/components/Courses.jsx b/week-7/client/src/components/Courses.jsx index 7853d615..b017392f 100644 --- a/week-7/client/src/components/Courses.jsx +++ b/week-7/client/src/components/Courses.jsx @@ -1,9 +1,11 @@ import axios from "axios"; import { useEffect, useState } from "react" +import { useNavigate } from "react-router-dom"; // use axios here, similar to register and login const Courses = () => { const [courses, setCourses] = useState([]) + const navigate = useNavigate(); useEffect(() => { const fetchCourses = async () => { @@ -18,20 +20,23 @@ const Courses = () => { fetchCourses(); }, []); + const handleRoute = (id) => { + navigate(`/updatecourse/${id}`) + } return (

All Courses

{ courses.map((item, index) => ( -
-
- Image +
handleRoute(item._id)}> +
+ Image +
+

{item.title}

+

{item.description}

+

Rs.{item.price}

+

{item.published ? 'Published' : 'Not Published'}

-

{item.title}

-

{item.description}

-

Rs.{item.price}

-

{item.published ? 'Published' : 'Not Published'}

-
)) }
diff --git a/week-7/client/src/components/Dashboard.jsx b/week-7/client/src/components/Dashboard.jsx index b5237b4c..4df58fa4 100644 --- a/week-7/client/src/components/Dashboard.jsx +++ b/week-7/client/src/components/Dashboard.jsx @@ -1,90 +1,50 @@ -import { useState } from 'react'; -import axios from 'axios'; +import axios from "axios"; +import { useState } from "react"; import Courses from "./Courses" - -const CreateCourse = () => { - const [title, setTitle] = useState(''); - const [description, setDescription] = useState(''); - const [price, setPrice] = useState(''); - const [imageLink, setImageLink] = useState(''); - const [published, setPublished] = useState(false); +const Dashboard = () => { + const [title, setTitle] = useState("") + const [description, setDescription] = useState("") + const [price, setPrice] = useState("") + const [imageLink, setImageLink] = useState("") + const [published, setPublished] = useState(false) const handleSubmit = async (e) => { e.preventDefault(); - try { - await axios.post( - 'http://localhost:3000/admin/courses', - { - title, - description, - price, - imageLink, - published - }, - { - headers: { - Authorization: `Bearer ${localStorage.getItem('adminToken')}` - } + await axios.post("http://localhost:3000/admin/courses", { + title, + description, + price, + imageLink, + published + }, { + headers: { + Authorization: `Bearer ${localStorage.getItem("adminToken")}` } - ); - - setTitle(''); - setDescription(''); - setPrice(''); - setImageLink(''); - setPublished(false); - // window.location.reload() + }) + window.location.reload(); } catch (error) { - console.log("Error", error); + console.log("Error in creating Post..", error) } - }; + } + return (

Create New Course

- - setTitle(e.target.value)} - required - /> - setDescription(e.target.value)} - required - /> - setPrice(e.target.value)} - required - /> - setImageLink(e.target.value)} - required - /> + setTitle(e.target.value)} required/> + setDescription(e.target.value)} required /> + setPrice(e.target.value)}required /> + setImageLink(e.target.value)} required/> - +
); }; -export default CreateCourse; +export default Dashboard; \ No newline at end of file diff --git a/week-7/client/src/components/UpdateCourse.jsx b/week-7/client/src/components/UpdateCourse.jsx new file mode 100644 index 00000000..0e46e981 --- /dev/null +++ b/week-7/client/src/components/UpdateCourse.jsx @@ -0,0 +1,187 @@ +// import axios from 'axios'; +// import { useEffect, useState } from 'react'; +// import { useParams } from 'react-router-dom'; + +// import { useState } from "react"; + +// const UpdateCourse = () => { +// const { id } = useParams(); // Get course ID from URL +// const [course, setCourse] = useState({ +// title: '', +// description: '', +// price: '', +// imageLink: '', +// published: false, +// }); +// const [error, setError] = useState(''); +// const [success, setSuccess] = useState(''); + +// useEffect(() => { +// // Use GET to fetch the course details +// const fetchCourse = async () => { +// try { +// const response = await axios.get(`http://localhost:3000/admin/courses/${id}`, { +// headers: { +// Authorization: `Bearer ${localStorage.getItem('adminToken')}`, +// }, +// }); +// console.log('The Response', response.data); + +// if (response.data.course) { +// setCourse(response.data.course); +// } +// } catch (error) { +// setError('Failed to fetch course details'); +// } +// }; +// fetchCourse(); +// }, [id]); + +// const handleUpdate = async (e) => { +// e.preventDefault(); +// setError(''); +// setSuccess(''); + +// try { +// // PUT request to update the course details +// await axios.put(`http://localhost:3000/admin/courses/${id}`, course, { +// headers: { +// Authorization: `Bearer ${localStorage.getItem('adminToken')}`, +// }, +// }); +// setSuccess('Course updated successfully'); +// } catch (error) { +// setError('Failed to update course'); +// } +// }; + +// return ( +//
+//

Update Course

+// {error &&

{error}

} +// {success &&

{success}

} +//
+// setCourse({ ...course, title: e.target.value })} +// required +// /> +//