diff --git a/client/src/context/ServerStatusProvider.tsx b/client/src/context/ServerStatusProvider.tsx index f6bee12..f4b28ae 100644 --- a/client/src/context/ServerStatusProvider.tsx +++ b/client/src/context/ServerStatusProvider.tsx @@ -19,7 +19,7 @@ export default function ServerStatusProvider({ children }: PropsWithChildren) { useEffect(() => { const checkServerStatus = async () => { try { - const { data } = await axios.get(`${ENV.SERVER_URL}/api/status`) + const { data } = await axios.get(`${ENV.SERVER_URL}/api/v1/status`) if (data.status) { setServerStatus(data) diff --git a/client/src/pages/cart/components/place-order/PlaceOrder.tsx b/client/src/pages/cart/components/place-order/PlaceOrder.tsx index d5e3263..8b57792 100644 --- a/client/src/pages/cart/components/place-order/PlaceOrder.tsx +++ b/client/src/pages/cart/components/place-order/PlaceOrder.tsx @@ -35,7 +35,7 @@ export default function PlaceOrder() { amount: order.amount, currency: 'INR', name: 'RazorPay', - description: 'Tutorial of RazorPay', + description: 'Secure payment through RazorPay', // image: 'https://avatars.githubusercontent.com/u/25058652?v=4', order_id: order.id, callback_url: 'http://localhost:5000/api/v1/paymentverification', diff --git a/client/src/pages/payment-success/PaymentSuccessPage.tsx b/client/src/pages/payment-success/PaymentSuccessPage.tsx index 62498e5..174ba4b 100644 --- a/client/src/pages/payment-success/PaymentSuccessPage.tsx +++ b/client/src/pages/payment-success/PaymentSuccessPage.tsx @@ -14,7 +14,7 @@ export default function PaymentSuccessPage() { if (referenceNum) { console.log(referenceNum) const response = await fetch( - `http://localhost:5000/verify-payment?paymentId=${referenceNum}` + `http://localhost:5000/api/v1/verify-payment?paymentId=${referenceNum}` ) const data = await response.json() if (data.success) { diff --git a/server/package-lock.json b/server/package-lock.json index 7b8067c..1b9be7d 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -15,14 +15,12 @@ "express": "^4.18.2", "jsonwebtoken": "^9.0.2", "mongoose": "^8.1.1", - "pg": "^8.11.3", "razorpay": "^2.9.2" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/node": "^20.10.5", - "@types/pg": "^8.10.9", "nodemon": "^3.0.3", "prettier": "^3.1.1", "ts-node": "^10.9.2", @@ -180,74 +178,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/pg": { - "version": "8.10.9", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.9.tgz", - "integrity": "sha512-UksbANNE/f8w0wOMxVKKIrLCbEMV+oM1uKejmwXr39olg4xqcfBDbXxObJAt6XxHbDa4XTKOlUEcEltXDX+XLQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@types/qs": { "version": "6.9.10", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", @@ -527,14 +457,6 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1626,12 +1548,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1643,11 +1559,6 @@ "node": ">= 0.8" } }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1666,98 +1577,6 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, - "node_modules/pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "^4.1.0" - } - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1770,47 +1589,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, "node_modules/prettier": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", @@ -2158,14 +1936,6 @@ "memory-pager": "^1.0.2" } }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "engines": { - "node": ">= 10.x" - } - }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", @@ -2448,14 +2218,6 @@ "node": ">=16" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/server/package.json b/server/package.json index 4db1370..66f0d0f 100644 --- a/server/package.json +++ b/server/package.json @@ -6,7 +6,8 @@ "dev": "nodemon src/index.ts", "start": "node index.js", "format": "prettier --write ./src", - "check-format": "prettier --check ./src" + "check-format": "prettier --check ./src", + "check-types": "tsc --pretty --noEmit" }, "dependencies": { "bcryptjs": "^2.4.3", @@ -16,14 +17,12 @@ "express": "^4.18.2", "jsonwebtoken": "^9.0.2", "mongoose": "^8.1.1", - "pg": "^8.11.3", "razorpay": "^2.9.2" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/node": "^20.10.5", - "@types/pg": "^8.10.9", "nodemon": "^3.0.3", "prettier": "^3.1.1", "ts-node": "^10.9.2", diff --git a/server/src/app.ts b/server/src/app.ts index f37314e..8c95ff1 100644 --- a/server/src/app.ts +++ b/server/src/app.ts @@ -17,33 +17,12 @@ app.use(express.static('public')) app.use(cookieParser()) // Routes -import { Payment } from './models/payment.model' -import paymentRoute from './routes/payment.routes' - -app.get('/api/status', (req, res) => { - res.json({ status: true, message: 'Server is running' }) -}) +import generalRoute from './routes/general.route' +import paymentRoute from './routes/payment.route' +import userRoute from './routes/user.route' +app.use('/api/v1', generalRoute) app.use('/api/v1', paymentRoute) - -app.get('/api/v1/get-key', (req, res) => - res.status(200).json({ key: ENV.RAZORPAY_API_KEY }) -) - -app.get('/verify-payment', async (req, res) => { - const paymentId = req.query.paymentId - console.log(paymentId) - try { - const payment = await Payment.findOne({ razorpay_payment_id: paymentId }) - - if (payment) { - res.json({ success: true }) - } else { - res.json({ success: false }) - } - } catch (error) { - res.status(500).json({ success: false }) - } -}) +app.use('/api/v1', userRoute) export default app diff --git a/server/src/controller/general/serverStatus.controller.ts b/server/src/controller/general/serverStatus.controller.ts new file mode 100644 index 0000000..30a568e --- /dev/null +++ b/server/src/controller/general/serverStatus.controller.ts @@ -0,0 +1,3 @@ +export const general = (req, res) => { + res.json({ status: true, message: 'Server is running' }) +} diff --git a/server/src/controller/payment/checkout.controller.ts b/server/src/controller/payment/checkout.controller.ts new file mode 100644 index 0000000..d6aeda9 --- /dev/null +++ b/server/src/controller/payment/checkout.controller.ts @@ -0,0 +1,14 @@ +import { razorpayInstance } from '../..' + +export const checkout = async (req, res) => { + const options = { + amount: Number(req.body.amount * 100), + currency: 'INR', + } + const order = await razorpayInstance.orders.create(options) + + res.status(200).json({ + success: true, + order, + }) +} diff --git a/server/src/controllers/payment.controller.ts b/server/src/controller/payment/payment.controller.ts similarity index 60% rename from server/src/controllers/payment.controller.ts rename to server/src/controller/payment/payment.controller.ts index 846c3d3..6d0b38e 100644 --- a/server/src/controllers/payment.controller.ts +++ b/server/src/controller/payment/payment.controller.ts @@ -1,22 +1,7 @@ import crypto from 'crypto' -// import { Payment } from '../models/payment.model.js' -import { ENV } from '../conf/conf' -import { CLIENT_BASE_URL } from '../constants' -import { razorpayInstance } from '../index' -import { Payment } from '../models/payment.model' - -export const checkout = async (req, res) => { - const options = { - amount: Number(req.body.amount * 100), - currency: 'INR', - } - const order = await razorpayInstance.orders.create(options) - - res.status(200).json({ - success: true, - order, - }) -} +import { ENV } from '../../conf/conf' +import { CLIENT_BASE_URL } from '../../constants' +import { Payment } from '../../model/payment.model' export const paymentVerification = async (req, res) => { const { razorpay_order_id, razorpay_payment_id, razorpay_signature } = @@ -47,3 +32,7 @@ export const paymentVerification = async (req, res) => { }) } } + +export const getKey = (req, res) => { + res.status(200).json({ key: ENV.RAZORPAY_API_KEY }) +} diff --git a/server/src/controller/payment/verifyPayment.controller.ts b/server/src/controller/payment/verifyPayment.controller.ts new file mode 100644 index 0000000..e9b26de --- /dev/null +++ b/server/src/controller/payment/verifyPayment.controller.ts @@ -0,0 +1,17 @@ +import { Payment } from '../../model/payment.model' + +export const verifyPayment = async (req, res) => { + const paymentId = req.query.paymentId + console.log(paymentId) + try { + const payment = await Payment.findOne({ razorpay_payment_id: paymentId }) + + if (payment) { + res.json({ success: true }) + } else { + res.json({ success: false }) + } + } catch (error) { + res.status(500).json({ success: false }) + } +} diff --git a/server/src/controller/user/login.controller.ts b/server/src/controller/user/login.controller.ts new file mode 100644 index 0000000..0ba6660 --- /dev/null +++ b/server/src/controller/user/login.controller.ts @@ -0,0 +1,39 @@ +import bcryptjs from 'bcryptjs' +import jwt from 'jsonwebtoken' +import { User } from '../../model/user.model' + +export const loginUser = async (req, res) => { + try { + const { username, password } = req.body + + const user = await User.findOne({ username }) + if (!user) { + return res.status(400).json({ error: 'User does not exist' }) + } + // Check password + const validPassword = await bcryptjs.compare(password, user.password) + if (!validPassword) { + return res.status(400).json({ error: 'Invalid password' }) + } + + // Create token data for JWT + const tokenData = { + id: user._id, + username: user.username, + } + + // Create token with JWT + const token = await jwt.sign(tokenData, 'secret', { + expiresIn: '1d', + }) + + res.cookie('token', token) + return res.json({ + message: 'Login successful', + success: true, + token, + }) + } catch (error) { + return res.status(500).json({ error: error.message }) + } +} diff --git a/server/src/controller/user/logout.controller.ts b/server/src/controller/user/logout.controller.ts new file mode 100644 index 0000000..298c55e --- /dev/null +++ b/server/src/controller/user/logout.controller.ts @@ -0,0 +1,11 @@ +export const logout = async (req, res) => { + try { + res.cookie('token', '', { maxAge: 0 }) + return res.json({ + message: 'Logout successfully', + success: true, + }) + } catch (error) { + return res.status(500).json({ error: error.message }) + } +} diff --git a/server/src/controller/user/register.controller.ts b/server/src/controller/user/register.controller.ts new file mode 100644 index 0000000..a34b11e --- /dev/null +++ b/server/src/controller/user/register.controller.ts @@ -0,0 +1,42 @@ +import bcryptjs from 'bcryptjs' +import jwt from 'jsonwebtoken' +import { User } from '../../model/user.model' + +export const registerUser = async (req, res) => { + try { + const { username, password } = req.body + // console.log(name, pass) + + const user = await User.findOne({ username }) + if (user) { + return res.status(400).json({ data: 'User already exists' }) + } + // Hash the password + const salt = await bcryptjs.genSalt(10) + const hashedPassword = await bcryptjs.hash(password, salt) + + const newUser = new User({ + username, + password: hashedPassword, + }) + const savedUser = await newUser.save() + + const tokenData = { + id: savedUser._id, + username: savedUser.username, + } + + // Create token with JWT + const token = await jwt.sign(tokenData, 'secret', { + expiresIn: '1d', + }) + + res.cookie('token', token) + return res.json({ message: 'User registered successfully', token }) + } catch (error) { + console.log(error) + return res + .status(500) + .json({ error: 'An error occurred while registering the user' }) + } +} diff --git a/server/src/middleware/verifyToken.middleware.ts b/server/src/middleware/verifyToken.middleware.ts new file mode 100644 index 0000000..ccda5cb --- /dev/null +++ b/server/src/middleware/verifyToken.middleware.ts @@ -0,0 +1,17 @@ +import jwt from 'jsonwebtoken' + +export const verifyToken = (req, res, next) => { + const token = req.cookies.token + + if (!token) { + return res.status(403).json({ error: 'Access Denied' }) + } + + try { + const verified = jwt.verify(token, 'secret') + req.user = verified + next() + } catch (err) { + res.status(400).json({ error: 'Token is not valid' }) + } +} diff --git a/server/src/middlewares/.gitkeep b/server/src/middlewares/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/server/src/models/payment.model.ts b/server/src/model/payment.model.ts similarity index 100% rename from server/src/models/payment.model.ts rename to server/src/model/payment.model.ts diff --git a/server/src/model/user.model.ts b/server/src/model/user.model.ts new file mode 100644 index 0000000..64e1c1e --- /dev/null +++ b/server/src/model/user.model.ts @@ -0,0 +1,17 @@ +import mongoose from 'mongoose' + +const userSchema = new mongoose.Schema( + { + username: { + type: String, + required: true, + }, + password: { + type: String, + require: true, + }, + }, + { timestamps: true } +) + +export const User = mongoose.model('User', userSchema) diff --git a/server/src/routes/general.route.ts b/server/src/routes/general.route.ts new file mode 100644 index 0000000..fed1a7e --- /dev/null +++ b/server/src/routes/general.route.ts @@ -0,0 +1,8 @@ +import { Router } from 'express' +import { general } from '../controller/general/serverStatus.controller' + +const generalRoute = Router() + +generalRoute.get('/status', general) + +export default generalRoute diff --git a/server/src/routes/payment.route.ts b/server/src/routes/payment.route.ts new file mode 100644 index 0000000..0fc3306 --- /dev/null +++ b/server/src/routes/payment.route.ts @@ -0,0 +1,16 @@ +import { Router } from 'express' +import { checkout } from '../controller/payment/checkout.controller' +import { + getKey, + paymentVerification, +} from '../controller/payment/payment.controller' +import { verifyPayment } from '../controller/payment/verifyPayment.controller' + +const paymentRoute = Router() + +paymentRoute.route('/checkout').post(checkout) +paymentRoute.route('/paymentverification').post(paymentVerification) +paymentRoute.route('/verify-payment').get(verifyPayment) +paymentRoute.route('/get-key').get(getKey) + +export default paymentRoute diff --git a/server/src/routes/payment.routes.ts b/server/src/routes/payment.routes.ts deleted file mode 100644 index e32015f..0000000 --- a/server/src/routes/payment.routes.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Router } from 'express' -import { - checkout, - paymentVerification, -} from '../controllers/payment.controller' - -const router = Router() - -router.route('/checkout').post(checkout) -router.route('/paymentverification').post(paymentVerification) - -export default router diff --git a/server/src/routes/user.route.ts b/server/src/routes/user.route.ts new file mode 100644 index 0000000..a8be25d --- /dev/null +++ b/server/src/routes/user.route.ts @@ -0,0 +1,12 @@ +import { Router } from 'express' +import { loginUser } from '../controller/user/login.controller' +import { logout } from '../controller/user/logout.controller' +import { registerUser } from '../controller/user/register.controller' + +const userRoute = Router() + +userRoute.route('/register').post(registerUser) +userRoute.route('/login').post(loginUser) +userRoute.route('/logout').get(logout) + +export default userRoute diff --git a/server/src/utils/ApiError.ts b/server/src/utils/ApiError.ts index 17ec11c..282f863 100644 --- a/server/src/utils/ApiError.ts +++ b/server/src/utils/ApiError.ts @@ -1,22 +1,21 @@ class ApiError extends Error { + statusCode: number + data: any + success: boolean + errors: any[] + constructor( - statusCode, - message = 'Something went wrong', - errors = [], - stack = '' + statusCode: number, + message: string = 'Something went wrong', + errors: any[] = [], + data: any = null ) { super(message) this.statusCode = statusCode - this.data = null - this.message = message + this.data = data this.success = false this.errors = errors - - if (stack) { - this.stack = stack - } else { - Error.captureStackTrace(this, this.constructor) - } + Error.captureStackTrace(this, this.constructor) } } diff --git a/server/src/utils/ApiResponse.ts b/server/src/utils/ApiResponse.ts index 2a9a3f5..1a97521 100644 --- a/server/src/utils/ApiResponse.ts +++ b/server/src/utils/ApiResponse.ts @@ -1,9 +1,14 @@ class ApiResponse { - constructor(statusCode, data, message = 'Success') { + statusCode: any + data: any + message: string + success: boolean + + constructor(statusCode: number, data: any, message: string = 'Success') { this.statusCode = statusCode this.data = data this.message = message - this.success = statusCode < 400 + this.success = this.statusCode >= 200 && this.statusCode < 300 } }